下载完cm后,这一次我也学习了shoooo大侠,立刻google了一下R6002
结果发现这个链接
http://msdn.microsoft.com/zh-cn/library/k1x26e0x(VS.80).aspx
初步跟踪了一下,问题是出在
跟进去发现是在对%e-%g的处理时直接调用了出错处理函数然后直接退出
也就误解成编译器优化没有把相应的代码链接进入可执行文件,于是先提交了一个笨办法,改0x420D81这句指令跳转到空闲空间0x421D00并实现如下代码
思路是在动态库里实现完整_snwprintf然后调用,my_snwprintf只有一条指令
然而,提交后才发现原来对浮点处理的代码其实是编译进了testfloat.exe,那为什么会出错呢?
原来是在程序启动阶段___tmainCRTStartup函数中调用了__cinit函数,在这个函数的第一个判断是校验浮点运算初始化函数指针所处的section是否为可写,如果可写的话就跳过浮点运算初始化函数,因此缺省情况下函数_snwprintf会直接显示出错信息并退出,如果该section,也就是.rdata不可写,代码会调用浮点运算初始化函数,缺省的指向出错函数的指针会被替换成正常处理函数,因此可以正常运算并显示 PI * 2 = 6.283180
可惜之前误解msdn还以为是编译器没有编译进去这部分代码,原来只不过是没调用而已,汗一个
这样一来解决办法就非常简单了,我们只需要改动一位,将.rdata的可写属性去掉,也就是修改文件地址0x22F处的.rdata section的特征符,将该数值从0xC0改成0x40即可
或许有些朋友好奇为什么upx之后就可以正常处理了,也同样是因为.rdata的characteristics的第31位被清零所致