A Linuxカーネルの機能は、クラフトをプレイするためのコマンドを挿入するには?

:昨夜アンダーソン氏は、祖母がアンダーソン氏を奪った後、私は記事を書いたん、完全に睡眠、トラブルで最も夜の始めた
https://blog.csdn.net/dog250/article/details/105093969を
、しかし、誰もがどのように実用的なものを行うことができます。

それは困難であるが、それは単純なことができます。

つまり、私は挿入、関数は単に相対オフセットに補正を必要としない、シンプルなカーネル関数を、選びたいです。しかし、私は私のために、このような機能テストを見つけられませんでした。私は1つを書くために準備ができていますので。以下は、例えば、カーネルモジュールです。

#include <linux/module.h>
#include <linux/proc_fs.h>

// 足够简单的函数!
static ssize_t hook_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos)
{
	int n = 0;
	return n;
}

static struct file_operations hook_ops = {
	.owner = THIS_MODULE,
	.read = hook_read,
};

static struct proc_dir_entry *ent;
static int __init hookstat_init(void)
{
	ent=proc_create("test",0660,NULL,&hook_ops);
	if (!ent)
		return -1;

	return 0;
}

static void __exit hookstat_exit(void)
{
	proc_remove(ent);
}

module_init(hookstat_init);
module_exit(hookstat_exit);
MODULE_LICENSE("GPL");

のロード。

次に、我々はこのhook_read機能を見てみましょう。

crash> dis hook_read
0xffffffffa0374000 <hook_read>: nopl   0x0(%rax,%rax,1) [FTRACE NOP]
0xffffffffa0374005 <hook_read+5>:       push   %rbp
0xffffffffa0374006 <hook_read+6>:       xor    %eax,%eax
0xffffffffa0374008 <hook_read+8>:       mov    %rsp,%rbp
0xffffffffa037400b <hook_read+11>:      pop    %rbp
0xffffffffa037400c <hook_read+12>:      retq

私はretq前にライン命令を挿入したいと思い、その役割はすることですpanic_on_oopsの価値体系をインクリメント!

私たちは、命令コードの値はダンプにインラインアセンブリASMによってpanic_on_oopsインクリメント:

asm ("incl 0xffffffff81977890" :::);

0xffffffff81977890あるpanic_on_oopsは、私は/ procの/ kallsymsには、もちろん、あなたも直接APIを持つシンボルを確認することができた対処します。

命令コードの7バイトの合計をダンプ:

	incl[0] = 0xff;
	incl[1] = 0x04;
	incl[2] = 0x25;
	incl[3] = 0x90;
	incl[4] = 0x78;
	incl[5] = 0x97;
	incl[6] = 0x81;
	incl[7] = 0xc3;

私たちは、フロントretqに7つのバイトを配置する必要があります。

このプロセスを完了するために、次のコード:

#include <linux/module.h>
#include <linux/cpu.h>

char *p;
static struct mutex *_text_mutex;

void test_sub1(void) __attribute__ ((aligned (1024))); // 提供足够大的空间容纳原始函数
void test_sub2(void) __attribute__ ((aligned (1024)));
void test_sub1(void)
{
	printk("yes\n");
}
void test_sub2(void)
{
	printk("yes yes\n");
}

static void *(*_text_poke_smp)(void *addr, const void *opcode, size_t len);
static int __init hotfix_init(void)
{
	unsigned char e9_jmp[5];
	unsigned char incl[8];
	char *addr;
	s32 offset;

	_text_poke_smp = (void *)0xffffffff8163e1f0;
	_text_mutex = (void *)0xffffffff81984920;

	p = test_sub1;
	addr = 0xffffffffa0374000; // 该地址是通过hook_read符号查到地址。

	_text_poke_smp(p, addr, 20); // 通过crash dis指令,20个字节够了

	offset = (s32)((long)p - (long)addr - 5);

	incl[0] = 0xff;
	incl[1] = 0x04;
	incl[2] = 0x25;
	incl[3] = 0x90;
	incl[4] = 0x78;
	incl[5] = 0x97;
	incl[6] = 0x81;
	incl[7] = 0xc3;
	incl[8] = 0xc3; // 原有的retq指令往后移7个字节
	_text_poke_smp(&p[12], incl, 8); // 在retq前插入incl指令

	e9_jmp[0] = 0xe9;
	(*(s32 *)(&e9_jmp[1])) = offset;
	get_online_cpus();
	mutex_lock(_text_mutex);
	_text_poke_smp(addr, e9_jmp, 5); // 替换原始函数的前面5个字节
	mutex_unlock(_text_mutex);
	put_online_cpus();

	return 0;
}

