如果想要成为一名出色的恶意代码分析师,我们需要掌握很多反汇编的工具,一般的反汇编工具分为动态分析工具,例如著名的OllyDbg,而在静态分析方面,就属大名鼎鼎的IDA了,IDA以其强大的功能和众多的插件成为了很多逆向分析师的首选。IDA pro是商业产品,不过IDA也提供了评估试用版本,本实验使用的是IDA Demo 6.6 for MS Windows评估版本。
在这里我们声明:以教学为目的,只使用其免费版本,支持大家购买正版使用。
本次实验地址:https://www.yijinglab.com/expc.do?ec=ECID172.19.104.182014111417054000001
任何一个伟大的成就,往往有一个很不起眼的开始。通过本课程的学习,你将会掌握到:
1、学会IDA常用功能和快捷键
2、学会查看字符串。
3、学会利用函数窗口定位函数和重命名
4、学会使用交叉引用这个功能
5、利用上述技巧分析一个小的demo程序,并找到最终的key
熟悉IDA的界面和常用模块
打开桌面IDA目录下的IDAPractice1.exe,将此文件拖拽至IDA下,开始分析的界面如下
由图中可以看到,IDA分了好几个模块。左侧部分叫做函数窗口,列出了程序中所有的函数。右侧较大的区域,是我们经常要用到的区域,系统默认显示的是整个程序的执行流程图,当然你可以使用空格键来切换,这时候就会显示全文本的汇编。左下角的图形窗口上,可以用鼠标移动,这时候右侧的流程图也会跟着变化。流程图上的各种箭头表示程序执行过程中的跳转。
1.在左侧的函数窗口上找到叫sub_401000的函数,双击,会看到右侧的窗口发生了变化,分析窗口跳转到了sub_401000的起始位置.一般的常用函数IDA会自动识别,所以在这些以sub_开头的函数,很可能就是程序员自己定义的,当然也不排除是ida没有识别的系统函数。
2.有时候程序里面的字符串对分析程序很有帮助,IDA有个模块可以将所有的字符串列出来。使用SHIFT+F12(或者在菜单中打开view-opensubview-strings),效果如下图所示
在这里,看到了“you got it \n”和“sorry,try again”这样的字符串,以“you got it\n”为例,双击,就会进入主窗口,我们会看到:
Dataxref:是数据引用的意思,你可以理解为程序中在哪里调用了这个字符串或数据,这里表示main函数中的local401055处调用了此字符串。再次双击,页面就跳转到:
这就是交叉引用,0x401055处,用了push指令,而push到的值刚好是这行字符串。
实验步骤二
这一阶段,我们要学习有关函数重命名和数值转化的知识。
1.函数重命名:有时候,ida无法分析出来程序的子函数是什么功能,只能以sub_前缀去命名,这为代码分析人员带来了很大的问题。ida提供了函数重命名的方法,可以再分析完子程序之后对其重命名,这样当再次分析的时候就会一目了然。
在main函数中,有条指令call sub_401000,sub表名这是个函数,点击sub_401000,按下n键,输入你认为合适的函数名,如“do_something”.
这时候会看到左侧的函数窗口中相应的函数名也发生了变化.
2.数值转化:内存中存放的二进制数可以被解释成8进制,16进制,字符串型,整型等等。Ida不能完全智能的判断到底属于哪种类型,不过可以使用数值转化键。以下面图片为例:
需要将0ch换成10进制,可以通过右键选择,或者直接在0cH处摁下h键,可来回切换。
在ida中,右键是个很常用的功能键,打开右键之后,一般都会有相应的快捷键提醒。
实验步骤三
最后,让我们分析一下这个程序的执行流程,并且分析出最终的key值.
1.首先,在右侧函数窗口中选择main函数,这是该程序的入口函数。
2.查看整个程序的流程图:
由蓝色箭头表示跳转可以看到,整个程序大体是个死循环,唯一跳出的地方是loc_401055处,当然,通过”you got it\n”也可以看出来。
那么,影响跳转的地方是jnz short_local401055这条指令,jnz表示jmp not zero,也就是根据上一条test eax,eax的值来选择跳转。Testeax,eax这条指令在检查eax是否为0.
eax往往是一个函数的返回值存放的位置。所以,就对上面的call do_something比较感兴趣了。这时候,将do_something改为check.
接下来,进入这个check函数中去,在check上按回车键,即可进入:
下面来分析一下这些指令:
Ida中,智能的将函数中的局部变量命名为var,将参数命名为arg.所以,movecx,[esp+arg_0]表示的应该是取出参数的值到ecx中去。
然后xoreax,eax将eax置0.cmp是要关注的重点,这条指令,是将ecx(实质就是函数调用的参数)和4D2H比较.我们用刚才使用的方法将这个十六进制数转化为十进制数,右键,选择H,发现是1234.
接下来,程序去判断,jnz表示jump not zero .当比较的值不相等(结果不为0)的时候,就会跳转到locret_401013处,这时候程序就返回了。此时返回值eax是0。如果相等(结果为0),那么就会执行下一条指令,将eax置为1.然后返回。
综合考虑一下,这个check函数的作用是:检查参数是否和1234相等,如果相等,则返回1,反之,返回0。
那么问题来了,这个函数调用的参数是什么。再返回到main函数去看,按esc键。
可以通过最上方的注释“please input the key”,和下方ida提示的call scanf确认是输入一个参数,通过”%d”,更能确认这是一个数字。
接下来,mov指令将输入的参数存放到ecx处,然后push到堆栈上。多么熟悉的指令组合 push a ;call b;add; ..,还原回来就是执行b(a)。
这个参数就是我们之前输入的参数。
那么,整个程序的流程大概就是:输入数字,检验是不是为1234,如果不是,继续循环输入并检查,直到输入的是1234为止。Key就是1234.
到现在为止,没有让程序执行,却慢慢的分析了程序的执行流程。读者可以通过执行这个程序来验证一下。
关于程序的流程图,还有一个快捷键是F12,IDA会列出当前光标所在函数的流程图。例如将光标放在check子函数上,按下F12键,就会看见如下图所示
可以看到,ida将条件跳转等转化成了对逻辑真假的标注。且更加整洁。
同样的,对main函数执行同样的操作,会发现:
流程图可以很直观的表现出程序的流程,应逐渐掌握这种操作方式。