首页
社区
课程
招聘
第三题分析报告
发表于: 2008-10-9 12:46 2808

第三题分析报告

2008-10-9 12:46
2808
第三题分析报告

运行程序,报错:
Runtime Error!R6002
- floating point support not loaded

然后用OD载入,不忽略所有异常,直接运行,发现没有捕捉到异常,说明这个MsgBox不是由于浮点出错导致的。

对MessageBoxA下断,返回后找到代码处理部分:

00420D59  fld     qword ptr [425DC0]
00420D5F  fstp    qword ptr [ebp-8]
00420D62  fld     qword ptr [ebp-8]
00420D65  fadd    st, st
00420D67  fstp    qword ptr [ebp-8]
00420D6A  sub     esp, 8
00420D6D  fld     qword ptr [ebp-8]
00420D70  fstp    qword ptr [esp]
00420D73  push    00425A34                    ;  pi * 2 = %f
00420D78  push    40
00420D7A  lea     edx, dword ptr [ebp-90]
00420D80  push    edx
00420D81  call    0040EE02
00420D86  add     esp, 14
00420D89  push    40
00420D8B  push    00425A4C                    ;  testfloag
00420D90  lea     eax, dword ptr [ebp-90]
00420D96  push    eax
00420D97  mov     ecx, dword ptr [ebp-94]
00420D9D  call    00405C75

在420D81处会弹出错误窗口,跟进:
……
0040EE7E  push    edi
0040EE7F  lea     eax, dword ptr [ebp+14]
0040EE82  push    eax
0040EE83  push    ebx
0040EE84  push    dword ptr [ebp+10]
0040EE87  lea     eax, dword ptr [ebp-20]
0040EE8A  push    eax
0040EE8B  call    00413871

继续跟进40EE8B处的CALL,发现是一个格式化字符串的代码,当扫描到%f时来到:

00413DEC  |push    eax
00413DED  |push    dword ptr [ebp-6C]
00413DF0  |movsx   eax, dl
00413DF3  |push    dword ptr [ebp-18]
00413DF6  |mov     dword ptr [ebp-28], ebx
00413DF9  |push    eax
00413DFA  |push    dword ptr [ebp-20]
00413DFD  |lea     eax, dword ptr [ebp-78]
00413E00  |push    esi
00413E01  |push    eax
00413E02  |push    dword ptr [42A0C8]
00413E08  |call    00412D4C                      ;  Call Float OEP DecodePointer
00413E0D  |pop     ecx
00413E0E  |call    eax                           ;  TestFloa.0041AE1F

这里先在00413E08处的CALL里用DecodePointer函数对[42A0C8]的值解码出一个地址,然后在413E0E处CALL这个地址。

在MSDN里搜索DecodePointer,解释是:每个进程都会产生一个随机的dword值,用户可以先用这个随机值用EncodePointer对数据进行加密,在需要时再用DecodePointer解密。

在OD里跟进这个API想了解加密方式,无解。

在google里搜索EncodePointer与DecodePointer,有解释为:EncodePointer对待加密的数据仅进行XOR,调用DecodePointer时再次对数据进行XOR还原。

在OD载入时,发现[0042A0C8]=0041AE1F,刚好与DecodePointer解码出来的值相等,因此只需要修改[0042A0C8]初始时的值为正确的地址,即可使程序正常运行。

自己做一个C控制台程序mytestFloat.cpp,写入代码:

// mytestFloat.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
        float f=3.14159;
        printf("PI = %f",f);
        return 0;
}

生成release程序后用OD调试:

