IDA Pro > IDA Pro教程 > 技术问题 > 在windows下使用IDA的调试器

在windows下使用IDA的调试器

发布时间:2022-10-13 17: 05: 53

This small tutorial introduces the main functionalities of the IDA Debugger plugin. IDA supports debugging of x86 Windows PE files, AMD64 Windows PE files, and x86 Linux ELF files,either locally or remotely. Let's see how the debugger can be used to locally debug a simple buggy C console program compiled under Windows.

 

The buggy program.

This program simply computes averages of a set of values (1, 2, 3, 4 and 5). Those values are stored in two arrays: one containing 8 bit values, the other containing 32-bit values.

 

#include 
char char_average(char array[], int count)
{
int i;
char average;
average = 0;
for (i = 0; i < count; i++)
average += array[i];
average /= count;
return average;
}
int int_average(int array[], int count)
{
int i, average;
average = 0;
for (i = 0; i < count; i++)
average += array[i];
average /= count;
return average;
}
void main(void) {
char chars[] = { 1, 2, 3, 4, 5 };
int integers[] = { 1, 2, 3, 4, 5 };
printf("chars[] - average = %d\n",
char_average(chars, sizeof(chars)));
printf("integers[] - average = %d\n",
int_average(integers, sizeof(integers)));
}

 

Running this program gives us the following results:

chars[] - average = 3
integers[] - average = 1054228

Obviously, the computed average on the integer array is wrong. Let's use IDA's debugger to understand the origin of this error !

 

Loading the file.

The debugger is perfectly integrated with IDA: to debug, we must first load the executable in IDA, to create a database. The user can disassemble the file interactively, and all the information which he will have added to the disassembly will be available during debugging. If the disassembled file is recognized as valid (x86/ARM64 PE or x86 ELF) by the debugger, a Debugger menu automatically appears in IDA's main window.

 

Instruction breakpoints.

Once we located our int_average() function in the disassembly, let's add a breakpoint just after itsprolog, by selecting the Add breakpoint command in the popup menu, or by pressing the F2 key.

 

Program execution.

Now, we can start the execution. We simply open the debugger window by using the appropriateicon, and run the program until it reaches our breakpoint, by pressing the F9 key or clicking the Start button in the debugger toolbar.

The stack.

The IDA View-ESP window now shows us the stack frame of the interesting functions. We easily locate the array argument of our int_average() function, pointing to the integer array in the calling function (main() function).

Now, we can start the execution. We simply open the debugger window by using the appropriate icon, and run the program until it reaches our breakpoint, by pressing the F9 key or clicking the Start button in the debugger toolbar.

 

Watches.

Why not add a watch on this array, in order to observe the evolution of its values during the process execution ?

Address evaluation.

By analyzing the disassembled code, we can now locate the loop which computes the sum of the values, and stores the result in the EBX register. The [edx+eax*4] operand clearly shows us that the EDX register points to the start of the array, and that the EAX register is used as an index in this array. Thus, this operand will successively point to each integer from the integers array.

Step by step and jump targets.

Let's advance step by step in the loop, by clicking on the adequate button in the debugger toolbar or by pressing the F8 key. If necessary, IDA draws a green arrow to show us the target of a jump instruction.

The bug uncovered.

Now, let's have a look at ESI's value. The EAX register (our index in the array) is compared to this register at each iteration: so, we can conclude that the ESI register is used as a counter in the loop. But, we also observe that ESI contains a rather strange number of elements: 14h (= 20). Remember that our original array contains only 5 elements ! It seems we just found the source of our problem...

Hardware breakpoints.

To be sure, let's add a hardware breakpoint, just behind the last value of our integers array (in fact, on the first value of the chars array). If we reach this breakpoint during the loop, it will indeed prove that we read integers outside our array. So, we setup a hardware breakpoint with a size of 4 bytes (classical size for an integer) in Read mode.

 

As foreseen, if we continue the execution, the hardware breakpoint indeed detects a read access to the first byte of the chars array. Remark that EIP points to the instruction following the one which caused the hardware breakpoint ! It is in fact rather logical: to cause the hardware breakpoint, the preceding instruction has been fully executed, so EIP now points to the next one.

