FoxitReaderPro 官方最新版本1.3,它是一款小巧绿色不用安装即使系统重装,只要从新启动一下就ok的PDF浏览器.
我一直在用它.可是每当看到它的窗口顶部出现个广告条就很不舒服,今天就与它来个亲密接触吧,舒服一下...
原程序用Microsoft Visual C++ MFC编写的,这里我一边分析汇编,一边分析MFC类库.水平有限错误之处,不吝指!
-----qiweixue

下边要跟踪几个MFC核心类库:CObject-->CCmdTarget-->CWnd-->CFrameWnd,CWinApp等...

第一:找窗口类,消息回调的路线地址请根据CWinApp类.当然也可以从汇编代码层开始我就是.这里我不仔细说看分析就可以!
第二:根据MFC注册的消息回调处理函数,筛选出自己想要的消息处理句柄来,分析如下:

先来个MFC类层次调用继承关系,如下就是MFC Message Dispatch and Message Routing:
AfxWndProc-->AfxCallWndProc-->CWnd::WindowProc--->CWnd::OnWndMsg--->CFrameWnd::OnCommand-->CWnd::OnCommand-->
CFrameWnd::OnCmdMsg-->CView::OnCmdMsg->CDocument::OnCmdMsg-->CCmdTarget::DispatchCmdMsg-->终点您亲密接触广告条吧.

第一站:
LRESULT CALLBACK AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
在AfxWndProc中有个特殊的消息处理句柄,它ID号为360,在MFC宏定义为WM_QUERYAFXWNDPROC,然后它就可以调用AfxCallWndProc.

