使用 IDA 打开 HOLA_REVERSER.exe 文件,IDA 会提示我们是否加载符号文件。由于这个程序不是我们写的,所以我们没有符号文件。点击否即可。

IDA 7.7 已经很聪明了,打开该文件后,自动定位到了 main 函数。

这个程序很简单,我们只需要分析 main 函数即可。

main函数

; Attributes: bp-based frame

; int __cdecl main(int argc, const char **argv, const char **envp)
_main proc near

Buffer= byte ptr -7Ch
var_4= dword ptr -4
argc= dword ptr  8
argv= dword ptr  0Ch
envp= dword ptr  10h

这里的信息可以看出来,该函数有3个参数,2个局部变量,以前说过,局部变量为负偏移。

单击其中任何一处,IDA 将会跳转到一个栈视图,静态地显示函数参数、局部变量,以及他们之间的距离:

image.png

可以看到 Buffer 变量占据了 120 个字节。那么它是一个什么类型呢?结构体还是数组还是其他的。

这里就需要结合汇编与反汇编代码来分析了。

切到反汇编视图,可以清楚的看到它是一个 char[] 类型。

我们看汇编代码,使用 Buffer 的位置:

lea     eax, [ebp+Buffer]
push    14h             ; Size
push    eax             ; Buffer
call    ds:gets_s
-----------------------------------------------------------------------
lea eax, [ebp+Buffer]: 将 Buffer 的地址加载到 eax 寄存器中。
push 14h: 将缓冲区的大小(20 字节,16 进制表示)压入栈中。
push eax: 将指向缓冲区的指针压入栈中。
call ds:gets_s: 调用 gets_s 函数,从标准输入读取字符串并存储到指定的缓冲区中。

这里调用了 gets_s 函数,而且参数的传递没有使用 eax 等寄存器,是直接使用的栈(push指令)。

这些汇编指令对应的代码为:

char Buffer[120];

gets_s(Buffer, 0x14u);

gets_s是一个标准函数,它接收一个 char * 类型:

char *gets_s(char *str, rsize_t size);

所以,我们确定 Buffer 是一个 char[] 类型。

在栈视图里面,右键单击 Buffer 这个位置,选择 Array 选项转化为数组可以将其转化为字符数组或者说缓存区: