反汇编工具IDA使用详解

目录

1、IDA反汇编工具简介

2、为什么需要IDA反汇编工具?

3、IDA的安装

4、IDA的使用

5、查看发生异常时的汇编指令的上下文

6、虚函数调用时的二次寻址

7、函数调用时的栈分布以及栈回溯原理

8、最后


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html       我们排查软件异常问题时,有时需要使用IDA反汇编工具去查看二进制文件对应的汇编代码,去辅助定位问题。今天我们就来详细地介绍一下IDA反汇编工具,并讲述一下该工具的使用方法。

1、IDA反汇编工具简介

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

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

2、为什么需要IDA反汇编工具?

       Windbg在分析静态dump文件时,如果设置了源代码的路径,则输入.ecxr命令会自动跳转到产生异常的源代码的那一行上。但有时仅仅定位到代码的行号,可能因为此行代码涉及的对象和接口较多,无法确定具体是何种原因导致的异常。这时就需要使用IDA反汇编工具来查看汇编代码的上下文来辅助定位问题了。很多时候,汇编指令才能最直观地反映出问题的所在。

       一行C++代码可能会对应多条汇编指令,并且release下编译器会对代码进行优化,汇编代码可能较难直接和我们的C++源代码完全对应上,为了方便查看汇编代码的上下文,我们在使用IDA也需要用到pdb文件。

       只需要将pdb文件放在目标二进制文件的同级目录中,这样IDA在打开二进制文件时,会自动加载其对应的pdb文件,这样IDA解析出来的汇编代码中会显示具体的函数名及更为详细的注释信息,这样也更方便我们查看汇编代码的上下文。

3、IDA的安装

       我们这边使用的是IDA Pro 6.1绿色版本,需要额外安装一个python程序,IDA内部需要python去执行一些解析任务。这里需要注意一下,需要安装对应版本的python,否则IDA识别不出来。我们当前版本IDA对应的是2.6版本的python

之前安装了一个最新版本的python,结果IDA启动时识别不了,导致IDA部分功能出现异常。

4、IDA的使用

       IDA安装完成后,双击启动程序,会弹出如下的提示框:

点击“New”即新建一个对象。紧接着弹出让选择要打开的文件:

可以找到目标文件的路径,打开目标文件即可。也可以点击取消,然后直接将文件拖到IDA中。打开文件时会让选择加载文件的方式:

对于Windows库,选择PE方式即可。

       接下来会弹出是否要加载pdb文件的提示框:

选择Yes即可。前面我们说过,需要将pdb文件放置到目标二进制文件的同一级目录中,这样IDA在打开二进制文件时就会搜索到对应的pdb文件。

       打开二进制文件后,我们可以点击菜单栏的Jump-->Jump o function

弹出二进制文件中所有函数的列表,点击窗口下方的Search按钮:

 直接搜索要查看的目标函数的名称,搜索到目标函数后双击条目,即会跳转到目标函数的汇编代码处:

       也可以按下快捷键g,直接跳转到指定地址的汇编代码行:

至于这个地址从哪来,我们下面会详细介绍的。


       在这里,给大家重点推荐一下我的几个热门畅销专栏,欢迎订阅:(博客主页还有其他专栏,可以去查看)

专栏1:(该精品技术专栏的订阅量已达到430多个,专栏中包含大量项目实战分析案例,有很强的实战参考价值,广受好评!专栏文章持续更新中,预计更新到200篇以上!欢迎订阅!)

C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931

本专栏根据多年C++软件异常排查的项目实践,系统地总结了引发C++软件异常的常见原因以及排查C++软件异常的常用思路与方法,详细讲述了C++软件的调试方法与手段,以图文并茂的方式给出具体的项目问题实战分析实例(很有实战参考价值),带领大家逐步掌握C++软件调试与异常排查的相关技术,适合基础进阶和想做技术提升的相关C++开发人员!

考察一个开发人员的水平,一是看其编码及设计能力,二是要看其软件调试能力!所以软件调试能力(排查软件异常的能力)很重要,必须重视起来!能解决一般人解决不了的问题,既能提升个人能力及价值,也能体现对团队及公司的贡献!

专栏中的文章都是通过项目实战总结出来的,包含大量项目问题实战分析案例,有很强的实战参考价值!专栏文章还在持续更新中,预计文章篇数能更新到200篇以上!