00555BE5  /.  55            push    ebp
00555BE6  |.  8BEC          mov     ebp, esp
00555BE8  |.  817D 0C 60030>cmp     dword ptr [ebp+C], 360 --->[ebp+C]是存放消息的寄存器,消息ID:360对应的宏为:WM_QUERYAFXWNDPROC     
00555BEF  |.  56            push    esi
00555BF0  |.  75 05         jnz     short 00555BF7--->不是就跳
00555BF2  |.  6A 01         push    1  --->参数成功置1,压栈
00555BF4  |.  58            pop     eax--->eax存放的处理WM_QUERYAFXWNDPROC的返回值.eax=1
00555BF5  |.  EB 34         jmp     short 00555C2B-->返回AfxWndProc
00555BF7  |>  8B75 08       mov     esi, [ebp+8] --->[ebp+C]是存放的hWnd变量
00555BFA  |.  56            push    esi
00555BFB  |.  E8 5FFFFFFF   call    00555B5F---->函数:CWnd::FromHandlePermanent(hWnd)作用把一个MFC窗口对象影射一个MFC类C++对象.
00555C00  |.  85C0          test    eax, eax
00555C02  |.  74 17         je      short 00555C1B ---如果eax返回的C++对象指针为空,就转向默认处理方式
00555C04  |.  3970 1C       cmp     [eax+1C], esi------------>VC的中一个检测变量安全的宏类似:ASSERT(m_hWnd == hWnd)
00555C07  |.  75 12         jnz     short 00555C1B----以上意思是如果没有找到一个与hWnd对应的C++对象(永久对象)就转向默认处理方式
00555C09  |.  FF75 14       push    dword ptr [ebp+14] --->  lpararm
00555C0C  |.  FF75 10       push    dword ptr [ebp+10] ---> wpaparm
00555C0F  |.  FF75 0C       push    dword ptr [ebp+C]--->nMsg
00555C12  |.  56            push    esi--->hWnd //00170144
00555C13  |.  50            push    eax------->pWnd //00C97BA8 
00555C14  |.  E8 54FDFFFF   call    0055596D     ------>换角色了:AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
00555C19  |.  EB 10         jmp     short 00555C2B
00555C1B  |>  FF75 14       push    dword ptr [ebp+14]   --- >lParam          
00555C1E  |.  FF75 10       push    dword ptr [ebp+10] ---> wParam             
00555C21  |.  FF75 0C       push    dword ptr [ebp+C] --->nMsg              
00555C24  |.  56            push    esi --->hWnd                             
00555C25  |.  FF15 CC165900 call    [<&USER32.DefWindowProcA>]  ---->没有找到一个与hWnd对应的C++对象(永久对象)就调用我了.
00555C2B  |>  5E            pop     esi
00555C2C  |.  5D            pop     ebp
00555C2D  \.  C2 1000       retn    10
第二站:
AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
在这个函数中要为每一个线程构造_AFX_THREAD_STATE结构体,用到MFC全局变量_afxThreadState,它的作用使得一个线程被安全局部化,
另外它还处理WM_DESTROY,WM_INITDIALOG这两个消息,另外在调用WindowProc(nMsg, wParam, lParam);
0055596D   $  B8 90625800   mov     eax, 00586290--->新SEH指针
00555972   .  E8 E528EFFF   call    0044825C--->构造新SEH栈
00555977   .  83EC 34       sub     esp, 34
0055597A   .  53            push    ebx //00000
0055597B   .  56            push    esi---保存窗口句柄hWnd
0055597C   .  57            push    edi ///0000
0055597D   .  B9 64C46000   mov     ecx, 0060C464 //全局变量0060C464为pThreadState结构指针...
00555982   .  8965 F0       mov     [ebp-10], esp
00555985   .  68 89185700   push    00571889 //全局变量00571889为_afxThreadState
0055598A   .  E8 D6EA0100   call    00574465--->调用_afxThreadState.GetData();
0055598F   .  8BD8          mov     ebx, eax
00555991   .  6A 07         push    7
00555993   .  59            pop     ecx
00555994   .  8D7D C0       lea     edi, [ebp-40]
00555997   .  8D43 34       lea     eax, [ebx+34]
0055599A   .  8365 FC 00    and     dword ptr [ebp-4], 0
0055599E   .  8BF0          mov     esi, eax
005559A0   .  895D EC       mov     [ebp-14], ebx
005559A3   .  F3:A5         rep     movs dword ptr es:[edi], dword p>
005559A5   .  8B4D 0C       mov     ecx, [ebp+C]
005559A8   .  8B75 10       mov     esi, [ebp+10]-->[ebp+10]
005559AB   .  8B7D 08       mov     edi, [ebp+8] 
005559AE   .  8908          mov     [eax], ecx
005559B0   .  8B45 14       mov     eax, [ebp+14]
005559B3   .  83FE 02       cmp     esi, 2--------------------->处理WM_DESTROY消息句柄
005559B6   .  8943 3C       mov     [ebx+3C], eax
005559B9   .  8B45 18       mov     eax, [ebp+18]
005559BC   .  8973 38       mov     [ebx+38], esi
005559BF   .  8943 40       mov     [ebx+40], eax
005559C2   .  75 0E         jnz     short 005559D2
005559C4   .  8B4F 34       mov     ecx, [edi+34]
005559C7   .  85C9          test    ecx, ecx
005559C9   .  74 07         je      short 005559D2
005559CB   .  8B01          mov     eax, [ecx]
005559CD   .  6A 00         push    0
005559CF   .  FF50 5C       call    [eax+5C]------>pWnd->m_pCtrlCont->OnUIActivate(NULL);
005559D2   >  8365 0C 00    and     dword ptr [ebp+C], 0
005559D6   .  81FE 10010000 cmp     esi, 110--------------->处理WM_INITDIALOG消息句柄
005559DC   .  75 0E         jnz     short 005559EC
005559DE   .  8D45 0C       lea     eax, [ebp+C]
005559E1   .  50            push    eax
005559E2   .  8D45 DC       lea     eax, [ebp-24]
005559E5   .  50            push    eax
005559E6   .  57            push    edi
005559E7   .  E8 0EFEFFFF   call    005557FA----->调用_AfxPreInitDialog(pWnd, rectOld, dwStyle);
005559EC   >  FF75 18       push    dword ptr [ebp+18]--->lParam
005559EF   .  8B07          mov     eax, [edi]
005559F1   .  8BCF          mov     ecx, edi--->edi把CWnd的对象指针给ecx
005559F3   .  FF75 14       push    dword ptr [ebp+14]--->wParam
005559F6   .  56            push    esi--->nMsg
005559F7   .  FF90 98000000 call    [eax+98] ------------>在这里调用CWnd::WindowProc(nMsg, wParam, lParam);               
005559FD   .  81FE 10010000 cmp     esi, 110-------------->处理WM_INITDIALOG消息句柄
00555A03   .  8945 08       mov     [ebp+8], eax
00555A06   .  75 43         jnz     short 00555A4B
00555A08   .  FF75 0C       push    dword ptr [ebp+C]                
00555A0B   .  8D45 DC       lea     eax, [ebp-24]                    
00555A0E   .  50            push    eax                             
00555A0F   .  57            push    edi                              
00555A10   .  E8 08FEFFFF   call    0055581D  ---->调用_AfxPostInitDialog(pWnd, rectOld, dwStyle);                 
00555A15   .  EB 34         jmp     short 00555A4B

