介绍
qwb2019的一道题,漏洞利用不难,就是洞藏的有点深,还是队友找出来的。
分析程序
首先说一下漏洞点,updatehash的时候有一个很明显的栈溢出,但是没用,因为溢出的地方就是canary。
但漏洞还是出在这里,v2 = abs(idx) % 15;
预期情况v2应该为0-14的一个数,这样就只能写hash了,但是如果输入0x80000000的话,v2的结果就是-8,就可以对hash的前8位进行写了。
漏洞的原因是因为abs(0x80000000)求出来的值还是0x80000000,0x80000000就是-2147483648,但int的最大值是2147483647,已经超出范围了。
求abs的汇编代码如下:
1 | .text:0000000000000D0C mov eax, [rbp+idx] |
也实验了一下,的确abs(0x80000000),会出现错误的结果。
1 |
|
回归正题,程序流程如下:
单选问题,可以new,set,show和updatehash
其中new的时候可以选择int Array或者string Array,会初始化一些参数,和一个vtable,因为它们的show和set有区别
它们的结构体如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16struct intNode{
void * vtable;
char hash[16];
int64 size;
int64 *content;
}
struct strNode{
void * vtable;
char hash[16];
int64 size;
int64 *xxx;
}
struct xxx{
char *content
int64 size;
}其中set、show操作比较简单就不赘述了。
利用方式
- 漏洞在updateHash的时候,如果你输入的ida为0x80000000,那么hash就会写到vtable处
- 由于保护全开,我们即使可以覆盖vtable也没有地址,这里的做法是类型混淆,将strNode的vtable改成intNode的vtable,后三位不同,patial overwrite,1/16的正确几率
- 将strNode转为intNode之后,我们就可以控制content指针(直接打印可以获得heap地址),也就是原本的xxx指针,我们只需伪造一个xxx结构体,并将指针只过去,再转回strNode,就可以有任意读和任意写了。
- 利用过程如下:
- 泄漏heap地址
- 泄漏heap上vtable地址,可以算出base基址
- 泄漏got表,可以算出libc地址
- 修改__malloc_hook为one_gadget
- 再次malloc即可getshell
脚本
1 | #!/usr/bin/env python2 |