首页
社区
课程
招聘
[第一阶段第三题]也秀秀俺的分析过程
发表于: 2008-10-10 13:16 12229

[第一阶段第三题]也秀秀俺的分析过程

2008-10-10 13:16
12229

一个新手的道路!

1.分析过程
A)由于不能通过窗口消息下断,因此只能另辟蹊径。这里我采用的是猜测法,根据从IDA中得到的CDialog的初始化函数OnInitDialog,查找相应的调用者,发现继承对话框的初始化函数地址420EC0,接着就在附近的几个函数地址处下断,点击‘Crash’来到函数420D20(OnCrash),这里正是需要我们详细分析的函数

B)跟着来到地址420D59处,完成对函数_snwprintf(_swprintf_c)的调用
00420D59  |.  DD05 C05D4200     FLD QWORD PTR DS:[425DC0]          ;  3.14159
00420D5F  |.  DD5D F8           FSTP QWORD PTR SS:[EBP-8]
00420D62  |.  DD45 F8           FLD QWORD PTR SS:[EBP-8]
00420D65  |.  DCC0              FADD ST,ST
00420D67  |.  DD5D F8           FSTP QWORD PTR SS:[EBP-8]          ;  6.28318
00420D6A  |.  83EC 08           SUB ESP,8
00420D6D  |.  DD45 F8           FLD QWORD PTR SS:[EBP-8]
00420D70  |.  DD1C24            FSTP QWORD PTR SS:[ESP]            ;  f = 6.28318
00420D73  |.  68 345A4200       PUSH TestFloa.00425A34             ;  "PI * 2 = %f"
00420D78  |.  6A 40             PUSH 40                            ;  0x40
00420D7A  |.  8D95 70FFFFFF     LEA EDX,DWORD PTR SS:[EBP-90]
00420D80  |.  52                PUSH EDX                           ;  buffer address [ebp-90]
00420D81  |.  E8 7CE0FEFF       CALL TestFloa.0040EE02             ;  _snwprintf(buffer address, 0x40, L"PI * 2 = %f", f);
00420D86  |.  83C4 14           ADD ESP,14

C)_snwprintf函数处,首先进行必要的参数检查,然后来到函数413871(_woutput_l),根据字符串格式进行相应的处理,我们这里是地址413E08处的函数调用。
00413E02  |.  FF35 C8A04200     |PUSH DWORD PTR DS:[42A0C8]
00413E08  |.  E8 3FEFFFFF       |CALL TestFloa.00412D4C            ;  __decode_pointer
00413E0D  |.  59                |POP ECX
00413E0E      FFD0              |CALL EAX                          ;  call decodepointer

这里就是异常出现并接着退出的地方,由于调用函数_decode_pointer时,传入的参数是数据区地址42A0C8处的值,通过IDA可以看到该值指向__fptrap函数地址,因此,通过调用函数__decode_pointer后,得到的将是函数__fptrap的地址,显然,接着CALL EAX调用的正是__fptrap函数,而该函数的代码正是进行“floating point support not loaded”的错误处理,因此,最后看到该消息的错误提示框,然后程序退出也就不奇怪啦。

根据该错误出现的解释,是因为程序在编译时在程序中没有发现浮点操作,为了提高效率而没有Load浮点运行库才会导致这个异常,而该程序在地址00420D59到00420D70处明显调用了浮点运算,浮点运算库完全是应该被Load的,然而为什么没有被Load呢,继续往下分析。

D)根据分析发现,初始化浮点运算操作的函数是__cfltcvt_init(00411dc6),该函数将包含几个浮点操作函数指针的数组_cfltcvt_tab(0042A0B0)进行初始化。而异常发生处本应该调用的函数_cfltcvt_l正是其中的第七个函数指针(PF6)。顺藤摸瓜,继续向上摸。
调用函数__cfltcvt_init的是函数__fpmath(00411E26),调用函数__fpmath的是函数__cinit(0040F618),调用函数__cinit的是函数__tmainCRTstartup(0040EA8F)。
以上正是浮点操作函数初始化的逆过程。经过详细逐个函数分析,发现在函数__cinit中,通过函数__IsNonwritableInCurrentImage(00415D90)判断地址0042405C是否不能被写入,如果是不能写入的,就会调用函数__pfmath(00411e26),而从上面的分析可知,该函数正是用来触发浮点函数初始化的。如果是可以写入的,函数__pfmath(00411e26)将不被调用,浮点函数也就不会被初始化。通过调试跟踪发现正是这里出现了问题,才导致了最后的程序异常。问题的根源已经找到,具体的修复请看下面。

/***********************************__cinit***************************************/
0040F618  /$  833D 5C404200 00          CMP DWORD PTR DS:[42405C],0            ;  __cinit
0040F61F  |.  74 1A                     JE SHORT TestFloa.0040F63B
0040F621  |.  68 5C404200               PUSH TestFloa.0042405C
0040F626  |.  E8 65670000               CALL TestFloa.00415D90                 ;  __IsNonwritableInCurrentImage
0040F62B  |.  85C0                      TEST EAX,EAX
0040F62D  |.  59                        POP ECX
0040F62E  |.  74 0B                     JE SHORT TestFloa.0040F63B
0040F630  |.  FF7424 04                 PUSH DWORD PTR SS:[ESP+4]
0040F634  |.  FF15 5C404200             CALL DWORD PTR DS:[42405C]             ;  testfloa.00411e26   __fpmath
0040F63A  |.  59                        POP ECX
0040F63B  |>  E8 AC660000               CALL TestFloa.00415CEC
/***********************************__cinit***************************************/

/***********************************_cfltcvt_tab***************************************/
typedef void (* PFV)(void);
extern PFV _cfltcvt_tab[10];
#define _CFLTCVT_TAB(i)       (_decode_pointer(_cfltcvt_tab[i]))

typedef void (* PF0)(double*, char*, size_t, int, int, int);
#define _cfltcvt(a,b,c,d,e,f) (*((PF0)_CFLTCVT_TAB(0)))(a,b,c,d,e,f)

typedef void (* PF1)(char*);
#define _cropzeros(a)         (*((PF1)_CFLTCVT_TAB(1)))(a)

typedef void (* PF2)(int, char*, char*);
#define _fassign(a,b,c)       (*((PF2)_CFLTCVT_TAB(2)))(a,b,c)

typedef void (* PF3)(char*);
#define _forcdecpt(a)         (*((PF3)_CFLTCVT_TAB(3)))(a)

typedef int (* PF4)(double*);
#define _positive(a)          (*((PF4)_CFLTCVT_TAB(4)))(a)

typedef void (* PF5)(_LONGDOUBLE*, char*, size_t, int, int, int);
#define _cldcvt(a,b,c,d,e,f)  (*((PF5)_CFLTCVT_TAB(5)))(a,b,c,d,e,f)

typedef void (* PF6)(double*, char*, size_t, int, int, int, _locale_t);
#define _cfltcvt_l(a,b,c,d,e,f,g) (*((PF6)_CFLTCVT_TAB(6)))(a,b,c,d,e,f,g)

typedef void (* PF7)(int, char*, char*, _locale_t);
#define _fassign_l(a,b,c,d)       (*((PF7)_CFLTCVT_TAB(7)))(a,b,c,d)

typedef void (* PF8)(char*, _locale_t);
#define _cropzeros_l(a,b)         (*((PF8)_CFLTCVT_TAB(8)))(a,b)

typedef void (* PF9)(char*, _locale_t);
#define _forcdecpt_l(a,b)         (*((PF9)_CFLTCVT_TAB(9)))(a,b)
/***********************************_cfltcvt_tab***************************************/

2. 修复方法

通过上面的分析,发现问题的根源是地址0042405C是可写的。查找其在镜像文件中的偏移位置0002405C,位于.rdata段,而该段的标志是C0000004,即可读取,可写入,包含已初始化数据。将可写入的属性去掉使该段标志变为40000004,程序将能正常运行。至此关于该程序的异常分析以及如何修复完毕。


[培训]科锐逆向工程师培训第53期2025年7月8日开班!

收藏
免费 7
支持
分享
最新回复 (16)
雪    币: 220
活跃值: (55)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
学习了。。。。
2008-10-10 13:37
0
雪    币: 232
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
顶,学习学习。
2008-10-11 00:28
0
雪    币: 107
活跃值: (2222)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
4
OD里楼主说的c函数一个也没提示,IDA全有。再一次领教了IDA的强大,在逆向分析中,不是OD能比的
2008-10-12 20:40
0
雪    币: 233
活跃值: (15)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
两个同时打开,利用各自的优点
2008-10-13 14:20
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
好~~glery,学习学习啊~
2008-10-15 17:23
0
雪    币: 156
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
学习,努力学习,顶起来
2008-10-24 17:00
0
雪    币: 233
活跃值: (15)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
8
十分感谢捧场,俺会继续努力的,哈哈
2008-10-26 17:01
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
呵呵,glery太谦虚了,我是真的想要学好,也想研究好。
奈何吾是新人,刚刚入门,还得向您多多请教。希望能够追到您的步伐。
2008-10-28 13:22
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
呵呵,我是习惯一边 开IDA 一边开 OD,这样 比较有感觉~~
2008-10-28 16:43
0
雪    币: 222
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
11
学习学习,好久没来了
2008-10-28 21:03
0
雪    币: 190
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
恩,很有思想阿,IDA我现在刚接触,能否有请教高手一些问题,QQ316992738
2008-11-5 21:52
0
雪    币: 233
活跃值: (15)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
13
过奖了,IDA用的也不是很好。但,仍然很乐意为你解答本人晓得的问题。
请站内联系
2008-11-6 09:39
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
glery,很负责的人哦。乐意为我这个初学者解答问题。谢谢先!~
2008-11-13 09:51
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
2008-12-30 14:13
0
雪    币: 197
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
顶~~~
2008-12-31 07:17
0
雪    币: 318
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
好啊,破解关键是思路的问题!!
2008-12-31 21:37
0
游客
登录 | 注册 方可回帖
返回