c - 替换linux内核函数有错误

标签 c linux linux-kernel

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/types.h>

#define CODESIZE 7

static unsigned char original_code[CODESIZE];

static unsigned char jump_code[CODESIZE] =
"\xb8\x00\x00\x00\x00" /* movq $0, %rax */
"\xff\xe0"                                                      /* jump *%rax */
    ;

void (*sync_readahead)( struct address_space *mapping, struct file_ra_state *ra, struct        file *filp, pgoff_t offset, unsigned long req_size ) = (void (*)(struct address_space *,  struct file_ra_state *, struct file *, pgoff_t , unsigned long ) )0xc0197100;


int hijack_start(void);
void hijack_stop(void);
void intercept_init(void);
void intercept_start(void);
void intercept_stop(void);
void fake_printk(struct address_space *mapping, struct file_ra_state *ra, struct file *filp, pgoff_t offset, unsigned long req_size);


int hijack_start()
{
printk(KERN_INFO "I can haz hijack?\n" );
intercept_init();

return 0;
}

void hijack_stop()
{
intercept_stop();
return;
}

void intercept_init()
{
printk(KERN_INFO "in the  intercept_init\n" );
memcpy( original_code, sync_readahead, 7 );
*(long *)&jump_code[1] = (long)fake_printk;

memcpy( sync_readahead, jump_code, 7 );

printk(KERN_INFO "in the  hijack?\n" );

//real_printk=NULL;

printk(KERN_INFO "begin the  hijack?\n" );
memcpy( sync_readahead, jump_code, CODESIZE );
printk(KERN_INFO "begin the  hijack?\n" );

return;
}



void intercept_stop()
{
memcpy( sync_readahead, original_code, CODESIZE );
}

void fake_printk(struct address_space *map, struct file_ra_state *a, struct file *fil,    pgoff_t offse, unsigned long req_siz)
{
printk(KERN_INFO "in the fake printk\n");
// return ret;
}
MODULE_LICENSE("GPL");

module_init( hijack_start );
module_exit( hijack_stop );

我想通过地址(/proc/kallsyms)替换 Linux 内核函数,但是当我memcpy 新函数到地址(Linux 内核)时:

memcpy( sync_readahead, jump_code, CODESIZE );

有错误(段错误)。我看过一些用同样的方式替换 Linux 内核函数的例子。你能帮我解决这个问题吗?非常感谢。

信息如下:

ubuntu kernel: [  574.826458] *pde = 0087d067 *pte = 00197161 
ubuntu kernel: [  574.826468] Modules linked in: hijack(+) test(+) binfmt_misc bridge stp bnep input_polldev video output vmblock vsock vmmemctl vmhgfs pvscsi acpiphp lp ppdev pcspkr psmouse serio_raw snd_ens1371 gameport snd_ac97_codec ac97_bus snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_dummy snd_seq_oss snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq snd_timer snd_seq_device snd soundcore snd_page_alloc vmci i2c_piix4 parport_pc parport intel_agp agpgart shpchp mptspi mptscsih mptbase scsi_transport_spi floppy fbcon tileblit font bitblit softcursor vmxnet
ubuntu kernel: [  574.826491] 
ubuntu kernel: [  574.826493] Pid: 4694, comm: insmod Tainted: G      D    (2.6.28-11-generic #42-Ubuntu) VMware Virtual Platform
ubuntu kernel: [  574.826496] EIP: 0060:[<f7c92101>] EFLAGS: 00010246 CPU: 0
ubuntu kernel: [  574.826498] EIP is at intercept_init+0x41/0x70 [hijack]
ubuntu kernel: [  574.826499] EAX: f5ec4b60 EBX: 00000000 ECX: ffffffff EDX: 00004c4c
ubuntu kernel: [  574.826501] ESI: f7c9252c EDI: c0197100 EBP: f5edbe18 ESP: f5edbe0c
ubuntu kernel: [  574.826502]  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
ubuntu kernel: [  574.826506]  f7c921a6 f7c92130 00000000 f5edbe24 f7c92147 f7c921d5 f5edbf8c c010111e
ubuntu kernel: [  574.826618] ---[ end trace ccc07e4b4d814976 ]---

最佳答案

内核函数劫持是一件非常棘手的事情,需要完全正确才能避免遇到各种问题。

我目前正在开发一个执行此操作的模块,它(在撰写本文时)适用于 2.6.18+ 内核:

https://github.com/cormander/tpe-lkm

您会对 hijacks.c 文件最感兴趣。

此过程的许多部分都依赖于体系结构、内核版本和 CPU 功能。

更新

该模块现在使用 0XE9 跳转操作码,应该适合您。细节在 hijacks.c 中,而您最感兴趣的“高级”逻辑在 security.c 中的 hijack_syscalls() 函数中

关于c - 替换linux内核函数有错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6493628/

相关文章:

c - 如何使用strncat()避免在运行时中止陷阱6错误?

c - 如何知道传递给函数的 char 数组的大小(以字节为单位)?

c - 为什么 fetestexcept() 在乘以 float 时有时会报错?

在 gdb 中查找环境变量地址时的奇怪事情

32 位和 64 位架构中结构成员对齐的混淆

c - 算法 c 求和 2 和 5 的倍数

c - 对于任何 double float ,可以用 "%1.17g"格式打印的最长字符串是多少?

c - 如何用随机(十六进制)字符填充字符串?

linux-kernel - 如何在/proc/driver 下创建 proc 条目?

linux proc fs 文档