使用IDA查看汇编代码,结合安卓系统生成的Tombstone文件,分析安卓app程序崩溃问题

news2024/11/24 4:51:26

目录

1、IDA工具介绍

2、产品及问题场景描述

3、查看Tombstone文件

4、使用IDA打开.so动态库文件,查看汇编代码的上下文,到C++源码中定位发生崩溃的那行代码

4.1、使用IDA打开.so动态库文件

4.2、切换到Text View文本视图模式

4.3、根据相对于函数的偏移,在汇编代码中找到对应位置,查看附近的汇编上下文

4.4、通过汇编代码上下文,找到对应的C++源代码位置

4.5、使用空指针去调用一个类成员函数,为啥会崩溃在函数调用处?

5、最后


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具从入门到精通案例集锦(专栏文章正在更新中...)https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)https://blog.csdn.net/chenlycly/category_11931267.html       我们在排查软件异常时,有时可能会用到IDA反汇编工具去查看二进制文件的汇编代码,去辅助分析问题。最近在排查安卓系统中的程序崩溃时,就使用了IDA工具,使用IDA打开.so动态文件查看汇编代码,结合安卓系统自动生成的Tombstone文件中的信息,最终找到了引发崩溃的原因。今天我们就来讲述一下这个问题的详细排查问题,以供大家借鉴或参考。

1、IDA工具介绍

       IDA是比利时Hex-Rays公司出品的一款强大的交互式静态反汇编工具。它可以直接反汇编出二进制文件的汇编代码,是目前软件逆向与安全分析领域最好用、最强大的一个静态反汇编软件,已成为众多软件安全分析人员不可缺少的利器!它支持Windows、Linux等多个平台,支持Intel X84、X64、ARM、MIPS等数十种CPU指令集。 IDA既支持打开Windows平台的.dll库文件,也支持打开Linux平台的.so库文件。

IDA是俄罗斯天才程序员llfak Guilfanov(尔法克-吉尔法诺威)开发的,llfak Guilfanov作为创始人兼首席执行官与2005年在比利时创建了Hex-Rays公司。

可能有很多人不知道,俄罗斯在软件领域很厉害,是个盛产天才程序员的地方,比如我们这里讲的最强大静态反汇编工具IDA就是俄罗斯人写的!备受欢迎的IDE开发工具IDEA、PyChram和WebStorm所属公司Jetbrains公司就是三个俄罗斯天才程序员创建的!在IT领域广泛使用的负载均衡与反向代理开源库Nginx以及大数据领域鼎鼎有名的ClickHouse开源库都是俄罗斯人写的!

俄罗斯人的逻辑思维很强,俄罗斯盛产数学家和化学家,比如伟大的数学家欧拉和高斯、发明元素周期表的化学家门捷列夫!

华为自研的数据库就是以高斯命名的(GaussDB),华为的服务器操作系统则是以欧拉命名的(EulerOS)!向伟人们致敬!

2、产品及问题场景描述

       本文中出现问题的是一台嵌入式硬件设备,设备中使用的是安卓系统,设备运行的是我们的应用程序。应用程序的主体是用Java开发的安卓app程序,app程序通过C++实现的底层业务模块实现和远端服务器的通信交互。

app程序通过调用封装好的JNI接口去操作底层的C++模块,本案例中的崩溃是发生在底层的C++模块中。崩溃虽然发生在底层的C++模块中,但底层C++模块也是运行在app程序进程中的,所以直接导致了app程序的崩溃。

       app程序发生崩溃时,安卓系统感知到了,并生成了包含异常崩溃信息的Tombstone(墓碑)文件,这个文件类似于Linux系统中生成的CoreDump文件,我们在分析软件异常崩溃时,就是去分析这些文件。

       我们先是打开了Tombstone文件,查看了发生异常崩溃的具体异常类型以及崩溃时的函数调用堆栈,但通过Tombstone文件只知道崩溃发生在哪个函数中,函数中的代码篇幅比较长,无法定位崩溃发生在哪一行。

       于是乎,我们使用IDA打开函数调用堆栈中的显示的.so模块文件去查看汇编代码,查看发生崩溃的那条汇编代码附近的上下文,最终找到了发生崩溃的那行C++源码。

3、查看Tombstone文件

       从嵌入式设备中取来发生崩溃时安卓系统自动生成的Tombstone文件,打开该文件,看到了如下的信息:

首先,看到当前崩溃的原因为:null pointer dereference,空指针引用,即程序中使用了空指针引发了崩溃紧接着,看到发生崩溃时的函数调用堆栈,从堆栈上看,崩溃发生在libxxservice_hddll.so动态库中的CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp函数中。调用堆栈中能看到具体的函数名,说明.so动态库文件中是有函数符号的。但看不到具体的代码行号,只能看到相对于函数CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp的偏移:

