安装:
首先,安装等待很久的问题参考之前发布的这个帖子http://bbs.pediy.com/thread-178928.htm。操作完了,不要解除OD的附加,下面还会用到。
然后,安装程序将文件复制完毕后,会出现无法退出程序,CPU利用率奇高不下的问题。
这时暂停运行,F8让程序单步走。走到类似下面的代码处:
CALL RegDeleteKey还是Value
CMP EDI,ESI ;需要修改这里的EDI为非零值,否则将无限循环 或者直接设置JE后的语句为新的IP
JE ......
POP XX
POP XX
RET
简单说就是安装程序中,安装完成本地文件后,设置安装信息的注册表时RegDeleteKey/Value删除注册表的键或者值失败了会陷入无限循环,需要跳过(win8.1下VB6的安装也会遇到这个问题)。
运行:
安装完成后,默认是无法运行的,网上给的办法是改名MSDEV.EXE。但是改名了就无法加载PYG的VAX破解了。所以觉得不完美,也不知道改名能过的原理。之前调试研究过一次,没研究出来。昨天晚饭前花时间再去研究了一次,终于知道为什么了。
OD调试启动运行MSDEV.EXE,一路F8单步走,会在某个CALL之后VC崩溃。所以在这个CALL处下断点(下次调试中命中该断点时F7步入再F8),取消之前的断点。这样往复,会带你逐层深入到真正的出错的地方。发现是在这里崩溃的:
(好像是在DEVSHL.DLL中)
50030AE7 E8 00020000 call <jmp.&MFC42.#CStringList::Find_2765>
F7进去后发现是在这里崩溃的
(mfc42.dll中)
0018ED20 00278010 |s1 = "devedit"
0018ED24 00278290 \s2 = "devprj"
6D4F7C28 FF15 0CA15A6D call dword ptr [<&msvcrt._mbscmp>]
也就是在调用导入表函数msvcrt.dll的_mbscmp。F7进去后看到进入了一片不像常规函数的区域,而且再一路F8继续运行下去就是未知指令了。这里肯定有问题。OD转到msvcrt._mbscmp的代码处看到是
770316B0 msvcrt._mbscmp 8BFF mov edi, edi
明显刚才CALL进去的不是这里,指令都不一样。
怀疑是mfc42.dll的导入表函数 [<&msvcrt._mbscmp>]未被正确设置。
重新调试,回到MSDEV.EXE的入口点,数据窗口中查看mfc42.dll的导入函数
6E8DA100 >76EB25C0 msvcrt._mbsupr
6E8DA104 >76E4AC50 msvcrt._mbspbrk
6E8DA108 >76E517C0 msvcrt._mbschr
6E8DA10C >00030000 ;导入函数msvcrt._mbscmp的位置
6E8DA110 >76E3C5A0 msvcrt.realloc
6E8DA114 >76E46710 msvcrt.fclose
6E8DA118 >76E42D40 msvcrt.fflush
发现导入表就msvcrt._mbscmp这个位置被设置成了莫明的地址。周围其他都正常,手动将该地址的值恢复成msvcrt._mbscmp的真正地址,F9继续运行,VC真的就跑起来了。
那么是谁这么干的呢。我们继续探索,怀疑是mfc42.dll自己如果检查到是MSDEV.EXE,就改掉自己的msvcrt._mbscmp的值。
mfc42.dll的Dll入口函数处下断,发现他的msvcrt._mbscmp已经被修改了,说明不是自己改的。
那么我们在ntdll的PE加载器上下断,在mfc42.dll被映射到内存后,在他的导入表被填充前对他的导入表 [<&msvcrt._mbscmp>]的位置下写入时中断的硬件断点。继续运行发现,第一次中断时,
0x6D140000
C:\Windows\SysWOW64\mfc42.dll 6D140000 0012F000
mfc42.dll:6D24A10C db 0B0h ;
mfc42.dll:6D24A10D db 16h
mfc42.dll:6D24A10E db 3
mfc42.dll:6D24A10F db 77h ; w
该位置被设置成了正确的值,这个调用来自ntdll内部,接着再继续运行,发现再次命中断点。这次是来自
C:\Windows\SysWOW64\apphelp.dll 71610000 000A0000
的_SepIatPatch函数,顾名思义就是什么导入表补丁的意思。
查看apphelp.dll的文件属性 他是“应用程序兼容性客户端库 ”,
就是他搞的鬼,真相终于水落石出了。
猜测微软在这个库中,应该内部标记了哪些程序是存在兼容性问题的程序,而对存在兼容性问题的程序进行可能的补丁修复。
MSDEV.EXE就在存在兼容性问题的程序之列。但是这里修复的是_mbscmp函数,ANSI本地语言多字节字符串比较函数。
由于某些有意或者无意的原因,该地址没被设置到正确的修复函数上。可能微软后面也发现问题了,但是想反正VC6都支持过期了,所以就懒得管了。
就和NSA工具漏洞一样,微软其实早就知道了这个问题,针对XP的修复补丁可能早就做好了(从后面发布的XP修复补丁的内部文件的签名日期可知该补丁2017年1月份就做好了,而3月份才NSA工具泄露,四月份才WannaCry爆发,阴谋论可能觉得是微软发布的这次病毒爆发(不然为什么还没查出来谁发布的),借机让大家认识到之前系统的不安全,win10的安全,间接推广win10新系统),但就是不到必要时就是不会放出来,对失去支持得系统及软件,都懒得管。
修复:
知道问题所在了,现在我们着手修复一下吧,为了不改变原始文件我们利用DLL劫持技术来完成工作,这里利用version.dll,因为这个文件会被VC6加载。
核心代码就是恢复mfc42.dll的导入表函数[<&msvcrt._mbscmp>]的函数地址为正确值。
详细见附件吧,完毕。
附件1是代码
附件2是成品文件,会优先加载MSDEV.EXE目录下的version.org.dll作为原始version.dll,这样做是为了让YPG的VAX补丁(名字也是version.dll,请先改名为version.org.dll再解压成品文件到VC6的程序目录)也可被顺利加载。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)