| 
注册时间2006-3-19
阅读权限10
最后登录1970-1-1UID9682 周游历练 
 
 TA的每日心情|  | 郁闷 2019-5-27 22:42
 | 
|---|
 签到天数: 3 天 [LV.2]偶尔看看I | 
 
| 破解声明:我只是一只小菜鸟,这是我第一次弄分析算法并且写注册机,如有失误的地方还望各位纠正. 破解过程:
 有壳,尝试脱壳机脱,失败.OD载入运行,随便输入注册码发现是由标签提示,说来也巧,以前在看雪看过用钩子触发注册码校验的,于是想到试一下,重新载入然后在SetWindowsHookExA下断,运行发现 除开MFC自己的钩子,程序还会安装一个键盘钩子
 ; [GetCurrentThreadId
 00401905  |.  50            push    eax                              ; /ThreadID
 00401906  |.  56            push    esi                              ; |hModule
 00401907  |.  68 50184000   push    00401850                         ; |Hookproc = cm_nf_v0.00401850
 0040190C  |.  6A 02         push    2                                ; |HookType = WH_KEYBOARD
 0040190E  |.  FF15 1C244200 call    dword ptr [42241C]               ; \SetWindowsHookExA
 然后直接看钩子函数:
 004018BE   .  66:3D 5A00    cmp     ax, 5A
 004018C2   .  77 05         ja      short 004018C9
 004018C4   .  E8 A7FEFFFF   call    00401770                ;校验注册码 键盘输入注册码的时候输入的是大写字母就会进入
 
 
 这里是进行注册码校验:
 004017B1   .  50            push    eax
 004017B2   .  B8 E8030000   mov     eax, 3E8
 004017B7   .  83C0 02       add     eax, 2
 004017BA   .  50            push    eax
 004017BB   .  FF35 D4F04200 push    dword ptr [42F0D4]
 004017C1   .  B8 CC174000   mov     eax, 004017CC
 004017C6   .  50            push    eax
 004017C7   .^ E9 84FDFFFF   jmp     00401550                         ;  直接跳到GetDlgItemTextA+2 取注册码
 004017CC   .  50            push    eax
 004017CD   .  8F45 FC       pop     dword ptr [ebp-4]
 004017D0   .  C785 F8FEFFFF>mov     dword ptr [ebp-108], 0
 004017DA   .  EB 0F         jmp     short 004017EB
 004017DC   >  8B85 F8FEFFFF mov     eax, dword ptr [ebp-108]
 004017E2   .  83C0 01       add     eax, 1
 004017E5   .  8985 F8FEFFFF mov     dword ptr [ebp-108], eax
 004017EB   >  83BD F8FEFFFF>cmp     dword ptr [ebp-108], 8
 004017F2   .  73 1E         jnb     short 00401812
 004017F4   .  8B8D F8FEFFFF mov     ecx, dword ptr [ebp-108]
 004017FA   .  0FBE940D FCFE>movsx   edx, byte ptr [ebp+ecx-104]
 00401802   .  8B85 F4FEFFFF mov     eax, dword ptr [ebp-10C]
 00401808   .  03C2          add     eax, edx
 0040180A   .  8985 F4FEFFFF mov     dword ptr [ebp-10C], eax
 00401810   .^ EB CA         jmp     short 004017DC                   ;  取注册码前八个字符的和
 00401812   >  81BD F4FEFFFF>cmp     dword ptr [ebp-10C], 272
 0040181C   .  75 2A         jnz     short 00401848                   ;  如果总和=0x270
 0040181E   .  0FBE8D FCFEFF>movsx   ecx, byte ptr [ebp-104]
 00401825   .  83F9 4E       cmp     ecx, 4E
 00401828   .  75 1E         jnz     short 00401848                   ;  第一个字符必须是 N
 0040182A   .  8D95 FCFEFFFF lea     edx, dword ptr [ebp-104]
 00401830   .  52            push    edx
 00401831   .  E8 5AFEFFFF   call    00401690                         ;  用注册码做KEY 解密代码
 00401836   .  83C4 04       add     esp, 4
 00401839   .  8D85 FCFEFFFF lea     eax, dword ptr [ebp-104]
 0040183F   .  50            push    eax
 00401840   .  E8 ABFDFFFF   call    004015F0                         ;  执行解密后的代码
 
 00401690部分代码:
 004016DC  |> /8B4C24 1C     /mov     ecx, dword ptr [esp+1C]
 004016E0  |. |8A06          |mov     al, byte ptr [esi]
 004016E2  |. |8A51 01       |mov     dl, byte ptr [ecx+1]            ;  取注册码的第二个字符为KEY
 004016E5  |. |32C2          |xor     al, dl                          ;  异或
 004016E7  |. |8D5424 14     |lea     edx, dword ptr [esp+14]
 004016EB  |. |884424 13     |mov     byte ptr [esp+13], al
 004016EF  |. |52            |push    edx
 004016F0  |. |8D4424 17     |lea     eax, dword ptr [esp+17]
 004016F4  |. |6A 01         |push    1
 004016F6  |. |50            |push    eax
 004016F7  |. |56            |push    esi
 004016F8  |. |FFD5          |call    ebp                             ;  kernel32.GetCurrentProcess
 004016FA  |. |50            |push    eax
 004016FB  |. |FFD3          |call    ebx                             ;  WriteProcessMemory 写回解密后的代码
 004016FD  |. |46            |inc     esi
 004016FE  |. |8D0C37        |lea     ecx, dword ptr [edi+esi]
 00401701  |. |83F9 78       |cmp     ecx, 78                         ;  解密0x78个字节
 00401704  |.^\7C D6         \jl      short 004016DC
 00401706  |.  6A 00         push    0                                ; /pOldProtect = NULL
 00401708  |.  6A 40         push    40                               ; |NewProtect = PAGE_EXECUTE_READWRITE
 0040170A  |.  6A 55         push    55                               ; |Size = 55 (85.)
 0040170C  |.  68 60154000   push    00401560                         ; |Address = cm_nf_v0.00401560
 00401711  |.  FF15 80224200 call    dword ptr [422280]               ; \VirtualProtect
 00401717  |.  BE 60154000   mov     esi, 00401560
 0040171C  |.  BF F1FFFFFF   mov     edi, -0F
 00401721  |.  83C6 0F       add     esi, 0F
 00401724  |.  81EF 60154000 sub     edi, 00401560
 0040172A  |>  8B5424 1C     /mov     edx, dword ptr [esp+1C]
 0040172E  |.  8A0E          |mov     cl, byte ptr [esi]
 00401730  |.  8A42 02       |mov     al, byte ptr [edx+2]            ;  取注册码第三个字符作为KEY 解密第二部分代码
 00401733  |.  8D5424 13     |lea     edx, dword ptr [esp+13]
 00401737  |.  32C1          |xor     al, cl
 00401739  |.  8D4C24 14     |lea     ecx, dword ptr [esp+14]
 0040173D  |.  51            |push    ecx
 0040173E  |.  6A 01         |push    1
 00401740  |.  52            |push    edx
 00401741  |.  56            |push    esi
 00401742  |.  884424 23     |mov     byte ptr [esp+23], al
 00401746  |.  FFD5          |call    ebp                             ;  kernel32.GetCurrentProcess
 00401748  |.  50            |push    eax
 00401749  |.  FFD3          |call    ebx                             ;  WriteProcessMemory 写回解密后的代码
 0040174B  |.  46            |inc     esi
 0040174C  |.  8D0437        |lea     eax, dword ptr [edi+esi]
 0040174F  |.  83F8 55       |cmp     eax, 55
 00401752  |.^ 7C D6         \jl      short 0040172A
 
 00401690这里会解密00401560和004015F0这两个函数里面的代码 注册码不对的话会解密成错误的代码,使程序出错.有意思的是在00401560和004015F0里面还进行了一次注册码的校验,如果注册码没完全正确的话那个对话框是不会出来的了
 解密后004015F0里面的代码:
 0040165C  |. /75 26         jnz     short 00401684                   ;  注册码第十个必须为X
 0040165E  |. |8078 0A 54    cmp     byte ptr [eax+A], 54
 00401662  |. |75 20         jnz     short 00401684                   ;  注册码第十一个必须为T
 00401664  |. |8D5424 10     lea     edx, dword ptr [esp+10]
 00401668  |. |C74424 10 000>mov     dword ptr [esp+10], 0
 00401670  |. |52            push    edx                              ; /pThreadId
 00401671  |. |6A 00         push    0                                ; |CreationFlags = 0
 00401673  |. |6A 00         push    0                                ; |pThreadParm = NULL
 00401675  |. |68 60154000   push    00401560                         ; |ThreadFunction = cm_nf_v0.00401560
 0040167A  |. |6A 00         push    0                                ; |StackSize = 0
 0040167C  |. |6A 00         push    0                                ; |pSecurity = NULL
 0040167E  |. |FF15 90224200 call    dword ptr [422290]               ; \CreateThread 弹出对话框  这里里面还会比较注册码
 
 解密后00401560里面的代码:
 00401570   .  68 FF000000   push    0FF                              ; /Count = FF (255.)
 00401575   .  50            push    eax                              ; |Buffer
 00401576   .  68 EA030000   push    3EA                              ; |ControlID = 3EA (1002.)
 0040157B   .  51            push    ecx                              ; |hWnd => 001309B8 ('N's FirsT cRack Me V0.4',class='#32770')
 0040157C   .  FF15 30244200 call    dword ptr [422430]               ; \GetDlgItemTextA 取注册码
 00401582   .  A1 D0F04200   mov     eax, dword ptr [42F0D0]
 00401587   .  85C0          test    eax, eax
 00401589   .  74 58         je      short 004015E3
 0040158B   .  0FBE5424 07   movsx   edx, byte ptr [esp+7]            ;  取第八个字符
 00401590   .  0FBE4424 03   movsx   eax, byte ptr [esp+3]            ;  取第四个字符
 00401595   .  03D0          add     edx, eax                         ;  相加 是否等于0x84
 00401597   .  81FA 84000000 cmp     edx, 84
 0040159D   .  75 44         jnz     short 004015E3
 0040159F   .  57            push    edi
 004015A0   .  8D7C24 04     lea     edi, dword ptr [esp+4]
 004015A4   .  83C9 FF       or      ecx, FFFFFFFF
 004015A7   .  33C0          xor     eax, eax
 004015A9   .  F2:AE         repne   scas byte ptr es:[edi]
 004015AB   .  F7D1          not     ecx
 004015AD   .  49            dec     ecx
 004015AE   .  5F            pop     edi
 004015AF   .  83F9 0C       cmp     ecx, 0C                          ;  注册码长度是否为是12
 004015B2   .  75 2F         jnz     short 004015E3
 004015B4   .  807C24 0B 5A  cmp     byte ptr [esp+B], 5A             ;  最后一个字母是否为Z
 004015B9   .  75 28         jnz     short 004015E3
 004015BB   .  807C24 08 41  cmp     byte ptr [esp+8], 41             ;  第九个字符是否小于A
 004015C0   .  7D 21         jge     short 004015E3
 004015C2   .  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
 004015C4   .  68 CCB04200   push    0042B0CC                         ; |Title = "Great!"
 004015C9   .  68 C0B04200   push    0042B0C0                         ; |Text = "Good Job!"
 004015CE   .  6A 00         push    0                                ; |hOwner = NULL
 004015D0   .  FF15 34244200 call    dword ptr [422434]               ; \MessageBoxA
 004015D6   .  8B0D D0F04200 mov     ecx, dword ptr [42F0D0]
 004015DC   .  51            push    ecx                              ; /hHook => 01430B21
 004015DD   .  FF15 38244200 call    dword ptr [422438]               ; \UnhookWindowsHookEx
 
 根据如上算法 用VB写了如下拙劣的KeyGen:
 
 Private Sub cmdKEY_Click()
 Dim key As String
 Do
 key = getkey()
 Loop While key = ""
 txtText1.Text = key
 End Sub
 
 Function getkey() As String
 Dim tmpstr As String
 Dim L As Integer
 Dim K As Integer
 K = (78 + 76 + &H43 + Asc("P")) + &H41
 I = 0
 Do While K <= 626
 If I = 5 Then
 L = &H41
 Else
 L = Int(Rnd() * (90 - 65 + 1) + 65)
 End If
 K = K + L
 tmpstr = tmpstr + Chr(L)
 If 626 - K >= 65 And 626 - K <= 90 Then
 L = 626 - K
 tmpstr = tmpstr + Chr(L - 2)
 getkey = "NLP" & Chr(&H43) & tmpstr & "A0XTZ"
 Exit Do
 End If
 I = I + 1
 Loop
 End Function
 Private Sub Form_Load()
 Randomize (Now())
 End Sub
 
 小节:总的说来,这个crackme代码是非常清晰的,算法也非常简单的(复杂的话就没本菜鸟的机会了),在没有脱壳的时候,可以把算法部分直接拿到IDA里面F5就看到代码了,这点是本菜鸟在昨天晚上想到的办法(呵呵 有点投机取巧 要把汇编详细的还原成原始代码,本人还是非常非常困难的).整个程序有三个校验注册码的地方,而且都是相互关联,必须解决了第一个才能进行下一步,而且在解密代码的部分的时候是难倒人了的,没办法,我是只有穷举了.
 
 | 
 
x本帖子中包含更多资源您需要 登录 才可以下载或查看,没有账号?加入我们 
  评分
查看全部评分
 |