CTF每日一题 | REVERSE练习之API定位
题目描述:
主机C:\Reverse\2目录下有一个CrackMe2.exe程序,运行这个程序的时候会提示输入一个密码,当输入正确的密码时,会弹出过关提示消息框,请对CrackMe2.exe程序进行逆向分析和调试,找到正确的过关密码。
实验步骤:
1、外部行为分析
在随便输入字符和不输入字符时情况如下:
所以目的是找到一个正确的密码输入。
2、查看是否加壳
选中程序后单击右键,在右键菜单中选择“Scan with PEiD”选项,就可以查看加壳信息了。看到的是Microsoft Visual C++ 6.0,说明CrackMe2.exe没有加壳,且它是使用VC6编译的。
3、使用OD动态调试
使用OD载入程序,如果继续使用实验CTF每日一题 | Reverse练习之初探中提到的方法查找字符串,提示找不到:
在反汇编指令列表中单击右键,在右键菜单中依次选择“查找”——“当前模块中的名称(标签)”:
点击弹出的名称窗口,在键盘上敲下MESSAGEBOXA,就会自动定位到MessageBoxA,点击鼠标选中MessageBoxA这一行,单击右键,在弹出的右键菜单中选择“在每个参考上设置断点”:
在OD最下方的状态栏上可以看到“已设置 2 个断点”的提示。(有对MessageBox两次的调用)
现在按F9运行程序,随便给程序输入一个密码(如TEST),单击确定按钮后程序将在OD中断下,断下的位置为对MessageBoxA的调用的位置:
这就是要找的关键函数,查看附近的代码,就找到了密码明文:
4、使用IDA静态分析
使用IDA载入CrackMe2.exe程序进行分析,等待分析完毕后,选择主窗口面板上的Imports页面,然后在键盘上敲下MESSAGEBOXA,将自动定位到MessageBoxA函数:
双击这个条目,来到MessageBoxA定义的位置,选中后按下X键,弹出交叉引用列表窗口,看到一共有四个条目:
不能直接看出哪一个引用就是要找的引用,所以需要一个一个进行查看,根据前面使用OD对程序的分析,知道在MessageBoxA之前有许多对LoadString的调用,通过对比几个交叉引用,可以断定sub_401450就是要找的函数。
使用F5还原sub_401450函数的伪代码,确定LoadString加载资源ID为0x6A的字符串就是要找的密码:
使用Restorator打开CrackMe2.exe程序来查看字符串资源,0x6A的十进制即106(=10X16^0+6X16^1),因此可以知道密码就是HeeTianLab:
5、总结:
Windows API:
ANSI的ASCII字符集及其派生字符集(也称多字节字符集)比较旧,而Unicode字符集比较新,固定以双字节表示一个字。Windows操作系统在声明一个API时,如果这个API存在字符串参数,便会指定字符集。每个含有字符串参数的API同时有两个版本:即ANSI,Unicode。尾部带A的API是ANSI版本,带W的API是Unicode版本。
例如:我们在编程时使用的MessageBox实际上是一个宏,根据字符集的不同被定义为不同版本的MessageBox,如果是UNICODE字符集,则实际上为MessasgeBoxW,如果是ANSI字符集,则实际上为MessageBoxA:
#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif // !UNICODE
交叉引用:
通过交叉引用(XREF)可以知道指令代码相互调用的关系, 在选的的函数上面按X键,可以打开交叉引用窗口,会列出所有调用了这个函数的地方。
十六进制转10进制:
十六进制数的第0位的权值为16的0次方,第1位的权值为16的1次方,第2位的权值为16的2次方……
假设有一个十六进数 2AF5, 那么如何换算成10进制?
用竖式计算:
2AF5换算成10进制:
第0位:
第1位:
第2位:
第3位:
直接计算就是: