记pwnable.tw上applestore
拿到手的是applestore和对应的libc
先放到ida中看看
关键函数应该是handler
分析handler中间的几个函数
add函数购买商品,买的商品构成下面的双向链表
FD买的下一件商品地址 BK就是上一件商品地址
delete函数没有free,uaf应该是没有的,但ulink感觉可以利用
也就是说会有*(BK+8)=FD *(FD+12)=BK,好了有了这个接下来看看能不能构建一个我们可以利用的结构体来实现地址读写。
checkout中函数我们可以注意到
如果你买的东西价格等于7174(也就是20个6plus和6个iphone6),这个地方insert(&v2)把一个栈地址中的数据加入了结构体链表中,也就是说我们现在如果可以找到相应位置栈的写入我们就可以控制这个结构体中间的数据。
由于都是由handler调用的,checkout,card,delete几个函数对应的其实是同一个ebp栈帧。再看看insert(&v2)中v2的地址
v2的地址是ebp-0x20
看看card函数或delete中函数中可以读入的buf地址
好家伙 可以写入的地址ebp-0x22正好
现在明白了,首先我们先满足checkout中消费7174,把添加一个栈空间的结构体到链表中,在控制这个结构体的数据实现地址读写
这里我先用card函数泄露出基址,在my_read中我构建字符串payload=b’y\x00’+p32(got_atoi)+p32(0)*3 这样我们验证buf==’y’时也可以成立,而在接下来的printf函数中i[0]就变成了我们写入的p32(got_atoi)很明显由此可以得到基址.
接下来原本想之间利用ulink改写got表直接调用system,但很快发现出错了,因为在删除链表结点时改写got表同时也会改写system的代码区。现在就要想如何绕过了。
可以利用environ来得到栈地址, 泄露了栈地址后通过调试算出偏移可以得到delete函数的ebp地址,delete函数中的ebp指向的是handler函数中的ebp
ebp -> handler_ebp
ebp -> handler_ebp
通过改写handler_ebp 为got_atoi + 0x22来完成对got表的覆写
注意位置
从delete函数返回到handler函数中, 还原栈帧的过程中ebp 的值为改写成got_atoi – 0x22, 这样在调用my_read 函数中时可以对got_atoi 进行覆写, 改写了got表后要考虑的就是/bin/sh 的位置, 可以看到atoi 的参数就是刚刚输入的数据, 这时可以输入p32(system) + “|| /bin/sh”或 p32(system) + “;/bin/sh” 来绕过system 调用/bin/sh
exp:
Ummmm,其实还有一种思路,用ulink把handler的ebp覆盖成我们输入nptr的栈地址,这样我们可以直接利用leave指令用栈来控制eip。