首页
社区
课程
招聘
[原创]Ring3下截获QQ2009密码
发表于: 2009-12-14 21:42 12571

[原创]Ring3下截获QQ2009密码

2009-12-14 21:42
12571

搞出来很久了,看到看雪上不少同学都很期待,干脆发出来。

本文大部分研究成果归功于mentaldease,欲读此文,请遵守以下约定:
1. 绝不可利用本文所揭示的技术编写或者辅助编写盗号木马,危害中国网民。
2. 也不可将本文所揭示的技术直接或间接传授给写盗号木马的败类。
3. 违背以上两点约定者,天打雷劈,断子绝孙...(以下省略2000字)。

**********************************************************

   不能遵守以上三点约定者,请立即离开!

**********************************************************
在分析QQ之前,尝试直接用低级键盘钩子截获密码。
笔者发现可以获取正确的QQ号,但是截获的QQ密码里面却有很多虚假按键:

事实上,只要将鼠标焦点放在密码输入框里,QQ就自动产生虚假按键。所以,靠低级键盘钩子不能截获正确的QQ密码。

用XueTr查看系统中的消息钩子。笔者发现只要用户双击打开QQ2009登录窗口,QQ就会创建一个WH_KEYBOARD_LL低级键盘钩子,如图2

我们知道WH_KEYBOARD_LL钩子的优先级高于WH_KEYBOARD和WH_GETMESSAGE钩子。显然QQ2009的低级键盘钩子会比其他类型的钩子先执行,QQ获取用户的真实按键后再伪造虚假按键。

笔者在成功截获QQ2009密码之后,挂钩了SetWindowHookEx观察QQ创建WH_KEYBOARD_LL钩子的过程:


由上图可见QQ2009每隔不到0.2秒就创建一个低级键盘钩子,这样确保自己的钩子始终在钩子队列的最顶层。

我们对SetWindowHookEx函数下断,但是断不下来,显然是QQ在这里有反调试。删除刚才的断点,下一个硬件断点,程序断下,执行到返回:

来到042437C5处,tssafeed模块中看到如下指令:
042437BB    56              push    esi
042437BC    50              push    eax
042437BD    FF75 0C         push    dword ptr [ebp+C]
042437C0    E8 AB550000     call    04248D70                         ; jmp 到 MSVCRT.memcmp
042437C5    8B3D 28A02404   mov     edi, dword ptr [424A028]         ; KERNEL32.GetCurrentProcess
042437CB    83C4 0C         add     esp, 0C
042437CE    85C0            test    eax, eax
042437D0    0F84 8F000000   je      04243865

猜测这里很可能就是用memcmp 函数校验SetWindowsHookExA(可能还有其他函数)的代码。在042437BB 处F2,再F9让程序运行,把鼠标焦点移到密码输入框时,断下来了:

单步执行到042437C0,看堆栈信息:

果然是对SetWindowsHookExA初的内存进行校验。memcmp返回0则认为该处内存没有改变。

在77D311D1处下硬件执行断点,成功断下后,堆栈信息如图:


HookType为13,即是WH_KEYBOARD_LL钩子,其HookProc为 04260F1B,转到该地址看看QQ的钩子回调例程:
04260F1B    55              push    ebp
04260F1C    8BEC            mov     ebp, esp
04260F1E    83EC 30         sub     esp, 30
04260F21    56              push    esi
04260F22    57              push    edi
04260F23    C745 FC F00C260>mov     dword ptr [ebp-4], 4260CF0
04260F2A    8D7D D0         lea     edi, dword ptr [ebp-30]
04260F2D    B9 07000000     mov     ecx, 7
04260F32    33C0            xor     eax, eax
04260F34    FC              cld
04260F35    F3:AB           rep     stos dword ptr es:[edi]
04260F37    8B45 10         mov     eax, dword ptr [ebp+10]
04260F3A    8945 F8         mov     dword ptr [ebp-8], eax
04260F3D    C745 F4 0000000>mov     dword ptr [ebp-C], 0
04260F44    E8 20000000     call    04260F69                       ; 跟进
… …

04260F69 处的call:
04260F69    5F              pop     edi
04260F6A    8B4D F4         mov     ecx, dword ptr [ebp-C]
04260F6D    833C8F 00       cmp     dword ptr [edi+ecx*4], 0
04260F71    74 1D           je      short 04260F90
04260F73    8B55 F4         mov     edx, dword ptr [ebp-C]
04260F76    8B0497          mov     eax, dword ptr [edi+edx*4]
04260F79    50              push    eax
04260F7A    8B4D FC         mov     ecx, dword ptr [ebp-4]
04260F7D    FF51 50         call    dword ptr [ecx+50]             ; USER32.GetAsyncKeyState
04260F80    0FBFD0          movsx   edx, ax
04260F83    81E2 00800000   and     edx, 8000
04260F89    75 05           jnz     short 04260F90
04260F8B    FF45 F4         inc     dword ptr [ebp-C]
04260F8E  ^ EB DA           jmp     short 04260F6A
04260F90    8B55 F8         mov     edx, dword ptr [ebp-8]
04260F93    8B02            mov     eax, dword ptr [edx]
04260F95    C745 F0 0000000>mov     dword ptr [ebp-10], 0
04260F9C    E8 3C000000     call    04260FDD                                        ;跟进
… …

