高级语言编写的程序有两种形式,一种编译成机器语言在CPU上执行,如Visual C ++、PASCAL等。由于机器语言与汇编语言几乎是一一对应的,因此可将机器语言转化成汇编语言,这个过程称为反汇编(Disassembler)。另一种高级语言是一边解释一边执行的,称之为解释性语言。如Visual Basic 3.0/4.0、Visual FoxPro等,这类语言编译的程序可以被还原成高级语言的原始结构,这个过程称为反编译(Decompiler)。
所谓静态分析,即从反汇编出来的程序清单上分析程序流程,了解关注模块完成的功能。
## 1.反汇编
编译执行的语言因为直接同CPU的指令集打交道,具有很强的指令依赖性和系统依赖性,但编译后的程序执行效率要比解释语言高得多,像现在的Visual C/C++等都是很好的编译语言。例如x86系统中,机器码“0xEB”对应的汇编语句是“jmp short xx ”。
例如下面一段VC程序:
```
TCHAR szBuffer[30]={0};
TCHAR cCode[30]={0};
……
case IDC_OK:
GetDlgItemText(hDlg,IDC_TXT1,cCode,sizeof(cCode)/sizeof(TCHAR)+1);
wsprintf(szBuffer,TEXT("%ld"),123);
if(lstrcmp(cCode, szBuffer)==0)
MessageBox(NULL, TEXT ("注册成功!"), TEXT ("恭喜你!"), 0) ;
break;
```
这段程序被Visual C++编译器编译后,就会变成机器语言程序,然后就可在机器上执行了。由于是机器语言了,直接分析是不可能。但解密者可以通过反汇编工具,如W32Dasm、IDA pro等,将二进制的机器语言反汇编成汇编代码,在汇编代码级别上来分析程序的功能。汇编代码如下:
```
: 00401080 6A1F push 0000001F ; 字符缓冲区的长度
:00401082 50 push eax ; 文本缓冲区指针
:00401083 68E8030000 push 000003E8 ; 控件标识号
:00401088 51 push ecx ; hDlg,对话框句柄
* Reference To: USER32.GetDlgItemTextA, Ord:0104h
:00401089 FF1598404000 Call dword ptr [00404098] ; 调用函数GetDlgItemTextA
:0040108F 6A7B push 0000007B ; 需转换的数字123的十六进制
:00401091 8D542404 lea edx, dword ptr [esp+04]
* Possible StringData Ref from Data Obj ->"%ld"
:00401095 6850504000 push 00405050 ; 指向参数%ld
:0040109A 52 push edx ; 转换后的缓冲区地址
* Reference To: USER32.wsprintfA, Ord:02ACh
:0040109B FF159C404000 Call dword ptr [0040409C] ; 函数wsprintfA
:004010A1 83C40C add esp, 0000000C ; 平衡堆栈
:004010A4 8D442400 lea eax, dword ptr [esp]
:004010A8 8D4C2420 lea ecx, dword ptr [esp+20]
:004010AC 50 push eax ; 指向字符“123”
:004010AD 51 push ecx ; 指向输入的字符
* Reference To: KERNEL32.lstrcmpA, Ord:02FCh
:004010AE FF1508404000 Call dword ptr [00404008] ; lstrcmpA函数比较两个字符
:004010B4 85C0 test eax, eax ; 如相等,返回0到eax寄存器
:004010B6 752E jne 004010E6 ; 不相等就跳转
:004010B8 50 push eax ; 消息框样式
* Possible StringData Ref from Data Obj ->"恭喜你!"
:004010B9 6844504000 push 00405044 ; 指向消息框标题
:004010BE 6838504000 push 00405038 ; 指向消息框文本
:004010C3 50 push eax ; 父窗口够句柄
* Reference To: USER32.MessageBoxA, Ord:01BEh
:004010C4 FF15A0404000 Call dword ptr [004040A0] ; 函数MessageBoxA
```
如果你有一定的汇编语言基础,再掌握点逆向分析技术,上面汇编代码的功能很容易理解的。一般情况下,编译成本地机器语言后,用工具是不能还原成源代码的。但现在情况不同了,IDA Pro这款极专业的反汇编工具,配合解密人员编程知识,一般采用Win SDK开发的程序,还是比较容易人工反编译为C源代码。
## 2.反编译
解释性语言在编译期间,它的程序代码不被直接转换成计算机识别的二进制代码,而是只生成一种中间代码,目的不是让计算机直接去执行,而只是为了进行先期语法检查。这些代码被放置到内存的“数据段”中,运行时由一个解释器再动态解释被存放于“数据段”的伪代码。因此,可以看到很多伪编译的程序都带有一个很大的DLL之类的文件,例如Visual Basic、Visual FoxPro、Power Builder、Java等。解释执行的语言由于其解释器不需要直接同机器码打交道,所以实现起来较为简单,而且便于在不同的平台上面移植。解释语言编译的代码实际上是“变形的源代码”,只要能理解其对应机制,就能做出反编译器来。这类语言编译的程序可以被还原成高级语言的原始结构,这个过程称为反编译(Decompiler)。
目前VB3、VB4、Visual FoxPro、Power Builder和Java等语言都可被反编译成原编译语言。VB5、VB6不再是单纯的解释程序,虽然里面还有解释执行的部分,但起码主程序部分是真正编译的。
最新的Microsoft Visual Studio.net也是一种解释语言,只是将名称换成“中间语言(Microsoft Intermediate Language)”。如果用W32Dasm反汇编一此类程序,将会看到莫名其妙的代码,因为它不再是传统意义上的汇编代码了,只有用P-code反编译器才能得到正确的代码,以从语言助记符上理解程序功能。如支持VB5/VB6 P-code的反编译器Exdec、WKTVBDE、VBDE,对付最新microsoft .net的反编译程序LDASM(.NET FRAMEWORK SDK中提供)等。