- UID
- 9682
注册时间2006-3-19
阅读权限10
最后登录1970-1-1
周游历练
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
评分
-
查看全部评分
|