0day书看完了,调了些milw0rm上公布的poc,基本还能搞定。
下了些不知名的服务器软件fuzzy一下没啥发现,
想下也是,一般的开发人员基本上都不会用strcpy这种了。
决定恶补一下汇编,我汇编很差,基本只懂mov,jmp,push这些,因为堆栈溢出有这些就够了。
在论坛上的ftp下了些书,PEDIY CrackMe 2007.chm这本有意思,
我试一下第一篇4nil写的那个,很多指令都是边翻书边查的。
里面有个cdq我都没查到,书上没有,我想应该是edx清0吧。
注册机,我基本上是抄汇编代码,抄错两处,边调试vc,边调od,一句一句对就出来了。
另外,程序好像有个隐藏boss,我跟了好久都没弄出来.(见最后一段分析)
Name 输入 12345678
序列号 l222222222222
bp GetDlgItemTextA
断下来之后 Alt+F9跳回用户程序领空
00401528 |. 68 00010000 push 100 ; /Count = 100 (256.)
0040152D |. 8D85 00FFFFFF lea eax, dword ptr [ebp-100] ; |
00401533 |. 50 push eax ; |Buffer
00401534 |. 6A 65 push 65 ; |ControlID = 65 (101.)
00401536 |. FF75 08 push dword ptr [ebp+8] ; |hWnd
00401539 |. E8 FA010000 call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
0040153E |. 89C3 mov ebx, eax
00401540 |. 09DB or ebx, ebx
00401542 |. 75 04 jnz short 00401548 ; 长度大于0则跳,否则直接挂掉
00401544 |. 31C0 xor eax, eax
00401546 |. EB 50 jmp short 00401598
00401548 |> BF BC020000 mov edi, 2BC
0040154D |. BE 30000000 mov esi, 30
00401552 |. B8 48000000 mov eax, 48
00401557 |. 99 cdq
00401558 |. F7FB idiv ebx
0040155A |. 29C6 sub esi, eax
0040155C |. 8D34B6 lea esi, dword ptr [esi+esi*4] ; esi 乘 5
0040155F |. 29F7 sub edi, esi
00401561 |. 6BFF 6B imul edi, edi, 6B ; edi乘6B
00401564 |. 81EF 6CCF0000 sub edi, 0CF6C
0040156A |. 81FF 00230000 cmp edi, 2300
00401570 |. 7F 08 jg short 0040157A ; edi 大于 2300 则跳
00401572 |. 81FF 90010000 cmp edi, 190
00401578 |. 7D 04 jge short 0040157E ; 小于等于190则跳
0040157A |> 31C0 xor eax, eax
0040157C |. EB 1A jmp short 00401598
0040157E |> 8D85 00FFFFFF lea eax, dword ptr [ebp-100] ; 用户名地址
00401584 |. 50 push eax
00401585 |. 53 push ebx ; 用户名长度
00401586 |. FF75 08 push dword ptr [ebp+8]
00401589 |. E8 77FDFFFF call 00401305 ; 关键算法call
00401305 /$ 55 push ebp
00401306 |. 89E5 mov ebp, esp
00401308 |. 81EC 2C040000 sub esp, 42C
0040130E |. 53 push ebx
0040130F |. 56 push esi
00401310 |. 57 push edi
00401311 |. 8DBD FCFEFFFF lea edi, dword ptr [ebp-104]
00401317 |. 8D35 38204000 lea esi, dword ptr [402038]
0040131D |. B9 40000000 mov ecx, 40
00401322 |. F3:A5 rep movs dword ptr es:[edi], dword ptr >
00401324 |. 8DBD E1FBFFFF lea edi, dword ptr [ebp-41F]
0040132A |. 8D35 38214000 lea esi, dword ptr [402138]
00401330 |. B9 40000000 mov ecx, 40
00401335 |. F3:A5 rep movs dword ptr es:[edi], dword ptr >
00401337 |. 8DBD E1FDFFFF lea edi, dword ptr [ebp-21F]
0040133D |. 8D35 38224000 lea esi, dword ptr [402238]
00401343 |. B9 40000000 mov ecx, 40
00401348 |. F3:A5 rep movs dword ptr es:[edi], dword ptr >
0040134A |. 8DBD E1FCFFFF lea edi, dword ptr [ebp-31F]
00401350 |. 8D35 38234000 lea esi, dword ptr [402338]
00401356 |. B9 40000000 mov ecx, 40
0040135B |. F3:A5 rep movs dword ptr es:[edi], dword ptr >
0040135D |. 8DBD DCFBFFFF lea edi, dword ptr [ebp-424]
00401363 |. 8D35 38244000 lea esi, dword ptr [402438]
00401369 |. B9 05000000 mov ecx, 5
0040136E |. F3:A4 rep movs byte ptr es:[edi], byte ptr [e>
00401370 |. 8DBD D6FBFFFF lea edi, dword ptr [ebp-42A]
00401376 |. 8D35 3D244000 lea esi, dword ptr [40243D]
0040137C |. B9 03000000 mov ecx, 3
00401381 |. F3:66:A5 rep movs word ptr es:[edi], word ptr [e>
00401384 |. 8DBD E1FEFFFF lea edi, dword ptr [ebp-11F]
0040138A |. 8D35 43244000 lea esi, dword ptr [402443]
00401390 |. B9 1B000000 mov ecx, 1B
00401395 |. F3:A4 rep movs byte ptr es:[edi], byte ptr [e>
00401397 |. C745 FC 00000>mov dword ptr [ebp-4], 0
0040139E |. 68 00010000 push 100 ; /Count = 100 (256.)
004013A3 |. 8D85 E1FCFFFF lea eax, dword ptr [ebp-31F] ; |
004013A9 |. 50 push eax ; |Buffer
004013AA |. 6A 66 push 66 ; |ControlID = 66 (102.)
004013AC |. FF75 08 push dword ptr [ebp+8] ; |hWnd
004013AF |. E8 84030000 call <jmp.&USER32.GetDlgItemTextA> ; \取注册码
004013B4 |. 09C0 or eax, eax
004013B6 |. 0F84 48010000 je 00401504 ; 长度为0跳走
004013BC |. B8 CF110000 mov eax, 11CF
004013C1 |. 0FB68D E1FCFF>movzx ecx, byte ptr [ebp-31F] ; 移注册码一个byte到ecx
004013C8 |. 99 cdq
004013C9 |. F7F9 idiv ecx ; 11cF 除 注册码第一位
004013CB |. 83FA 17 cmp edx, 17
004013CE |. 74 07 je short 004013D7 ; 11CF % 注册码第一位 不等于17则挂
004013D0 |. 31C0 xor eax, eax
004013D2 |. E9 2D010000 jmp 00401504
004013D7 |> 31DB xor ebx, ebx
004013D9 |. EB 0B jmp short 004013E6
004013DB |> 8B45 10 /mov eax, dword ptr [ebp+10] ; 取用户名
004013DE |. 0FBE0418 |movsx eax, byte ptr [eax+ebx] ; 取下一位用户名
004013E2 |. 0145 FC |add dword ptr [ebp-4], eax ; 每一位用户名相加放入ebp-4
004013E5 |. 43 |inc ebx
004013E6 |> 3B5D 0C cmp ebx, dword ptr [ebp+C]
004013E9 |.^ 7C F0 \jl short 004013DB ; 用用户名长度作循环
004013EB |. 31DB xor ebx, ebx
004013ED |. E9 83000000 jmp 00401475
004013F2 |> 8B55 10 /mov edx, dword ptr [ebp+10]
004013F5 |. 0FBE3C1A |movsx edi, byte ptr [edx+ebx] ; 取下一位用户名
004013F9 |. 8B75 FC |mov esi, dword ptr [ebp-4] ; 取每位用户名相加的值
004013FC |. 89D9 |mov ecx, ebx
004013FE |. C1E1 02 |shl ecx, 2 ; 当前计数值左移两位
00401401 |. 89DA |mov edx, ebx
00401403 |. 42 |inc edx ; 计数值加一
00401404 |. 29D1 |sub ecx, edx
00401406 |. 0FB68C0D E1FE>|movzx ecx, byte ptr [ebp+ecx-11F] ; ebp-11F为 A-Z
0040140E |. 89FA |mov edx, edi
00401410 |. 31CA |xor edx, ecx
00401412 |. 89F1 |mov ecx, esi
00401414 |. 0FAFCB |imul ecx, ebx
00401417 |. 29F1 |sub ecx, esi
00401419 |. 89CE |mov esi, ecx
0040141B |. 83F6 FF |xor esi, FFFFFFFF
0040141E |. 8DB432 4D0100>|lea esi, dword ptr [edx+esi+14D]
00401425 |. 8B4D 0C |mov ecx, dword ptr [ebp+C]
00401428 |. 89DA |mov edx, ebx
0040142A |. 83C2 03 |add edx, 3
0040142D |. 0FAFCA |imul ecx, edx
00401430 |. 0FAFCF |imul ecx, edi
00401433 |. 89F0 |mov eax, esi
00401435 |. 01C8 |add eax, ecx
00401437 |. B9 0A000000 |mov ecx, 0A
0040143C |. 31D2 |xor edx, edx
0040143E |. F7F1 |div ecx
00401440 |. 83C2 30 |add edx, 30 ; 程序到处用余数+0x30来保证注册码为数字
00401443 |. 88941D FCFEFF>|mov byte ptr [ebp+ebx-104], dl
0040144A |. 0FB6BC1D FCFE>|movzx edi, byte ptr [ebp+ebx-104]
00401452 |. 81F7 ACAD0000 |xor edi, 0ADAC
00401458 |. 89DE |mov esi, ebx
0040145A |. 83C6 02 |add esi, 2
0040145D |. 89F8 |mov eax, edi
0040145F |. 0FAFC6 |imul eax, esi
00401462 |. B9 0A000000 |mov ecx, 0A
00401467 |. 99 |cdq
00401468 |. F7F9 |idiv ecx
0040146A |. 83C2 30 |add edx, 30
0040146D |. 88941D FCFEFF>|mov byte ptr [ebp+ebx-104], dl
00401474 |. 43 |inc ebx
00401475 |> 3B5D 0C cmp ebx, dword ptr [ebp+C] ; 再拿用户名长度作循环
00401478 |.^ 0F8C 74FFFFFF \jl 004013F2
0040147E |. 8D85 FCFEFFFF lea eax, dword ptr [ebp-104] ; 得到中间注册码63850965
00401484 |. 50 push eax
00401485 |. 6A 54 push 54
00401487 |. 8D85 DCFBFFFF lea eax, dword ptr [ebp-424]
0040148D |. 50 push eax ; |Format
0040148E |. 8D85 E1FBFFFF lea eax, dword ptr [ebp-41F] ; |
00401494 |. 50 push eax ; |s
00401495 |. E8 CE020000 call <jmp.&USER32.wsprintfA> ; \变成 T+中间注册码形式 T63850965
0040149A |. 8B7D 0C mov edi, dword ptr [ebp+C]
0040149D |. 89F8 mov eax, edi ; 取用户名长度
0040149F |. 0FAF45 FC imul eax, dword ptr [ebp-4] ; 长度 * 用户名相加
004014A3 |. B9 64000000 mov ecx, 64
004014A8 |. 99 cdq
004014A9 |. F7F9 idiv ecx ; 值除64
004014AB |. 89D7 mov edi, edx
004014AD |. 83C7 30 add edi, 30 ; 余数加30 = 108
004014B0 |. 57 push edi
004014B1 |. 8DBD E1FBFFFF lea edi, dword ptr [ebp-41F] ; T63850965
004014B7 |. 57 push edi
004014B8 |. 8DBD D6FBFFFF lea edi, dword ptr [ebp-42A] ; %s-%d
004014BE |. 57 push edi ; |Format
004014BF |. 8DBD E1FDFFFF lea edi, dword ptr [ebp-21F] ; |12F6D5
004014C5 |. 57 push edi ; |s
004014C6 |. E8 9D020000 call <jmp.&USER32.wsprintfA> ; \T63850965-108
004014CB |. 83C4 20 add esp, 20
004014CE |. 8D8D E1FDFFFF lea ecx, dword ptr [ebp-21F]
004014D4 |. 83C8 FF or eax, FFFFFFFF
004014D7 |> 40 /inc eax ; 取T63850965-108的每一位做循环
004014D8 |. 803C01 00 |cmp byte ptr [ecx+eax], 0
004014DC |.^ 75 F9 \jnz short 004014D7 ; 算字符串长度
004014DE |. 50 push eax ; /Arg3
004014DF |. 8D85 E1FCFFFF lea eax, dword ptr [ebp-31F] ; |注册码
004014E5 |. 50 push eax ; |Arg2
004014E6 |. 8D85 E1FDFFFF lea eax, dword ptr [ebp-21F] ; |T63850965-108
004014EC |. 50 push eax ; |Arg1
004014ED |. E8 D0FDFFFF call 004012C2 ; \unpacked.004012C2
004012C2 /$ 55 push ebp
004012C3 |. 89E5 mov ebp, esp
004012C5 |. 53 push ebx
004012C6 |. 56 push esi
004012C7 |. 57 push edi
004012C8 |. 8B5D 10 mov ebx, dword ptr [ebp+10] ; 取T63850965-108长度
004012CB |. 31F6 xor esi, esi
004012CD |. 46 inc esi
004012CE |. EB 29 jmp short 004012F9
004012D0 |> 8B55 08 /mov edx, dword ptr [ebp+8] ; (x^ 0x20) % 0x0a + 0x30
004012D3 |. 0FBE3C32 |movsx edi, byte ptr [edx+esi]
004012D7 |. 89F8 |mov eax, edi
004012D9 |. 83F0 20 |xor eax, 20
004012DC |. B9 0A000000 |mov ecx, 0A
004012E1 |. 99 |cdq
004012E2 |. F7F9 |idiv ecx
004012E4 |. 89D7 |mov edi, edx
004012E6 |. 83C7 30 |add edi, 30
004012E9 |. 8B55 0C |mov edx, dword ptr [ebp+C]
004012EC |. 0FBE1432 |movsx edx, byte ptr [edx+esi]
004012F0 |. 39D7 |cmp edi, edx ; 序列号比较,不匹配则挂
004012F2 |. 74 04 |je short 004012F8
004012F4 |. 31C0 |xor eax, eax
004012F6 |. EB 08 |jmp short 00401300
004012F8 |> 46 |inc esi
004012F9 |> 39DE cmp esi, ebx
004012FB |.^ 7C D3 \jl short 004012D0 ; 循环处理T63850965-108
004012FD |. 31C0 xor eax, eax
004012FF |. 40 inc eax
00401300 |> 5F pop edi
00401301 |. 5E pop esi
00401302 |. 5B pop ebx
00401303 |. 5D pop ebp
00401304 \. C3 retn
全部匹配可以跳到这里SHiT ... you entered the correct serial!
但是看到case 3好像才是最完美的。
程序跟了多次次,发现每次对eax的处理都是 xor eax,eax inc eax这样出来,没办法把eax变为3啊。
0040162F |. 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401631 |. 8D45 C7 lea eax, dword ptr [ebp-39] ; |
00401634 |. 50 push eax ; |Title
00401635 |. 8D45 D3 lea eax, dword ptr [ebp-2D] ; |
00401638 |. 50 push eax ; |Text = "SHiT ... you entered the correct serial!"
00401639 |. FF75 08 push dword ptr [ebp+8] ; |hOwner
0040163C |. E8 1B010000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
00401641 |. EB 3D jmp short 00401680
00401643 |> 8D05 0E264000 lea eax, dword ptr [40260E] ; Case 3 of switch 004015F1
00401649 |. 8945 F8 mov dword ptr [ebp-8], eax
0040164C |. 8D05 93254000 lea eax, dword ptr [402593]
00401652 |. 8945 F4 mov dword ptr [ebp-C], eax
00401655 |. 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401657 |. FF75 F8 push dword ptr [ebp-8] ; |Title
0040165A |. 50 push eax ; |Text => "You have to make an own working keygen!",LF,"Send the solutions to: t.h.e.b.i.g.m.a.n@gmx.net",LF,"Patching is not allowed!",LF,LF,"Enjoy !"
0040165B |. FF75 08 push dword ptr [ebp+8] ; |hOwner
0040165E |. E8 F9000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
注册机:
最后的注册码简简单单就弄出来了,那段算中间序列号的费了好大劲,把他整个算法给抄下来了。
#include <stdio.h>
#include <string.h>
int main(int argc,char** argv)
{
int i =0;
char Name[100] = {0};
char MidKey[255] ={0};
char Key[255]={0};
char s[] = "ABCDEFGHIJKLNMOPQRSTUEWXYZ";
printf("请输入注册名:");
scanf("%s",Name);
if( (0x2bc - (0x30 - (0x48 / (strlen(Name)-1)) )*0x5 )*0x6b-0xcF6C > 0x2300
|| (0x2bc - (0x30 - (0x48 / (strlen(Name)-1)) )*0x5 )*0x6b-0xcF6C <= 0x190 )
{
printf("用户名长度不对\n");
return -1;
}
//算中间码
int ebp4 = 0;
for(i =0; i < strlen(Name); ++i)
{
ebp4 += Name[i];
}
int edi,ecx,edx,esi,eax;
for(i =0; i < strlen(Name); ++i)
{
edi = Name[i];
ecx = i << 2;
edx = i +1 ;
ecx = ecx - edx;
if( ecx < 0 ){
ecx = 0;
}
else {
ecx = s[ecx];
}
edx = edi ^ ecx;
esi = ebp4 * i - ebp4;
esi = esi ^ 0xFFFFFFFF;
esi = edx +0x14D+esi;
ecx = strlen(Name);
edx = i +3;
ecx = ecx * edx;
ecx = ecx * edi;
eax = esi + ecx;
edi = (eax % 0x0a + 0x30) & 0x0000FFFF;
edi = edi ^ 0x0ADAC;
eax = edi * (i+2);
edx = (eax % 0x0a + 0x30) & 0x0000FFFF;
MidKey[i] = edx;
}
int end = (strlen(Name) * ebp4) % 0x64 + 0x30;
sprintf(Key,"T%s-%d",MidKey,end);
//printf("T%s\n",Key);
printf("注册码:");
for(i =0; i < strlen(Key); ++i)
{
printf("%c",(Key[i] ^ 0x20) % 0x0a + 0x30 );
}
printf("\n");
getchar();
return 0;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)