HeapSnap工具原理及其应用

  • HeapSnap工具原理及其应用

    • 简介
    • HeapSnap工具演示
    • HeapSnap工具的实现原理

简介

HeapSnap工具,其名称源于Heap Snapshot,意即堆内存快照。其实现方式是:在不同的时间点上保存堆内存的快照,然后对比这些不同时间点的快照,找出导致内存增长的泄露点。

HeapSnap工具专门用于处理Android系统中native进程的heap内存泄露问题。它的实现是基于Android已有的libc debug机制,对目标进程的影响小,易于使用,且解决问题的概率高。

源码下载: https://github.com/albuer/heapsnap

HeapSnap工具演示

演示环境: Android5.1
  • 使能malloc leak调试开关
    setprop libc.debug.malloc 1
  • 启动测试程序,该程序每3秒钟泄露4KB大小的内存,测试代码如下:
 1 #include <stdio.h>2 #include <stdlib.h>3 #include <android/log.h>4 5 void* foo(void)6 {7         void* p = malloc(4096);8         memset(p, 0x5A, 4096);9         return p;10 }11 12 int main(void)13 {14         int count=0;15         void * p = NULL;16         while(1) {17                 p = foo();18                 ++count;19                 printf("%d: %p\n", count, p);20                 sleep(3);21         }22         return 0;23 }
  • 向目标进程注入代码,从而让目标进程拥有保存heap快照的功能
    heapsnap -p <进程ID> -l libheapsnap.so
  • 保存heap快照
    kill -21 <进程ID>

    从logcat信息中可以看到heap快照被保存在/data/local/tmp/heap_snap/proc_7104_0000.heap,其内容如下:

Heap Snapshot v0.2Total memory: 103424
Allocation records: 2size     4096, dup   25, 0xb6ec576e, 0xb6f3d282, 0xb6fa74ba, 0xb6fa73ac, 0xb6f3d39c, 0xb6fa7428#00  pc 0000676e  /system/lib/libc_malloc_debug_leak.so (leak_malloc+101)#01  pc 00012282  /system/lib/libc.so (malloc+9)#02  pc 000004ba  /system/bin/leak_test#03  pc 000003ac  /system/bin/leak_test#04  pc 0001239c  /system/lib/libc.so (__libc_init+43)#05  pc 00000428  /system/bin/leak_test
size     1024, dup    1, 0xb6ec576e, 0xb6f3d282, 0xb6f60efa, 0xb6f65eb2, 0xb6f61bac, 0xb6f63172, 0xb6f61128, 0xb6fa73b8, 0xb6f3d39c, 0xb6fa7428#00  pc 0000676e  /system/lib/libc_malloc_debug_leak.so (leak_malloc+101)#01  pc 00012282  /system/lib/libc.so (malloc+9)#02  pc 00035efa  /system/lib/libc.so (__smakebuf+21)#03  pc 0003aeb2  /system/lib/libc.so (__swsetup+105)#04  pc 00036bac  /system/lib/libc.so#05  pc 00038172  /system/lib/libc.so (vfprintf+17)#06  pc 00036128  /system/lib/libc.so (printf+23)#07  pc 000003b8  /system/bin/leak_test#08  pc 0001239c  /system/lib/libc.so (__libc_init+43)#09  pc 00000428  /system/bin/leak_test******** MAPS ********
其中:
  • Total memory: 103424,指的是进程申请的堆内存大小,此处是103424 Bytes
  • Allocation records: 2,总共有2条内存分配路径
  • size 4096, dup 25, 0xb6ec576e, … ,size指的是每块内存的大小,此处为4096Bytes,dup指重复的次数,此处为25,表示这个内存分配路径被调用了25次,后面的地址就是backtrace,以及对backtrace解析后的信息。

这个demo程序中只有两条heap分配记录,第一条的size为4096,dup为25,表明这个heap分配路径被重复执行了25次,且分配的内存都没有释放掉,因些我们能够很明显看出这个内存分配路径就是泄露点了。

从backtrace我们可以看到调用malloc函数的位置是

#02 pc 000004ba /system/bin/leak_test

我们调用addr2line查询地址”0x000004ba”所指向的代码行:

arm-linux-gnueabi-addr2line -ife out/target/product/rk3288/symbols/system/bin/leak_test 0x4ba
test
/home/cmy/WORK/android-src/android5.1-vr/external/heapsnap/leak_test.c:7

通过addr2line命令反查到”0x4ba”这个地址指向leak_test.c文件的第7行,foo()函数。

