S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

[某著名IM软件]输入密码-[XXSafeEdit]-保护破释分析2008-12-16 07:41【破文标题】[某著名IM软件]输入密码-[XXSafeEdit]-保护破释分析
【对  象】初入门的新手
【下载地址】www.xx.com
【破解工具】OD
【保护方式】消息加密保护
【任  务】找出原始消息记录触发点
【破文作者】thomasyzh
【组  织】没有
【破解声明】这篇破文图的是速度,和解决问题---没有更加多的深入分析保护方式-总共12小时,3天,每天4小时
【备  注】老手勿看,别浪费你的时间
【电  邮】machinesy@163.com
【破解过程】

首先,要知道其对于密码的保护方式。其用键盘记录精灵等驱动级记录失效果。以及在内存中无法找到明文输入。

具体测试过程如下:
1。使用键盘记录精灵记录你要输入的密码。

测试结果。得到的并非自己输入的。

2。使用WinHex等工具,直接内存中搜索你输入的明文字符串。

测试结果。没有查找到。

有了如上两点后,我们开发分析其保护方式,首先要确定其是驱动级保护,还是非驱动级保护。


于是使用OD,打开。载入c。

F2。下断Kernel32->CreateFile.

这里大概提提R3进R0的几种方式。

.最为常规的驱动通信采用CreateFile,和DeviceIoContral.其次,还有中断门,陷阱门等手法。(具体参见看雪rootkit学习)

由于XX是大型应用程序软件,从软件设计的角度上来考虑,其基本上不可能去挂接中断门,等硬件很底层的东西,因为,这样做的话会造成他们的软件茁壮性非常低。

所以这里我只考虑了CreateFile.

这时候我们让程序跑起来,看其会访问什么驱动。

在CreateFile,后并没有发现其访问什么驱动。所以我认为。XX的保护,并非驱动级了。


这时候我们再来分析r3下的用户键盘输入。

这里提一下R3下用户键盘输入的几种可能:
1。如果是一个窗口程序,会触发WM_KEYDOWN.这个消息.
2。如果是控制台程序,会向基本输入流里写入一个字符.
3。如果是Dx,或者其它非主流应用程序的API,或者涉及到com相关技术的东西,大概其会把输入放入到一个Buffer里。

下面谈谈R3下取EDIT里字符的方法。既然是Edit,就一定是窗口程序了。所以不涉及到程序情况2(控制台程序)。

一般情况下,写程序的人会用GetWindowText,或者GetDlgItemText取窗口上输入的字符。也有可能在WM_KEYDOWN时就把字符,放如Buffer,而不使用这两个函数。在com和dx里,其一定是放入Buffer里.大概就这两种情况。

1。根据特点,我们首先测试GetWindowText这个函数。

测试结果:好的,发现没有使用。

2.根据直接放到Buffer这种情况,直接下XP下的万能断点。

测试结果:是的,它没有走到万难断点这里,又或者是对那个断点进行保护。

------这里提一提,对于XX游戏,下万难断点,是能够取到密码输入的。

至于万能断点在哪里,可以查看看雪工具下载。里边有提供工具。


这时候,我们就只能从消息入手了。毕竟是窗口程序,消息循环是绝对存在的。

这里提提,对消息挂接的几种方式。
1。SetWindowHook.----消息钩子。
2。SetWindowLong.----这个函数,主要用于窗口子类化。

-----这里我们先不着急,分析其消息钩子,先对于SetWindowLong函数下端。(由于XX窗口,会做的漂亮点,通常会使用SetWindowLong函数)

这里我们要找到那个Edit窗口具体是什么窗口,找窗口有很多工具的,就不具体谈了。

[XXSafeEdit]是其密码输入保护的主要模块。那么我们先在LoadLibrary下点。大概会断在这里:

608F6684     E8 53CA0000      call     <jmp.&MFC42.#4160_CString::LoadStringA>
608F6689     68 9A860000      push     869A
608F668E     8D4D EC          lea      ecx, dword ptr [ebp-14]
608F6691     E8 46CA0000      call     <jmp.&MFC42.#4160_CString::LoadStringA>
608F6696     FF75 E8          push     dword ptr [ebp-18]
608F6699     8B3D 30A19060    mov      edi, dword ptr [<&KERNEL32.LoadLibraryA>] ; kernel32.LoadLibraryA
608F669F     FFD7             call     edi
608F66A1     3BC3             cmp      eax, ebx
608F66A3     8986 A0020000    mov      dword ptr [esi+2A0], eax
608F66A9     75 18            jnz      short 608F66C3
608F66AB     6A 30            push     30
608F66AD     68 14869160      push     60918614                                   ; ASCII "XX"
608F66B2     FF75 F0          push     dword ptr [ebp-10]
608F66B5     8BCE             mov      ecx, esi
608F66B7     E8 BACC0000      call     <jmp.&MFC42.#4224_CWnd::MessageBoxA>
608F66BC     53               push     ebx
608F66BD     FF15 8CA69060    call     dword ptr [<&MSVCRT.exit>]                 ; msvcrt.exit
608F66C3     FF75 EC          push     dword ptr [ebp-14]
608F66C6     50               push     eax
608F66C7     FF15 54A19060    call     dword ptr [<&KERNEL32.GetProcAddress>]     ; kernel32.GetProcAddress
608F66CD     3BC3             cmp      eax, ebx
608F66CF     75 18            jnz      short 608F66E9
608F66D1     6A 30            push     30
608F66D3     68 14869160      push     60918614                                   ; ASCII "XX"
608F66D8     FF75 F0          push     dword ptr [ebp-10]
608F66DB     8BCE             mov      ecx, esi
608F66DD     E8 94CC0000      call     <jmp.&MFC42.#4224_CWnd::MessageBoxA>
608F66E2     53               push     ebx
608F66E3     FF15 8CA69060    call     dword ptr [<&MSVCRT.exit>]                 ; msvcrt.exit
608F66E9     8D4E 64          lea      ecx, dword ptr [esi+64]
608F66EC     51               push     ecx
608F66ED     FFD0             call     eax
608F66EF     395E 64          cmp      dword ptr [esi+64], ebx
608F66F2     75 18            jnz      short 608F670C
608F66F4     6A 30            push     30
608F66F6     68 14869160      push     60918614                                   ; ASCII "XX"
608F66FB     FF75 F0          push     dword ptr [ebp-10]
608F66FE     8BCE             mov      ecx, esi
608F6700     E8 71CC0000      call     <jmp.&MFC42.#4224_CWnd::MessageBoxA>
608F6705     53               push     ebx
608F6706     FF15 8CA69060    call     dword ptr [<&MSVCRT.exit>]                 ; msvcrt.exit
608F670C     3BF3             cmp      esi, ebx
608F670E     75 08            jnz      short 608F6718

 

-----其加载[XXSafeEdit]的时候会在这里。这里其Load模块之后,会取出一Get出一个函数,然后创建一个XXX,我们就不逆,有时间在逆。

逆完之后,完全可以模仿出一个他那个模块的行为然后再XXX。或者XXX。

在[XXSafeEdit]   Load之后,我们下SetWindowLong函数断。


然后观察栈的窗口数据,大概到这里
0012ECA4    00ED2E0C   /CALL 到 SetWindowLongA 来自 TSSafeEd.00ED2E09
0012ECA8    00020994   |hWnd = 00020994 ('Q',class='Edit',parent=0004099A)
0012ECAC    FFFFFFFC   |Index = GWL_WNDPROC
0012ECB0    00ED283F   \NewValue = ED283F


好的...这个SetWindowLong,来自SafeEdit.窗口正是我们开始用XXX找到的密码输入窗口,GWL_WNDPROC代表NewValue是一个新的窗口消息处理过程。那么地址就是ED283F。


这时候,我们就去ED283F,下条件断点,大概判断是什么消息。当是WM_KEYDOWN的时候,我们就断下来。