static void __exit hotfix_exit(void)
{
}

module_init(hotfix_init);
module_exit(hotfix_exit);
MODULE_LICENSE("GPL");

この時の負荷、我々は猫の/ proc /テストを継続し、その後panic_on_oopsの値を見てみましょう。

[root@localhost ~]# cat /proc/test
[root@localhost ~]# sysctl -a|grep panic_on_oops
kernel.panic_on_oops = 9
[root@localhost ~]# cat /proc/test
[root@localhost ~]# sysctl -a|grep panic_on_oops
kernel.panic_on_oops = 10
[root@localhost ~]# cat /proc/test
[root@localhost ~]# sysctl -a|grep panic_on_oops
kernel.panic_on_oops = 11

効果はそのようなものです。

私たちは正常な機能をフックするために行けば今、例複雑さについて話?私たちのhook_read関数は次のようになった場合:

static ssize_t dump_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos)
{
	char kbuf[16] = {0};

	if (*ppos != 0) {
		return 0;
	}

	n = snprintf(kbuf, 16, "%d\n", 1234);
	memcpy(ubuf, kbuf, n);
	*ppos += n;

	return n;
}

私は、元の関数を見てみたいです。

crash> dis hook_read
0xffffffffa0365000 <hook_read>: nopl   0x0(%rax,%rax,1) [FTRACE NOP]
0xffffffffa0365005 <hook_read+5>:       push   %rbp
0xffffffffa0365006 <hook_read+6>:       mov    %rsp,%rbp
0xffffffffa0365009 <hook_read+9>:       push   %r13
0xffffffffa036500b <hook_read+11>:      push   %r12
0xffffffffa036500d <hook_read+13>:      push   %rbx
0xffffffffa036500e <hook_read+14>:      mov    %rcx,%rbx
0xffffffffa0365011 <hook_read+17>:      sub    $0x18,%rsp
0xffffffffa0365015 <hook_read+21>:      mov    %gs:0x28,%rax
0xffffffffa036501e <hook_read+30>:      mov    %rax,-0x20(%rbp)
0xffffffffa0365022 <hook_read+34>:      xor    %eax,%eax
0xffffffffa0365024 <hook_read+36>:      cmpq   $0x0,(%rcx)
0xffffffffa0365028 <hook_read+40>:      jne    0xffffffffa036505f <hook_read+95>
0xffffffffa036502a <hook_read+42>:      lea    -0x30(%rbp),%rdi
0xffffffffa036502e <hook_read+46>:      mov    %rsi,%r13
0xffffffffa0365031 <hook_read+49>:      mov    $0x4d2,%ecx
0xffffffffa0365036 <hook_read+54>:      mov    $0xffffffffa0366024,%rdx
0xffffffffa036503d <hook_read+61>:      mov    $0x10,%esi
0xffffffffa0365042 <hook_read+66>:      callq  0xffffffff812fd8f0 <snprintf>
0xffffffffa0365047 <hook_read+71>:      lea    -0x30(%rbp),%rsi
0xffffffffa036504b <hook_read+75>:      movslq %eax,%r12
0xffffffffa036504e <hook_read+78>:      mov    %r13,%rdi
0xffffffffa0365051 <hook_read+81>:      mov    %r12,%rdx
0xffffffffa0365054 <hook_read+84>:      callq  0xffffffff812ff530 <__memcpy>
0xffffffffa0365059 <hook_read+89>:      add    %r12,(%rbx)
0xffffffffa036505c <hook_read+92>:      mov    %r12,%rax
0xffffffffa036505f <hook_read+95>:      mov    -0x20(%rbp),%rdx
0xffffffffa0365063 <hook_read+99>:      xor    %gs:0x28,%rdx
0xffffffffa036506c <hook_read+108>:     jne    0xffffffffa0365079 <hook_read+121>
0xffffffffa036506e <hook_read+110>:     add    $0x18,%rsp
0xffffffffa0365072 <hook_read+114>:     pop    %rbx
0xffffffffa0365073 <hook_read+115>:     pop    %r12
0xffffffffa0365075 <hook_read+117>:     pop    %r13
0xffffffffa0365077 <hook_read+119>:     pop    %rbp
0xffffffffa0365078 <hook_read+120>:     retq
0xffffffffa0365079 <hook_read+121>:     callq  0xffffffff81074510 <__stack_chk_fail>

