新手破解练习Crackme160之096 - register
-
脱壳
xp下用PEiD的通用脱壳插件去壳成功~
-
去NAG
OD载入去壳后程序, 单步执行到00438517处弹出提示框, 所以我们把这行nop掉, 不让弹, 保存~
-
用户名与注册码
由IDR反编译源码分析可得注册码输入框Edit1change事件入口00437D28, 向下找到关键算法方法00435DC8处, 进入方法分析具体算法(用户名的输入框是Edit2, 事件有验证用户名长度是否6位, 是的话改变注册码框的可写性)
1). 00435E00 ~ 00435E13 循环6次将每一位值加起来存到[ebx]中
2).
[ebx] += len(user)
[ebx] *= 0x15C10E
[ebx] /= 3
[ebx] += 0x29A
[ebx] /= 1388
[ebx] *= len(user)
[ebx] *= user[2]
[ebx] *= user[4]
if([ebx] <= 0x5F5E0FF) { goto E77; }
if([ebx] < 0x3B9ACA00) { goto EB2; }
E77:
[ebx] += len(user)
[ebx] *= user[0]
[ebx] *= [43A99C]
if([ebx] >= 0) { goto EA2; }
[ebx] *= -1
EA2:
if([ebx] <= 0x5F5E0FF) { goto E77; }
if([ebx] >= 0x3B9ACA00 )算法分析完成, 开始写注册机: keygen.c
#include <stdio.h>
#include <string.h>
int main() {
char name[7] = {0};
int len = 0;
long code = 0, code1, val = 0xC27E1BDB;
while(len != 6){
printf("请输入用户名(6位): ");
scanf("%s", name);
len = strlen(name);
}
for(int i=0; i<6; i++){
code += name[i];
}
code += len;
code *= 0x15C10E;
code /= 3;
code += 0x29A;
code /= 0x1388;
code *= len;
code *= name[2];
code *= name[4];
if(code <= 0x5F5E0FF) goto E77;
if(code >= 0x3B9ACA00) {
E77:
code += len;
code *= name[0];
code *= val;
code &= 0xFFFFFFFF;
if(code < 0) code *= -1;
if(code <= 0x5F5E0FF) goto E77;
if(code >= 0x3B9ACA00) goto E77;
}
code1 = code;
EB6:
code1 /= len;
code1 = code1 - val / code1;
if(code1 < 0x2710) { code1 *= code1; } //平方
code1 &= 0xFFFFFFFF;
if(code1 <= 0x270F) goto EB6;
if(code1 >= 0x186A0) goto EB6;
printf("用户名为: %s\n注册码为: %ld\n滑块码为: %ld\n", name, code, code1);
getchar();getchar();
return 0;
}
运行示例:
用户名为: abc123
注册码为: 826371706
滑块码为: 72640
输入测试正常~
-
滑块验证
这个比较简单, 需要上一步完成后便可以得到正确的码~
-
文件验证
IDR中查看所有方法可知, 在TForm1.FormCreate事件(00435F70)中包含了文件验证lockey.key 和 register.exe, 进入方法, 反编译代码如下:
Unit1::TForm1.FormCreate
00435F70 push ebp
00435F71 mov ebp,esp
00435F73 add esp,0FFFFFEB0
00435F79 push ebx
00435F7A xor ecx,ecx
00435F7C mov dword ptr [ebp-150],ecx
00435F82 mov ebx,eax
00435F84 xor eax,eax
00435F86 push ebp
00435F87 push 436234
00435F8C push dword ptr fs:[eax]
00435F8F mov dword ptr fs:[eax],esp
00435F92 mov al,63
00435F94 call 004358CC
00435F99 mov [0043A99C],eax
00435F9E mov edx,436248; 'lockey.key'
00435FA3 lea eax,[ebp-14C]
00435FA9 call @Assign
00435FAE mov edx,4
00435FB3 lea eax,[ebp-14C]
00435FB9 call @ResetFile
00435FBE call IOResult
00435FC3 test eax,eax
>00435FC5 jne 0043603C
00435FC7 mov eax,436248; 'lockey.key'
00435FCC call 00435954
00435FD1 cmp eax,5E62823F
>00435FD6 jne 00436002
00435FD8 mov byte ptr ds:[43A995],1
00435FDF mov eax,dword ptr [ebx+28C]; TForm1.Label25:TLabel
00435FE5 mov eax,dword ptr [eax+50]; TLabel.?f50:dword
00435FE8 mov edx,80000008
00435FED call TFont.SetColor
00435FF2 mov edx,43625C; 'valid'
00435FF7 mov eax,dword ptr [ebx+28C]; TForm1.Label25:TLabel
00435FFD call TControl.SetText
00436002 mov eax,436248; 'lockey.key'
00436007 call 00435954
0043600C cmp eax,5E62823F
>00436011 je 00436058
00436013 lea eax,[ebp-14C]
00436019 call @Close
0043601E call @_IOTest
00436023 mov byte ptr ds:[43A995],0
0043602A mov edx,43626C; 'invalid'
0043602F mov eax,dword ptr [ebx+28C]; TForm1.Label25:TLabel
00436035 call TControl.SetText
>0043603A jmp 00436058
0043603C mov eax,[0043A7AC]; 0x0
00436041 mov eax,dword ptr [eax+28C]; TForm1.Label25:TLabel
00436047 mov edx,43627C; 'not found'
0043604C call TControl.SetText
00436051 mov byte ptr ds:[43A995],0
00436058 mov eax,436290; 'register.exe'
0043605D call 00435954
00436062 mov [0043A998],eax
00436067 cmp dword ptr ds:[43A998],53E8C9D0
>00436071 je 0043608E
00436073 push 2010
00436078 push 4362A0; 'File patched (?)!'
0043607D push 4362B4; 'File REGISTER.EXE has been modified.\rIf you didn't change anything try to get a genuine one\r(or try without patching... :-) )'
00436082 push 0
00436084 call USER32.MessageBoxA
00436089 call @Halt0
0043608E push 0
00436090 mov eax,[00439AA8]; ^Application:TApplication
00436095 mov eax,dword ptr [eax]
00436097 mov eax,dword ptr [eax+24]; TApplication.?f24:dword
0043609A push eax
0043609B call USER32.ShowWindow
004360A0 call 00435A84
004360A5 mov edx,43633C; 'unregistered'
004360AA mov eax,dword ptr [ebx+1F4]; TForm1.Label4:TLabel
004360B0 call TControl.SetText
004360B5 lea edx,[ebp-150]
004360BB mov eax,dword ptr [ebx+204]; TForm1.TrackBar3:TTrackBar
004360C1 mov eax,dword ptr [eax+130]; TTrackBar.Position:Integer
004360C7 call IntToStr
004360CC mov edx,dword ptr [ebp-150]
004360D2 mov eax,dword ptr [ebx+210]; TForm1.Label5:TLabel
004360D8 call TControl.SetText
004360DD lea edx,[ebp-150]
004360E3 mov eax,dword ptr [ebx+1FC]; TForm1.TrackBar1:TTrackBar
004360E9 mov eax,dword ptr [eax+130]; TTrackBar.Position:Integer
004360EF call IntToStr
004360F4 mov edx,dword ptr [ebp-150]
004360FA mov eax,dword ptr [ebx+214]; TForm1.Label6:TLabel
00436100 call TControl.SetText
00436105 lea edx,[ebp-150]
0043610B mov eax,dword ptr [ebx+200]; TForm1.TrackBar2:TTrackBar
00436111 mov eax,dword ptr [eax+130]; TTrackBar.Position:Integer
00436117 call IntToStr
0043611C mov edx,dword ptr [ebp-150]
00436122 mov eax,dword ptr [ebx+218]; TForm1.Label7:TLabel
00436128 call TControl.SetText
0043612D lea edx,[ebp-150]
00436133 mov eax,dword ptr [ebx+208]; TForm1.TrackBar4:TTrackBar
00436139 mov eax,dword ptr [eax+130]; TTrackBar.Position:Integer
0043613F call IntToStr
00436144 mov edx,dword ptr [ebp-150]
0043614A mov eax,dword ptr [ebx+21C]; TForm1.Label8:TLabel
00436150 call TControl.SetText
00436155 lea edx,[ebp-150]
0043615B mov eax,dword ptr [ebx+20C]; TForm1.TrackBar5:TTrackBar
00436161 mov eax,dword ptr [eax+130]; TTrackBar.Position:Integer
00436167 call IntToStr
0043616C mov edx,dword ptr [ebp-150]
00436172 mov eax,dword ptr [ebx+220]; TForm1.Label9:TLabel
00436178 call TControl.SetText
0043617D mov edx,9
00436182 mov eax,dword ptr [ebx+204]; TForm1.TrackBar3:TTrackBar
00436188 call TTrackBar.SetPosition
0043618D mov edx,9
00436192 mov eax,dword ptr [ebx+1FC]; TForm1.TrackBar1:TTrackBar
00436198 call TTrackBar.SetPosition
0043619D mov edx,9
004361A2 mov eax,dword ptr [ebx+200]; TForm1.TrackBar2:TTrackBar
004361A8 call TTrackBar.SetPosition
004361AD mov edx,9
004361B2 mov eax,dword ptr [ebx+208]; TForm1.TrackBar4:TTrackBar
004361B8 call TTrackBar.SetPosition
004361BD mov edx,9
004361C2 mov eax,dword ptr [ebx+20C]; TForm1.TrackBar5:TTrackBar
004361C8 call TTrackBar.SetPosition
004361CD xor edx,edx
004361CF mov eax,dword ptr [ebx+1DC]; TForm1.Edit1:TEdit
004361D5 call TControl.SetEnabled
004361DA xor edx,edx
004361DC mov eax,dword ptr [ebx+1FC]; TForm1.TrackBar1:TTrackBar
004361E2 call TControl.SetEnabled
004361E7 xor edx,edx
004361E9 mov eax,dword ptr [ebx+200]; TForm1.TrackBar2:TTrackBar
004361EF call TControl.SetEnabled
004361F4 xor edx,edx
004361F6 mov eax,dword ptr [ebx+204]; TForm1.TrackBar3:TTrackBar
004361FC call TControl.SetEnabled
00436201 xor edx,edx
00436203 mov eax,dword ptr [ebx+208]; TForm1.TrackBar4:TTrackBar
00436209 call TControl.SetEnabled
0043620E xor edx,edx
00436210 mov eax,dword ptr [ebx+20C]; TForm1.TrackBar5:TTrackBar
00436216 call TControl.SetEnabled
0043621B xor eax,eax
0043621D pop edx
0043621E pop ecx
0043621F pop ecx
00436220 mov dword ptr fs:[eax],edx
00436223 push 43623B
00436228 lea eax,[ebp-150]
0043622E call @LStrClr
00436233 ret
<00436234 jmp @HandleFinally
<00436239 jmp 00436228
0043623B pop ebx
0043623C mov esp,ebp
0043623E pop ebp
0043623F ret
在00435FD1 cmp eax,5E62823F处有个关键比较, 所以上一行 00435FCC call 00435954 应该就是关键算法了, 我们跟进去瞧瞧, 代码如下:
Unit1::sub_00435954
00435954 push ebp
00435955 mov ebp,esp
00435957 add esp,0FFFFF6D0
0043595D push ebx
0043595E push esi
0043595F mov dword ptr [ebp-10],eax
00435962 mov eax,dword ptr [ebp-10]
00435965 call @LStrAddRef
0043596A lea ebx,[ebp-0C]
0043596D xor eax,eax
0043596F push ebp
00435970 push 435A75
00435975 push dword ptr fs:[eax]
00435978 mov dword ptr fs:[eax],esp
0043597B mov eax,[00439AE4]; ^FileMode:Byte
00435980 mov byte ptr [eax],0
00435983 mov edx,dword ptr [ebp-10]
00435986 lea eax,[ebp-15C]
0043598C call @Assign
00435991 mov edx,4
00435996 lea eax,[ebp-15C]
0043599C call @ResetFile
004359A1 call IOResult
004359A6 test eax,eax
>004359A8 jne 00435A58
004359AE lea eax,[ebp-15C]
004359B4 call @FileSize
004359B9 call @_IOTest
004359BE mov edx,eax
004359C0 sar edx,1
>004359C2 jns 004359C7
004359C4 adc edx,0
004359C7 lea eax,[ebp-15C]
004359CD call @Seek
004359D2 call @_IOTest
004359D7 lea eax,[ebp-15C]
004359DD call @FileSize
004359E2 call @_IOTest
004359E7 mov esi,eax
004359E9 dec esi
004359EA lea eax,[ebp-15C]
004359F0 call @FilePos
004359F5 call @_IOTest
004359FA sub esi,eax
004359FC mov dword ptr [ebp-8],esi
004359FF cmp dword ptr [ebp-8],1F4
>00435A06 jle 00435A0F
00435A08 mov dword ptr [ebp-8],1F4
00435A0F push 0
00435A11 lea edx,[ebp-930]
00435A17 mov ecx,dword ptr [ebp-8]
00435A1A lea eax,[ebp-15C]
00435A20 call @BlockRead
00435A25 call @_IOTest
00435A2A lea eax,[ebp-15C]
00435A30 call @Close
00435A35 call @_IOTest
00435A3A lea eax,[ebp-930]
00435A40 mov dword ptr [ebp-4],eax
00435A43 xor eax,eax
00435A45 xor ecx,ecx
00435A47 mov edi,dword ptr [ebp-4]
00435A4A add eax,dword ptr [edi+ecx*4]
00435A4D inc ecx
00435A4E cmp ecx,dword ptr [ebp-8]
<00435A51 jl 00435A4A
00435A53 mov dword ptr [ebp-0C],eax
>00435A56 jmp 00435A5F
00435A58 mov byte ptr ds:[43A995],0
00435A5F xor eax,eax
00435A61 pop edx
00435A62 pop ecx
00435A63 pop ecx
00435A64 mov dword ptr fs:[eax],edx
00435A67 push 435A7C
00435A6C lea eax,[ebp-10]
00435A6F call @LStrClr
00435A74 ret
<00435A75 jmp @HandleFinally
<00435A7A jmp 00435A6C
00435A7C mov eax,dword ptr [ebx]
00435A7E pop esi
00435A7F pop ebx
00435A80 mov esp,ebp
00435A82 pop ebp
00435A83 ret
这段代码里面我们又看到了几个关键函数 FileSize, Seek, FilePos, BlockRead 同理还得分别进去看, 对应都有算法, 所以我们在OD中找到对应的位置下相关入口断点~ 接着便是慢慢的分析了~
我们先创建好lockey.key文件, 写入80字节内容(因为算法中有除以4的运算,所以整个4的倍数的)"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()_+'-=[]"
1). eax = filesize (00404BDD) 假设有80字节 -- filesize
2). eax /= 4 (00404BE9) (20)
3). edx=eax sar 1 => edx /= 2 (004359C0) (10)
4). eax = edx * 4 (00404DA4) (40) -- seek 文件指针移动到了40的位置了
5). eax += 1 (00404DB0) (41)
6). eax = filesize (80) -- filesize
7). eax /= 4 (20)
8). esi = eax, esi -= 1 (004359E9) (19)
9). esi -= eax; (9)
10). eax = (40) / 4 (00404BA9) (10) -- filepos
11). esi -= eax (004359FA) (9)
12). eax = esi * 4 (00404B03) (36) -- BlockRead 从文件40位置开始读取36字节
13). str = "EFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()_+`" (00404B06)
14). eax = str每4位相加(ESI 9次循环) = 60848AA1
15). eax ?= 0x5E62823F, (00435FD1) 相等则验证成功
到此算法分析完成~ 就是从文件的某个位置开始读取一些内容, 然后加起来与固定值比较
假设循环次数ESI = 1, 那么就有 (filesize / 4 - 1) - filesize / 4 / 2 = 1 得到 filesize = 16
再正算出 文件取内容位置 = 16 / 4 / 2 * 4 = 8, 取4字节内容, 所以文件内容即为(16进制):
00 00 00 00 00 00 00 00 3F 82 62 5E 00 00 00 00 (其中00可任意16进制数)
重新运行程序验证通过, 进入00436058, 开始验证第二个文件register.exe, 用了同样的算法, 结果与0x53E8C9D0比较, 原文件验证通过(未脱壳的文件), 所以破解时, 原文件得保留, 其他脱壳, 去NAG等文件需要另存为, 不然可能这步会验证不过~, 弹框提示文件被修改过~, 到此所有破解完成~
1~160每个破解过程,在吾爱破解论坛都有高手破解过了,也有整理好现成的, 我这边主要就是自己动手操作的过程,与他们的不太一样
附上高手们的连接: 点击前往查看
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载
新人入门教程"玩玩破解,写给新人看" 点击前往查看
我就是从这里开始的,对我这样的小白感觉超级友好~
下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~


浙公网安备 33010602011771号