00ED283B     5E               pop      esi
00ED283C     C2 0400          retn     4
00ED283F >   55               push     ebp                               ; dword ptr[esp+8] == 100
00ED2840     8BEC             mov      ebp, esp
00ED2842     83EC 14          sub      esp, 14
00ED2845     8B0D 4891ED00    mov      ecx, dword ptr [ED9148]
00ED284B     8365 FC 00       and      dword ptr [ebp-4], 0
00ED284F     8065 F6 00       and      byte ptr [ebp-A], 0
00ED2853     53               push     ebx
00ED2854     33C0             xor      eax, eax
00ED2856     56               push     esi
00ED2857     85C9             test     ecx, ecx
00ED2859     57               push     edi
00ED285A     C645 EC 75       mov      byte ptr [ebp-14], 75
00ED285E     C645 ED 73       mov      byte ptr [ebp-13], 73
00ED2862     C645 EE 65       mov      byte ptr [ebp-12], 65


这里,我们就能在WM_KEYDOWN了。当WM_KEYDOWN的时候,我们就能取得用户按的键了,具体是WM_KEYDOWN触发时的LPARAM.里边保存的是VK数据。

这里给出VK数据值。

出自VC6。头文件。41是a怎么怎么的。

这时候我们发现,我们的WM_KEYDOWN是乱码。也就是说,我们取的WM_KEYDOWN并非我们真实按下的键盘。

因为,我们按A的时候,每一次得到的都是不一样的数据。

好的,我们来分析下它是杂个让WM_KEYDWON..在消息下变化的。

在WIN32 R3下有一组键盘操作函数:

大概是下边这些:

具体参考SDK,在MapVirtualKeyA下断点。我们可以发现。
0012F968    00ED54D3   /CALL 到 MapVirtualKeyA 来自 TSSafeEd.00ED54CD
0012F96C    00000032   |Key = 32
0012F970    00000000   \Action = 0
0012F974    00000113
0012F978    00000000
0012F97C    00000113


[XXSafeEdit]在不停的调用这个,这个函数,这时候,我们就对其下条件断点进行中断条件过滤。直到我们按下的时候,我们才让它断下来。

我们按下的时候,断下来的栈大概是这样:
0012F9DC    0108D16A   /CALL 到 MapVirtualKeyA 来自 0108D167
0012F9E0    00000054   |Key = 54
0012F9E4    00000000   \Action = 0
0012F9E8    00000100
0012F9EC    00000000


好的,我们发现,它不是跳到[XXSafeEdit]模块里了,而是0108d167这个位置了。于是,我们就到那里去。

我们在那个点下断。

这里,大胆做个猜测,对于加密这个理论,一定是针对于明文的。那么在密文之前的某一时刻,一定是存在明文的。

那么,我们就继续向这段代码之前的代码跟踪。

-------对于这段代码的用途,和XX SafeEdit的一些其它用途,我就不多说了,让大家有多点的享受机会,具体自己跟跟。


在这里回朔跟踪,我们就能找到这个点
0108D0D2     51               push     ecx
0108D0D3     8B55 0C          mov      edx, dword ptr [ebp+C]
0108D0D6     52               push     edx
0108D0D7     E8 7CFEFFFF      call     0108CF58------------注意这里
0108D0DC     85C0             test     eax, eax-------------注意这里
0108D0DE     0F85 BF000000    jnz      0108D1A3
0108D0E4     8B4D FC          mov      ecx, dword ptr [ebp-4]---------这里下断
0108D0E7     8B51 24          mov      edx, dword ptr [ecx+24]
0108D0EA     33C0             xor      eax, eax
0108D0EC     8A02             mov      al, byte ptr [edx]
0108D0EE     8B4D F8          mov      ecx, dword ptr [ebp-8]


好的,我们在那个test之后的,108d0e4处下点,短下后,我们看栈

0012F9E8    00000100
0012F9EC    00000000
0012F9F0    0117CD16   ASCII "铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪 铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪铪 铪铪?...
0012F9F4    00000041

恩,这里,出现41了。41=VK_A.是的,PACH这个点,我们就能记录[某著名IM软件]的密码了。

这里,给出看见点的特征码8b4dfc8b512433c08a02

接下来,我们写个程序,pach之。

总结:

[某著名IM软件],的保护,比起之前NP保护,各有长短。去看,还是能破的。

稍后,提交PACH代码。和关于[某著名IM软件]的一些其它特性。
 

 


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理