$ gcc -g -o got got.c $ gdb ./got (gdb) l 5 #include <stdio.h> 6 7 #define GOT 0x8049614 8 9 int main(int argc, char *argv[]) 10 { 11 long got2, got3; 12 long old_addr, new_addr; 13 14 got2=*(long *)(GOT+4); (gdb) l 15 got3=*(long *)(GOT+8); 16 old_addr=*(long *)(GOT+24); 17 18 printf("Hello World\n"); 19 20 new_addr=*(long *)(GOT+24); 21 22 printf("got2: 0x%0x, got3: 0x%0x, old_addr: 0x%0x, new_addr: 0x%0x\n", 23 got2, got3, old_addr, new_addr); 24 (gdb) break 18 #在第一个printf处设置一个断点 Breakpoint 1 at 0x80483c3: file got.c, line 18. (gdb) break 22 #在第二个printf处设置一个断点 Breakpoint 2 at 0x80483dd: file got.c, line 22. (gdb) r #运行到第一个printf之前会停止 Starting program: /mnt/hda8/Temp/c/program/got
Breakpoint 1, main () at got.c:18 18 printf("Hello World\n"); (gdb) x/8x 0x8049614 #查看执行printf之前的全局偏移表内容 0x8049614 <_GLOBAL_OFFSET_TABLE_>: 0x08049548 0xb7f3c6d8 0xb7f33f10 0x080482aa 0x8049624 <_GLOBAL_OFFSET_TABLE_+16>: 0xb7ddbd20 0x080482ca 0x080482da 0x00000000 (gdb) disassemble 0x080482da #查看GOT表项的最有一项,发现刚好是PLT表中push指令的地址,说明此时还没有进行进行符号的重定位,不过发现并非printf,而是puts(1) Dump of assembler code for function puts@plt: 0x080482d4 <puts@plt+0>: jmp *0x804962c 0x080482da <puts@plt+6>: push $0x18 0x080482df <puts@plt+11>: jmp 0x8048294 <_init+24> (gdb) disassemble 0xb7f33f10 #查看GOT第三项的内容,刚好是dl-linux对应的代码, #可通过nm /lib/ld-linux.so.2 | grep _dl_runtime_resolve进行确认 Dump of assembler code for function _dl_runtime_resolve: 0xb7f33f10 <_dl_runtime_resolve+0>: push %eax 0xb7f33f11 <_dl_runtime_resolve+1>: push %ecx 0xb7f33f12 <_dl_runtime_resolve+2>: push %edx (gdb) x/8x 0xb7f3c6d8 #查看GOT表第二项处的内容,看不出什么特别的信息,反编译时提示无法反编译 0xb7f3c6d8: 0x00000000 0xb7f39c3d 0x08049548 0xb7f3c9b8 0xb7f3c6e8: 0x00000000 0xb7f3c6d8 0x00000000 0xb7f3c9a4 (gdb) break *(0xb7f33f10) #在*(0xb7f33f10)指向的代码处设置一个断点,确认它是否被执行 break *(0xb7f33f10) Breakpoint 3 at 0xb7f3cf10 (gdb) c Continuing.
Breakpoint 3, 0xb7f3cf10 in _dl_runtime_resolve () from /lib/ld-linux.so.2 (gdb) c #继续运行,直到第二次调用printf Continuing. Hello World
Breakpoint 2, main () at got.c:22 22 printf("got2: 0x%0x, got3: 0x%0x, old_addr: 0x%0x, new_addr: 0x%0x\n", (gdb) x/8x 0x8049614 #再次查看GOT表项,发现GOT表的最后一项的值应该被修改 0x8049614 <_GLOBAL_OFFSET_TABLE_>: 0x08049548 0xb7f3c6d8 0xb7f33f10 0x080482aa 0x8049624 <_GLOBAL_OFFSET_TABLE_+16>: 0xb7ddbd20 0x080482ca 0xb7e1ea20 0x00000000 (gdb) disassemble 0xb7e1ea20 #查看GOT表最后一项,发现变成了puts函数的代码,说明进行了符号puts的重定位(2) Dump of assembler code for function puts: 0xb7e1ea20 <puts+0>: push %ebp 0xb7e1ea21 <puts+1>: mov %esp,%ebp 0xb7e1ea23 <puts+3>: sub $0x1c,%esp
|