今天在搜索怎样解决脱壳后文件跨平台运行问题时,发现汉化新世纪有这样一篇文章,说ImportREC自动修复IAT时会有一些函数地址错误,个人感觉有些道理,请各位探讨一下。
原文地址:http://www.hanzify.org/teach/index.php?Go=Show::597-1153241398
本人转载的地址:
http://hi.baidu.com/tjt999/blog/item/dceff7dda7f89e5895ee3720.html事情原由是我一次请 曾半仙 帮我测试一个软件脱壳后汉化的非标字体情况。
后来 半仙 立即提示我的那个脱壳后的程序无法运行,提到了 ImportREC 自动修复导入表时的错误问题,而后来 ImportREC 作者 MackT/uCF 出的修正版(经 Cao_Cong 兄提醒,是 MaRKuS_TH-DJM 修正了这个版本而非作者)也只是修复了一个导入表函数,我这个菜鸟在 半仙 的帮助提示下,用 Ollydbg 查看 IAT 中的函数与 ImportREC 实际保存的 导入表目录树 对比了一下,发现真如 半仙 所说的:ImportREC 的自动修复大约有 20 个左右的函数错误。而这些可能引起汉化后跨平台等问题。
这个 ImportREC 的修正版目前看似乎修正了一个函数,将 RestoreLastError 替换为 SetLastError,因为在 XP 下脱壳后用 ImportREC 自动修复就会使用 RestoreLastError,而 xp 以前的操作系统似乎没有这个函数,换为 SetLastError 后可以跨平台(9x)了。
如我上面所说:修正版的 ImportREC 自动修复时,似乎仍然有错误约 20 个左右,而 Ollydbg 查看时 IAT 中的函数是软件原程序真正使用到的函数,应该保持与软件用到的原始函数相同就没问题了。(当然,有些猛壳加密/破坏 IAT,需要高深技术用 Ollydbg 来还原/修复 IAT,我这个菜鸟也不懂,暂时不去说这些目前非我能及的内容)这样我们汉化脱壳后的文件应该可以避免跨平台问题。
废话结束,谈点我这菜鸟根据咱们 半仙 提示后的对比情况吧:
找一个 Win98 下的记事本程序 Notepad.exe,我用 Aspack 2.12r 加壳压缩(当然有自动脱壳工具,我只是举个例子),然后用 Ollydbg 手脱时到达 OEP,先用 LordPE 来完全转储(Dump Full)下进程保存为 dumped.exe,然后看下图:
(这里按照“看雪学院”老大 kanxue 的〈脱壳基础知识入门〉-9 “手动确定 IAT 的地址与大小”方法来查看 IAT 的起始处和结尾处,以及大小)看到那个 kernel32.GetCommandLineA 函数调用,在命令栏输入 d 4063e4 然后回车,内存区就会转到这个函数调用地址,接着在内存区地址(Address)右键鼠标,在弹出菜单中选择 Long - Address,内存区就会以 Long 长型显示方式表达 IAT 函数列表,看图:
变成 Long 长型显示列表函数:
各 DLL 之间以四个 00 间隔,然后拉动滚动条向上翻,一直到没有出现 DLL 函数的内容,往下翻,同样直到没有 DLL 函数内容,从第一个 DLL 到最后一个 DLL 函数内容,把这之间的内容全选,复制保存为 org.txt 中以待一会儿后的对比吧。
再用 ImportREC 填入 OEP,自动搜索 IAT 并获取导入表,但暂时不要修复转储(Fix Dump)的 dumped.exe 文件。
ImportREC 中没有显示 无效 的指针,都是 yes,那么现在按 Save Tree(保存列表树) 为 fix.txt 吧。按图中1/2/3 的步骤保存导入表列表树文件。
对比 org.txt 和 fix.txt,发现以下几处不同:
org.txt fix.txt
kernel32._lwrite kernel32._hwrite
kernel32.lstrcmpiA kernel32.lstrcmpi
kernel32.lstrlenA kernel32.lstrlen
kernel32.lstrcpynA kernel32.lstrcpyn
kernel32.lstrcmpA kernel32.lstrcmp
kernel32.lstrcatA kernel32.lstrcat
ntdll.RtlGetLastWin32Error kernel32.GetLastError <--这个正确,不用修改
kernel32.lstrcpyA kernel32.lstrcpy
kernel32._lread kernel32._hread
shell32.DragQueryFileA shell32.DragQueryFile
USER32.RegisterWindowMessageA USER32.RegisterClipboardFormatA
USER32.IsDialogMessageA USER32.IsDialogMessage
USER32.TranslateAcceleratorA USER32.TranslateAccelerator
这个记事本脱壳后用 ImportREC 的自动修复出现了 13 处错误,其中上面指出的一个是 ImportREC 自动重定位 GetLastError 了是正确的,所以是 12 处错误。
我们汉化时,秉承软件原程序的原则,所以将 fix.txt 中的错误的地方按 org.txt 修复保存,存为 fix_2.txt 吧,然后用 ImportREC 的 Load Tree(加载列表树)载入这个正确的 导入表 列单。
ImportREC 提示加载成功后,按 Fix Dump 修复刚才保存的 dumped.exe,生成 dumped_.exe 才是导入表与原程序相同的正确文件。如图 1/2 步骤。
记事本是个小程序,使用到的 DLL 函数也不多,所以上面只有 12 处错误,如果一些大一点的程序手脱后,用 ImportREC 自动修复时,会出现大约 20 个左右错误,我最多一个发现了 23 个,除了上面列出的几个,我再把我遇到的 ImportREC 自动修复通常有错误的几个列出来,如下(C 程序):
错误 正确
//KERNEL32.dll:
lstrlen > lstrlenA
lstrcpy > lstrcpyA
lstrcat > lstrcatA
lstrcmp > lstrcmpA
lstrcmpi > lstrcmpiA
lstrcpyn > lstrcpynA
RestoreLastError > SetLastError <--- 这个 ImportREC 修正版已解决这个问题。
LockResource > SetHandleCount
GetEnvironmentStrings > GetEnvironmentStringsA
//user32.dll:
DestroyCursor > DestroyIcon
***** RegisterClipboardFormatW > RegisterWindowMessageW *****(不是经常出现)
RegisterClipboardFormatA > RegisterWindowMessageA
IsDialogMessage > IsDialogMessageA
TranslateAccelerator > TranslateAcceleratorA
//shell32.dll:
SHGetFileInfo > SHGetFileInfoA
ShellExecuteEx > ShellExecuteExA
SHBrowseForFolder > SHBrowseForFolderA
SHGetPathFromIDList > SHGetPathFromIDListA
DragQueryFile > DragQueryFileA
//comctl32.dll:
ImageList_LoadImage > ImageList_LoadImageA
PropertySheet > PropertySheetA
CreatePropertySheetPage > CreatePropertySheetPageA
以上是一个脱壳菜鸟在汉化时遇到导入表问题后请教 半仙 及看了脱壳界的一些文章的体会,希望汉化人在汉化脱壳后的软件时,通过上述几个函数快速手动修复,其他我未发现的错误,大家也可以以后通过 ollydbg 来对比修正,或发给大家共享,也在此感谢俺们 半仙 :-) 和这些脱壳界高手的文章。
希望这几个通常 ImportREC 自动修复错误的函数能对大家以后脱壳汉化时碰到导入表问题有所帮助(IAT 被加密/破坏导致导入表函数错误等猛壳引起的问题我小菜暂时不会搞,大家向脱壳牛人请教吧),以防脱壳后汉化经常引起的跨平台问题。
以上如有什么错误的地方,或不足,请各位指正或补充,谢谢。
附上 Win98 下的 记事本程序 Notepad.exe,并加上 Aspack 2.12r 的壳,大家有兴趣可以测试一下。
附件:NOTEPAD_98_aspack.rar
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课