在实际的程序中,heap快照中的分配记录通常都是非常多的,不容易找出哪个内存分配路径是泄露点,此时可以通过对比不同时间点上,相同内存分配路径下的dup次数来做出判断,如果某个分配路径的dup次数处于持续增长的状态,那么它就很可能是一个泄露点了。

HeapSnap工具的实现原理

  • 获取进程的heap信息
    我们首先来看下在Android中,进程的heap分配的backtrace信息是如何被保存以及如何读取的。

    方法很简单,只需要先打开malloc调试开关之后,再执行目标进程,那么在这个新运行的进程内发生的所有heap分配的backtrace信息就会被记录下来,之后在该进程内调用get_malloc_leak_info函数即可获取到所有前面保存的heap’s backtrace记录。

    1. malloc调试开关

      • 调用’setprop libc.debug.malloc 1’设置好属性后,malloc开关就使能了且被设置为leak模式(注:在Android7以及之后的版本,设置属性”setprop libc.debug.malloc.options backtrace”)。

      • 接着,我们开始执行目标进程,进行启动过程上中会初始化一个加载器,在Android中是/system/bin/linker

      • 通过加载器linker,把所有需要用到的so文件都加载进来。

      • 在linker加载so文件过程中,会自动执行so文件内的.init/.init_array section代码

      • 在libc.so中,定义了一个函数”attribute((constructor)) static void libc_preinit()”,修饰符“__attribute((constructor))”告知编译器把__libc_preinit函数指针放到.init_array section,于是函数__libc_preinit在so被linker加载时被自动执行了

      • 在__libc_preinit()函数中,会去读取libc.debug.malloc属性值,并根据所获得的值设置malloc/free…等函数指针指向不同的函数实现,此处libc.debug.malloc为1,则函数指针指向leak_malloc/leak_free….等leak_xxxx形式的函数实现。

      于是,属性libc.debug.malloc决定了所使用到的mallc/free的实现函数。

    2. heap’s backtrace信息的保存与读取

      • 当malloc调试开关设置为leak模式后,在进程内执行malloc/calloc等函数时候,实际调用的是leak_malloc/leak_calloc等函数,这些函数会在分配的内存前面附加一个头部信息,在该头部信息里面保存了此次内存分配的backtrace信息。
      • libc提供了一个函数get_malloc_leak_info,通过该函数我们就能获得当前进程所有未释放的heap的backtrace信息了。最终我们获取到的backtrace信息如前面所示。
  • 进程注入
    前面说到调用get_malloc_leak_info可以获得当前进程的heap信息,但要怎么才能让目标进程去调用get_malloc_leak_info函数,一种是修改代码目标代码,加入获取进程heap快照的相关代码后重新编译;还有另外一种方式就是使用进程注入,它能把一段代码注入到目标进程中并执行。

    进程注入流程图如下所示:
    

    大致流程描述如下:

    1. 先调用ptrace(PTRACE_ATTACH, …)把当前程序附着在目标进程之上,即成为目标进程的父进程。

    2. 在目标进程中开辟一块内存空间用于传递参数信息到目标进程

    3. 把要注入的程序库文件名信息保存在前面开辟出来的内存空间,并调用dlopen把该程序库加载到目标进程中。

    4. 在程序库中定义有一个“extern “C” void attribute((constructor)) prepare()”函数,这个函数会在so被加载到目标进程后被自动执行,它会为信号SIGTTIN注册一个处理函数,当该信号被触发后,其注册的处理函数会调用get_malloc_leak_info获得当前进程的heap快照,并保存成文件。

    5. 至此,注入程序已经把指定代码注入到目标进程中,并且在目标进程中注册了一个函数用于处理信号SIGTTIN,于是我们可以用kill命令向目标进程发送SIGTTIN信号,然后目标进程的当前heap快照就会被保存下来了。

    6. 最后,我们需要把先前在目标进程中开辟的那块内存空间释放掉,还原寄存器,调用ptrace(PTRACE_DETACH, pid, …)结束对该进程的追踪,目标进程就能沿着原来的流程继续执行下去了,只是在它内部多了我们注入的代码。