第三站:

LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
在这个函数中先调用OnWndMsg(message, wParam, lParam, &lResult)函数来过滤处理消息句柄.如果程序中没有此消息然后返回
调用 DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)函数来默认处理.这两个函数都是虚拟函数.
    

00556A8D  /$  55            push    ebp
00556A8E  |.  8BEC          mov     ebp, esp
00556A90  |.  51            push    ecx
00556A91  |.  56            push    esi
00556A92  |.  8BF1          mov     esi, ecx---->ecx把CWnd对象指针给esi
00556A94  |.  8D4D FC       lea     ecx, [ebp-4] 
00556A97  |.  8365 FC 00    and     dword ptr [ebp-4], 0--->并且把它内容清零,用来返回函数结果用
00556A9B  |.  8B06          mov     eax, [esi]-->取虚拟表指针
00556A9D  |.  51            push    ecx---->&lResult
00556A9E  |.  FF75 10       push    dword ptr [ebp+10]----->消息字参数lParam
00556AA1  |.  8BCE          mov     ecx, esi--->对象指针又在传递之中.
00556AA3  |.  FF75 0C       push    dword ptr [ebp+C]----->消息字参数wParam,高字节是通知code,低字节为ID表识
00556AA6  |.  FF75 08       push    dword ptr [ebp+8]--->消息参数message
00556AA9  |.  FF90 9C000000 call    [eax+9C]---------->开始调用CWnd::OnWndMsg(message, wParam, lParam, &lResult)虚函数
00556AAF  |.  85C0          test    eax, eax
00556AB1  |.  75 16         jnz     short 00556AC9
00556AB3  |.  FF75 10       push    dword ptr [ebp+10] //lParam
00556AB6  |.  8B06          mov     eax, [esi]
00556AB8  |.  8BCE          mov     ecx, esi--->esi把CWnd对象指针给ecx
00556ABA  |.  FF75 0C       push    dword ptr [ebp+C]//wParam
00556ABD  |.  FF75 08       push    dword ptr [ebp+8] //message
00556AC0  |.  FF90 A0000000 call    [eax+A0]-------->默认处理虚函数:CWnd::DefWindowProc(message, wParam, lParam);
00556AC6  |.  8945 FC       mov     [ebp-4], eax
00556AC9  |>  8B45 FC       mov     eax, [ebp-4]
00556ACC  |.  5E            pop     esi
00556ACD  |.  C9            leave
00556ACE  \.  C2 0C00       retn    0C

第四站:

进入CWnd::OnWndMsg消息处理虚函数

BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
它主要处理WM_COMMAN,WM_NOTIFY, WM_ACTIVATE,WM_SETCURSOR这四个特殊消息句柄,另外在查找匹配处理消息影射表中的事件句柄.
要经过:OnCommand(wParam, lParam)、OnNotify(wParam, lParam, &lResult)等过程...

