尽管IdaPro Advanced 版本很好、很强大,但那毕竟是商业版,要合法使用就得掏银子。可是DataRescue 公司也很好、很厚道,提供了Ida Freeware Version 4.9 版本可以免费下载使用。该版本对于仅分析Windows 32-bit 平台的粉丝们而言也很好、很够用。下载地址为:http://tiarater.datarescue.be/freefiles/idafree49.exe
下载完双击idafree49.exe 可按提示安装Ida Freeware Version4.9 。安装好后运行idag.exe 时,在About 对话框将选项Do not display PDF file next time 打勾,以免自动显示idafreeware.pdf 文件。当调用帮助信息(单击菜单Help->Help Index)时会出现找不到idahelp.hlp 文件的消息框,并询问是否亲自查找该文件。因为Ida Freeware Version 4.9 的帮助文件是chm 格式的,而不是hlp 格式,所以找不到。但是如果按帮助键F1 却可以正常打开chm 格式的帮助文件。
下面看看如何用Ida Freeware Version 4.9 来解决问题。可以用idag.exe 打开idag.exe 自身进行分析。在运行idag.exe 之前先用notepad 或其他文本编辑器对配置文件cfg\idagui.cfg 进行修改如下:
1)为了启用补丁及idc脚本命令功能,将 DISPLAY_PATCH_SUBMENU = NO // Display the Edit,Patch submenu
DISPLAY_COMMAND_LINE = NO // Display the expressions/IDC command line
改为 DISPLAY_PATCH_SUBMENU = YES // NO // Display the Edit,Patch submenu
DISPLAY_COMMAND_LINE = YES // NO // Display the expressions/IDC command line
2)为了禁用“未定义”及“设置函数末尾”提示选项,将CONFIRM_UNDEFINE_COMMAND = CONFIRM_UNDEFINE_YES // Confirm the "undefine" command
CONFIRM_SETFUNCEND_COMMAND = YES // Confirm the "set function end" command (E hotkey) 改为CONFIRM_UNDEFINE_COMMAND = CONFIRM_UNDEFINE_BLOCK // CONFIRM_UNDEFINE_YES // Confirm the "undefine" command
CONFIRM_SETFUNCEND_COMMAND = NO // YES // Confirm the "set function end" command (E hotkey)
3)为了启用“文件偏移跳转”快捷键(Alt+O),将"JumpFileOffset" = 0 改为"JumpFileOffset" = "Alt-O" // 0
4)为了启用“符号改变”快捷键(Shift+-),将//"ChangeSign" = "Shift+-" 改为"ChangeSign" = "Shift+-"
5)为了启用“计算”快捷键,将//"Calculate" = '?' 改为"Calculate" = '?'
修改好以上内容后,将cfg\idagui.cfg 文件存盘。
双击idag.exe ,启动ida后单击菜单File->Open 找到idag.exe 后将其打开,ida会自动分析执行文件。等待分析完毕后,单击菜单Search->text... (或按快捷键Alt+T )出现Text search (slow) 对话框,输入Help1Click 单击OK 搜索文本"Help1Click"可以找到如下信息:.data:0053AE9F dd offset sub_406640
.data:0053AEA3 aHelp1click db 10,'Help1Click'
双击sub_406640 可以找到如下代码:.text:00406640 sub_406640 proc near ; DATA XREF: .data:0053AE9Fo
.text:00406640 mov eax, [eax+158h]
.text:00406646 mov edx, ds:@Forms@Application ; Forms::Application
.text:0040664C push eax ; dwData
.text:0040664D push 1 ; uCommand
.text:0040664F mov edx, [edx]
.text:00406651 add edx, 50h
.text:00406654 mov eax, [edx]
.text:00406656 test eax, eax
.text:00406658 jz short loc_40665E
.text:0040665A mov ecx, [edx]
.text:0040665C jmp short loc_406663
.text:0040665E ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:0040665E
.text:0040665E loc_40665E: ; CODE XREF: sub_406640+18j
.text:0040665E mov ecx, offset szHelp
.text:00406663
.text:00406663 loc_406663: ; CODE XREF: sub_406640+1Cj
.text:00406663 push ecx ; lpszHelp
.text:00406664 push 0 ; hWndMain
.text:00406666 call WinHelpA
.text:0040666B retn
.text:0040666B sub_406640 endp
可见函数sub_406640 就是实现"Help1Click"功能的,而且还调用API中的WinHelpA 函数,该函数将打开hlp 格式的帮助文件。于是就出现了一开始提到的bug:找不到idahelp.hlp 文件。
既然按快捷键F1 能正常调出idahelp.chm 帮助文件,我们可以通过将函数sub_406640 改造成快捷键F1 来实现“Help1Click"功能。单击菜单Search->text... (或按快捷键Alt+T )搜索文本".chm"可以找到如下信息(函数sub_466020 ):.text:00466020 sub_466020 proc near ; CODE XREF: sub_403EE0+14Dp
.text:00466020
.text:00466020 var_11C = dword ptr -11Ch
.text:00466020 var_108 = dword ptr -108h
.text:00466020
.text:00466020 push ebx
.text:00466021 push esi
.text:00466022 mov esi, eax
.text:00466024 push edi
.text:00466025 add esp, 0FFFFFEFCh
.text:0046602B xor ebx, ebx
.text:0046602D mov eax, [esi+4]
.text:00466030 mov edi, edx
.text:00466032 test eax, eax
.text:00466034 jz short loc_4660A0
.text:00466036 push offset a_chm ; ".chm"
.text:0046603B mov edx, ds:@Forms@Application ; Forms::Application
.text:00466041 mov eax, [edx]
.text:00466043 add eax, 50h
.text:00466046 mov edx, [eax]
.text:00466048 test edx, edx
.text:0046604A jz short loc_466050
.text:0046604C mov ecx, [eax]
.text:0046604E jmp short loc_466055
.text:00466050 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:00466050
.text:00466050 loc_466050: ; CODE XREF: sub_466020+2Aj
.text:00466050 mov ecx, offset unk_555AF8
.text:00466055
.text:00466055 loc_466055: ; CODE XREF: sub_466020+2Ej
.text:00466055 push ecx
.text:00466056 push 104h
.text:0046605B lea eax, [esp+114h+var_108]
.text:0046605F push eax
.text:00466060 call IDA_1016
.text:00466065 push esp
.text:00466066 call IDA_992
.text:0046606B test al, al
.text:0046606D jz short loc_4660A0
.text:0046606F test edi, edi
.text:00466071 jnz short loc_46608B
.text:00466073 push 0
.text:00466075 push 1
.text:00466077 lea edx, [esp+124h+var_11C]
.text:0046607B push edx
.text:0046607C push 0
.text:0046607E call dword ptr [esi+4]
.text:00466081 test eax, eax
.text:00466083 setnz bl
.text:00466086 and ebx, 1
.text:00466089 jmp short loc_4660A0
.text:0046608B ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:0046608B
.text:0046608B loc_46608B: ; CODE XREF: sub_466020+51j
.text:0046608B push edi
.text:0046608C push 0Fh
.text:0046608E lea eax, [esp+124h+var_11C]
.text:00466092 push eax
.text:00466093 push 0
.text:00466095 call dword ptr [esi+4]
.text:00466098 test eax, eax
.text:0046609A setnz bl
.text:0046609D and ebx, 1
.text:004660A0
.text:004660A0 loc_4660A0: ; CODE XREF: sub_466020+14j
.text:004660A0 ; sub_466020+4Dj ...
.text:004660A0 mov eax, ebx
.text:004660A2 add esp, 104h
.text:004660A8 pop edi
.text:004660A9 pop esi
.text:004660AA pop ebx
.text:004660AB retn
.text:004660AB sub_466020 endp
因为仅有一处出现".chm",所以可以断定这就是打开idahelp.chm 帮助文件的函数。再双击交叉引用sub_403EE0 ,可得到如下代码:.text:00404026 loc_404026: ; CODE XREF: sub_403EE0+13Dj
.text:00404026 mov eax, offset byte_57F4C0
.text:0040402B mov edx, esi
.text:0040402D call sub_466020
由此可见sub_466020 需要两个参数eax 和edx (典型的Delphi调用)。eax 的参数为offset byte_57F4C0 ,但edx 的参数为esi 不能确定其值是多少。我们可以在".text:00404026 loc_404026: "处下断点(快捷键为F2 )对其进行跟踪。单击菜单Debugger->Start process (或快捷键F9 )对idag.exe 进行调试,这时又会出现一个Ida 图形界面(点击Yes 关闭Debugger warning 对话框,再点击OK 关闭About 对话框)。然后按F1 ,这时程序就停在断点loc_404026: 处,观察寄存器esi 发现其值为0 。这样两个参数就定下来了。
如果想确认sub_466020 的功能,可以单步跟踪到sub_466020 内部,连按三下快捷键F7 就会出现sub_466020 的代码同前(为了便于阅读这里再抄写一遍):.text:00466020 sub_466020 proc near ; CODE XREF: sub_403EE0+14Dp
.text:00466020
.text:00466020 var_11C = dword ptr -11Ch
.text:00466020 var_108 = dword ptr -108h
.text:00466020
.text:00466020 push ebx
.text:00466021 push esi
.text:00466022 mov esi, eax
.text:00466024 push edi
.text:00466025 add esp, 0FFFFFEFCh
.text:0046602B xor ebx, ebx
.text:0046602D mov eax, [esi+4]
.text:00466030 mov edi, edx
.text:00466032 test eax, eax
.text:00466034 jz short loc_4660A0
.text:00466036 push offset a_chm ; ".chm"
.text:0046603B mov edx, ds:@Forms@Application ; Forms::Application
.text:00466041 mov eax, [edx]
.text:00466043 add eax, 50h
.text:00466046 mov edx, [eax]
.text:00466048 test edx, edx
.text:0046604A jz short loc_466050
.text:0046604C mov ecx, [eax]
.text:0046604E jmp short loc_466055
.text:00466050 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:00466050
.text:00466050 loc_466050: ; CODE XREF: sub_466020+2Aj
.text:00466050 mov ecx, offset unk_555AF8
.text:00466055
.text:00466055 loc_466055: ; CODE XREF: sub_466020+2Ej
.text:00466055 push ecx
.text:00466056 push 104h
.text:0046605B lea eax, [esp+114h+var_108]
.text:0046605F push eax
.text:00466060 call IDA_1016
.text:00466065 push esp
.text:00466066 call IDA_992
.text:0046606B test al, al
.text:0046606D jz short loc_4660A0
.text:0046606F test edi, edi
.text:00466071 jnz short loc_46608B
.text:00466073 push 0
.text:00466075 push 1
.text:00466077 lea edx, [esp+124h+var_11C]
.text:0046607B push edx
.text:0046607C push 0
.text:0046607E call dword ptr [esi+4]
.text:00466081 test eax, eax
.text:00466083 setnz bl
.text:00466086 and ebx, 1
.text:00466089 jmp short loc_4660A0
.text:0046608B ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:0046608B
.text:0046608B loc_46608B: ; CODE XREF: sub_466020+51j
.text:0046608B push edi
.text:0046608C push 0Fh
.text:0046608E lea eax, [esp+124h+var_11C]
.text:00466092 push eax
.text:00466093 push 0
.text:00466095 call dword ptr [esi+4]
.text:00466098 test eax, eax
.text:0046609A setnz bl
.text:0046609D and ebx, 1
.text:004660A0
.text:004660A0 loc_4660A0: ; CODE XREF: sub_466020+14j
.text:004660A0 ; sub_466020+4Dj ...
.text:004660A0 mov eax, ebx
.text:004660A2 add esp, 104h
.text:004660A8 pop edi
.text:004660A9 pop esi
.text:004660AA pop ebx
.text:004660AB retn
.text:004660AB sub_466020 endp
简言之在.text:0046607B 处下断点(F2 )或将光标定位在.text:0046607B (按快捷键G 出现Jump to address 对话框,输入0046607B 后点击OK )处按快捷键F4 ,此时双击寄存器edx 可以发现它指向帮助文件idahelp.hlp (我将ida Freeware Vesion 4.9 安装在文件夹C:\ida49free\ ):Stack[00000B2C]:0013F460 aFTemp49freeApp db 'C:\ida49free\idahelp.chm',0
按快捷键Ctrl+F2 结束程序调试。
有了参数就可以修改函数sub_406640 了,将光标定位到如下一行代码(按快捷键G 出现Jump to address 对话框,输入406640 后点击OK ):.text:00406640 mov eax, [eax+158h] 点击菜单Edit->Patch program->Assemble... 出现Assemble instruction 对话框,进行如下操作:
输入mov eax, 57F4C0h 点击OK ;
输入xor edx, edx 点击OK ;
输入xor edx, edx 点击OK ;
输入xor edx, edx 点击OK ;
输入call 466020h 点击OK ;
输入ret 点击OK ;
点击Cancel 。
操作完成后得到如下代码:.text:00406640 unk_406640 db 0B8h ; ? ; DATA XREF: .data:0053AE9Fo
.text:00406641 db 0C0h ; ?
.text:00406642 db 0F4h ; ?
.text:00406643 db 57h ; W
.text:00406644 db 0
.text:00406645 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:00406645 xor edx, edx
.text:00406647 xor edx, edx
.text:00406649 xor edx, edx
.text:0040664B call sub_466020
.text:00406650 retn
.text:00406651 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:00406651 add edx, 50h
......
在.text:00406640 行按快捷键C (Code命令)及快捷键P (Program命令)得到如下代码:.text:00406640 sub_406640: proc near ; DATA XREF: .data:0053AE9Fo
.text:00406640 mov eax, offset off_57F4C0
.text:00406645 xor edx, edx
.text:00406647 xor edx, edx
.text:00406649 xor edx, edx
.text:0040664B call sub_466020
.text:00406650 retn
.text:00406651 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:00406651 add edx, 50h
.text:00406654 mov eax, [edx]
.text:00406656 test eax, eax
.text:00406658 jz short loc_40665E
.text:0040665A mov ecx, [edx]
.text:0040665C jmp short loc_406663
.text:0040665E ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:0040665E
.text:0040665E loc_40665E: ; CODE XREF: .text:00406658j
.text:0040665E mov ecx, offset szHelp
.text:00406663
.text:00406663 loc_406663: ; CODE XREF: .text:0040665Cj
.text:00406663 push ecx ; lpszHelp
.text:00406664 push 0 ; hWndMain
.text:00406666 call WinHelpA
.text:0040666B retn
到此为止补丁就打好了。
至于为何有三行xor edx, edx 指令,那是因为在.text:00406648 处有一个外部引用。在.text:00406647 处按快捷键U (Undefine命令)得到以下内容:.text:00406640 sub_406640 proc near ; DATA XREF: .data:0053AE9Fo
.text:00406640 mov eax, offset off_57F4C0
.text:00406645 xor edx, edx
.text:00406645 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:00406647 db 31h ; 1
.text:00406648 db 0D2h ; ?OFF32 SEGDEF [_idata,58F688]
.text:00406649 db 31h ; 1
.text:0040664A db 0D2h ; ?
.text:0040664B db 0E8h ; ?
.text:0040664C db D0h ; [
.text:0040664D db 0F9h ; ?
.text:0040664E db 5
.text:0040664F db 0
.text:00406650 db 0C3h ; ?
.text:00406650 sub_406640 endp
即[I].text:00406648 db 0D2h ; ?OFF32 SEGDEF [_idata,58F688][/I]有外部引用。为了避免出问题,就多加了两行xor edx,edx 代码,从而保证调用call sub_466020 更加可靠。
下面可以生成打好补丁与源文件的比较结果:
点击菜单File->Produce file->Create DIF file... 出现对话框Please enter DIF file name for idag.exe ,此时可以将文件保存为Ida49FreePatch.dif 。该文件内容如下:
----------------------------------------------------------------This difference file is created by The Interactive Disassembler
idag.exe
00005C40: 8B B8
00005C41: 80 C0
00005C42: 58 F4
00005C43: 01 57
00005C45: 00 31
00005C46: 8B D2
00005C47: 15 31
00005C48: 88 D2
00005C49: F6 31
00005C4A: 58 D2
00005C4B: 00 E8
00005C4C: 50 D0
00005C4D: 6A F9
00005C4E: 01 05
00005C4F: 8B 00
00005C50: 12 C3
-----------------------------------------------------------------
然后可以用任何二进制文件编辑器如WinHex 或UltraEdit 对idag.exe 进行手工修改(修改前要先备份原文件以防意外)。也可用我开发的小程序AnyPatch.exe打补丁(要求idag.exe和Ida49FreePatch.dif两个文件在同一文件夹下),在命令行窗口中的用法如下:
"anypatch Ida49FreePatch.dif"
按提示操作即可。
遗憾的是我没有上传附件的权限。庆幸的是可以在临时空间下载anyPatch.exe。地址为:http://rapidshare.de/files/38687295/AnyPatch.exe.html
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!