这个函数中有很多花指令,这里就不仔细分析了,对GetForegroundWindow下断,只要将鼠标焦点移到QQ登录窗口,就会断下,再对CallNextHookEx下断观察。它的大概功能猜也猜得出来:QQ自己获取按键之后,发送虚假按键,然后直接返回。现在就是找出QQ2009到底是用什么函数发送虚假按键。对keybd_event下硬件执行断点,没有断下,对sendInput下硬件断点,断下了:

Sendinput函数原型:
UINT SendInput(
  UINT nInputs,     // count of input events
  LPINPUT pInputs,  // array of input events
  int cbSize        // size of structure
);
typedef struct tagINPUT {
  DWORD   type;
  union {
      MOUSEINPUT      mi;
      KEYBDINPUT      ki;
      HARDWAREINPUT   hi;
  };
} INPUT, *PINPUT;
观察堆栈:

数据窗口跟随到0012FA94:

如图所示 01表示的是输入类型INPUT_KEYBOARD,pInouts的结构如下:
typedef struct tagKEYBDINPUT {
  WORD      wVk;
  WORD      wScan;
  DWORD     dwFlags;
  DWORD     time;
  ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT;
如图所示0x38对应的虚拟按键是数字8,用我们刚才写的那个低级键盘钩子可以看到,所接收到的虚假按键正是8.

现在我们能够写出QQ的低级键盘钩子处理例程:
HWND hwnd = GetForegroundWindow();
If( hWnd == hPassEditWnd)
{
        MapVirtualKey();
        SendInput();
        return  1;
}
else
{
        return  CallNextHookEx(ncode,…);
}
现在2009登录窗口保护的原理已经分析清楚,获取QQ密码的方法也就有了。其关键就是绕过QQ对SetWindowsHookExA等函数的内存校验,然后hook SetWindowsHookExA,判断如果是QQ的WH_KEYBOARD_LL钩子,就替换其回调函数,然后在my_KeyboardllProc中截获密码,下图是截获密码的效果图:

PS:QQ2009的软键盘也被我和mentaldease兄突破,并成功截获密码:


演示程序:


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 10
支持
分享
最新回复 (42)
雪    币: 2105
活跃值: (424)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
围观~~~~~
2009-12-14 21:46
0
雪    币: 324
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
沙发!站位,太牛逼了
2009-12-14 21:59
0
雪    币: 348
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
支持楼主的钻研精神! 像楼主学习
2009-12-14 22:05
0
雪    币: 224
活跃值: (21)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
占位学习! 楼主强大
2009-12-14 22:39
0
雪    币: 184
活跃值: (56)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
不错~值得学习!
2009-12-15 00:27
0
雪    币: 558
活跃值: (46)
能力值: ( LV2,RANK:16 )
在线值:
发帖
回帖
粉丝
7
牛文也。。。。
学习一个
2009-12-15 00:39
0
雪    币: 215
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
这回乱了 呵呵
2009-12-15 09:52
0
雪    币: 5
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
实在是厉害啊!
2009-12-15 10:07
0
雪    币: 358
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
学习LZ的钻研精神   

希望文章不要被和谐
2009-12-15 10:24
0
雪    币: 296
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
思路清晰,浅显易懂。。。学习!!
2009-12-15 10:26
0
雪    币: 171
活跃值: (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
貌似梦幻也是用发送虚假按键防止盗号!当时我找出他的处理函数想去hook却没成功!
  原来是这么回事!学习了!
2009-12-15 11:15
0
雪    币: 445
活跃值: (52)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
13
学习~~再学习
2009-12-15 11:56
0
雪    币: 287
活跃值: (18)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
很好,分析的很好,谢谢
2009-12-15 12:33
0
雪    币: 287
活跃值: (18)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
15
键盘能截获,可是截获不了软键盘输入密码
2009-12-15 12:47
0
雪    币: 431
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
16
看看 学习一下~
2009-12-15 12:48
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
实在是太棒了
2009-12-15 15:13
0
雪    币: 336
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
18
楼主很好,很强大,哈哈
2009-12-15 16:53
0
雪    币: 234
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
prove u 太strong了
2009-12-15 16:55
0
雪    币: 310
活跃值: (111)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
20
看不懂!
2009-12-15 16:56
0
雪    币: 89
活跃值: (185)
能力值: ( LV9,RANK:270 )
在线值:
发帖
回帖
粉丝
21
很不错的说!
2009-12-15 17:33
0
雪    币: 65
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
好文,这种值得精神学习。
2009-12-15 17:33
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
23
QQ密保咋办?
2009-12-15 17:52
0
雪    币: 213
活跃值: (147)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
楼主充分证明了,调试这活儿,只要努力去做,多半是有戏的,怕就怕光看不做
2009-12-15 17:59
0
雪    币: 324
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
这个太危险了!
2009-12-15 19:10
0
游客
登录 | 注册 方可回帖
返回
//