Una función del núcleo de Linux para insertar un comando para jugar nave?

Ayer por la noche el Sr. Anderson comenzó a problemas casi toda la noche, por completo el sueño, después de que la abuela le quitó el Sr. Anderson, escribí un artículo:
https://blog.csdn.net/dog250/article/details/105093969
Sin embargo, nadie ¿cómo se puede hacer cosas prácticas.

Aunque es difícil, pero puede ser simple.

Es decir, yo quiero elegir una función de núcleo simple, en el que la inserción, la función simplemente no requiere corrección al desplazamiento relativo. Pero no he encontrado una prueba de esa función para mí. Así que estoy listo para escribir uno. El siguiente es un ejemplo de módulo del kernel:

#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");

Cargar de.

A continuación, nos fijamos en esta función 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

Me gustaría insertar unas instrucciones de línea antes de retq, su papel es el de incrementar el sistema de valores de panic_on_oops!

Incrementamos el valor del código de instrucción panic_on_oops por ASM línea de montaje a la basura:

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

0xffffffff81977890 que es panic_on_oops abordan encontré en / proc / kallsyms, por supuesto, también se puede comprobar directamente el símbolo con el API.

volcar un total de siete bytes de código de instrucción:

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

Tenemos que poner siete bytes en el retq delante.

El siguiente código para completar este proceso:

#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");

Carga de este tiempo, seguimos cat / proc / prueba, y luego miramos el valor de 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

El efecto es así.

Ahora hablar de la complejidad del caso, si nos vamos a enganchar una función normal? Si nuestra función hook_read se convierte en la siguiente forma:

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;
}

Me gusta ver la función original:

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>

A continuación, lo miramos como gancho:

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>

el infierno se desató el salto, porque no hay ah corrección de la desviación.

Sin embargo, y asignar una instrucción separada en comparación con una función de copia de memoria, toda la función directamente en las proximidades de la traducción sería mejor, en retq general tras la cola, habrá algo de espacio libre, después de la función PAN abajo, abajo el espacio vacío se puede insertar instrucciones.

De hecho, sólo tiene que insertar un salto relativo, suficiente espacio, puede saltar JMP en otro lugar y luego de vuelta ah llegado!

Bueno, el sueño.


Wenzhou zapatos mojados, el agua de lluvia no será grasa.

Liberadas 1580 artículos originales · ganado elogios 5111 · Vistas 11.130.000 +

Supongo que te gusta

Origin blog.csdn.net/dog250/article/details/105129254
Recomendado
Clasificación