首先说怎么找那个出错的地方
出错函数在_snwprintf()里面,用IDA看一下button的代码,然后下断点,跟一下就知道了
不多说了
下面是为什么会出错:
首先,自己写一个一摸一样的程序,见附件,然后编译,发现没有任何问题,OK,调自己的程序,和题目对比,发现在
_decode_pointer这个地方出错
正确的解出是下面函数
00413F51 |. E8 A5EEFFFF |call _decode_pointer
00413F56 |. 59 |pop ecx ; testfloa._cfltcvt_l
00413F57 |. FFD0 |call eax
而题目解不出,说明没有调用过_encode_pointer这个过程!
OK,重新载入自己的程序,对_encode_pointer下断点,发现testfloa._cfltcvt_l的时候返回看地方
00415E3C testfloa._initp_misc_cfltcvt_tab /$ 56 push esi
00415E3D |. 57 push edi
00415E3E |. 33FF xor edi, edi
00415E40 |> 8DB7 B0B04200 /lea esi, dword ptr [edi+_cfltcvt_tab]
00415E46 |. FF36 |push dword ptr [esi]
00415E48 |. E8 37CFFFFF |call _encode_pointer
00415E4D |. 83C7 04 |add edi, 4 ; 返回这里
00415E50 |. 83FF 28 |cmp edi, 28
00415E53 |. 59 |pop ecx
00415E54 |. 8906 |mov dword ptr [esi], eax
00415E56 |.^ 72 E8 \jb short 00415E40
00415E58 |. 5F pop edi
00415E59 |. 5E pop esi
00415E5A \. C3 retn
再返回
0040F6D8 testfloa._cinit /$ 833D 44404200>cmp dword ptr [_FPinit], 0
0040F6DF |. 74 1A je short 0040F6FB
0040F6E1 |. 68 44404200 push offset _FPinit
0040F6E6 |. E8 F5670000 call _IsNonwritableInCurrentImage
0040F6EB |. 85C0 test eax, eax
0040F6ED |. 59 pop ecx
0040F6EE |. 74 0B je short 0040F6FB
0040F6F0 |. FF7424 04 push dword ptr [esp+4]
0040F6F4 |. FF15 44404200 call dword ptr [_FPinit] ; testfloa._fpmath
0040F6FA |. 59 pop ecx
0040F6FB |> E8 3C670000 call _initp_misc_cfltcvt_tab
0040F700 |. 68 90244200 push offset __xi_z ; 返回这里
然后开OD,载入题目有问题的程序,到相同位置比较一下,发现是一个地方验证没通过跳走了,没初始化
0040F6D8 testfloa._cinit /$ 833D 44404200>cmp dword ptr [_FPinit], 0
0040F6DF |. 74 1A je short 0040F6FB
0040F6E1 |. 68 44404200 push offset _FPinit
0040F6E6 |. E8 F5670000 call _IsNonwritableInCurrentImage
0040F6EB |. 85C0 test eax, eax
0040F6ED |. 59 pop ecx
0040F6EE |. 74 0B je short 0040F6FB ; 这里跳走了
0040F6F0 |. FF7424 04 push dword ptr [esp+4]
0040F6F4 |. FF15 44404200 call dword ptr [_FPinit] ; testfloa._fpmath
0040F6FA |. 59 pop ecx
0040F6FB |> E8 3C670000 call _initp_misc_cfltcvt_tab
问题就在上面一个call里面
OK,重新来,进call,发现在找到.rdata区段后验证这个区段是否可写
00415F33 . 50 push eax
00415F34 . 68 00004000 push 00400000
00415F39 . E8 52FFFFFF call _FindPESection
00415F3E . 83C4 08 add esp, 8 ; 返回.rdata区段
00415F41 . 85C0 test eax, eax
00415F43 . 74 3B je short 00415F80
00415F45 . 8B40 24 mov eax, dword ptr [eax+24] ; 区段属性
00415F48 . C1E8 1F shr eax, 1F
00415F4B . F7D0 not eax ; 这里判断区段是否可写:含有0x80000000属性
00415F4D . 83E0 01 and eax, 1 ; 不含有就是1,即不可写
OK,那么看一下有问题的exe,发现.rdata属性是 0xC0000040,可写,改成0x40000040,保存,运行正常
最后,我列举几个原因,我理解中,评委要的根本原因应该是
.rdata区段属性可写
不知道对不对,如果不对,我再加几个
_snwprintf函数出错
浮点支持库未加载
解决方案:
.rdata改成不可写即可
好了,详细文档,根本原因,修复方法都有了
不知道评委还有什么问题
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!