android 释放 so,一种检测Android SO的UAF和heap over-flow方法

原标题:一种检测Android SO的UAF和heap over-flow方法

44ccafba1d1b75e33a42806cd9289a17.png

本文为看雪论坛精华文章

看雪论坛作者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;

}

5afea548f3dc5847b8e44d796e7a5977.png

我们看到在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;

}

编译后运行结果如下:

1d96cc8a336e485086c8a8753f0ac8b8.png

此时我们已经可以检测到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;

}

运行结果如下:

77e27e3df7dcfb289bf659a4c6fbdf01.png

实现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漏洞)

以上只是个人的想法与观点,如有不当之处,望各位大佬指出。共同学习进步。

77a1c2aa401b78b6a39372f552d263a8.png

看雪ID:scxc

https://bbs.pediy.com/user-638330.htm

*本文由看雪论坛 scxc 原创,转载请注明来自看雪社区

进阶安全圈,不得不读的一本书返回搜狐,查看更多

责任编辑:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值