00556AD1  /$  B8 08635800   mov     eax, 00586308        -------------->SEH新指针
00556AD6  |.  E8 8117EFFF   call    0044825C                          ;构造新SEH框架函数
00556ADB  |.  83EC 54       sub     esp, 54 ---------->分配54字节栈
00556ADE  |.  8365 F0 00    and     dword ptr [ebp-10], 0  ----->初始化指针变量*pResult的为0
00556AE2  |.  53            push    ebx
00556AE3  |.  8B5D 08       mov     ebx, [ebp+8]    ----------- > [ebp+8] 为消息Msg结构体的Message域里边存放的是消息ID号
00556AE6  |.  56            push    esi
00556AE7  |.  57            push    edi
00556AE8  |.  81FB 11010000 cmp     ebx, 111  ---->注意这里:111为WM_COMMAND消息ID号,开始进行消息判断
00556AEE  |.  8BF9          mov     edi, ecx  ------>ecx是所谓的this指针...
00556AF0  |.  75 18         jnz     short 00556B0A--->如果不是WM_COMMAND就跳过去.
00556AF2  |.  FF75 10       push    dword ptr [ebp+10]                ;  Case 111 (WM_COMMAND) of switch 00556AE8
00556AF5  |.  8B07          mov     eax, [edi]  ---->  [edi] 指向一个  MFC MainFrame 对象,它把对象指针传给eax,给下边的虚函数用
00556AF7  |.  FF75 0C       push    dword ptr [ebp+C]---------->注意这里:菜单ID号入栈了...这里是:8024
00556AFA      FF50 78       call    [eax+78]--------->这是CFrameWnd::OnCommand(wparam,lparam)虚函数
00556AFD  |.  85C0          test    eax, eax -->eax存放函数返回值,把结果放到*pResult指针变量中.
00556AFF  |.  0F84 55010000 je      00556C5A-->当eax为0,转
00556B05  |.  E9 1D040000   jmp     00556F27-->当eax为1,转
00556B0A  |>  83FB 4E       cmp     ebx, 4E----------------------------------------->这里4E为 WM_NOTIFY消息ID号,
00556B0D  |.  75 28         jnz     short 00556B37
00556B0F  |.  8B45 10       mov     eax, [ebp+10]                    
00556B12  |.  8338 00       cmp     dword ptr [eax], 0
00556B15  |.  0F84 3F010000 je      00556C5A--->--->如果不是WM_NOTIFY就跳到WM_ACTIVATE消息处理
00556B1B  |.  8B17          mov     edx, [edi]
00556B1D  |.  8D4D F0       lea     ecx, [ebp-10]---->&lResult指针地址保存到ecx中压栈传参用.
00556B20  |.  51            push    ecx
00556B21  |.  50            push    eax
00556B22  |.  FF75 0C       push    dword ptr [ebp+C]
00556B25  |.  8BCF          mov     ecx, edi
00556B27  |.  FF52 7C       call    [edx+7C]---->这是CWnd::OnNotify(wParam,lparam,&lResult)虚函数
00556B2A  |> /85C0          test    eax, eax
00556B2C  |. |0F85 39040000 jnz     00556F6B
00556B32  |. |E9 23010000   jmp     00556C5A

第五站:
因为我这里要处理的是WM_COMMAND的消息嘛,所以进入:
BOOL CFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam)
对了还有一个参数就是菜单的ID号:80A2,存放在wParam低字节中.
恩,是这样得当我用鼠标触发那个广告菜单命令的时候,广告就出现在菜单工具栏上,所以菜单ID不能少!
还有个关键问题:
FoxitReaderPro对象好象重载了OnCommand(WPARAM wParam, LPARAM lParam)方法,那以后的消息路线转变了:
应该是调用CFoxitReaderFrameWnd::OnCommand然后在调用FrameWnd::OnCommand和CWnd::OnCommand方法.在普通的MFC类库中FrameWnd::OnCommand里边没有很多实例方法,它是直接调用CWnd::OnCommand