#00 pc 0000000000075200  /xxxkyui/lib64/libxxservice_hddll.so (CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp(mtmsg::CMtMsg*, unsigned int, unsigned int)+1048) (BuildId: d6e3064a3e1a03d9bea3c4496e78cb4942d187d1)

而CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp函数中的代码篇幅比较长,我们没法确定崩溃发生在哪一行代码上。

当然如果问题是必现的,或者很好复现,则可以添加打印,将函数中用到的所有指针的值打印出来,崩溃后我们查看日志就能确定了。但有些问题是很难复现的,我们还是要多掌握一些分析手段才好!

       既然从函数调用堆栈中能看到具体的函数名及相对于函数(首地址)的偏移,我们可以使用IDA反汇编工具去查看函数所在模块libxxservice_hddll.so的汇编代码上下文,去辅助定位问题。

4、使用IDA打开.so动态库文件,查看汇编代码的上下文,到C++源码中定位发生崩溃的那行代码

4.1、使用IDA打开.so动态库文件

       我们的嵌入式硬件设备使用的安卓系统,主控CPU是基于ARM架构的,程序的代码也是在ARM平台的环境中编译的,IDA反汇编工具是支持ARM平台的,所以可以直接使用IDA打开程序的二进制文件查看汇编代码的。

       直接在Windows系统中启动IDA,会弹出如下的窗口:

点击New按钮去反汇编一个新的文件,然后弹出IDA的主窗口。然后直接将libxxservice_hddll.so文件拖入到IDA主窗口中打开,会提示使用64位的IDA打开该文件,如下:

libxxservice_hddll.so动态库是64位程序,所以要使用64位的IDA打开:

我们之前打开的是32位的IDA。

       于是通过桌面快捷方式找到安装路径,到路径中启动64版本IDA,然后将libxxservice_hddll.so拖入到IDA主窗口中,然后会弹出选择打开二进制文件的格式,如下所示:

IDA会自动识别二进制文件的类型,按默认的文件格式打开即可。

4.2、切换到Text View文本视图模式

        打开二进制文件后,会默认显示Graphic View视图模式:

 要右键单击,在弹出的右键菜单中单击“Text View”菜单项,切换到文本模式页面,如下:

4.3、根据相对于函数的偏移,在汇编代码中找到对应位置,查看附近的汇编上下文

        首先,我们需要找到在IDA显示的汇编代码中找到CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp函数的位置。在菜单栏中中点击Jump -> Jump to function...,打开如下的窗口:

点击窗口下方的Search按钮,在弹出的窗口中输入函数名OnTextImageCreateBannerInfoRsp:

然后点击OK按钮,在函数列表中搜索到该函数,双击之直接跳转到该函数的汇编代码中,如下所示:

可以看到该函数的函数地址(函数首地址)为0x0000000000074DE8,根据Tombstone文件中显示的相对函数的偏移:

#00 pc 0000000000075200  /xxxkyui/lib64/libxxservice_hddll.so (CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp(mtmsg::CMtMsg*, unsigned int, unsigned int)+1048) (BuildId: d6e3064a3e1a03d9bea3c4496e78cb4942d187d1)

计算新的地址:

0x0000000000074DE8 + 0x418(对应于10进制的1048)=  0x0000000000075200

然后在IDA中搜索该地址0x0000000000074DE8,找到对应的汇编代码行。具体的做法是,将鼠标点进汇编代码窗口中(使该窗口获得焦点),然后按下快捷键g,弹出Jump to address窗口,输入上面计算出来的地址0x0000000000075200:

点击OK,就会跳转到对应的行,如下所示:

4.4、通过汇编代码上下文,找到对应的C++源代码位置

       我们平时看惯了X86平台的汇编代码,看这个ARM架构的汇编代码很不习惯,无论是汇编指令的名称,还是寄存器的名称,都有很大的差异。感觉还是X86平台的汇编代码好阅读一些。

       上面我们在汇编代码中定位到了位置,但与汇编代码对应的C++源码是哪一行呢?此外,Release下编译时编译器会对C++代码进行优化(有些变量或函数调用可能会被优化掉),导致汇编代码和C++代码是不完全一致。

       该怎么将汇编代码与C++源码对应起来呢?难道我们要一句一句汇编代码去啃?强行去阅读汇编代码上下文,是需要有一定的汇编功底的,一般人比较难做到。一般我们借助汇编上下文中的注释信息去辅助阅读,本例中我们就是使用注释信息快读定位的。

       0x0000000000075200地址对应的汇编代码行,该行代码下面紧接就看到注释,是常量值字符串的注释:

但看不到完整的字符串。这个地方有个技巧,可以将鼠标移动到变量上,就会以TooTip的方式显示变量中的完整内容,如下所示:

这个地方巧了,这样的字符串是打印日志中的,于是到C++源码中找到CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp函数,在函数中找“[CMtServiceHMpHandler::OnTextImageCreateBannerInfoRsp] dispatch”这样的打印,确实有这行打印,如下所示:

所以就找到了0x0000000000075200地址对应的C++源码大概的行了,所以本例中的空指针问题应该就是上图中的ptTip指针,即该指针值为空,结果使用该指针调用value接口产生了崩溃。

       关于IDA工具介绍及详细使用说明,可以参见我之前写的文章:

IDA反汇编工具使用详解https://blog.csdn.net/chenlycly/article/details/120635120使用IDA查看汇编代码上下文去辅助排查C++软件异常问题https://blog.csdn.net/chenlycly/article/details/128942626使用反汇编工具IDA查看发生异常的汇编代码的上下文去辅助分析C++软件异常https://blog.csdn.net/chenlycly/article/details/132158574

4.5、使用空指针去调用一个类成员函数,为啥会崩溃在函数调用处?

       为啥崩溃在函数调用处呢?如果调用的函数是个普通函数(非虚函数),函数调用处一般不会崩溃的,如果函数内部访问了所在类的成员变量,则使用空指针调用会崩溃在被调用函数内部,而不是崩溃call函数时!

       有一种可能该函数是虚函数,对于虚函数的调用,需要通过二次寻址到虚函数表中找到虚函数的地址(虚函数代码段地址,此处需要区分一下代码段地址与数据段地址),在二次寻址的过程中将空指针作为内存地址去访问内存,就触发了内存访问违例,引发崩溃。

       还有一种情况,被调用函数种定义了占用很大栈内存的局部变量(比如使用一个定义很大的结构体去定义了一个局部变量),导致当前线程栈溢出(当前线程占用的栈空间达到了线程创建时分配的栈空间的上限)。对于这种线程栈溢出的场景,可能就会崩溃在函数调用的地方,这类问题我们在项目中遇到过。

5、最后

       本文详细讲述了如何将Tombstone文件和IDA反汇编工具结合起来快速定位崩溃的完整过程,希望能给大家提供一定的借鉴与参考。此外,通过该问题详细讲解了如何使用IDA反汇编工具。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/876983.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux进程篇】环境变量

【Linux进程篇】环境变量 目录 【Linux进程篇】环境变量基本概念常见环境变量查看环境变量方法测试PATH测试HOME测试SHELL和环境变量相关的命令环境变量的组织方式通过代码如何获取环境变量命令行参数命令行第三个参数通过第三方变量environ获取 本地变量通过系统调用获取或设置…

【Sklearn】基于K邻近算法的数据分类预测(Excel可直接替换数据)

