【文章标题】: 【原创】Bxm的第3个CrackMe分析
【文章作者】: domin
【软件名称】: Bxm的第3个CrackMe
【下载地址】: http://bbs.pediy.com/attachment.php?s=&attachmentid=3014
【使用工具】: OD
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
----------------------------------------------------------------------
----------
第一次发分析贴,请多指教,另请版主给个上传附件权限吧
【详细过程】
一、反调试
这个程序一用OD调试就会退出,具体怎么弄的我还没搞清楚,我真的是新手:),反正他是用ExitProcess退出,那我们
就跟一下。看到下面的代码:
004023C9 . 3BF4 cmp esi, esp
004023CB . E8 BAFBFFFF call <jmp.&MSVCRTD._chkesp>
004023D0 . 837D C8 00 cmp dword ptr [ebp-38], 0
004023D4 EB 42 jmp short 00402407 ; 改这里
004023D6 . 837D CC 00 cmp dword ptr [ebp-34], 0
004023DA . 75 2B jnz short 00402407
004023DC . 837D D8 00 cmp dword ptr [ebp-28], 0
004023E0 . 75 25 jnz short 00402407
004023E2 . 837D DC 00 cmp dword ptr [ebp-24], 0
004023E6 . 75 1F jnz short 00402407
004023E8 . 837D E0 00 cmp dword ptr [ebp-20], 0
004023EC . 75 19 jnz short 00402407
004023EE . 837D D0 00 cmp dword ptr [ebp-30], 0
004023F2 . 75 13 jnz short 00402407
004023F4 . 837D D4 00 cmp dword ptr [ebp-2C], 0
004023F8 . 75 0D jnz short 00402407
004023FA . 8B55 E4 mov edx, [ebp-1C]
004023FD . 81E2 80000000 and edx, 80
00402403 . 85D2 test edx, edx
00402405 . 74 11 je short 00402418
00402407 > 8BF4 mov esi, esp
00402409 . 6A 00 push 0 ; /ExitCode = 0
0040240B . FF15 9C734100 call [<&KERNEL32.ExitProcess>] ; \ExitProcess
00402411 . 3BF4 cmp esi, esp
从004023D6开始有一系列的判断,如果有一点不对就转00402407,那些判断具体是些什么我们先不管它吧,我们注意到
跳到00402407的严重后果就是进程终止,那我们先改一下将004023D4的代码改成jmp short 00402418,然后复制到
可执行文件保存文件。再ctrl-f2重新开始,我们就可以正常的跟踪它了。
二、算法分析
ctrl-n看了下,函数很多,根据经验(其实也没多少经验:))在strcpy上设了断点,F9,程序运行,在对话框中输入
用户名:abcdefg,序列号:12345678确定,程序断下
00401A0D |. E8 EA050000 call <jmp.&MSVCRTD.strcpy> ; \strcpy
00401A12 |. 83C4 08 add esp, 8
00401A15 |. 8B4D FC mov ecx, [ebp-4]
00401A18 |. 83C1 60 add ecx, 60
一看eax中就是放用户名的缓冲区指针,看来这个地方差不多,再看后面
00401A0D |. E8 EA050000 call <jmp.&MSVCRTD.strcpy> ; \strcpy
00401A12 |. 83C4 08 add esp, 8
00401A15 |. 8B4D FC mov ecx, [ebp-4]
00401A18 |. 83C1 60 add ecx, 60
00401A1B |. E8 58050000 call <jmp.&MFC42D.#2640>
00401A20 |. 83F8 05 cmp eax, 5 ; 判断长度是否小于5
00401A23 |. 7D 18 jge short 00401A3D
00401A25 |. 6A 00 push 0
00401A27 |. 6A 00 push 0
00401A29 |. 8D95 7CFFFFFF lea edx, [ebp-84]
00401A2F |. 52 push edx
00401A30 |. 8B4D FC mov ecx, [ebp-4]
00401A33 |. E8 3A050000 call <jmp.&MFC42D.#3517> ; 弹对话框告诉你用户名太短
00401A38 |. E9 F3010000 jmp 00401C30
00401A3D |> 8B4D FC mov ecx, [ebp-4] ; 长度符合条件的话就跳到这里了
00401A40 |. 83C1 60 add ecx, 60
00401A43 |. E8 30050000 call <jmp.&MFC42D.#2640> ; 取长度
00401A48 |. 8945 A8 mov [ebp-58], eax
00401A4B |. C745 AC 00000>mov dword ptr [ebp-54], 0
00401A52 |. EB 09 jmp short 00401A5D
00401A54 |> 8B45 AC /mov eax, [ebp-54] ; for(V_54=0;V_54<V_58;V_54++)
00401A57 |. 83C0 01 |add eax, 1
00401A5A |. 8945 AC |mov [ebp-54], eax
00401A5D |> 8B4D AC mov ecx, [ebp-54]
00401A60 |. 3B4D A8 |cmp ecx, [ebp-58]
00401A63 |. 7D 13 |jge short 00401A78
00401A65 |. 8B55 AC |mov edx, [ebp-54]
00401A68 |. 0FBE4415 E4 |movsx eax, byte ptr [ebp+edx-1C] ; 取字符
00401A6D |. 8B4D 9C |mov ecx, [ebp-64] ; 变量V_64初值为1
00401A70 |. 0FAFC8 |imul ecx, eax
00401A73 |. 894D 9C |mov [ebp-64], ecx ; 每个字符累乘,放入变量V_64中
00401A76 |.^ EB DC \jmp short 00401A54
00401A78 |> C745 AC 00000>mov dword ptr [ebp-54], 0
00401A7F |> 8B45 9C /mov eax, [ebp-64] ; 把上步结果变成10进制数的字符,不过顺序是倒的
00401A82 |. 99 |cdq ; 用AX和DX的符号位填充EAX和EDX的符号位
00401A83 |. B9 0A000000 |mov ecx, 0A
00401A88 |. F7F9 |idiv ecx ; 除10取余
00401A8A |. 83C2 30 |add edx, 30 ; 变成相应字符
00401A8D |. 8B45 AC |mov eax, [ebp-54]
00401A90 |. 885405 B4 |mov [ebp+eax-4C], dl
00401A94 |. 8B45 9C |mov eax, [ebp-64]
00401A97 |. 99 |cdq
00401A98 |. B9 0A000000 |mov ecx, 0A
00401A9D |. F7F9 |idiv ecx
00401A9F |. 8945 9C |mov [ebp-64], eax ; 除10取整
00401AA2 |. 8B55 AC |mov edx, [ebp-54]
00401AA5 |. 83C2 01 |add edx, 1
00401AA8 |. 8955 AC |mov [ebp-54], edx
00401AAB |. 837D 9C 00 |cmp dword ptr [ebp-64], 0
00401AAF |.^ 75 CE \jnz short 00401A7F
00401AB1 |. 8B45 AC mov eax, [ebp-54] ; "0044639502"放入V_4c中
00401AB4 |. C64405 B4 00 mov byte ptr [ebp+eax-4C], 0 ; 加个结束符
00401AB9 |. 8D4D B4 lea ecx, [ebp-4C]
00401ABC |. 51 push ecx ; /s
00401ABD |. E8 34050000 call <jmp.&MSVCRTD.strlen> ; \strlen
00401AC2 |. 83C4 04 add esp, 4
00401AC5 |. 8945 A4 mov [ebp-5C], eax
00401AC8 |. C745 AC 00000>mov dword ptr [ebp-54], 0
00401ACF |. EB 09 jmp short 00401ADA
00401AD1 |> 8B55 AC /mov edx, [ebp-54] ; 将用户名的字符加上其偏移的2倍abcdefg变成adgjmps
00401AD4 |. 83C2 01 |add edx, 1
00401AD7 |. 8955 AC |mov [ebp-54], edx
00401ADA |> 8B45 AC mov eax, [ebp-54]
00401ADD |. 3B45 A8 |cmp eax, [ebp-58] ; 58是用户名长度
00401AE0 |. 7D 31 |jge short 00401B13
00401AE2 |. 8B4D AC |mov ecx, [ebp-54]
00401AE5 |. 0FBE540D E4 |movsx edx, byte ptr [ebp+ecx-1C] ; 1C是存用户名的地方
00401AEA |. 8B45 AC |mov eax, [ebp-54]
00401AED |. 8D0C42 |lea ecx, [edx+eax*2]
00401AF0 |. 8B55 AC |mov edx, [ebp-54]
00401AF3 |. 884C15 E4 |mov [ebp+edx-1C], cl
00401AF7 |. 8B45 AC |mov eax, [ebp-54]
00401AFA |. 0FBE4C05 E4 |movsx ecx, byte ptr [ebp+eax-1C]
00401AFF |. 83F9 7A |cmp ecx, 7A
00401B02 |. 7E 0D |jle short 00401B11
00401B04 |. 8B55 AC |mov edx, [ebp-54]
00401B07 |. 83C2 61 |add edx, 61
00401B0A |. 8B45 AC |mov eax, [ebp-54]
00401B0D |. 885405 E4 |mov [ebp+eax-1C], dl ; 结果仍然放在V_1C中
00401B11 |>^ EB BE \jmp short 00401AD1
00401B13 |> 8B4D A8 mov ecx, [ebp-58]
00401B16 |. 3B4D A4 cmp ecx, [ebp-5C]
00401B19 |. 7D 12 jge short 00401B2D
00401B1B |. 8B55 A8 mov edx, [ebp-58]
00401B1E |. 8955 A0 mov [ebp-60], edx
00401B21 |. 8B45 A0 mov eax, [ebp-60]
00401B24 |. 8D4C05 E4 lea ecx, [ebp+eax-1C]
00401B28 |. 894D B0 mov [ebp-50], ecx
00401B2B |. EB 10 jmp short 00401B3D
00401B2D |> 8B55 A4 mov edx, [ebp-5C]
00401B30 |. 8955 A0 mov [ebp-60], edx
00401B33 |. 8B45 A0 mov eax, [ebp-60]
00401B36 |. 8D4C05 B4 lea ecx, [ebp+eax-4C]
00401B3A |. 894D B0 mov [ebp-50], ecx
00401B3D |> C745 AC 00000>mov dword ptr [ebp-54], 0
00401B44 |. EB 09 jmp short 00401B4F
00401B46 |> 8B55 AC /mov edx, [ebp-54] ; 这个循环将变化过的用户名和前面算出来的结果叠在一起0a0d4g4j6m3p9s
00401B49 |. 83C2 01 |add edx, 1
00401B4C |. 8955 AC |mov [ebp-54], edx
00401B4F |> 8B45 AC mov eax, [ebp-54]
00401B52 |. 3B45 A0 |cmp eax, [ebp-60]
00401B55 |. 7D 1E |jge short 00401B75 ; 看哪个结果长
00401B57 |. 8B4D AC |mov ecx, [ebp-54] ; 用户名比较长
00401B5A |. 8B55 AC |mov edx, [ebp-54]
00401B5D |. 8A4415 B4 |mov al, [ebp+edx-4C]
00401B61 |. 88444D C4 |mov [ebp+ecx*2-3C], al
00401B65 |. 8B4D AC |mov ecx, [ebp-54]
00401B68 |. 8B55 AC |mov edx, [ebp-54]
00401B6B |. 8A4415 E4 |mov al, [ebp+edx-1C]
00401B6F |. 88444D C5 |mov [ebp+ecx*2-3B], al
00401B73 |.^ EB D1 \jmp short 00401B46
00401B75 |> 8B4D AC mov ecx, [ebp-54] ; 上步算出来的整数字符串比较长
00401B78 |. C6444D C4 00 mov byte ptr [ebp+ecx*2-3C], 0
00401B7D |. 8B55 B0 mov edx, [ebp-50]
00401B80 |. 52 push edx ; /src
00401B81 |. 8D45 C4 lea eax, [ebp-3C] ; |
00401B84 |. 50 push eax ; |dest
00401B85 |. E8 66040000 call <jmp.&MSVCRTD.strcat> ; \strcat
00401B8A |. 83C4 08 add esp, 8
00401B8D |. 8D4D C4 lea ecx, [ebp-3C]
00401B90 |. 51 push ecx ; /s
00401B91 |. E8 60040000 call <jmp.&MSVCRTD.strlen> ; \strlen
00401B96 |. 83C4 04 add esp, 4
00401B99 |. 8BF0 mov esi, eax ; 算出来的序列号的长度
00401B9B |. 8B4D FC mov ecx, [ebp-4]
00401B9E |. 83C1 64 add ecx, 64
00401BA1 |. E8 D8030000 call <jmp.&MFC42D.#880> ; 取得输入的序列号
00401BA6 |. 50 push eax ; /s
00401BA7 |. E8 4A040000 call <jmp.&MSVCRTD.strlen> ; \strlen
00401BAC |. 83C4 04 add esp, 4
00401BAF |. 3BF0 cmp esi, eax ; 比较两个长度
00401BB1 |. 75 7D jnz short 00401C30
00401BB3 |. C745 AC 00000>mov dword ptr [ebp-54], 0
00401BBA |. EB 09 jmp short 00401BC5
00401BBC |> 8B55 AC /mov edx, [ebp-54] ; 这个循环将对产生的组合字符串与输入的key串作异或然后
00401BBF |. 83C2 01 |add edx, 1 ; 与“bxm"比较
00401BC2 |. 8955 AC |mov [ebp-54], edx
00401BC5 |> 8D45 C4 lea eax, [ebp-3C]
00401BC8 |. 50 |push eax ; /s
00401BC9 |. E8 28040000 |call <jmp.&MSVCRTD.strlen> ; \strlen
00401BCE |. 83C4 04 |add esp, 4
00401BD1 |. 3945 AC |cmp [ebp-54], eax
00401BD4 |. 73 34 |jnb short 00401C0A
00401BD6 |. 8B4D AC |mov ecx, [ebp-54]
00401BD9 |. 0FBE740D C4 |movsx esi, byte ptr [ebp+ecx-3C]
00401BDE |. 8B55 AC |mov edx, [ebp-54]
00401BE1 |. 52 |push edx
00401BE2 |. 8B4D FC |mov ecx, [ebp-4]
00401BE5 |. 83C1 64 |add ecx, 64
00401BE8 |. E8 7F030000 |call <jmp.&MFC42D.#850>
00401BED |. 0FBEC0 |movsx eax, al
00401BF0 |. 33F0 |xor esi, eax
00401BF2 |. 8B45 AC |mov eax, [ebp-54]
00401BF5 |. 99 |cdq
00401BF6 |. B9 03000000 |mov ecx, 3
00401BFB |. F7F9 |idiv ecx
00401BFD |. 0FBE5415 98 |movsx edx, byte ptr [ebp+edx-68]
00401C02 |. 3BF2 |cmp esi, edx
00401C04 |. 74 02 |je short 00401C08
00401C06 |. EB 02 |jmp short 00401C0A
00401C08 |>^ EB B2 \jmp short 00401BBC
00401C0A |> 8D45 C4 lea eax, [ebp-3C]
00401C0D |. 50 push eax ; /s
00401C0E |. E8 E3030000 call <jmp.&MSVCRTD.strlen> ; \strlen
00401C13 |. 83C4 04 add esp, 4
00401C16 |. 3945 AC cmp [ebp-54], eax
00401C19 |. 75 15 jnz short 00401C30 ; 如果提前跳出循环说明不对
00401C1B |. 6A 00 push 0 ; 到这里就对啦
00401C1D |. 8D4D 90 lea ecx, [ebp-70]
00401C20 |. 51 push ecx
00401C21 |. 8D95 70FFFFFF lea edx, [ebp-90]
00401C27 |. 52 push edx
00401C28 |. 8B4D FC mov ecx, [ebp-4]
00401C2B |. E8 42030000 call <jmp.&MFC42D.#3517>
过程如下:
1.将username中的字符累乘放入整数中,如"abcdefg"就变成整数2059364400
2.将该整数变成字符串,不过顺序是到的"0044639502",记为result1。
3.将username的每个字符加上它偏移的2倍,第0个加0,第1个加2,第2个加四...
这样"abcdefg"就变成了"adgjmps",记为result2。
4.将上两步产生的字符串result1和result2组合起来
如果result1长或两串等长,那么新串的长度是result2串长度的2倍
0a0d4g4j6m3p9s
result1后面有剩的话就丢掉
如果是result2长
那么新串的长度是result1串长度的2倍
result1串剩下的接在组合串的后面
这个串记为result3吧
5.将result3与输入的key每个字符进行异或,看结果是否等于制定的值:"bxm"呵呵就是作者
key[i]^result2[i]==bxm[i%3]?
如果都对的话那就是注册成功啦
这样写注册机的话就是
key[i]=result2[i]^bxm[i%3];
不过不幸的是key中有不可打印字符
试了一下12345居然可以是RI]VJZPB[_
三、注册机
void keygen(char *username,char *key)
{
char bxm[4]="bxm";
int usize=strlen(username);
int pruduct=1;
int re;
char result1[30];
char result2[60];
for(int i=0;i<usize;i++)
pruduct*=username[i];
for(i=0;pruduct>0;i++)
{
re=pruduct%10;
pruduct/=10;
result1[i]=re+0x30;
}
result1[i]=0;
int size1=strlen(result1);
for(i=0;i<usize;i++)
{
username[i]+=i*2;
}
if(size1>=usize)
{
for(i=0;i<usize;i++)
{
result2[i*2]=result1[i];
result2[i*2+1]=username[i];
}
result2[i*2]=0;
}
else
{
for(i=0;i<size1;i++)
{
result2[i*2]=result1[i];
result2[i*2+1]=username[i];
}
result2[i*2]=0;
}
strcat(result2,username+i);
int size2=strlen(result2);
for(i=0;i<size2;i++)
{
key[i]=result2[i]^bxm[i%3];
}
key[i]=0;
}
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年10月13日 18:16:05
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课