0056DD6D   .  53            push    ebx-->:CWnd::OnWndMsg函数中的message参数变量,这里是WM_COMMAND消息ID
0056DD6E   .  56            push    esi-->保存对象指针00C97BA8
0056DD6F   .  57            push    edi-->保存对象指针00C97BA8,
0056DD70   .  8BF9          mov     edi, ecx ---->ecx与edi指向同一对象指针
0056DD72   .  6A 00         push    0
0056DD74   .  E8 4B040000   call    0056E1C4 ---> 调用CWnd::GetTopLevelFrame(),这个函数发了WM_MDIGETACTIVE消息得到当前MDI Child Window
0056DD79   .  8B5C24 10     mov     ebx, [esp+10]  ---> 菜单ID号出现 80A2
0056DD7D   .  BE 11010000   mov     esi, 111
0056DD82   .  85C0          test    eax, eax ->函数的返回值,由于广告条在父窗口中并没有在子类或者其他CView类出现,所以我把所以子窗口全部shutdown了,免的又在阴沟over了!
0056DD84   .  74 13         je      short 0056DD99------>在这里跳!
0056DD86   .  FF7424 14     push    dword ptr [esp+14]
0056DD8A   .  53            push    ebx
0056DD8B   .  56            push    esi
0056DD8C   .  FF70 1C       push    dword ptr [eax+1C]
0056DD8F   .  50            push    eax
0056DD90   .  E8 D87BFEFF   call    0055596D--->注意这个虚函数中有很多对象实例方法里边判断广告的显示方法也在其中了,通过分析它才知道FoxitReaderPro对象应该重载了OnCommand(WPARAM wParam, LPARAM lParam)方法。
0056DD95   .  85C0          test    eax, eax
0056DD97   .  75 30         jnz     short 0056DDC9
0056DD99   >  FF7424 14     push    dword ptr [esp+14]---//这个变量为0
0056DD9D   .  8BCF          mov     ecx, edi--->赋值CFrameWnd对象指针.
0056DD9F   .  53            push    ebx        ----->触发菜单ID号:8042                      
0056DDA0   .  E8 4BE1FFFF   call    0056BEF0    ---------------------------来到这里是通往广告条的显示之门.
0056DDA5   .  85C0          test    eax, eax
0056DDA7   .  

进入FoxitReaderPro判断广告条的实例方法:  call    0056BEF0 (wParam,lParam)


0056BEF0  /$  53            push    ebx
0056BEF1  |.  56            push    esi
0056BEF2  |.  57            push    edi
0056BEF3  |.  8BF1          mov     esi, ecx--->对象指针.
0056BEF5  |.  0FB77C24 10   movzx   edi, word ptr [esp+10] ----》 触发广告条菜单ID号: 8024
0056BEFA  |.  E8 D7B3FEFF   call    005572D6                                  ;  c++对象指针与窗口句柄影射
0056BEFF  |.  33C9          xor     ecx, ecx
0056BF01  |.  3948 50       cmp     [eax+50], ecx
0056BF04  |.  74 4C         je      short 0056BF52--->走到了,开始跳了
0056BF06  |.  394C24 14     cmp     [esp+14], ecx
0056BF0A  |.  75 46         jnz     short 0056BF52
0056BF0C  |.  81FF 46E10000 cmp     edi, 0E146   --->其他彩单ID 0E146
0056BF12  |.  74 3E         je      short 0056BF52
0056BF14  |.  BB 47E10000   mov     ebx, 0E147  --->其 菜单ID E147
0056BF19  |.  3BFB          cmp     edi, ebx
0056BF1B  |.  74 35         je      short 0056BF52
0056BF1D  |.  81FF 45E10000 cmp     edi, 0E145
0056BF23  |.  74 2D         je      short 0056BF52

...中间省略了不必要的代码看关键部分
从上边跳过来的.
0056BF52  |> \FF7424 14     push    dword ptr [esp+14]  |Arg1---> 这个参数是我触发显示广告菜单的ID号:8042                   
0056BF56  |.  8BCE          mov     ecx, esi                                 
0056BF58  |.  FF7424 14     push    dword ptr [esp+14]  |Arg2--->大家注意拉!看堆栈!                    
0056BF5C  |.  E8 0FB1FEFF   call    00557070 ============>这是关键广告函数,真是没有想到FoxitReaderPro给这个ID号另起炉灶了!
0056BF61  |>  5F            pop     edi
0056BF62  |.  5E            pop     esi
0056BF63  |.  5B            pop     ebx
0056BF64  \.  C2 0800       retn    8

看堆栈:
0012FB40   000080A2  |Arg1 = 000080A2 =====触发菜单ID号:8042,这个参数是wParam
0012FB44   00000000  |Arg2 = 00000000



00557070  /$  55            push    ebp
00557071  |.  8BEC          mov     ebp, esp
00557073  |.  83EC 2C       sub     esp, 2C
00557076  |.  8B45 08       mov     eax, [ebp+8] ---》wParam参数
00557079  |.  53            push    ebx
0055707A  |.  56            push    esi
0055707B  |.  57            push    edi
0055707C  |.  0FB7F8        movzx   edi, ax
0055707F  |.  33DB          xor     ebx, ebx
00557081  |.  8BF1          mov     esi, ecx
00557083  |.  C1E8 10       shr     eax, 10  ----把wParam右移动16位,这时候wParam变为0了.
00557086  |.  395D 0C       cmp     [ebp+C], ebx---->[ebp+c]
00557089  |.  8945 08       mov     [ebp+8], eax
0055708C  |.  75 3A         jnz     short 005570C8---》到这里相当跳.
0055708E  |.  3BFB          cmp     edi, ebx
00557090  |.  74 66         je      short 005570F8
00557092  |.  8D4D D4       lea     ecx, [ebp-2C]
00557095  |.  E8 A9FFFFFF   call    00557043
0055709A  |.  8B06          mov     eax, [esi]
0055709C  |.  8D4D D4       lea     ecx, [ebp-2C]                             ;  lpararm c++对象指针
0055709F  |.  53            push    ebx
005570A0  |.  51            push    ecx
005570A1  |.  6A FF         push    -1
005570A3  |.  57            push    edi                                       ;  彩单ID
005570A4  |.  8BCE          mov     ecx, esi
005570A6  |.  897D D8       mov     [ebp-28], edi                             ;  80A2 菜单ID号...
005570A9  |.  FF50 0C       call    [eax+C]                                   ;  a.0056ddd6   比较之处
005570AC  |.  395D FC       cmp     [ebp-4], ebx
005570AF  |.  74 3E         je      short 005570EF
005570B1  |.  895D 08       mov     [ebp+8], ebx
005570B4  |>  8B06          mov     eax, [esi]
005570B6  |.  53            push    ebx
005570B7  |.  53            push    ebx
005570B8  |.  8BCE          mov     ecx, esi
005570BA  |.  FF75 08       push    dword ptr [ebp+8]
005570BD  |.  57            push    edi
005570BE  |.  FF50 0C       call    [eax+C]       ------------------------》关键函数:
005570C1  |>  5F            pop     edi
005570C2  |.  5E            pop     esi
005570C3  |.  5B            pop     ebx
005570C4  |.  C9            leave
005570C5  |.  C2 0800       retn    8


第六站直接亲密
.....
我写这累了,相比你看这也累了,我直接给出结局来!

原来的时候我是下USER32.dll.ShowWindow断点可是广告条根本就不吃这一套,断不下来的!还有当点击广告条的时候会进入它官方网站,这时候又下的SHELL32.ShellExecute 断点等也没有断下来.只能断个MessageBox,感觉交互信息太少,还有它的菜单ID迟迟不比较等等!直到最后跟到这里才恍然大悟...
原来FoxitReaderPro是用的InsertMenuA插入广告条
用DeleteMenu删除广告条
用DrawMenuBar来刷新广告条的颜色,你会看到红,绿等色的交替!
用SetRectEmpty来清理广告条的矩形对象
如下:

0040C9C0  /$  56            push    esi
0040C9C1  |.  57            push    edi
0040C9C2  |.  8BF9          mov     edi, ecx
0040C9C4  |.  8B47 1C       mov     eax, [edi+1C]
0040C9C7  |.  50            push    eax                                       ; /hWnd
0040C9C8  |.  FF15 44175900 call    [<&USER32.GetMenu>]                       ; \GetMenu
0040C9CE  |.  50            push    eax
0040C9CF  |.  E8 E5D21400   call    00559CB9
0040C9D4  |.  8BF0          mov     esi, eax
0040C9D6  |.  85F6          test    esi, esi
0040C9D8      0F85 90000000 jnz     0040CA6E
0040C9DE  |.  8B4424 0C     mov     eax, [esp+C]
0040C9E2  |.  83F8 05       cmp     eax, 5
0040C9E5  |.  75 40         jnz     short 0040CA27
0040C9E7  |.  68 00410000   push    4100
0040C9EC  |.  56            push    esi
0040C9ED  |.  8BCF          mov     ecx, edi
0040C9EF  |.  E8 3CFBFFFF   call    0040C530
0040C9F4  |.  83F8 FF       cmp     eax, -1                                   ;  打开 advise....
0040C9F7      75 61         jnz     short 0040CA5A
0040C9F9  |.  8B4E 04       mov     ecx, [esi+4]
0040C9FC  |.  68 0C875D00   push    005D870C                                  ; /pNewItem = "PDF 编?,AD,"?,F7,""
0040CA01  |.  68 00410000   push    4100                                      ; |NewItemID = 4100 (16640.)
0040CA06  |.  68 00450000   push    4500                                      ; |Flags = MF_BYPOSITION|MF_ENABLED|MF_STRING|MF_OWNERDRAW|MF_HELP
0040CA0B  |.  50            push    eax                                       ; |ItemID
0040CA0C  |.  51            push    ecx                                       ; |hMenu
0040CA0D  |.  FF15 28175900 call    [<&USER32.InsertMenuA>]                   ; \InsertMenuA
0040CA13  |.  8B4F 1C       mov     ecx, [edi+1C]
0040CA16  |.  51            push    ecx                                       ; /hWnd
0040CA17  |.  FF15 30175900 call    [<&USER32.DrawMenuBar>]                   ; \DrawMenuBar
0040CA1D      5F            pop     edi
0040CA1E      B8 01000000   mov     eax, 1
0040CA23  |.  5E            pop     esi
0040CA24  |.  C2 0400       retn    4
0040CA27  |>  85C0          test    eax, eax
0040CA29  |.  75 2F         jnz     short 0040CA5A
0040CA2B  |.  68 00410000   push    4100
0040CA30  |.  56            push    esi
0040CA31  |.  8BCF          mov     ecx, edi
0040CA33  |.  E8 F8FAFFFF   call    0040C530
0040CA38  |.  83F8 FF       cmp     eax, -1
0040CA3B  |.  74 1D         je      short 0040CA5A
0040CA3D  |.  8B56 04       mov     edx, [esi+4]
0040CA40  |.  68 00040000   push    400                                       ; /Flags = MF_BYPOSITION|MF_ENABLED|MF_STRING
0040CA45  |.  50            push    eax                                       ; |ItemId
0040CA46  |.  52            push    edx                                       ; |hMenu
0040CA47  |.  FF15 34175900 call    [<&USER32.DeleteMenu>]                    ; \DeleteMenu
0040CA4D  |.  8D87 28020000 lea     eax, [edi+228]
0040CA53  |.  50            push    eax                                       ; /pRect
0040CA54  |.  FF15 B4175900 call    [<&USER32.SetRectEmpty>]                  ; \SetRectEmpty
0040CA5A  |>  8B4F 1C       mov     ecx, [edi+1C]
0040CA5D  |.  51            push    ecx                                       ; /hWnd
0040CA5E  |.  FF15 30175900 call    [<&USER32.DrawMenuBar>]                   ; \DrawMenuBar
0040CA64  |.  5F            pop     edi
0040CA65  |.  B8 01000000   mov     eax, 1
0040CA6A  |.  5E            pop     esi
0040CA6B  |.  C2 0400       retn    4
0040CA6E  |>  5F            pop     edi
0040CA6F  |.  33C0          xor     eax, eax
0040CA71  |.  5E            pop     esi
0040CA72  \.  C2 0400       retn    4

任务完成了,该找出来的都出来,到这里你稍微一动鼠标,广告就over掉了......
末了:
FoxitReaderPro 的做的广告条正是以菜单栏为父窗口,因此为什么当跟踪的时候始终没有看到影射出一个CWnd类或者是CFarme类的C++对象,还有那些ShowWindow等窗体的断点API根本不管用的!

另外FoxitReaderPro还有一个有意思的地方就是当你点击广告条的时候,它会启动浏览器然后加载它的主页地址.我一开始用的是SHELL32.ShellExecute断点,不管用!它用的&KERNEL32.CreateProcess,它把官方URL作为参数启动IE,当触发事件的时候就执行了CreateProcess.....

好累了,直到写完了我才吃了点东西!

Copyright © 2000 - 2006 PEdiy.com All Rights Reserved.By KanXue Studio