IDA反汇编工具使用详解
目录
1、IDA反汇编工具简介
2、为什么需要IDA反汇编工具?
3、IDA的安装
4、IDA的使用
5、查看发生异常时的汇编指令的上下文
6、虚函数调用时的二次寻址
7、函数调用时的栈分布以及栈回溯原理
8、最后
C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931 我们排查软件异常问题时,有时需要使用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,直接跳转到指定地址的汇编代码行:
至于这个地址从哪来,我们下面会详细介绍的。
5、查看发生异常时的汇编指令的上下文
首先,Windbg中发生异常的那条汇编指令,我们需要到IDA中找到对应的位置,然后查看目标位置的汇编指令的上下文。
发生异常的汇编指令的地址,是程序实际运行时的代码段地址,需要计算出该地址相对于所在模块起始地址的偏移值,然后加上IDA中该模块的的默认加载地址,就能得到当前汇编指令在IDA中的静态地址,然后直接go过去,就能看到产生异常的汇编指令的上下文了。根据汇编代码的上下文,结合C++源代码,分析出到底是何处产生的崩溃。比如下图中是Windbg显示的发生异常的那条指令:
从上图看出,发生异常的汇编指令位于xxx.exe模块中,于是使用lm命令查看xxx.exe模块的起始地址:
同时使用IDA打开xxx.exe文件,查看该模块默认的加载地址:
这样,我们就能计算出发生异常的那条汇编指令在IDA中的位置:
0x014b5e9d - 0x01260000 + 0x400000 = 0x655E9D
然后到IDA中go到这个地址处:
.text:00655E70 ; void __thiscall CXXXWnd__AttachXXXWnd(CXXXWnd *this)
.text:00655E70 ?AttachXXXWnd@CXXXWnd@@QAEXXZ proc near
.text:00655E70 ; CODE XREF: CMainFrameWnd::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@CYYYWnd@@KAPAV1@XZ ; CYYYWnd::Instance(void)
.text:00655E7E mov ecx, eax ; this
.text:00655E80 call ?GetYYYWnd@CYYYWnd@@IAEPAVCContainerUI@DirectUICore@@XZ ; CYYYWnd::GetYYYWnd(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]
.text:00655EAF add ecx, 1Ch
.text:00655EB2 push ecx ; pManager
.text:00655EB3 mov edx, [ebp+this]
.text:00655EB6 mov eax, [edx+8]
.text:00655EB9 push eax ; hParentWnd
这样就可以看到目标汇编指令的上下文了。有点需要注意一下,此处我们讲的地址都是代码段的地址,和数据段的内存地址,是两个完全不同的概念。
查看汇编代码时,我们需要了解一些常用的汇编指令,还需要了解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]
相关的注解,见下面的截图:
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
IDA反汇编工具使用详解相关推荐
- Dumpbin工具参数详解
Dumpbin工具参数详解 Dumpbin简介 DUMPBIN是在Windows平台下用于显示COFF格式文件信息的一个命令行工具.你可以使用DUMPBIN去显示COFF格式的文件信息,比如像vc编译 ...
- ceph-dencoder工具使用详解
文章目录 简介 使用 decode命令用法 encode 简介 ceph-dencoder工具是一个序列化编码.解码并且打印ceph数据结构的工具.它主要用来调试和测试ceph不同版本之间的兼容性问题 ...
- 【linux】Valgrind工具集详解(八):Memcheck命令行参数详解
[linux]Valgrind工具集详解(五):命令行详解中不够全,在此专门针对Memcheck工具中的命令行参数做一次详细的解释. Memcheck命令行选项 –leak-check=<no| ...
- 【转】Linux命令工具 top详解
Linux命令工具 top详解 top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器.top是一个动态显示过程,即可以通过用户按键来不 ...
- PowerShell攻防进阶篇:nishang工具用法详解
PowerShell攻防进阶篇:nishang工具用法详解 导语:nishang,PowerShell下并肩Empire,Powersploit的神器. 开始之前,先放出个下载地址! 下载地址:htt ...
- 【Android 应用开发】Ubuntu 下 Android Studio 开发工具使用详解 (旧版本 | 仅作参考)
. 基本上可以导入项目开始使用了 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21035637 ...
- Android复习14【高级编程:推荐网址、抠图片上的某一角下来、Bitmap引起的OOM问题、三个绘图工具类详解、画线条、Canvas API详解(平移、旋转、缩放、倾斜)、矩阵详解】
目 录 推荐网址 抠图片上的某一角下来 8.2.2 Bitmap引起的OOM问题 8.3.1 三个绘图工具类详解 画线条 8.3.16 Canvas API详解(Part 1) 1.transla ...
- 13.5.虚拟化工具--jhat详解、13.6.虚拟化工具--jstack详解
13.5.虚拟化工具–jhat详解 一般不通过这个命令执行,而是通过图形化工具类查看jvm信息. 在页面下有: 查看什么是OQL语句 在页面上有OQL help,可以查看OQL的语法. 13.6.虚拟 ...
- 13.4.虚拟化工具--jmap详解
13.4.虚拟化工具–jmap详解 13.4.1.jmap命令基本概述 13.4.2.命令格式 13.4.3.参数说明 13.4.虚拟化工具–jmap详解 13.4.1.jmap命令基本概述 jmap ...
- 13.3.虚拟化工具--jinfo详解
13.3.虚拟化工具–jinfo详解 实时查看和调整虚拟机的各项参数. jinfo命令可以用来查看java进程运行的JVM参数,命令如下: [root@admin ~]# jinfo --help U ...
最新文章
- CCTouchDispatcher sharedDispatcher 方法过期
- 【LeetCode】0136. 只出现一次的数字
- XCTF_Web_新手练习区:cookie
- leetcode majority number
- Atom与markdown
- 德鲁克的《卓有成效的管理者》
- Oracle内部错误:ORA-07445[kcflfi()+466] [INT_DIVIDE_BY_ZERO]一例
- nodejs字符与字节之间的转换
- C++中new和malloc
- TensorFlow 机器学习秘籍中文第二版·翻译完成
- mysql注入 xfkxfk_WSS最新版多处SQL注入直接获取数据三(官方demo演示及快速定位漏洞技巧)...
- OpenSessionInViewFilter失效问题
- 【纸牌识别】基于matlab形态学扑克牌识别【含Matlab源码 1352期】
- 【滤波器】基于matlab GUI FIR+IIR数字滤波器设计【含Matlab源码 324期】
- 台式机黑苹果 Mojave 10.14.6 安装驱动
- 基于eNSP的千人中型校园企业网络设计与规划(可以自己按步骤实现)
- 这么用 if-else,小鹿差点被辞退!
- c#模拟看板控件_C#TIPTOP电子看板
- JavaScript--ES6【Promise】对象详解
- RLC电阻电容电感基础知识——电容篇
热门文章
- NetApp 数据存储解决方案:广泛的全闪存、混合闪存和对象存储系统产品组合
- 知乎获2000赞的Java 多线程超详细总结笔记,看这一篇彻底搞懂线程池
- 计算机组成原理的各种常见英文缩写介绍--<<方便复习的笔记>>
- python异常值处理实例_Python对杂乱文本数据进行处理实例
- TCGA临床数据整理
- pythonforandroid下载中文_SL4A、PythonForAndroid和Android 7.0 Noug
- 实例分割:R-CNN、Fast R-CNN、Faster R-CNN、Mask R-CNN
- python爬虫练习--爬上海法院开庭公告信息
- Java高级类特性(二)
- 将最新Chromium浏览器集成到.NET应用程序中