实验环境:
- pwntools:3.12.1
- wsl debian
- libc:2.24
- gdb+gef,IDA
checksec:
1 | $ checksec ./stkof |
breakpoints:
- main ep:0x400c58
- 获取四个函数的输入值: b *0x400d16
patch alarm()
调试时第一坑就是 alarm() 运行时间警告,
0x400c6f-0x40078
使用 keypatch patch 掉就可以。
程序的四个主功能
IDA F5 查看对照着汇编代码总算找到了点眉目。首先程序运行开始 while 循环
要求输入,根据输入值调用不同function,输入值为 1~4,如果输入为其他值会提示”FAIL”
这个时候会申请一段内存,0x210,0xe05010,存储输入的值
结合 objdump -R ./stkof 查看重定位表,可摸索出这四个 function 的逻辑
- 0x400cac Malloc_1,将输入的值作为大小然后分配内存,然后 print 当前分配的堆序号 换行 “OK”
- 0x400cbb Fread_2,第一次获取输入的堆块序号,判断是否在堆里,第二次获取输入的大小,第三次获取输入的值然后写入对应序号的堆内存里,输出 “OK” 换行
- 0x400cca Free_3,获取堆序号输入,free 堆序号对应的堆内存
- 0x400cd9 Fgets_strlen_put
执行成功输出 “OK”,这个时候也会申请一段内存,0x210,0xe05280,存储 “OK” 值,继续 while 循环
- .bss addr: 0x6020c0
- .got.plt: 0x60200
- 存储申请的堆地址:0x6020c0+0x88,0x602148
利用思路
- 连续申请三次堆,这样第二个和第三个堆内存物理相连
- 覆写2号堆,伪造 chunk
- free 3 号堆,bypass unlink
- 编辑 2 号堆覆写 free got 内容为 puts plt,leak function addr
- 计算得到 system() addr
- 接下来有两种思路可getshell:
- 再次覆写 free got 为 system addr,然后申请一个堆,写入”/bin/sh”, 再 free 掉这个堆即可实现 getshell
- 覆写 atoi got 为 system addr,这样程序在陷入获取功能序号的时候,输入 ‘/bin/sh’,调用 atoi 转换也可实现 getshell
getshell 脚本及执行过程
这里采用第一种覆写 free got 的方式 getshell,因为比较稳
1 | #-* coding:utf -* |