在内核模块中以十六进制字符串查找内存地址

时间:2013-08-08 14:48:13

标签: c linux linux-kernel gdb hex

我正在编写一个内核模块,通过首先搜索地址旁边的十六进制字节来查找do_debug(0xffffffff8134f709)的内存地址。我不确定我使用的是正确的十六进制字节:“\ xe8 \ x61 \ x07 \ x00 \ x00”(我希望坚持C而不是汇编。)

struct desc_ptr idt_register;
store_idt(&idt_register);
printk("idt_register.address: %lx\n", idt_register.address); // same as in /boot/System.map*

gate_desc *idt_table = (gate_desc *)idt_register.address;

unsigned char *debug = (unsigned char *)gate_offset(idt_table[0x1]);
printk("debug: %lx\n", (unsigned long)debug); // same as in /boot/System.map*

int count = 0;
while(count < 150){
    if( (*(debug) == 0xe8) && (*(debug + 1) == 0x61) && (*(debug + 2) == 0x07) && (*(debug + 3) == 0x00) && (*(debug + 4) == 0x00) ){
        debug += 5;

        unsigned long *do_debug = (unsigned long *)(0xffffffff00000000 | *((unsigned long *)(debug)));
        if((unsigned long)do_debug != 0xffffffff8134f709){
               printk("do_debug: %lx\n", (unsigned long)do_debug); // wrong address !
               return;
           }

           break;
    }

    debug++;
    count++;
}

GDB:

gdb ./vmlinux-3.2.0-4-amd64
...
(gdb) info line debug
Line 54 of "/build/linux-s5x2oE/linux-3.2.46/drivers/pci/hotplug/pci_hotplug_core.c" is at address 0xffffffff811cf02b <power_read_file+2> but contains no code.
Line 1322 of "/build/linux-s5x2oE/linux-3.2.46/arch/x86/kernel/entry_64.S"
starts at address 0xffffffff8134ef80 and ends at 0xffffffff8134efc0.
(gdb) disas 0xffffffff8134ef80,0xffffffff8134efc0
Dump of assembler code from 0xffffffff8134ef80 to 0xffffffff8134efc0:
0xffffffff8134ef80: callq  *0x2c687a(%rip)        # 0xffffffff81615800
0xffffffff8134ef86: pushq  $0xffffffffffffffff
0xffffffff8134ef88: sub    $0x78,%rsp
0xffffffff8134ef8c: callq  0xffffffff8134ed40
0xffffffff8134ef91: mov    %rsp,%rdi
0xffffffff8134ef94: xor    %esi,%esi
0xffffffff8134ef96: subq   $0x1000,%gs:0x1137c
0xffffffff8134efa3: callq  0xffffffff8134f709 <do_debug>
0xffffffff8134efa8: addq   $0x1000,%gs:0x1137c
0xffffffff8134efb5: jmpq   0xffffffff8134f160
0xffffffff8134efba: nopw   0x0(%rax,%rax,1)
End of assembler dump.
(gdb) x/i 0xffffffff8134efa3
0xffffffff8134efa3: callq  0xffffffff8134f709 <do_debug>
(gdb) x/xw 0xffffffff8134efa3
0xffffffff8134efa3: 0x000761e8
(gdb)

readelf:

ffffffff8134ef96:   65 48 81 2c 25 7c 13    subq   $0x1000,%gs:0x1137c
ffffffff8134ef9d:   01 00 00 10 00 00 
ffffffff8134efa3:   e8 61 07 00 00          callq  ffffffff8134f709 <do_debug>
ffffffff8134efa8:   65 48 81 04 25 7c 13    addq   $0x1000,%gs:0x1137c
ffffffff8134efaf:   01 00 00 10 00 00 

修改

(gdb) print do_debug
$1 = {void (struct pt_regs *, long int)} 0xffffffff8134f709 <do_debug>
(gdb)

1 个答案:

答案 0 :(得分:0)

我不熟悉linux内核。 在while语句中,当你进入第一个if语句时, debug 然后指向ffffffff8134efa8

ffffffff8134efa8:   65 48 81 04 25 7c 13    addq   $0x1000,%gs:0x1137c # debug point here
ffffffff8134efaf:   01 00 00 10 00 00 

下一个声明

 unsigned long *do_debug = (unsigned long *)(0xffffffff00000000 |
 *((unsigned long *)(debug)));

会得到这个结果。

do_debug = (unsigned long *)(0xffffffff00000000 | 0x01137c2504814865) = 0xffffffff04814865

如果你想获得do_debug地址,你应该这样做:

if( (*(debug) == 0xe8) && (*(debug + 1) == 0x61) && (*(debug + 2) == 0x07) && (*(debug + 3) == 0x00) && (*(debug + 4) == 0x00) ){
    //debug += 5;
    uint32_t offset = ntohl(*(unsigned int *)(debug+1)); //get the do_debug function offset

    unsigned long *do_debug = (debug+5)+offset; // next_code_instruction + offset
    //debug+5 point to ffffffff8134efa8
    //offset is 0x761
    //so ffffffff8134efa8+0x761 = 0xffffffff8134f709
    if((unsigned long)do_debug != 0xffffffff8134f709){
           printk("do_debug: %lx\n", (unsigned long)do_debug); // wrong address !
           return;
       }

       break;
}