fatwolf08 发表于 2010-1-25 10:39:51

QQPlay1.5多开分析

【标题】QQPlay1.5多开分析
【作者】fatwolf08
【邮箱】fatwolf2008#163.com(请修改#)
【主页】http://hi.baidu.com/fatwolf08
【工具】OD
【平台】WinXP
------------------------------------------------------------------------
【分析过程】
目标文件QQ影音1.5版。
PEID查壳,显示是UPX壳,ESP定律脱壳ImportREC修复。可以运行。我们可以假想程序在初始化开始时就要判断有没有程序打开过,所以我们就单步跟踪看看它是如何判断的。
OD载入后,F8单步跟踪,
到达下面时窗口出现:
0056C9DF    E8 A2AB0100   call    00587586

我们F7跟进,
00587586   /E9 1F000000   jmp   <jmp.&mfc80u.#1198>
0058758B   |E8 AC47FEFF   call    <jmp.&mfc80u.#1079>
00587590   |8A4C24 04       mov   cl, byte ptr
00587594   |8848 14         mov   byte ptr , cl
00587597   |8B4C24 08       mov   ecx, dword ptr
0058759B   |8948 44         mov   dword ptr , ecx
0058759E   |33C0            xor   eax, eax
005875A0   |40            inc   eax
005875A1   |C2 0800         retn    8
005875A4-|FF25 200FAF00   jmp   dword ptr [<&msvcr80.#882>]            
005875AA-\FF25 080CAF00   jmp   dword ptr [<&mfc80u.#1198>]      跳向MFC模块   

来到下面代码:
7831D25F    53            push    ebx
7831D260    56            push    esi
7831D261    57            push    edi
7831D262    83CB FF         or      ebx, FFFFFFFF
7831D265    E8 CA2CFFFF   call    7830FF34
7831D26A    8B70 04         mov   esi, dword ptr
7831D26D    E8 4F2CFFFF   call    7830FEC1
7831D272    FF7424 1C       push    dword ptr
7831D276    8B78 04         mov   edi, dword ptr
7831D279    FF7424 1C       push    dword ptr
7831D27D    FF7424 1C       push    dword ptr
7831D281    FF7424 1C       push    dword ptr
7831D285    E8 F3CA0200   call    78349D7D
7831D28A    85C0            test    eax, eax
7831D28C    74 3C         je      short 7831D2CA
7831D28E    85FF            test    edi, edi
7831D290    74 0E         je      short 7831D2A0
7831D292    8B07            mov   eax, dword ptr
7831D294    8BCF            mov   ecx, edi
7831D296    FF90 98000000   call    dword ptr
7831D29C    85C0            test    eax, eax
7831D29E    74 2A         je      short 7831D2CA
7831D2A0    8B06            mov   eax, dword ptr
7831D2A2    8BCE            mov   ecx, esi
7831D2A4    FF50 58         call    dword ptr              此处CALL将出现窗口
7831D2A7    85C0            test    eax, eax
7831D2A9    75 16         jnz   short 7831D2C1

   
F7跟进上面的CALL:

004CDB60    55            push    ebp
004CDB61    8BEC            mov   ebp, esp
004CDB63    6A FF         push    -1
004CDB65    68 2F756300   push    0063752F
004CDB6A    64:A1 00000000mov   eax, dword ptr fs:
004CDB70    50            push    eax
。。。。。。。。。。。。。
。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。
004CDCE3    68 64318900   push    00893164                               ; UNICODE "QQPlayer Window"
004CDCE8    6A 01         push    1
004CDCEA    6A 00         push    0
004CDCEC    FF15 5003AF00   call    dword ptr [<&kernel32.#94>]            ; kernel32.CreateMutexW
004CDCF2    8986 A4000000   mov   dword ptr , eax
004CDCF8    FF15 A802AF00   call    dword ptr [<&kernel32.#361>]         ; ntdll.RtlGetLastWin32Error
004CDCFE    33C9            xor   ecx, ecx
004CDD00    3D B7000000   cmp   eax, 0B7                               ; ERROR_ALREADY_EXISTS==0xB7
004CDD05    0F94C1          sete    cl
004CDD08    8BC1            mov   eax, ecx
004CDD0A    85C0            test    eax, eax
004CDD0C    74 16         je      short 004CDD24                         ; 关键跳转,不跳则不能运行
004CDD0E    8B96 A4000000   mov   edx, dword ptr
004CDD14    52            push    edx
004CDD15    8D8D 00FFFFFF   lea   ecx, dword ptr
004CDD1B    E8 B018F6FF   call    0042F5D0                               继续查找窗口类名
004CDD20    85C0            test    eax, eax
004CDD22    75 22         jnz   short 004CDD46
004CDD24    FF15 B002AF00   call    dword ptr [<&kernel32.#317>]         ; kernel32.GetCurrentProcessId
004CDD2A    50            push    eax
004CDD2B    68 40358900   push    00893540                               ; UNICODE "ProcessID"
004CDD30    E8 6B690100   call    004E46A0                               ; 注册表保存进程ID


在004CDCE3处压入三个参数后调用CreateMutexW函数来创建一个命名的互斥对象,名称是“QQPlayer Window”, 接着调用
GetLastError来获得错误原因,如果互斥对象的名称已经存在的话,将返回ERROR_ALREADY_EXISTS,其定义正好为0xB7,
下面就判断是不是0xB7,如果是那么就不跳转,然后程序就是进入004CDD1B的CALL。

0042F5D0    55            push    ebp
0042F5D1    8BEC            mov   ebp, esp
0042F5D3    51            push    ecx
0042F5D4    53            push    ebx
0042F5D5    56            push    esi
0042F5D6    8BF1            mov   esi, ecx
0042F5D8    F646 1C 08      test    byte ptr , 8
0042F5DC    57            push    edi
0042F5DD    8975 FC         mov   dword ptr , esi
0042F5E0    C706 00000000   mov   dword ptr , 0
0042F5E6    74 2B         je      short 0042F613
0042F5E8    8B45 08         mov   eax, dword ptr
0042F5EB    68 30750000   push    7530
0042F5F0    50            push    eax
0042F5F1    FF15 8803AF00   call    dword ptr [<&kernel32.#896>]         ; kernel32.WaitForSingleObject
0042F5F7    85C0            test    eax, eax
0042F5F9    0F84 E1000000   je      0042F6E0
0042F5FF    5F            pop   edi
0042F600    C706 01000000   mov   dword ptr , 1
0042F606    5E            pop   esi
0042F607    B8 01000000   mov   eax, 1
0042F60C    5B            pop   ebx
0042F60D    8BE5            mov   esp, ebp
0042F60F    5D            pop   ebp
0042F610    C2 0400         retn    4
0042F613    8B1D 8C10AF00   mov   ebx, dword ptr [<&user32.#231>]      ; USER32.FindWindowW
0042F619    6A 00         push    0
0042F61B    68 30798600   push    00867930                               ; UNICODE "QQPlayer Window"
0042F620    C745 08 0000000>mov   dword ptr , 0
0042F627    BF D0070000   mov   edi, 7D0                               ; 设置查找窗口时间段
0042F62C    FFD3            call    ebx                                    ; 查找是否存在类名为“QQPlayer Window”的窗口
0042F62E    8BF0            mov   esi, eax
0042F630    85F6            test    esi, esi
0042F632    75 24         jnz   short 0042F658                         ; 存在则跳转
0042F634    85FF            test    edi, edi
0042F636    7E 1C         jle   short 0042F654
0042F638    6A 64         push    64
0042F63A    FF15 6C02AF00   call    dword ptr [<&kernel32.#836>]         ; 睡眠64ms
0042F640    6A 00         push    0
0042F642    68 30798600   push    00867930                               ; UNICODE "QQPlayer Window"
0042F647    FFD3            call    ebx                                    ; 继续查找
0042F649    8BF0            mov   esi, eax
0042F64B    83EF 64         sub   edi, 64
0042F64E    85F6            test    esi, esi
0042F650^ 74 E2         je      short 0042F634                         ; 循环查找
0042F652    EB 04         jmp   short 0042F658
0042F654    85F6            test    esi, esi
0042F656    74 51         je      short 0042F6A9

这个CALL是循环查找是否存在窗口类名为“QQPlayer Window”的窗口,如果不存在,那么就运行播放器,如果存在就打开这个窗口,本进程退出。

------------------------------------------------------------------------
【总结】

这种判断多开的方法是很常用的,原理就是创建一个命名的互斥对象,如果名称已经存在就查找有没有规定的窗口类名称的窗口,如果有那么就退出。

------------------------------------------------------------------------
【版权声明】本文纯属技术交流, 转载请注明作者信息并保持文章的完整, 谢谢!

[ 本帖最后由 fatwolf08 于 2010-1-25 11:39 编辑 ]

月之精灵 发表于 2010-1-25 11:37:13

不错,学习下
页: [1]
查看完整版本: QQPlay1.5多开分析