【Sklearn】基于K邻近算法的数据分类预测(Excel可直接替换数据) 1.模型原理模型原理:数学模型: 2.模型参数3.文件结构4.Excel数据5.下载地址6.完整代码7.运行结果 1.模型原理 K最近邻(K-Nearest Neighbors&#xff0c…

C++入门篇8---vector

vecctor是动态顺序表 一、了解vector的相关接口及其功能 1.构造函数相关接口 函数声明功能介绍vector()无参构造vector(size_type n,const value_type& valvalue_type())构造并初始化n个valvector(const value& x)拷贝构造vector(InputIterator first, InputIterato…

ad+硬件每日学习十个知识点(33)23.8.13 (导出gerber)

文章目录 1.第一次制造输出2.第二次制造输出3.第三次制造输出 1.第一次制造输出 答: 2.第二次制造输出 答: 3.第三次制造输出 答:

企业计算机服务器中了Devos勒索病毒怎么办,勒索病毒解密

社会在发展,科技在进步,企业的生产也得到了很大改善,但是随着网络技术的不断发展,越来越多的企业遭到的网络安全威胁开始增多,其中较为明显的就是勒索病毒攻击。预防勒索病毒攻击成为日常生活中不可或缺的一部分工作。…

Python—行命令搭建HTTP服务器并外网访问本地SQL Server数据库【无公网IP内网穿透】

在强者的眼中,没有最好,只有更好。我们是移动开发领域的优质创作者,同时也是阿里云专家博主。 ✨ 关注我们的主页,探索iOS开发的无限可能! 🔥我们与您分享最新的技术洞察和实战经验,助您在移动…

MySQL中事务特性以及隔离机制

目录 一、什么是事务 二、事务特性——即ACID特性 三、事务的隔离级别 1、脏读 2、不可重复读 3、幻读 Read uncommitted: Read committed: Repeatable read: Serializable: 一、什么是事务 事务(Transaction)——一个最…

小程序用户隐私新规,微信小程序开发者需满足新要求

微信公众平台运营中心最新公告指出,从2023年9月15日开始,涉及处理用户个人信息的小程序开发者需要满足新要求。开发者须主动同步用户同意并遵守小程序的隐私保护指引和其他信息处理规则,方可调用微信提供的隐私接口。 并且,在确认…

第四章,向量组,1-向量组与线性组合、线性表示

第四章,向量组,1-向量组与线性组合、线性表示 向量方程向量与向量组向量向量组 线性组合与线性表示线性组合 线性表示定理定义 多表多(单向)定理推论 定义 等价(多表多:双向) 知识回顾 玩转线性…

用免费Leangoo敏捷看板工具进行可视化的缺陷跟踪管理

用Leangoo敏捷看板进行可视化的缺陷跟踪管理 缺陷管理通常关注如下几个方面: 1. 缺陷的处理速度 2. 缺陷处理的状态 3. 缺陷的分布 4. 缺陷产生的原因 使用Leangoo敏捷看板我们可以对缺陷进行可视化的管理,方便我们对缺陷的处理进展、负责人、当前…

转行软件测试四个月学习,第一次面试经过分享

我是去年上半年从销售行业转行到测试的,从销售公司辞职之后选择去培训班培训软件测试,经历了四个月左右的培训,在培训班结课前两周就开始投简历了,在结课的时候顺利拿到了offer。在新的公司从事软件测试工作已经将近半年有余&…

云渲染效果不对?云渲染前的四个细节表明你的问题出在这里!

云渲染针对3D渲染行业,帮助本地电脑解决渲染慢的问题,大幅提高设计师的工作效率。但小编发现,有不少小伙伴在使用云渲染时,出现了渲染效果不对或丢失的问题,根据小伙伴们的问题和我们创意云云渲染平台给出的解决方案&a…

vue之动态表单(优化)

代码资源在这儿 ↑ vue之动态表单优化 vue2js动态表单优化vue3ts动态表单优化 vue2js动态表单优化 效果图 目录结构 五个文件的完整代码: 以下是App.vue <template><div><router-view></router-view><Formpage /></div> </templa…

【数据结构】栈与队列

1 栈 1.1 栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出 LIFO (Last In First Out) 的原则。 压栈&#xff1a;栈…

java中右移>>和无符号右移>>>的区别

public static void main(String[] args) {byte[] dest new byte[2];dest[0] 0x15; //0001 0101dest[1] (byte) 0xfb;//1111 1011System.out.println((dest[0] >> 4) & 0xff);//右移 应该是0000 0001 十进制结果显示1 结果也是1&#xff0c;正确System.out.printl…

【小练习】交互式网格自定义增删改错误记录及解决(进行中)

经过之前的学习&#xff0c;已经能创建简单的交互式网格并设置自定义增删改按钮&#xff0c;但是实现上还是存在一些问题&#xff0c;来完善优化一下。 首先是修改&#xff0c;正常修改都会弹出修改框&#xff0c;里面是之前存储的信息&#xff0c;根据实际需要对其进行修改&a…

小程序多图片组合

目录 子组件 index.js 子组件 index.wxml 子组件 index.wxss 父组件引用&#xff1a; 子组件&#xff1a;preview-image 子组件 index.js Component({properties: {previewData: {type: Array,default: [],observer: function (newVal, oldVal) {console.log(newVal, ol…

AppStream下载元数据失败

错误&#xff1a;为仓库 AppStream 下载元数据失败 : Cannot prepare internal mirrorlist: No URLs in mirrorlist 目录 一、域名解析 二、CentOS-AppStream.repo 三、CentOS-Base.repo 四、CentOS-Extras.repo 五、rpm更新 一、域名解析 先验证 ping www.baidu.com 不…

【C语言】结构体解谜:拆解数据的力量!

&#x1f341;博客主页&#xff1a;江池俊的博客 &#x1f4ab;收录专栏&#xff1a;C语言—探索高效编程的基石 &#x1f4a1;代码仓库&#xff1a;江池俊的代码仓库 &#x1f3aa;我的社区&#xff1a;GeekHub &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐…

9:00面试,9:06就出来了,问的问题实在有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到5月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%,…