专栏2: 

C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html

以多年的开发实战经验为基础,总结并讲解一些的C/C++基础与进阶内容,以图文并茂的方式对C++相关知识点进行详细地展开与剖析!专栏涉及了C/C++开发领域多个方面的内容,同时给出C/C++及网络方面的常见笔试面试题,并详细讲述Visual Studio常用调试手段与技巧!

专栏3: 

VC++常用功能开发汇总icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585

专栏将10多年C++开发实践中常用的功能,以高质量的代码展现出来,并对相关功能的实现细节进行了详细的说明。这些常用的代码,其质量与稳定性是有保证的,可以直接拿过去使用,可以有效地解决C++软件开发过程中遇到的问题。


5、查看发生异常时的汇编指令的上下文

       首先,Windbg中发生异常的那条汇编指令,我们需要到IDA中找到对应的位置,然后查看目标位置的汇编指令的上下文。

       发生异常的汇编指令的地址,是程序实际运行时的代码段地址,需要计算出该地址相对于所在模块起始地址的偏移值,然后加上IDA中该模块的的默认加载地址,就能得到当前汇编指令在IDA中的静态地址,然后直接go过去,就能看到产生异常的汇编指令的上下文了。根据汇编代码的上下文,结合C++源代码,分析出到底是何处产生的崩溃。比如下图中是Windbg显示的发生异常的那条指令:

从上图看出,发生异常的汇编指令的地址为0x00eb3787(这是代码段地址,不是数据段地址),该汇编指令位于TestDlg.exe模块的函数CTestDlgDlg::OnBnClickedButton1中。

0x00eb3787这个汇编指令的地址,是程序实际运行起来的地址,不能直接拿到IDA中去搜索查找的!

        我们先要计算出当前发生异常的这条汇编指令相对于所在模块TestDlg.exe的偏移,于是使用lm命令查看TestDlg.exe模块的起始地址:

 TestDlg模块的起始地址为0x00ea0000,所以当前发生异常的这条汇编指令相对于所在模块TestDlg.exe的偏移为:

0x00eb3787 - 0x00ea0000

         然后使用IDA打开TestDlg.exe二进制文件,查看该模块静态默认的加载地址:

 所以,我们就能计算出发生异常的那条汇编指令在IDA中的静态位置:(发生异常的汇编指令的偏移 + 模块默认首地址)

0x00eb3787 - 0x00ea0000 + 0x00400000 = 0x00413787

然后到IDA中go到地址0x00413787处:

这样就可以看到目标汇编指令的上下文了。有点需要注意一下,此处我们讲的地址都是代码段的地址,和数据段的内存地址,是两个完全不同的概念。

        查看汇编代码时,我们需要了解一些常用的汇编指令,还需要了解Windows平台上的汇编代码的常用约定,比如eax寄存器通常用来存放函数调用的返回值;在调用C++类成员函数时,ecx中存放的是当前类对象的地址(通过ecx传递C++对象的地址)。如果遇到不熟悉的汇编指令,可以去搜索,去详细了解一下它们的含义。

6、虚函数调用时的二次寻址

       我们在阅读汇编代码时,我们需要了解虚函数调用在汇编代码上是什么样子的。

       多态在C++代码中随处可见,主要体现在虚函数调用上。因此,我们在阅读汇编代码时,有必要了解虚函数调用时汇编代码上的二次寻址:通过C++对象的this指针,得到当前对象的虚函数表指针,取出该指针变量中的值(一次寻址),即虚函数表的首地址,然后根据目标虚函数在虚函数表中的偏移,找出目标虚函数在虚函数表(数组)中位置,即确定目标虚函数在表中的地址,再次取出内存的值(二次寻址),即是虚函数的地址(代码段地址),直接call这个虚函数地址即完成虚函数的调用。比如如下的汇编代码片段:

.text:00655E70 ; void __thiscall CXXXWnd__AttachXXXoWnd(CVideoWnd *this)
.text:00655E70 ?AttachXXXWnd@CXXXWnd@@QAEXXZ proc near
.text:00655E70                                         ; CODE XREF: CZZZWnd::AttachXXXWnd(void)+10p
.text:00655E70
.text:00655E70 var_C           = dword ptr -0Ch
.text:00655E70 var_8           = dword ptr -8
.text:00655E70 this            = dword ptr -4
.text:00655E70
.text:00655E70                 push    ebp
.text:00655E71                 mov     ebp, esp
.text:00655E73                 sub     esp, 0Ch
.text:00655E76                 mov     [ebp+this], ecx
.text:00655E79                 call    ?Instance@CXXXWnd@@KAPAV1@XZ ; CXXXWnd::Instance(void)
.text:00655E7E                 mov     ecx, eax        ; this
.text:00655E80                 call    ?GetXXXWnd@CXXXWnd@@IAEPAVCContainerUI@DirectUICore@@XZ ; CXXXWnd::GetXXXWnd(void)
.text:00655E85                 push    eax
.text:00655E86                 mov     eax, [ebp+this]
.text:00655E89                 mov     ecx, [eax+240h]
.text:00655E8F                 mov     edx, [ebp+this]
.text:00655E92                 mov     eax, [edx+240h]
.text:00655E98                 add     eax, 1B0h
.text:00655E9D                 mov     edx, [ecx+1B0h]
.text:00655EA3                 mov     ecx, eax
.text:00655EA5                 mov     eax, [edx+10h]
.text:00655EA8                 call    eax
.text:00655EAA                 push    1               ; bShowRecBar
.text:00655EAC                 mov     ecx, [ebp+this]

相关的注解,见下面的截图:

5bca4b78dd5f45898521d65c8416a3ca.png

7、函数调用时的栈分布以及栈回溯原理

       我们在阅读汇编代码时,还需要了解一下函数调用时参数如何入栈及栈分布的情况,然后有必要再了解一下解析出函数调用堆栈的栈回溯原理

上图中显示了A函数调用B函数时的栈内存分布情况。通过上图,我们也能搞清楚函数调用堆栈的回溯原理,具体的回溯过程是这样子的:

1)B函数的栈基址ebp指向的栈内存中存放的是主调函数A的栈基址,先取出A函数的栈基址保存下来,供后续步骤使用;

2)接着第一步向下看,存放的是主调函数A的返回地址,这是调用函数B时的下一条汇编指令的地址,每个函数在代码段都有一个其实地址和结束地址,通过遍历就能知道返回地址是落在哪个函数中了,即通过栈上保存的返回地址,追溯到主调函数A;

3)通过第一步中记录A函数的ebp栈基址,按照前面的两步进行推理,就能得到调用A函数的主调函数了,直到找到最上层的函数为止。

       至此,整个函数调用堆栈就回溯出来了,这就是函数调用堆栈回溯的整个过程。

8、最后

       其实我们用的只是IDA一小部分功能,主要是用它来查看二进制文件的汇编代码,至于IDA更深层次的功能,可以查看IDA的相关书籍去了解一下。

IDA Pro等工具的下载链接如下:

链接:https://pan.baidu.com/s/1ID6_0RSYKbiy_tzfYDX3Ew 
提取码:tn6i

  • 114
    点赞
  • 187
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 86
    评论
人工智能在自然语言处理(Natural Language Processing,NLP)中有广泛的应用。以下是一些常见的例子: 1. 文本分类情感分析:人工智能可以用于将文本照不同的类别进行分类,例如垃圾邮件过滤、新闻分类等。情感分析则是通过人工智能技术来识别和分析文本中的情感倾向,例如判断一篇文章是积极还是消极的。 2. 文本生成和机器翻译:人工智能可以通过生成模型和语言模型来生成自然语言文本,例如生成文章、对话等。机器翻译则是利用人工智能技术将一种语言的文本自动翻译成另一种语言。 3. 问答系统:人工智能可以用于构建问答系统,通过理解用户提出的问题,并从大量的信息中找到答案。这种系统可以应用于智能助手、在线客服等场景。 4. 命名实体识别和实体关系抽取:人工智能可以通过训练模型来识别文本中的命名实体,例如人名、地名、组织机构等。同时,它也可以从文本中抽取出实体之间的关系,例如人与公司之间的雇佣关系。 5. 文本摘要和文本生成:人工智能可以通过摘要生成模型来从长文本中提取出关键信息,生成简洁的摘要。同时,它也可以通过生成模型来根据给定的上下文生成连贯的文本,例如自动生成新闻报道、故事等。 这些只是人工智能在自然语言处理中的一些应用示例,随着技术的不断发展,人工智能在NLP领域的应用将会更加广泛和深入。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dvlinker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值