9.2 符号文件#
目标文件:HOLA_REVERSER.exe
查看目标文件架构:
目标文件是 32 位程序,VC++ 2015 编译。
双击运行程序,提示输入数字
程序会判断输入的字符是否正确
9.3 定位 main 函数#
先看下字符串
找到了目标程序运行时输出的一些字符串,双击上图中红线画出来的。
来到如下位置:
上图中,0x402108 是这个字符串的地址,地址右侧的 16 进制是机器码,机器码右侧的 aPoneUnNumerito 是这个字符串的标记或名称,字符串前面的 a 表示这是个 ascii 码,后面的 db 表示这是个字节序列。
按 D 键可以查看每一个字节的值:
再按 A 键可以重新显示成字符串。
将鼠标放置再右侧引用的箭头上,可以查看具体的引用位置,按 X 键可以进入具体的引用位置。
从这个引用就可以找到 main 函数。
9.4 函数的栈#
上述图中有个局部变量 var_4,大小是 dword。
32 位函数调用栈视图
首先所有的函数参数被传入栈中,然后是返回地址,返回地址的上方是上一级函数 EBP,产生于函数的第一句指令PUSH EBP
,最上面的是局部变量。
9.5 Main 函数参数#
来到 main 函数处
按 X 键查看 main 函数是在哪里被引用的。
main 函数调用
上图中有三个 push 指令,通过这三个指令进行传参,在三个指令的注释中,可以了解到传递了三个参数,分别位 argc、argv 和 envp 等,是函数的默认参数。
9.6 局部变量#
var_c 是一个局部变量,按 X 键可以查看在哪里被引用了,从下图可知,有两个地方引用了这个局部变量。
9.7 Atoi 函数#
atoi 函数将字符串转换为一个整数,如果因为数字太大导致无法转换,会产生错误并且返回 0。当然如果比最小的负整数 (int) 还小,也会出错返回 0,所有输入的内容都会被转换为一个整数。如果输入 41424344, 将会被转换为一个十六进制数保存到 EAX。
#include <stdlib.h>
int atoi(const char *string);
通过上图可以知道,目标程序会把所有输入的字符串转换成整数。如果atoi
或者_wtoi
无法将输入的内容转换为日标类型将会返回 0。
atoi 返回值
eax 返回值传给 esi,在输出用户输入的原始字符串后,esi 的值会和0x12457
比较,
用户输入的十进制数字符串会被解析并返回一个十六进制数,然后再与那个硬编值进行比较,如果输入硬编值对应的十进制数,应该会成功。
上图中用了 jnz 指令(不相等 / 不为 0),则输出bad reverser
,如果相等,则输出good reverser
。
0x124578
,16 进制转成 10 进制为 1197432
在目标程序中,输入这个十进制 1197432 ,可以看到成功验证,输出good reverser
。
目标程序分析也到这结束了,这一章学习了函数栈的逆向分析,包括函数如何传参、局部变量和 atoi 函数等。