原标题:一种检测Android SO的UAF和heap over-flow方法
本文为看雪论坛精华文章
看雪论坛作者ID:scxc
离职三个月在家闭门造车学习漏洞挖掘,开始的时候是使用各种开源的fuzz框架对github一顿挖,看各种fuzzer和asan实现的原理。直到挖到第一个UAF类型的漏洞,我终于感觉我可能已经入门了。于是便有了此文,分享一下我研究出来的Android全局的UAF和heap over-flow检测的简单思路,供大家一同进步。
UAF
https://github.com/mpv-player/mpv/issues/6808
这是我用honggfuzz发现mpv的一个UAF漏洞。调试完后我有了自己对UAF的理解。
在我看来就是系统free的时候没有将数据清除导致之前存储的内容依然存在,使得该程序依然能够正常运行。但凡free后被其他申请的内存覆盖则程序才有可能报错。
UAF demo
自己写了一个demo来测试UAF:
#include
#include
#include
structsample_1{
char* name;
};
structsample_2{
char* name;
structsample_1* v0;
};
intmain(intargc,char** argv){
structsample_1* smp1=(structsample_1*)malloc(sizeof(structsample_1));
smp1->name= "smp1";
structsample_2* smp2=(structsample_2*)malloc(sizeof(structsample_2));
smp2->name= "smp2";
smp2->v0=smp1;
free(smp2);
printf( "%sn",smp2->name);
printf( "%sn",smp2->v0->name);
return0;
}
我们看到在free(smp2)以后程序依然正常运行。
UAF检测思路
看过asan的源码,他采取的是替换free和malloc函数,所以我这里也替换free和malloc,在malloc的时候多分配一个size_t大小用于存储malloc的buffer大小,并放置在buffer前。
在free的时候获取存储的buffer大小进行memset,后在释放。
为测试代码添加了signal处理函数(如果不添加处理函数会显示Segmentation fault: 11),当程序崩溃的时候打印堆栈。
#include
#include
#include
#include
#include
#defineSTORESIZE sizeof(size_t)
structsample_1{
char* name;
};
structsample_2{
char* name;
structsample_1* v0;
};
voidshow_stack
{
inti;
void*buffer[ 1024];
intn = backtrace(buffer, 1024);
char**symbols = backtrace_symbols(buffer, n);
for(i = 0; i < n; i++) {
printf( "%sn", symbols[i]);
}
}
voidsignal_handler(intsig){
if(SIGSEGV==sig)
{
show_stack;
exit( -1);
}
else{
printf( "signal with %dn",sig);
}
}
voidmy_free(void* addr){
printf( "free addr:%p size:%d append_size:%dn",addr,*( size_t*)(( size_t)addr-STORESIZE),STORESIZE);
memset(addr, 0xFF,*( size_t*)(( size_t)addr-STORESIZE));
free(( void*)(( size_t)addr-STORESIZE));
}
void* my_malloc(size_tlen){
void* addr= malloc(len+STORESIZE);
printf( "malloc addr:%p size:%d app_size:%dn",( void*)(( size_t)addr+STORESIZE),len,STORESIZE);
*( size_t*)addr=len;
return( void*)(( size_t)addr+STORESIZE);
}
intmain(intargc,char** argv){
signal(SIGSEGV, signal_handler);
structsample_1* smp1=(structsample_1*)my_malloc(sizeof(structsample_1));
smp1->name= "smp1";
structsample_2* smp2=(structsample_2*)my_malloc(sizeof(structsample_2));
smp2->name= "smp2";
smp2->v0=smp1;
my_free(smp2);
printf( "%sn",smp2->name);
printf( "%sn",smp2->v0->name);
return0;
}
编译后运行结果如下:
此时我们已经可以检测到UAF,并且捕获了异常。
heap over-flow 检测思路
溢出的检测是在malloc的buffer前后分别添加一个buffer的size 类似[len][buffer][len],在free的时候检测头尾的len是否相等。如不相等则溢出。
voidmy_free(void* addr){
printf( "free addr:%p size:%d append_size:%dn",addr,*( size_t*)(( size_t)addr-STORESIZE), 2*STORESIZE);
memset(addr, 0xFF,*( size_t*)(( size_t)addr-STORESIZE));
if(*( size_t*)(( size_t)addr-STORESIZE)!=(( size_t)addr+*( size_t*)(( size_t)addr-STORESIZE)))
{
printf( "heap over_flow!n");
show_stack;
exit( -1);
}
free(( void*)(( size_t)addr-STORESIZE));
}
void* my_malloc(size_tlen){
void* addr= malloc(len+ 2*STORESIZE);
printf( "malloc addr:%p size:%d app_size:%dn",( void*)(( size_t)addr+STORESIZE),len, 2*STORESIZE);
*( size_t*)addr=len;
*( size_t*)(( size_t)addr+len+STORESIZE)=len;
return( void*)(( size_t)addr+STORESIZE);
}
intmain(intargc,char** argv){
charsrc[ 120]= "";
void* dst=my_malloc( 100);
memcpy(dst,src, 120);
my_free(dst);
return0;
}
运行结果如下:
实现Android上的全局UAF和heap over-flow检测
这里只说一下思路:
1、全局hook具体方法可以在论坛找(比如注入app_process)
2、hook malloc和 free函数将其替换
3、在注入的so中添加signal处理函数,将崩溃或heap overflow的信息记录到文件。
4、运行app(此时已经可以检测该app的so是否存在uaf或heap over-flow漏洞)
以上只是个人的想法与观点,如有不当之处,望各位大佬指出。共同学习进步。
看雪ID:scxc
https://bbs.pediy.com/user-638330.htm
*本文由看雪论坛 scxc 原创,转载请注明来自看雪社区
进阶安全圈,不得不读的一本书返回搜狐,查看更多
责任编辑: