题目:Pwnable.tw-starbound
解法1:ret2libc
1.进入程序进行观察:
这是一个交互小游戏,存在多处用户输入的位置,很有可能存在栈溢出漏洞。
2.查看文件保护状态:
3.使用IDA中查看文件内容:
这个文件较之平时的其他题目代码量大了很多,存在许多输入位置,但是找了一圈没有可以直接利用的栈溢出漏洞。
4.在反汇编代码中发现一个逻辑漏洞:
在用户输入时,程序只对输入值进行了strtol()处理,并把该值作为数组下标,也就是说对于输入的数字只要不为零都是可以利用p_choice指针调用到我们想要的指针。另外虽然我们的输入数字之后的内容都会被过滤掉,但是其内容还是可以完整地写入内存中,这可以作为后续利用的地方。
5.观察p_choice在bss段中的位置:
可以发现在p_choice的低地址方向存在着用户可控的p_playername字段,也就是说只要我们提前控制了p_playername中的内容,就可以操纵p_choice对任意代码进行调用。
6.分析调用函数时的栈状态:
可以看到进入被调函数时栈顶的参数对于我们来说用处不大,无法直接作为常用的pwn函数如read、gets、puts等的参数。所以我们需要寻找一段合适的ROP改变这个情况。
7.寻找可利用的ROP:
寻找过程中存在几种不同的思路,一是因为在汇编代码中可以发现read函数的写入地址由ebx决定,所以我们可以寻找能够将ebx中的地址改为一个更高的地址的gadget,这样就可以直接修改当前栈帧的ebp和返回地址;二是将ebp地址改为一个更低的地址,原理同一;三是在步骤4中我们发现输入的数字之后的内容是可控的,那我们可以将esp往高地址移动,这样就可以对ROP的返回地址或后续被调函数的参数进行控制……
根据以上思路使用ROPgadget工具寻找合适的ROP,最终确定一个合适的ROP:
这个ROP符合我们第三种思路,这样我们就可以通过步骤4中的逻辑漏洞控制ROP的返回地址。
8.确认攻击方法并构造payload
此时存在几种攻击思路,一是从ROP返回到puts函数执行ret2libc攻击方式;二是继续寻找能够改变寄存器值的ROP,执行ret2syscall攻击方式;三是dl_resolve……
我选择了第一种思路,构造payload如下:
from pwn import *
r = process("./starbound")
elf = ELF('./starbound')
rel_plt_addr = elf.get_section_by_name('.rel.plt').header.sh_addr #0x80487c8
dynsym_addr = elf.get_section_by_name('.dynsym').header.sh_addr #0x80481dc
dynstr_addr = elf.get_section_by_name('.dynstr').header.sh_addr #0x80484fc
resolve_plt = 0x08048940
add_addr=0x08048e48
ppp_ret_addr=0x80491ba
start=0x08057D90+0x10 #0x08057da0
align=0x8-