その後、我々はそれのようにフックを見て:

crash> dis 0xffffffffa0374000 100
0xffffffffa0374000 <test_sub1>: nopl   0x0(%rax,%rax,1) [FTRACE NOP]
0xffffffffa0374005 <test_sub1+5>:       push   %rbp
0xffffffffa0374006 <test_sub1+6>:       mov    %rsp,%rbp
0xffffffffa0374009 <test_sub1+9>:       push   %r13
0xffffffffa037400b <test_sub1+11>:      push   %r12
0xffffffffa037400d <test_sub1+13>:      push   %rbx
0xffffffffa037400e <test_sub1+14>:      mov    %rcx,%rbx
0xffffffffa0374011 <test_sub1+17>:      sub    $0x18,%rsp
0xffffffffa0374015 <test_sub1+21>:      mov    %gs:0x28,%rax
0xffffffffa037401e <test_sub1+30>:      mov    %rax,-0x20(%rbp)
0xffffffffa0374022 <test_sub1+34>:      xor    %eax,%eax
0xffffffffa0374024 <test_sub1+36>:      incl   0xffffffff81977890
0xffffffffa037402b <test_sub1+43>:      retq
0xffffffffa037402c <test_sub1+44>:      jge    0xffffffffa0373ffe
0xffffffffa037402e <test_sub1+46>:      mov    %rsi,%r13
0xffffffffa0374031 <test_sub1+49>:      mov    $0x4d2,%ecx
0xffffffffa0374036 <test_sub1+54>:      mov    $0xffffffffa0366024,%rdx
0xffffffffa037403d <test_sub1+61>:      mov    $0x10,%esi
0xffffffffa0374042 <test_sub1+66>:      callq  0xffffffff8130c8f0 <zlib_inflate+2384>
0xffffffffa0374047 <test_sub1+71>:      lea    -0x30(%rbp),%rsi
0xffffffffa037404b <test_sub1+75>:      movslq %eax,%r12
0xffffffffa037404e <test_sub1+78>:      mov    %r13,%rdi
0xffffffffa0374051 <test_sub1+81>:      mov    %r12,%rdx
0xffffffffa0374054 <test_sub1+84>:      callq  0xffffffff8130e530 <lzo1x_1_do_compress+672>
0xffffffffa0374059 <test_sub1+89>:      add    %r12,(%rbx)
0xffffffffa037405c <test_sub1+92>:      mov    %r12,%rax
0xffffffffa037405f <test_sub1+95>:      mov    -0x20(%rbp),%rdx
0xffffffffa0374063 <test_sub1+99>:      xor    %gs:0x28,%rdx
0xffffffffa037406c <test_sub1+108>:     jne    0xffffffffa0374079 <test_sub1+121>
0xffffffffa037406e <test_sub1+110>:     add    $0x18,%rsp
0xffffffffa0374072 <test_sub1+114>:     pop    %rbx
0xffffffffa0374073 <test_sub1+115>:     pop    %r12
0xffffffffa0374075 <test_sub1+117>:     pop    %r13
0xffffffffa0374077 <test_sub1+119>:     pop    %rbp
0xffffffffa0374078 <test_sub1+120>:     retq
0xffffffffa0374079 <test_sub1+121>:     callq  0xffffffff81083510 <exit_ptrace+128>

何のオフセット補正ああがないのでジャンプの地獄は、緩んで破りました。

しかし、メモリコピー機能に比べて独立した命令を割り当て、翻訳の近傍に直接全体の機能が尾後に一般retqで、良いだろう、いくつかの空き領域が存在することになる空きスペースを挿入することができますダウン機能の後、ダウンパン指示。

実際には、あなただけの相対的なジャンプを挿入する必要があり、スペースに十分な、あなたはどこか別の場所JMPジャンプして、ああ戻って来ることができます!

まあ、睡眠。


温州の靴は、雨水が脂肪ではありません、濡れました。

リリース1580元の記事 ウォンの賞賛5111 ビュー1113万+

おすすめ

転載: blog.csdn.net/dog250/article/details/105129254