支付宝COM组件浅析

/**************************************
/* 作者:半斤八兩
/* 博客:http://cnblogs.com/bjblcracked
/* 日期:2014-01-08  12:01
/**************************************

只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!

 

工具: ie 6.0  od1.0 支付宝

环境:xp sp3  

 

  Ddv群里面有个朋友问我怎样给淘宝的密码框发送诸如wm_settext之类的消息心想现在也没工作了,反正闲着也是闲着,就看看.

首先直接打开www.支付宝.com 可以看到,密码框处会提示 请先安装控件然后浏览器上方会显示 需要下载的文件

 

 

 

 

我们只要点击下载文件然后安装,安装后,直接刷新或者重新打开浏览器即可.

印象中,安装控件有的时候下载是exe文件,有的时候是直接下载com组件(exe)

 

安装好了之后,我们就可以正常的登录了.我们来写一个发消息的,看看是否如那位朋友所说.

 

1 Private Sub Command1_Click()
2 
3     SendMessage &H10B90, WM_SETTEXT, 0, "bjbl"
4 
5 End Sub

 

点了按钮之后果真没有反映.

我们首先要确定消息是否有到达.

可以打开spy来看看.

 

 

 

 

通过spy回显,我们可以知道消息是已经到达了.

但是 fSucceeded:False 的提示.我们现在知道消息是到达的.

只是支付宝处理(过滤掉).

那么我们就来看看支付宝做了哪些”手脚”.

我们大家都知道支付宝是b/s框架的.(好像也有c/s,本文只讲b/s).

我们来打开一个browser 然后看一下他用了哪些模块.

 

这里browser我用的ie 6.0  模块查看工具用的 xuetr(它支持直接显示非系统模块)

 

我们可以直观的看出目录为 3.6.0.0 的模块是可疑的.

既然是b/s那这些模块肯定就是com程序.

下面我们直接用od 加载 ie . 看看它的导出函数.

我们随便找个aliedit.dll 模块看看.

 

 

通过那四个 DLLxxxxx 的导出函数名,我们就能基本判定这个是com.

Com的程序怎么分析看雪有一篇贴子有详细的介绍如何分析.

 

链接:跟踪调试COM组件的接口

 

文中的方法大致就是对oleaut32.dispcallfunc 下断点.然后com里面调用了哪些函数就都会断下来.

我自己写了一个com程序,用了这个方法试了一下,并没有断下来 :(

而支付宝断是会断下来,但并不是响应我们想要他断下来的消息.当我们输入密码的时候.它并不会断下来所以这个贴子的方法,对于我们来说,是没有用的 :(

 

这里给出另一种可用的方法.

首先go到 user32.getwindowthreadprocessid 这个函数下.

 

 1 77D18A80 user32.> $  8BFF          mov edi,edi
 2 77D18A82          .  55            push ebp
 3 77D18A83          .  8BEC          mov ebp,esp
 4 77D18A85          .  56            push esi
 5 77D18A86          .  FF75 08       push dword ptr ss:[ebp+8]
 6 77D18A89          .  E8 38000000   call user32.77D18AC6
 7 77D18A8E          .  8BF0          mov esi,eax
 8 77D18A90          .  85F6          test esi,esi
 9 77D18A92          .  74 28         je short user32.77D18ABC
10 77D18A94          .  E8 BCFBFFFF   call user32.77D18655
11 77D18A99          .  3BF0          cmp esi,eax
12 77D18A9B          .^ 0F85 49FCFFFF jnz user32.77D186EA
13 77D18AA1          .  8B4D 0C       mov ecx,dword ptr ss:[ebp+C]
14 77D18AA4          .  85C9          test ecx,ecx
15 77D18AA6          .  74 0B         je short user32.77D18AB3
16 77D18AA8          .  64:A1 1800000>mov eax,dword ptr fs:[18]
17 77D18AAE          .  8B40 20       mov eax,dword ptr ds:[eax+20]
18 77D18AB1          .  8901          mov dword ptr ds:[ecx],eax
19 77D18AB3          >  64:A1 1800000>mov eax,dword ptr fs:[18]
20 77D18AB9          .  8B40 24       mov eax,dword ptr ds:[eax+24]
21 77D18ABC          >  5E            pop esi
22 77D18ABD          .  5D            pop ebp
23 77D18ABE          .  C2 0800       retn 8

 

其中

1 77D18A9B          .^\0F85 49FCFFFF jnz user32.77D186EA

这里就是关键.

我们在go到 77D186EA 

 

 1 77D186EA          > /8B75 0C       mov esi,dword ptr ss:[ebp+C]
 2 77D186ED          . |85F6          test esi,esi
 3 77D186EF          . |74 0C         je short user32.77D186FD
 4 77D186F1          . |6A 00         push 0
 5 77D186F3          . |FF75 08       push dword ptr ss:[ebp+8]
 6 77D186F6          . |E8 E0FFFFFF   call user32.77D186DB
 7 77D186FB          . |8906          mov dword ptr ds:[esi],eax
 8 77D186FD          > |6A 01         push 1
 9 77D186FF          . |FF75 08       push dword ptr ss:[ebp+8]
10 77D18702          . |E8 D4FFFFFF   call user32.77D186DB
11 77D18707          . |E9 B0030000   jmp user32.77D18ABC
12 77D1870C          $ |55            push ebp
13 77D1870D          . |8BEC          mov ebp,esp
14 77D1870F          . |56            push esi
15 77D18710          . |57            push edi
16 77D18711          . |53            push ebx
17 77D18712          . |68 CDABBADC   push DCBAABCD
18 77D18717          . |56            push esi
19 77D18718          . |FF75 18       push dword ptr ss:[ebp+18]
20 77D1871B          . |FF75 14       push dword ptr ss:[ebp+14]
21 77D1871E          . |FF75 10       push dword ptr ss:[ebp+10]
22 77D18721          . |FF75 0C       push dword ptr ss:[ebp+C]
23 77D18724          . |64:A1 1800000>mov eax,dword ptr fs:[18]
24 77D1872A          . |8088 B40F0000>or byte ptr ds:[eax+FB4],1
25 77D18731          . |FF55 08       call near dword ptr ss:[ebp+8]
26 77D18734          . |64:8B0D 18000>mov ecx,dword ptr fs:[18]
27 77D1873B          . |80A1 B40F0000>and byte ptr ds:[ecx+FB4],0
28 77D18742          . |817C24 04 CDA>cmp dword ptr ss:[esp+4],DCBAABCD
29 77D1874A          . |0F85 607C0200 jnz user32.77D403B0
30 77D18750          > |83C4 08       add esp,8
31 77D18753          . |5B            pop ebx
32 77D18754          . |5F            pop edi
33 77D18755          . |5E            pop esi
34 77D18756          . |5D            pop ebp
35 77D18757          . |C2 1400       retn 14

 

其中下面这句就是com的毕竟桥梁.我们在这里下个f2断点即可.

1 77D18731          . |FF55 08       call near dword ptr ss:[ebp+8]

我们还可以用另外一个方法.直接搜索这个数值: 0xDCBAABCD. 

 

1 References in user32:.text to constant DCBAABCD
2 Address    Disassembly  
3 77D186F3   push dword ptr ss:[ebp+8]
4 77D18712   push DCBAABCD
5 77D18742   cmp dword ptr ss:[esp+4],DCBAABCD
6 77D403B0   cmp dword ptr ss:[esp],DCBAABCD

 

会有上面四个结果双击 cmp dword ptr ss:[esp+4],DCBAABCD 这一句进去.

这样就会看到和上面一个方法一样的结果了.

我们在刚刚 77D18731  com必经桥梁下好断点后.现在就可以去输入密码.

我们会发现还没有等我们输入密码,od就已经断下来了.

断下来我们可以看信息窗口显示.

Stack ss:[0013EA90]=06740FB0

我们go到 06740FB0 .

 

 

从图中我们可以看出,当前是主线程.

而在06740FB8 处 可以看到,将要跳向flash32 这个com.

那么我们就可以认为这个是和我们无关的,我们直接f9.

又断下来了,我们接着看信息窗口.

Stack ss:[0013E464]=75F4348B (BROWSEUI.75F4348B)

这下,我们直接从信息窗口中可以看出是 browseui 这个模块.

我们一直f9 会发现一直中断在这几个无关的模块下.

那么我们可以用条件断点过滤掉.

我们首先看一下我们判断的那几个模块的地址.

 

1 Executable modules
2 Base       Size        Entry       Name
3 07BF0000   00098000   07C852D0   Alidcp.dll
4 07A30000   000BC000   07AE90E0   aliedit.dll
5 07070000   0001D000   0707820C   itrusenroll.dll
6 10000000   000C5000   100C2640   npAliSecCtrl.dll
7 070A0000   00021000   070B19AB   pta.dll
8 00400000   00019000   00402451   IEXPLORE.EXE

 

知道地址后,我们可以对着必经桥梁按下shift+f2 写入下面的条件断点.

 

因为这几个模块地址的跨度比较大,为了省时间就不写复杂的条件语句了.

我们就一个一个的试过去.

 

 1 aliedit.dll
 2 [ebp+8]>=7a30000&[ebp+8]<=7AEC000
 3 
 4 Alidcp.dll
 5 [ebp+8]>=7bf0000&[ebp+8]<=7C88000
 6 
 7 itrusenroll.dll
 8 [ebp+8]>=7070000&[ebp+8]<=708D000
 9 
10 npAliSecCtrl.dll
11 [ebp+8]>=10000000&[ebp+8]<=100C5000
12 
13 pta.dll
14 [ebp+8]>=70A0000&[ebp+8]<=70C1000
15 
16 IEXPLORE.EXE
17 [ebp+8]>=400000&[ebp+8]<=419000

 

全部试下来,发现都没有中断.这是哪里的问题?

大家还记得刚刚中断的时候,是在主线程里面吧?所以我们这样写是不行的.

应该像下面这样.

 

[ebp+8]!=06740FB0&[ebp+8]<=7a30000

断下来了,看信息窗口.

Stack ss:[0013E77C]=06660F90

GO过去看反汇编.

 

1 06660F90           C74424 04 104BE>mov dword ptr ss:[esp+4],2E44B10
2 06660F98         - E9 D8529A09     jmp npAliSec.10006275

 

可以看到这时才是jmp 到 支付宝的模块里面了.

用此方法可以方便的定位到支付宝的com组件处理流程里面.

此方法我也测试过我写的com demo,也是可以轻松定位到的 :)

剩下的我们就是直接到 10006275分析即可.

之前的条件断点取消掉,在 10006275处下断点. F9运行.

 

 1 10006275         /.  55            push ebp
 2 10006276         |.  8BEC          mov ebp,esp
 3 10006278         |.  83EC 24       sub esp,24
 4 1000627B         |.  56            push esi
 5 1000627C         |.  8B75 08       mov esi,[arg.1]
 6 1000627F         |.  85F6          test esi,esi
 7 10006281         |.  0F84 C1000000 je npAliSec.10006348
 8 10006287         |.  8B06          mov eax,dword ptr ds:[esi]
 9 10006289         |.  85C0          test eax,eax
10 1000628B         |.  0F84 B7000000 je npAliSec.10006348
11 10006291         |.  837E 1C 00    cmp dword ptr ds:[esi+1C],0
12 10006295         |.  0F84 AD000000 je npAliSec.10006348
13 1000629B         |.  57            push edi
14 1000629C         |.  6A 01         push 1
15 1000629E         |.  FF75 14       push [arg.4]
16 100062A1         |.  8D4D DC       lea ecx,[local.9]
17 100062A4         |.  FF75 10       push [arg.3]
18 100062A7         |.  FF75 0C       push [arg.2]
19 100062AA         |.  50            push eax
20 100062AB         |.  E8 B8F4FFFF   call npAliSec.10005768
21 100062B0         |.  FF76 20       push dword ptr ds:[esi+20]
22 100062B3         |.  8B7E 24       mov edi,dword ptr ds:[esi+24]
23 100062B6         |.  8B4E 1C       mov ecx,dword ptr ds:[esi+1C]
24 100062B9         |.  8D55 08       lea edx,[arg.1]
25 100062BC         |.  52            push edx
26 100062BD         |.  FF75 14       push [arg.4]
27 100062C0         |.  8D45 DC       lea eax,[local.9]
28 100062C3         |.  FF75 10       push [arg.3]
29 100062C6         |.  8946 24       mov dword ptr ds:[esi+24],eax
30 100062C9         |.  FF75 0C       push [arg.2]
31 100062CC         |.  8B01          mov eax,dword ptr ds:[ecx]
32 100062CE         |.  FF36          push dword ptr ds:[esi]
33 100062D0         |.  FF10          call near dword ptr ds:[eax]
34 100062D2         |.  897E 24       mov dword ptr ds:[esi+24],edi
35 100062D5         |.  85C0          test eax,eax
36 100062D7         |.  75 69         jnz short npAliSec.10006342
37 100062D9         |.  53            push ebx
38 100062DA         |.  BB 82000000   mov ebx,82
39 100062DF         |.  395D 0C       cmp [arg.2],ebx
40 100062E2         |.  74 15         je short npAliSec.100062F9
41 100062E4         |.  FF75 14       push [arg.4]
42 100062E7         |.  8BCE          mov ecx,esi
43 100062E9         |.  FF75 10       push [arg.3]
44 100062EC         |.  FF75 0C       push [arg.2]
45 100062EF         |.  E8 B5F3FFFF   call npAliSec.100056A9
46 100062F4         |.  8945 08       mov [arg.1],eax
47 100062F7         |.  EB 48         jmp short npAliSec.10006341
48 100062F9         |>  8B06          mov eax,dword ptr ds:[esi]
49 100062FB         |.  8B3D ECF20710 mov edi,dword ptr ds:[1007F2EC]
50 10006301         |.  6A FC         push -4
51 10006303         |.  50            push eax
52 10006304         |.  FFD7          call near edi
53 10006306         |.  FF75 14       push [arg.4]
54 10006309         |.  8BCE          mov ecx,esi
55 1000630B         |.  FF75 10       push [arg.3]
56 1000630E         |.  8945 0C       mov [arg.2],eax
57 10006311         |.  53            push ebx
58 10006312         |.  E8 92F3FFFF   call npAliSec.100056A9
59 10006317         |.  8945 08       mov [arg.1],eax
60 1000631A         |.  8B46 18       mov eax,dword ptr ds:[esi+18]
61 1000631D         |.  3B05 D4F20710 cmp eax,dword ptr ds:[1007F2D4]
62 10006323         |.  74 19         je short npAliSec.1000633E
63 10006325         |.  8B06          mov eax,dword ptr ds:[esi]
64 10006327         |.  6A FC         push -4
65 10006329         |.  50            push eax
66 1000632A         |.  FFD7          call near edi
67 1000632C         |.  3B45 0C       cmp eax,[arg.2]
68 1000632F         |.  75 0D         jnz short npAliSec.1000633E
69 10006331         |.  FF76 18       push dword ptr ds:[esi+18]
70 10006334         |.  6A FC         push -4
71 10006336         |.  FF36          push dword ptr ds:[esi]
72 10006338         |.  FF15 E8F20710 call near dword ptr ds:[1007F2E8]
73 1000633E         |>  8326 00       and dword ptr ds:[esi],0
74 10006341         |>  5B            pop ebx
75 10006342         |>  8B45 08       mov eax,[arg.1]
76 10006345         |.  5F            pop edi
77 10006346         |.  EB 02         jmp short npAliSec.1000634A
78 10006348         |>  33C0          xor eax,eax
79 1000634A         |>  5E            pop esi
80 1000634B         |.  C9            leave
81 1000634C         \.  C2 1000       retn 10

 

立马中断F9运行,又中断如是重复再通过堆栈观察不难看出是下面四个参数.

 

1 BOOL IsDealMsg( 
2 
3                 LPMSG lpMsg,        // message information 
4 
5                 HWND  hWnd,         // handle to window 
6 
7                 UINT  wMsgFilterMin,// first message 
8 
9                 UINT  wMsgFilterMax // last message);

 

我们把里面的msg都纪录一下.大概有如下一些消息.

 

 1 #define WM_SETFOCUS                     0x0007
 2 #define WM_KILLFOCUS                    0x0008
 3 #define WM_SETTEXT                      0x000C
 4 #define WM_GETTEXT                      0x000D
 5 #define WM_PAINT                        0x000F
 6 #define WM_ERASEBKGND                   0x0014
 7 #define WM_CANCELMODE                   0x001F
 8 #define WM_SETCURSOR                    0x0020
 9 #define WM_MOUSEACTIVATE                0x0021
10 #define WM_WINDOWPOSCHANGING            0x0046
11 #define WM_WINDOWPOSCHANGED             0x0047
12 #define WM_NCCALCSIZE                   0x0083
13 #define WM_NCHITTEST                    0x0084
14 #define WM_NCPAINT                      0x0085
15 #define WM_NCMOUSEMOVE                  0x00A0
16 #define WM_CTLCOLOREDIT                 0x0133
17 #define WM_MOUSEFIRST                   0x0200
18 #define WM_LBUTTONDOWN                  0x0201
19 #define WM_LBUTTONUP                    0x0202
20 #define WM_CAPTURECHANGED               0x0215
21 #define WM_IME_SETCONTEXT               0x0281
22 #define WM_IME_NOTIFY                   0x0282
23 
24 #define EM_GETSEL                       0x00B0
25 #define EM_SETSEL                       0x00B1

 

我们自己发的消息是wm_settext 对应的值是 0xc

那么我们直接在函数首下个条件断点 [esp+8]==0xc 即可

断下来后我们单步,走到这里的时候不该跳的,他却跳了.所以,我们只要把这句nop掉即可 :)

1 100062D7         |. /75 69         jnz short npAliSec.10006342

Nop 我们来用工具测试一下.

 

 

测试是okay.我们的目的就达到了 :)

 

但是大家应该能看出好像哪里还有问题.

没错,问题就出现在密码是明文的了.我们点登录测试,

也是不成功的,会提示 “系统忙,请稍候再试” 的字样.

 

当我们再在 10006275 处下好wm_settext 条件断点.

然后直接运行在密码框处 输入 “b”

然后中断看 lparam 这个参数里面直接显示的是 “*”

 

同样用工具测试的时候,查看 lparam 而是显示 “bjbl”

说明在wm_settext 之前还做了些手脚.okay.

 

考虑到有些童鞋拿去做坏事,剩下的,就不写了.后面的分析方法和前面讲的都差不多.

那位朋友又问我如果不patch 可以实现吗?

方法还是有很多的比如 patch com文件 ,(当然也可能会有Crc 文件完整性效验)

甚至我们重写一份 edit 的 com 程序,也是可以的.

 

本文主要还是讲解com组件的调试分析方法,大家不要做坏事~

 

com demo和pdf下载地址:<看雪学院>

 

posted @ 2014-01-08 20:54  半斤八兩  阅读(1627)  评论(1编辑  收藏  举报