00401000  /$  DD05 F0204000    fld     qword ptr [4020F0]
00401006  |.  83EC 08          sub     esp, 8                      ; /<%f>
00401009  |.  DD1C24           fstp    qword ptr [esp]             ; |
0040100C  |.  68 E4204000      push    004020E4                    ; |format = "PI = %f"
00401011  |.  FF15 9C204000    call    dword ptr [<&MSVCR80.printf>; \printf
00401017  |.  83C4 0C          add     esp, 0C
0040101A  |.  33C0             xor     eax, eax
0040101C  \.  C3               retn

跟进00401011的CALL:

781422F3 >/$  6A 0C            push    0C
781422F5  |.  68 38501B78      push    781B5038
781422FA  |.  E8 7967FFFF      call    78138A78
781422FF  |.  33C0             xor     eax, eax
78142301  |.  33F6             xor     esi, esi
78142303  |.  3975 08          cmp     dword ptr [ebp+8], esi
78142306  |.  0F95C0           setne   al
78142309  |.  3BC6             cmp     eax, esi
7814230B  |.  75 1D            jnz     short 7814232A
7814230D  |.  E8 A01FFFFF      call    _errno
78142312  |.  C700 16000000    mov     dword ptr [eax], 16
78142318  |.  56               push    esi
78142319  |.  56               push    esi
7814231A  |.  56               push    esi
7814231B  |.  56               push    esi
7814231C  |.  56               push    esi
7814231D  |.  E8 3E65FFFF      call    _invalid_parameter
78142322  |.  83C4 14          add     esp, 14
78142325  |.  83C8 FF          or      eax, FFFFFFFF
78142328  |.  EB 5F            jmp     short 78142389
7814232A  |>  E8 05FDFEFF      call    __p__iob
7814232F  |.  6A 20            push    20
78142331  |.  5B               pop     ebx
78142332  |.  03C3             add     eax, ebx
78142334  |.  50               push    eax
78142335  |.  6A 01            push    1
78142337  |.  E8 67BFFFFF      call    7813E2A3
7814233C  |.  59               pop     ecx
7814233D  |.  59               pop     ecx
7814233E  |.  8975 FC          mov     dword ptr [ebp-4], esi
78142341  |.  E8 EEFCFEFF      call    __p__iob
78142346  |.  03C3             add     eax, ebx
78142348  |.  50               push    eax
78142349  |.  E8 2FEEFFFF      call    7814117D
7814234E  |.  59               pop     ecx
7814234F  |.  8BF8             mov     edi, eax
78142351  |.  8D45 0C          lea     eax, dword ptr [ebp+C]
78142354  |.  50               push    eax
78142355  |.  56               push    esi
78142356  |.  FF75 08          push    dword ptr [ebp+8]
78142359  |.  E8 D6FCFEFF      call    __p__iob
7814235E  |.  03C3             add     eax, ebx
78142360  |.  50               push    eax
78142361  |.  E8 8DF0FFFF      call    781413F3

再次跟进78142361处的call    781413F3,会发现里面的代码与目标程序testFloat.exe中的格式化字符串的代码00413871处几乎完全相同!

在这里做大胆猜测:testFloat.exe把printf格式化字符串的代码全部都编译到自己的程序体里了。对比发现,目标程序对printf代码进行了修改,用DecodePointer对浮点处理过程的入口进行了处理。

测试程序中对浮点处理的调用为:

781419F7  |push    eax                        ; /Arg7
781419F8  |push    dword ptr [ebp-78]         ; |Arg6
781419FB  |movsx   eax, dl                    ; |
781419FE  |push    dword ptr [ebp-20]         ; |Arg5
78141A01  |mov     dword ptr [ebp-2C], edi    ; |
78141A04  |push    eax                        ; |Arg4
78141A05  |push    dword ptr [ebp-68]         ; |Arg3
78141A08  |lea     eax, dword ptr [ebp-80]    ; |
78141A0B  |push    ebx                        ; |Arg2
78141A0C  |push    eax                        ; |Arg1
78141A0D  |call    78149BC9                   ; \MSVCR80.78149BC9

进入78141A0D处的CALL:

78149BC9  /$  55            push    ebp
78149BCA  |.  8BEC          mov     ebp, esp
78149BCC  |.  8B45 14       mov     eax, dword ptr [ebp+14]
78149BCF  |.  83F8 65       cmp     eax, 65                     ;  Switch (cases 41..66)
78149BD2  |.  74 5F         je      short 78149C33
78149BD4  |.  83F8 45       cmp     eax, 45
78149BD7  |.  74 5A         je      short 78149C33
78149BD9  |.  83F8 66       cmp     eax, 66
78149BDC  |.  75 19         jnz     short 78149BF7
78149BDE  |.  FF75 20       push    dword ptr [ebp+20]          ;  Case 66 ('f') of switch 78149BCF
78149BE1  |.  FF75 18       push    dword ptr [ebp+18]
78149BE4  |.  FF75 10       push    dword ptr [ebp+10]
78149BE7  |.  FF75 0C       push    dword ptr [ebp+C]
78149BEA  |.  FF75 08       push    dword ptr [ebp+8]
78149BED  |.  E8 0BFEFFFF   call    781499FD
78149BF2  |.  83C4 14       add     esp, 14
78149BF5  |.  5D            pop     ebp
78149BF6  |.  C3            retn

观察这一段代码的二进制值,发现使用的都是相对地址,在testFloat.exe中搜索这一部分二进制代码558BEC8B451483F865745F83F845745A83F8667519,来到这里:

00418D69  /$  55            push    ebp                         ;  format string for float
00418D6A  |.  8BEC          mov     ebp, esp                    ;  (initial cpu selection)
00418D6C  |.  8B45 14       mov     eax, dword ptr [ebp+14]
00418D6F  |.  83F8 65       cmp     eax, 65                     ;  Switch (cases 41..66)
00418D72  |.  74 5F         je      short 00418DD3
00418D74  |.  83F8 45       cmp     eax, 45
00418D77  |.  74 5A         je      short 00418DD3
00418D79  |.  83F8 66       cmp     eax, 66
00418D7C  |.  75 19         jnz     short 00418D97
00418D7E  |.  FF75 20       push    dword ptr [ebp+20]          ;  Case 66 ('f') of switch 00418D6F
00418D81  |.  FF75 18       push    dword ptr [ebp+18]
00418D84  |.  FF75 10       push    dword ptr [ebp+10]
00418D87  |.  FF75 0C       push    dword ptr [ebp+C]
00418D8A  |.  FF75 08       push    dword ptr [ebp+8]
00418D8D  |.  E8 26FEFFFF   call    00418BB8
00418D92  |.  83C4 14       add     esp, 14
00418D95  |.  5D            pop     ebp
00418D96  |.  C3            retn

能找到浮点处理过程的代码入口00418D69,说明编译程序时把这段代码已经编译进去了,但是DecodePointer是对固定[0042A0C8]处的数据进行解码,而[0042A0C8]=0041AE1F存的不是浮点处理代码入口,而是报“floating point support not loaded”错误的代码入口。

现在就已经找到解决办法了:只需要修改程序初始时[0042A0C8]的值为浮点处理过程的入口00418D69,就可以解决这个问题了。

0042A0C8的物理偏移为2A0C8,用16进制工具修改2A0C8处的值为:

2A0C8:1F AE 41 00==>69 8D 41 00

保存后运行,点击Crach按钮,弹出“PI * 2 = 6.283180”对话框,成功!

为避免暗桩,在16进制工具中搜索“1F AE 41 00”,发现从2A0B0到2A0D8全部都是这个值,全部改成“69 8D 41 00”,再次测试,成功!


由于条件有限,只能用手机上网,无法提交附件,只能说一下文件修改方法了:
修改testFloat.exe二进制代码,从2A0B0到2A0D8全部都改成“69 8D 41 00”。


PS:最后弹出的MsgBox中的标题写成“testFloag”了。。。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 264
活跃值: (30)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
2
请再仔细考虑!!!
2008-10-14 15:25
0
游客
登录 | 注册 方可回帖
返回
//