首页
社区
课程
招聘
[旧帖] [原创]爆破riijj_cm_20041217.zip_783 0.00雪花
发表于: 2016-2-4 23:54 1431

[旧帖] [原创]爆破riijj_cm_20041217.zip_783 0.00雪花

2016-2-4 23:54
1431
CrackMe提供者:riijj
原帖:http://bbs.pediy.com/showthread.php?t=8541

工具:od
平台:winxpsp3

这是一个多进程程序。主程序非常简单清晰。主要是创建进程sub3.ooo,
00401021  |.  51            push    ecx                              ; /pProcessInfo
00401022  |.  52            push    edx                              ; |pStartupInfo
00401023  |.  6A 00         push    0                                ; |CurrentDir = NULL
00401025  |.  6A 00         push    0                                ; |pEnvironment = NULL
00401027  |.  6A 03         push    3                                ; |CreationFlags = DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS
00401029  |.  6A 00         push    0                                ; |InheritHandles = FALSE
0040102B  |.  6A 00         push    0                                ; |pThreadSecurity = NULL
0040102D  |.  6A 00         push    0                                ; |pProcessSecurity = NULL
0040102F  |.  6A 00         push    0                                ; |CommandLine = NULL
00401031  |.  68 4C504000   push    0040504C                         ; |ModuleFileName = "sub3.ooo"
00401036  |.  FF15 08404000 call    dword ptr [<&KERNEL32.CreateProc>; \CreateProcessA

然后等待该进程退出。
00401077  |> /8D4424 5C     /lea     eax, dword ptr [esp+5C]
0040107B  |. |6A FF         |push    -1
0040107D  |. |50            |push    eax
0040107E  |. |FFD6          |call    esi                             ;  kernel32.WaitForDebugEvent
00401080  |.  8B4424 5C     |mov     eax, dword ptr [esp+5C]
00401084  |.  48            |dec     eax                             ;  Switch (cases 5..5)
00401085  |.  74 05         |je      short 0040108C
00401087  |.  83E8 04       |sub     eax, 4
0040108A  |.  74 13         |je      short 0040109F
0040108C  |>  8B4C24 64     |mov     ecx, dword ptr [esp+64]         ;  Default case of switch 00401084
00401090  |.  8B5424 60     |mov     edx, dword ptr [esp+60]
00401094  |.  68 02000100   |push    10002                           ;  UNICODE "LLUSERSPROFILE=C:\Documents and Settings\All Users"
00401099  |.  51            |push    ecx
0040109A  |.  52            |push    edx
0040109B  |.  FFD7          |call    edi                             ;  kernel32.ContinueDebugEvent
0040109D  |.^ EB D8         \jmp     short 00401077
0040109F  |> \5F            pop     edi                              ;  Case 5 of switch 00401084
004010A0  |.  33C0          xor     eax, eax
004010A2  |.  5E            pop     esi
004010A3  |.  81C4 B4000000 add     esp, 0B4
004010A9  \.  C2 1000       retn    10

sub3.ooo进程和主程序一样啥事不做,创建进程sub2.ooo,
00401021  |.  51            push    ecx                              ; /pProcessInfo
00401022  |.  52            push    edx                              ; |pStartupInfo
00401023  |.  6A 00         push    0                                ; |CurrentDir = NULL
00401025  |.  6A 00         push    0                                ; |pEnvironment = NULL
00401027  |.  6A 03         push    3                                ; |CreationFlags = DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS
00401029  |.  6A 00         push    0                                ; |InheritHandles = FALSE
0040102B  |.  6A 00         push    0                                ; |pThreadSecurity = NULL
0040102D  |.  6A 00         push    0                                ; |pProcessSecurity = NULL
0040102F  |.  6A 00         push    0                                ; |CommandLine = NULL
00401031  |.  68 30504000   push    00405030                         ; |ModuleFileName = "sub2.ooo"
00401036  |.  FF15 08404000 call    dword ptr [<&KERNEL32.CreateProc>; \CreateProcessA

在sub2.ooo进程中作者开始使用编程技巧,这种技巧类似于我曾看到的一些壳编程技巧,就是不直接调用API函数,改用函数指针的形式调用。表现在汇编代码中就是不能直接看到函数名,要走到调用处才能看到。同时作者尝试了对申请的虚拟内存写指令,并且运行中调用使用的技术。
sub2.ooo仍然是创建一个进程sub1.ooo,
0040117C  |.  6A 00         push    0
0040117E  |.  6A 00         push    0
00401180  |.  6A 03         push    3
00401182  |.  6A 00         push    0
00401184  |.  6A 00         push    0
00401186  |.  6A 00         push    0
00401188  |.  6A 00         push    0
0040118A  |.  68 30604000   push    00406030                         ;  ASCII "sub1.ooo"
0040118F  |.  FF15 D4674000 call    dword ptr [4067D4]                ;\CreateProcessA       

然后是一个类似的自定义调试循环,不同的是该循环不再是简单响应sub1.ooo退出消息,而是对某些特定情况进行了响应。当我试图分析有价值的响应时,发现sub1.ooo窗口出现不久,该程序收到了退出信息,所有进程退出了。
这说明sub1.ooo有反调试代码。载入sub1.ooo,发现程序是SDK框架,vc编译。sdk框架的程序结构是非常清晰的,看样子作者并不想太为难我们。
00401E13  |.  50            push    eax                              ; /pWndClassEx
00401E14  |.  FF15 BC504000 call    dword ptr [<&USER32.RegisterClas>; \RegisterClassExA
00401E1A  |.  E8 41FFFFFF   call    00401D60
00401E1F  |.  E8 0CFFFFFF   call    00401D30          ;设置定时器
在定时器函数中,
00401C69   .  50            push    eax                              ; /lppe
00401C6A   .  57            push    edi                              ; |hSnapshot
00401C6B   .  E8 06030000   call    <jmp.&KERNEL32.Process32First>   ; \Process32First
00401C70   >  8D4C24 3C     lea     ecx, dword ptr [esp+3C]
00401C74   .  6A 5C         push    5C
00401C76   .  51            push    ecx
00401C77   .  E8 14040000   call    00402090
00401C7C   .  83C4 08       add     esp, 8
00401C7F   .  8D70 01       lea     esi, dword ptr [eax+1]
00401C82   .  85C0          test    eax, eax
00401C84   .  75 04         jnz     short 00401C8A
00401C86   .  8D7424 3C     lea     esi, dword ptr [esp+3C]
00401C8A   >  68 5C614000   push    0040615C                         ;  ASCII "SUB1.OOO"
00401C8F   .  56            push    esi
00401C90   .  E8 6B030000   call    00402000
00401C95   .  83C4 08       add     esp, 8
00401C98   .  85C0          test    eax, eax
00401C9A   .  75 05         jnz     short 00401CA1
00401C9C   .  BB 01000000   mov     ebx, 1
00401CA1   >  68 50614000   push    00406150                         ;  ASCII "SUB2.OOO"
00401CA6   .  56            push    esi
00401CA7   .  E8 54030000   call    00402000
00401CAC   .  83C4 08       add     esp, 8
00401CAF   .  85C0          test    eax, eax
00401CB1   .  75 05         jnz     short 00401CB8
00401CB3   .  BD 01000000   mov     ebp, 1
00401CB8   >  68 44614000   push    00406144                         ;  ASCII "SUB3.OOO"
00401CBD   .  56            push    esi
00401CBE   .  E8 3D030000   call    00402000
00401CC3   .  83C4 08       add     esp, 8
00401CC6   .  85C0          test    eax, eax
00401CC8   .  75 08         jnz     short 00401CD2
00401CCA   .  C74424 14 010>mov     dword ptr [esp+14], 1
00401CD2   >  68 34614000   push    00406134                         ;  ASCII "CRACKME4.exe"
00401CD7   .  56            push    esi
00401CD8   .  E8 23030000   call    00402000
00401CDD   .  83C4 08       add     esp, 8
00401CE0   .  85C0          test    eax, eax
00401CE2   .  75 08         jnz     short 00401CEC
00401CE4   .  C74424 10 010>mov     dword ptr [esp+10], 1
00401CEC   >  8D5424 18     lea     edx, dword ptr [esp+18]
00401CF0   .  52            push    edx                              ; /lppe
00401CF1   .  57            push    edi                              ; |hSnapshot
00401CF2   .  E8 79020000   call    <jmp.&KERNEL32.Process32Next>    ; \Process32Next

很明显的检测进程代码。作者采用定时器函数简单检查4个进程是否存在,不是全部存在(意味着如我们这样进程被单独调试)就退出。爆破掉。现在可以专心看流程了。
随意输入用户名和密码,点注册按钮。不用我们找,程序自己就断在响应处理函数处。
00401F40  /.  55            push    ebp
00401F41  |.  8BEC          mov     ebp, esp
00401F43  |.  8B45 0C       mov     eax, dword ptr [ebp+C]
00401F46  |.  53            push    ebx
00401F47  |.  56            push    esi
00401F48  |.  3D 11010000   cmp     eax, 111
00401F4D  |.  57            push    edi
00401F4E  |.  75 10         jnz     short 00401F60
00401F50  |.  66:817D 10 EA>cmp     word ptr [ebp+10], 3EA
00401F56  |.  75 08         jnz     short 00401F60
00401F58  |.  60            pushad
00401F59  |.  B8 01000000   mov     eax, 1
00401F5E  |.  CC            int3
00401F5F  |.  61            popad
00401F60  |>  5F            pop     edi
00401F61  |.  5E            pop     esi
00401F62  |.  33C0          xor     eax, eax
00401F64  |.  5B            pop     ebx
00401F65  |.  5D            pop     ebp
00401F66  \.  C2 1000       retn    10

问题是该处理函数从上到下也不见真正的处理过程。显然是利用函数中的软中断和sub2.ooo交互。可是我们没法同时调试两个进程。至此,调试陷入了困境。我也曾再次调试sub2.ooo,但是程序捕获注册调试事件后的处理我没能独立分析清楚。主要是作者使用的SetThreadContex函数完全是空白。
在此,向daxia200N表示感谢。看了daxia200N的回帖,寥寥几句就把程序精华部分解析的清清楚楚。查了Msdn和winnt.h,结合程序反复学习,终于对该函数有了基本的了解。在此,同时向作者表示感谢。这个程序显示的一些技巧让我获益良多。
作为初学者,继续简单解析一下。
sub1.ooo进程分别在4处设置了软中断,每处利用eax寄存器标识事件,然后sub2.ooo根据eax标识进行相应处理。因为是直接利用eax,我猜想部分代码应该是使用的内联汇编代码。
eax=0ff 传递注册响应函数入口地址。
eax=0fe 传递用户名和注册码地址。
eax=0   传递输入的用户名和注册码。
eax=1   通知父进程用户点击了注册按钮。
当sub2.ooo接到注册通知后,
0040123E  |.  68 80674000   |push    00406780                                  ;  Case 1 of switch 0040121D
00401243  |.  E8 E8FDFFFF   |call    00401030        ;计算用户名
00401248  |.  68 A0674000   |push    004067A0
0040124D  |.  E8 AEFDFFFF   |call    00401000         ;计算注册码

程序对输入的用户名和注册码分别计算,安然写回sub1.ooo,并且利用SetThreadContext函数调整sub1.ooo进程指令寄存器指向真正的响应函数。该函数貌似比较复杂,直接爆破。在第一个跳转处爆破即可。由于作者在sub2.ooo中计算用户名使用了除法运算,我仅爆破了验证部分,所以用户名不能为空。很晚了,到此为止。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//