调试下的plt&got
源码
// Build with: gcc -m32 -no-pie -g -o plt plt.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
puts("Hello world!");
exit(0);
}
setions信息
@ubuntu:~$ readelf -S plt
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[12] .plt PROGBITS 080482f0 0002f0 000040 04 AX 0 0 16
[14] .text PROGBITS 08048340 000340 000192 00 AX 0 0 16
[23] .got PROGBITS 08049ffc 000ffc 000004 04 WA 0 0 4
[24] .got.plt PROGBITS 0804a000 001000 000018 04 WA 0 0 4
以下是原图:
gdb-peda:put@plt首探
gdb-peda$ disass main
Dump of assembler code for function main:
0x0804843b <+0>: lea ecx,[esp+0x4]
0x0804843f <+4>: and esp,0xfffffff0
0x08048442 <+7>: push DWORD PTR [ecx-0x4]
0x08048445 <+10>: push ebp
0x08048446 <+11>: mov ebp,esp
0x08048448 <+13>: push ecx
0x08048449 <+14>: sub esp,0x4
0x0804844c <+17>: sub esp,0xc
0x0804844f <+20>: push 0x80484f0
0x08048454 <+25>: call 0x8048300 <puts@plt>
0x08048459 <+30>: add esp,0x10
0x0804845c <+33>: sub esp,0xc
0x0804845f <+36>: push 0x0
0x08048461 <+38>: call 0x8048310 <exit@plt>
End of assembler dump.
gdb-peda$ break * 0x08048454
Breakpoint 1 at 0x8048454: file plt.c, line 5.
gdb-peda$ r
...
gdb-peda$ x/i $eip
=> 0x8048454 <main+25>: call 0x8048300 <puts@plt>
结合.plt section信息 0x8048300就在.plt section,puts@plt是特殊符号名称
gdb-peda$ set $eip = 0x8048300
gdb-peda$ p $eip
$1 = (void (*)()) 0x8048300 <puts@plt>
gdb-peda$ x/i $eip
=> 0x8048300 <puts@plt>: jmp DWORD PTR ds:0x804a00c
0x804a00c(指针)在.got.plt节这里
gdb-peda$ b *0x8048300
Note: breakpoint 3 also set at pc 0x8048300.
Breakpoint 4 at 0x8048300
gdb-peda$ j *0x8048300
gdb-peda$ x/wx 0x804a00c
0x804a00c: 0x08048306
...
=> 0x8048300 <puts@plt>: jmp DWORD PTR ds:0x804a00c
| 0x8048306 <puts@plt+6>: push 0x0
| 0x804830b <puts@plt+11>: jmp 0x80482f0
| 0x8048310 <exit@plt>: jmp DWORD PTR ds:0x804a010
| 0x8048316 <exit@plt+6>: push 0x8
|-> 0x8048306 <puts@plt+6>: push 0x0
0x804830b <puts@plt+11>: jmp 0x80482f0
0x8048310 <exit@plt>: jmp DWORD PTR ds:0x804a010
0x8048316 <exit@plt+6>: push 0x8
乍一看就得很奇怪,为什么要莫名其妙的跳到紧接着下一条指令处?那是因为我们之前从未调用过puts函数,所以我们需要出发首次查找,push 0x0 在栈上压入(0x0),然后调用例程以查找符号名称。 这恰好是.plt节的开始(jmp 0x80482f0)
gdb-peda$ x/10i 0x80482f0
=> 0x80482f0: push DWORD PTR ds:0x804a004
0x80482f6: jmp DWORD PTR ds:0x804a008
0x80482fc: add BYTE PTR [eax],al
0x80482fe: add BYTE PTR [eax],al
0x8048300 <puts@plt>: jmp DWORD PTR ds:0x804a00c
0x8048306 <puts@plt+6>: push 0x0
0x804830b <puts@plt+11>: jmp 0x80482f0
0x8048310 <exit@plt>: jmp DWORD PTR ds:0x804a010
0x8048316 <exit@plt+6>: push 0x8
0x804831b <exit@plt+11>: jmp 0x80482f0
以下的第一个(0xf7ffd918)指向ld.so的数据段(可写),第二个(0xf7fedfe0)指向可执行区域
gdb-peda$ x/2wx 0x804a004
0x804a004: 0xf7ffd918 0xf7fedfe0
gdb-peda$ vmmap
Start End Perm Name
0xf7fd9000 0xf7ffc000 r-xp /lib32/ld-2.23.so
0xf7ffc000 0xf7ffd000 r--p /lib32/ld-2.23.so
0xf7ffd000 0xf7ffe000 rw-p /lib32/ld-2.23.so
链接器/加载器(ld.so)在加载二进制文件时填充了.got.plt节中的这两个地址。因此,我将把ld.so中发生的事情视为黑匣子(查找符号的过程)可以说,最终我们将从ld.so代码中获取有关解析符号的内容。
原文:
https://systemoverlord.com/2017/03/19/got-and-plt-for-pwning.html
zer0_1s