$ 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
|