该题是模拟了apple的商店,来售卖apple的各种产品,其提供了6个功能:
- 1: 展示商店的商品
- 2: 添加商品到购物车
- 3: 从购物车里面将某一商品删除
- 4: 展示购物车里面的商品
- 5: 结算
- 6: 退出
其中,购物车是用双向链表实现的,其每一项的结构如下,其在32位机器下的大小为16字节。链表头是一个全局变量,存在0x804b068处。1
2
3
4
5
6struct cart_entry{
char* product_name,
int price,
cart_entry* next,
cart_entry* previous
};
程序分析
下面简单的分析添加,删除,购物车输出和结算功能。
添加商品
添加商品是在add()函数中实现的,其在ida中反汇编出来的结果如下图所示:
该函数的逻辑也比较简单,其首先通过malloc在堆上分配16自己大小的空间,然后进行初始化,最后将该结构体添加到双向链表中。
结算
结算功能是在checkout()函数中实现的,其在ida中反汇编出来的结果如下图所示:
由上图可知,其当满足总金额=7174时,则将一个临时变量v2(位于ebp-0x20)加入到双向链表中,而ebp-0x20处的内存如果能被我们所控制的话就可能进行攻击(泄露内存等)。而通过分析可知在cart()函数接收输入的时候我们的输入是能够覆盖到ebp-0x20处的。所以此时只需要满足购物车的总金额=7174即可。我们观察到一共有4种不同的价格(199,299,399,499),我们可以列个方程求出多种解。最直接的方法是交给z3求解器,具体求解如下:
1 |
|
即可求出结果,使得满足购物车总金额=7174.
输出购物车
输出购物车功能是在cart()函数中实现的,其在ida中反汇编出来的结果如下图所示:
在cart()函数中,有一个可以利用的地方就是在my_read()时,用户能输入0x15大小的数据,而输入的数据存进的内存即在ebp-0x22开始处,正好可以将checkout中的添加到双向链表的临时变量(ebp-0x20)给覆盖掉。如果我们将临时变量的第一个元素(存放商品名称)的地方存入atoi的got地址,则可以将libc的地址泄露出来。
删除
删除功能是在delete()函数中实现的,其在ida中反汇编出来的结果如下图所示:
删除操作就是在双向链表中找到要删除的项,然后就是正规的双向链表操作。由于我们可以通过输入控制ebp-0x20处的项的数据,如果我们将next和previous元素修改成特定的值,就有可能修改got表项,此时就造成了控制流的劫持。一开始我是将next修改成got[‘atoi’]-0xc,将previous改成system的地址,最后发生segment fault. 仔细一想,此时确实将atoi的got表项改成了system的地址了,但是也需要将system.addr+8赋值为got[‘atoi’]-0xc,而system.addr+8处是代码段,改程序又开了NX保护,所以会发生segment fault.
Attack
通过前面的分析,我们可以利用cart()函数覆盖ebp-0x20处的内容,进而可以进行内存泄露攻击,将glibc的地址和栈中的地址泄露出来。通过delete函数,我们可以修改某一内存处的内容,如果我们修改ebp的值,使其在leave操作(mov esp, ebp; pop ebp)时,将修改后的ebp值赋给ebp寄存器,从而控制栈,进而修改got表项。
内存泄露
通过前面的分析我们可以看到在cart()函数中,如果将ebp-0x20处的内容覆盖为got[‘atoi’]的地址,则在cart函数输出的时候,就可以将atoi的got表项的内容泄露出来,即glibc的atoi函数的地址。
泄露栈中的地址,一开始没有思路,通过网上的write up,学到了一个方法:glibc有一个全局变量’environ’,该变量保存用户环境,其是一个char**类型,在程序运行时,将用户环境指向栈上,所以environ存储的地址就是栈上的地址,如果我们将environ变量的内容泄露出来也就泄露出来了栈上的地址。
修改Got
此前尝试直接将atoi的got表项改为system的地址会失败,通过查找write up发现有一个比较巧妙的方法: 通过修改子函数(delete函数)的saved ebp值为got[‘atoi’]+0x22的值,则返回delete函数到handle函数时,此时ebp即是got[‘atoi’]+0x22,此时通过my_read()函数将用户输入的值放入ebp-0x22处,即got[‘atoi’],此时可以达到修改atoi的got表项的目的。而修改saved ebp值可以通过delete函数来实现。
完整攻击
完整攻击代码如下
1 | from pwn import * |