HeapSnap工具原理及其应用相关推荐

  1. Avaddon勒索解密工具原理解析

    文章目录 Avaddon勒索 解密工具 解密工具原理 解密工具优化 关于文件大小的疑惑 Avaddon勒索加密流程补充 解密工具实现 相关资料 Avaddon勒索 该勒索病毒使用C++语言进行编写,采 ...

  2. H5 可视化构建工具原理解析(一)

    前言 总共进 8 万行代码实现H5可视化构建工具,自去年十月开始陆续做了大半年,现已投入到业务中使用,虽然算是个人项目,但组件和部署模块涉及大量公司业务代码,就不开源了,主要讲讲实现思路,算是该项目的 ...

  3. 所谓的内存释放工具——原理

    所谓的内存释放工具--原理 刚才逆向了一个内存释放的小工具,原来是调用了SetProcessWorkingSetSize()函数,MSDN一下. 此函数原型如下: BOOL SetProcessWor ...

  4. 软件打包安装工具第四篇(打包工具原理及技术)

    打包工具原理及技术 1.MV模型 2.打包原理 2.1.方案一 2.2.方案二 3.结束语 1.MV模型 打包工具采用的是MV模型,采用此模型的原因是因为打包界面中打包列表.文件列表以及属性面板显示的 ...

  5. linux的diff工具原理之Myers算法

    linux的diff工具原理之Myers算法 前言 diff diff与图搜索 Myers算法 具体实现 1.为什么d的取值范围是[0,N+M]呢? 2.为什么k的取值范围为[-d,d],并且步长为2 ...

  6. 2d Laser 和 Odomter 内外参数标定工具原理及使用方法

    前言 两轮差速轮式机器人可以基于码盘数据和两轮间距以及车轮半径进行航迹推演,得到机器人的轨迹.激光雷达也可以利用 icp 等算法计算出两时刻间机器人的相对运动量.因此,可以利用两者数据进行融合定位,本 ...

  7. 2d Laser 和 camera 标定工具原理及使用方法

    2d 激光和相机之间的标定早在 04 年就出了成熟的论文和方法,17 年 ICCV, IROS,今年 IROS 等依然还有论文产出,具体的论文列表可以参考我的<论文阅读整理>博客.本篇博客 ...

  8. scardsvr 智能卡修复工具原理及代码

    程序有英语 简体中文 两种语言,根据操作系统环境来选择language.       代码下载:http://bilaopao.download.csdn.net/       开发工具:VS 200 ...

  9. 小骥autorun专杀工具原理初探

    前几天用小骥autorun专杀工具,来去除autorun病毒.对其原理却不能理解,为什么说kill以后还出现了,autorun.inf,和pagefile.inf两个文件,但是已经把哪个磁盘上的aut ...

  10. pt-osc工具原理与实践

    MySQL在5.7版本对于online ddl支持的并不是非常优化,比如说将大表int字段类型修改成bigint或者对大表进行字符编码的改造.对于业务来说都是需要停业去处理的,对于高速发展的互联网行业 ...

最新文章

  1. 怎么检查linux是否中病毒,linux中怎么检查是否有安装xinted这个服务
  2. 省时省事省力 巧用阿里ECS D1构建大数据处理平台
  3. 前端之JavaScript:JS之DOM对象一
  4. 数组 verilog_SystemVerilog语言简介(与Verilog的30点对比)
  5. Django08:模型层(ORM)--测试脚本/必知的13条/神器的双下划线查询/多表操作
  6. 【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用
  7. 实现页面适配_微信公众号文章页面适配深色模式
  8. 一个专科生学习JAVA目标月薪2万是否不切实际?
  9. rocketmq 顺序消费_RocketMQ核心概念扫盲
  10. day08—css布局解决方案之多列布局
  11. TCP Socket
  12. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-7.授权登录获取微信用户个人信息实战...
  13. 中国钢铁行业十四五形势展望与发展战略研究报告2022版
  14. 亮道剧学铭:激光雷达系统量产上车没那么容易
  15. 目标主机showmount -e信息泄露(CVE-1999-0554),如何禁止只允许特定主机使用showmount -e查看挂载列表
  16. vmdk to vhdx 虚拟磁盘格式转换qemu-img
  17. linux的文件系统及vim编辑器系统指令
  18. 要学习使用的安全工具
  19. 创业公司如何应对大公司的冲击
  20. 计算机网络安全三个时代,信息网络安全的三个时代是什么

热门文章

  1. 视频监控存储解决方案——快速、可靠的视频存储
  2. 网页版微博HTML解析和提取,使用Beautiful Soup抽取网页数据,解析微博用户关注信息...
  3. 【预测模型】基于蝙蝠算法改进SVM实现预测matlab源码
  4. MySql ALTER用法
  5. 随机森林模型sklearn_sklearn之随机森林
  6. QT TCP网络编程
  7. 再谈Redis应用场景
  8. 《图解TCPIP》知识学习(1.4):协议由谁规定
  9. 40行代码自己动手写pdf转word小工具(文末附工具下载)
  10. DW-办公自动化02(Excel)