Stack trace.

By looking at the disassembly, we see that the value stored in ESI comes from the count argument of our int_average() function. Let's try to understand why the caller gives us such a strange argument: If we open the Stack Trace window, we see a stack of all caller functions. Simply double click on the main() function, to jump to the caller code. With the help of IDA's PIT (Parameter Identification and Tracking) technology, we easily locate the push 20 instruction, passing an erroneous count value to our int_average() function.

Now, by looking closer at the C source code, we understand our error: we used the sizeof() operator,which returns the number of bytes in the array, rather than returning the number of items in this array ! As, for the chars array, the number of bytes was equal to the number of items, we didn't notice the error...

 

Other features.

IDA's debugger gives you access to all the segments of a debugged process's memory space, allowing you to use all of IDA's powerful features: you can apply structures to bytes in memory, draw graphs, create breakpoints in DLLs, ...

The way the debugger reacts to exceptions is fully configurable by the user.

This debugger is thus the essential complement to IDA itself, allowing you to interactively disassemble and debug everything, everywhere.

 

中文翻译:

这个小教程介绍了IDA调试器插件的主要功能。IDA支持调试x86 Windows PE文件,AMD64 Windows PE文件和x86 Linux ELF文件,可以在本地或远程调试。让我们看看如何使用调试器在Windows下本地调试一个简单的有缺陷的C控制台程序。

 

有缺陷的程序。

这个程序只是计算一组值(1、2、3、4和5)的平均值。这些值存储在两个数组中:一个包含8位值,另一个包含32位值。

 

#include

char char_average(char array[], int count)

{

int i;

char average;

average = 0;

for (i = 0; i < count; i++)

average += array[i];

average /= count;

return average;

}

int int_average(int array[], int count)

{

int i, average;

average = 0;

for (i = 0; i < count; i++)

average += array[i];

average /= count;

return average;

}

void main(void) {

char chars[] = { 1, 2, 3, 4, 5 };

int integers[] = { 1, 2, 3, 4, 5 };

printf("chars[] - average = %d\n",

char_average(chars, sizeof(chars)));

printf("integers[] - average = %d\n",

int_average(integers, sizeof(integers)));

}

 

运行这个程序,我们得到了以下结果:

chars[] - average = 3

integers[] - average = 1054228

Obviously, the computed average on the integer array is wrong. Let's use IDA's debugger to understand the origin of this error !

 

加载文件

调试器与IDA完美地集成在一起:为了进行调试,我们必须首先在IDA中加载可执行文件,以创建一个数据库。用户可以交互式地反汇编文件,所有添加到反汇编中的信息都将在调试期间可用。如果调试器将反汇编的文件识别为有效文件(x86 / ARM64 PE或x86 ELF),则Debugger菜单会自动出现在IDA的主窗口中。

 

指令断点

一旦我们在反汇编中定位了int_average()函数,让我们在它的Prolog之后添加一个断点,方法是选择弹出菜单中的添加断点命令,或按F2键。

 

程序执行

现在,我们可以开始执行。我们只需使用相应的图标打开调试器窗口,并通过按F9键或单击调试器工具栏中的“开始”按钮,运行程序直到达到我们的断点。

 

 

堆栈

IDA View-ESP窗口现在向我们显示了感兴趣的函数的堆栈帧。我们很容易找到我们的int_average()函数的数组参数,该参数指向调用函数(main()函数)中的整数数组。

 

现在,我们可以开始执行。我们只需使用相应的图标打开调试器窗口,并通过按F9键或单击调试器工具栏中的“开始”按钮,运行程序直到达到我们的断点。

 

观察点

为什么不在该数组上添加一个观察点,以便在进程执行期间观察其值的变化?

 

 

地址评估

通过分析反汇编代码,我们现在可以找到计算值的和并将结果存储在EBX寄存器中的循环。[edx + eax * 4]操作数清楚地向我们显示EDX寄存器指向数组的开始,并且EAX寄存器用作此数组中的索引。因此,此操作数将依次指向整数数组中的每个整数。

 

 

逐步执行和跳转目标。

让我们逐步在循环中前进,通过在调试器工具栏中单击适当的按钮或按F8键。如有必要,IDA会绘制一个绿色的箭头,以显示跳转指令的目标。

 

发现错误。

现在,让我们看一下ESI的值。EAX寄存器(数组中的索引)在每次迭代时与此寄存器进行比较:因此,我们可以得出结论,ESI寄存器在循环中用作计数器。但是,我们还观察到ESI包含相当奇怪的元素数量:14h(= 20)。请记住,我们原始的数组仅包含5个元素!似乎我们刚刚发现了问题的来源...

 

硬件断点

为了确保我们的推测,让我们在整数数组的最后一个值后面添加一个硬件断点(实际上是在字符数组的第一个值上)。如果在循环期间到达此断点,它确实会证明我们读取了数组之外的整数。因此,我们以“读”模式设置了一个大小为4字节(整数的经典大小)的硬件断点。

正如预料的那样,如果我们继续执行,硬件断点确实检测到了对字符数组的第一个字节的读取访问。请注意,EIP指向导致硬件断点的指令之后的指令!事实上,这是相当合理的:为了引起硬件断点,之前的指令已被完全执行,因此EIP现在指向下一个指令。

堆栈跟踪

通过查看反汇编,我们可以看到存储在ESI中的值来自我们的int_average()函数的count参数。让我们试着理解为什么调用者给了我们这样一个奇怪的参数:如果我们打开堆栈跟踪窗口,我们会看到所有调用者函数的堆栈。只需双击main()函数即可跳转到调用者代码。借助IDA的PIT(参数识别和跟踪)技术,我们很容易找到将一个错误的count值传递给我们的int_average()函数的push 20指令。

 

现在,通过仔细查看C源代码,我们了解了我们的错误:我们使用了sizeof()运算符,该运算符返回数组中的字节数,而不是返回该数组中的项数!因为对于字符数组,字节数等于项数,所以我们没有注意到错误......

其他功能

IDA的调试器可以访问调试过程的内存空间中的所有段,使您可以使用IDA的所有强大功能:您可以将结构应用于内存中的字节,绘制图形,为DLL创建断点......

 

调试器对异常的反应方式完全可由用户配置。

 

因此,这个调试器是IDA本身的必备补充,允许您交互式地反汇编和调试任何内容,任何地方。

展开阅读全文

标签:

读者也访问过这里:
邀请您进入交流群 点击扫码
400-8765-888 kefu@makeding.com

专业销售为您服务

欢迎添加好友,了解更多IDA优惠信息,领逆向工程学习资料礼包1份!
热门文章
exe反编译工具哪个好?反编译能力强的工具盘点
随着软件技术的发展,exe(可执行文件)已经成为了电脑、手机等多个平台上的主要软件运行格式,而对于exe文件的反编译也成为了逆向工程中不可缺少的一个步骤。本文将介绍一些常用的exe反编译工具,并评价其优缺点,帮助读者选择合适的工具。
2023-04-12
idapro怎么改为中文
IDA Pro是一款功能强大的反汇编和反编译工具,广泛应用于逆向工程和软件开发领域。在使用IDA Pro时,如果我们不习惯英文界面,可以将其改为中文界面。本文将介绍IDA Pro怎么改为中文界面。IDA Pro界面改成中文主要有两种方法,下面是详细介绍。
2023-04-19
c++反编译工具有哪些
反编译C++代码的工具一般是针对可执行文件和库文件的反汇编和逆向分析工具。本文将给大家介绍c++反编译工具有哪些的内容。市面说的c++反编译工具有很多,下面介绍几款使用认识较多的软件。
2023-04-23
ida怎么查找字符串 ida字符串窗口快捷键
在数字化时代,逆向工程作为解密软件和分析程序的关键技术,正日益受到广泛关注。在逆向分析的过程中,IDA(Interactive DisAssembler)是一款备受推崇的工具,它为逆向工程师们提供了强大的功能和灵活的操作。本文将带您深入探讨如何在IDA中查找字符串,优化字符串窗口的使用,并探讨IDA如何将变量转换成字符串,帮助您更加熟练地驾驭这一工具,为逆向分析的世界增添一抹精彩。
2023-09-27
ida如何转伪代码 ida伪代码怎么看
IDA Pro是一款常用的反汇编和反编译工具,可以帮助我们分析二进制文件的实现细节和执行过程,以便更好地理解程序的执行过程和逻辑。在进行逆向工程的过程中,我们经常需要将反汇编结果转换为伪代码,以便更好地进行分析和修改。本文将介绍如何使用IDA Pro转换为伪代码,并简单讲解ida伪代码怎么看。
2023-04-14
最新文章
IDA Pro怎么导出C代码 IDA Pro导出的C代码缺少变量声明如何处理
IDA Pro通过Hex-Rays反编译器把机器指令转换为接近C语言的伪代码,并不等于恢复原始工程。处理“IDA Pro怎么导出C代码IDA Pro导出的C代码缺少变量声明如何处理”时,应先修正函数边界、参数类型和局部变量,再执行导出;未经整理的伪代码容易出现声明折叠、变量合并和调用原型错误。
2026-08-04
IDA Pro反编译BIN怎么设置基地址 IDA Pro基地址设置错误后引用关系如何修复
BIN文件通常只保存连续的机器码和数据,不包含处理器类型、加载地址、段表及入口点。使用IDA Pro分析时,基地址一旦设置错误,函数地址、全局变量、跳转目标和交叉引用都会随之偏移。处理“IDA Pro反编译BIN怎么设置基地址IDA Pro基地址设置错误后引用关系如何修复”,应先确认固件实际映射位置,再决定重新加载还是对现有数据库整体重定位。
2026-08-04
IDA Pro反编译APK怎么选择目标架构 IDA Pro加载错误架构的SO文件如何更换
APK中的Java或Kotlin代码主要位于DEX文件,IDA Pro更适合分析其中的本地SO库。同一个安装包可能同时包含ARM、ARM64、x86和x86_64版本,同名SO的指令集、位宽和调用约定并不相同。处理“IDA Pro反编译APK怎么选择目标架构IDA Pro加载错误架构的SO文件如何更换”,应先确认应用实际使用的ABI,再核对ELF位宽和IDA处理器,不能只凭文件名判断。
2026-08-04
IDA Pro反编译SO怎么查找JNI注册函数 IDA Pro动态注册的Native方法如何定位
Android应用中的Native方法有静态注册和动态注册两种形式。静态注册通常能在SO导出表中看到以Java_开头的函数名,动态注册则会在运行时通过RegisterNatives把Java方法名、方法签名和Native函数地址建立对应关系。IDA Pro反编译SO怎么查找JNI注册函数IDA Pro动态注册的Native方法如何定位,重点是找到注册入口、识别JNINativeMethod数组,再沿函数指针进入真正的Native实现。
2026-08-04
IDA Pro反编译DLL怎么修正调用约定 IDA Pro调用约定识别错误会造成什么影响
DLL中的导出函数、内部函数和回调函数可能采用不同的参数传递方式。IDA Pro会根据处理器、编译器特征和调用现场推断函数原型,但优化编译、符号缺失、间接调用及自定义寄存器传参都会影响识别结果。“IDA Pro反编译DLL怎么修正调用约定IDA Pro调用约定识别错误会造成什么影响”涉及函数类型、栈平衡和跨函数数据流等内容。
2026-08-04
IDA Pro反编译C++怎么识别虚函数 IDA Pro虚函数调用关系显示错误如何调整
APK中的Java或Kotlin代码主要位于DEX文件,Native代码通常位于不同ABI目录下的ELF共享库。动态调试时看到大量sub_xxx、loc_xxx或无意义类名,往往不是调试器没有连接成功,而是当前数据库、运行模块与符号文件没有正确对应。处理“IDA Pro动态调试APK怎么加载符号IDA Pro调试APK时符号名称缺失如何补全”时,应先区分DEX符号和Native符号,再按照实际加载地址补充调试信息。
2026-08-04

通过微信咨询我们

欢迎添加好友,了解更多IDA优惠信息,领取逆向工程学习资料礼包1份!

读者也喜欢这些内容: