飘云老大的Keygenme2007_B简单分析
因为比较简单,我这样的菜鸟来献个丑,算法很简单,高手略过PEiD侦壳,NsPack,用ESP定律轻松搞定,不说。
跟注册码算法有关一共有三个地方,先找到402490这里:
004024A5 .8378 F8 2C cmp dword ptr , 2C
004024A9 .0F85 FF000000 jnz 004025AE
这里比较注册码位数是44位,不是就死。往下来到这里:
004024B7 > \8B8E 2C010000 mov ecx, ;注册码
004024BD .8A41 06 mov al, ;第7位
004024C0 .8A51 05 mov dl, ;第6位
004024C3 .33C2 xor eax, edx
004024C5 .0FBE51 07 movsx edx, byte ptr ;第8位
004024C9 .83E0 7F and eax, 7F
004024CC .0FBE49 04 movsx ecx, byte ptr ;第5位
004024D0 .0FAFC2 imul eax, edx
004024D3 .03C1 add eax, ecx
004024D5 .B9 6B000000 mov ecx, 6B
004024DA .99 cdq
004024DB .F7F9 idiv ecx
004024DD .85D2 test edx, edx
004024DF .0F85 C9000000 jnz 004025AE
这里就是(第7位 xor 第6位)*第8位+第5位=107的整数倍,自己随便凑个数就过了这里。
后面的同类的计算还有3处,算法都很简单,不详细说了,这段里面不少花指令,不过都比较简单,不影响阅读。
4处注册码计算都过了之后来到这里:
00402586 > \817E 60 A4DB6>cmp dword ptr , 260DBA4
0040258D .74 18 je short 004025A7
0040258F .74 03 je short 00402594
00402591 .75 01 jnz short 00402594
这里的比较如果没过的话不是真正注册成功,因此要观察的值,下硬件访问断点。当输入用户名的时候断在这里:
00402790 .56 push esi
00402791 .8BF1 mov esi, ecx
00402793 .6A 01 push 1
00402795 .E8 385A0000 call <jmp.&mfc42.#6334_CWnd::UpdateDa>
0040279A .8B86 30010000 mov eax,
004027A0 .8378 F8 05 cmp dword ptr , 5 ;用户名要大于5位
004027A4 .7C 1E jl short 004027C4
004027A6 .8B8E 2C010000 mov ecx,
004027AC .8379 F8 2C cmp dword ptr , 2C ;注册码一共44位
004027B0 .75 12 jnz short 004027C4
004027B2 .8B56 20 mov edx,
004027B5 .6A 00 push 0 ; /Timerproc = NULL
004027B7 .6A 0A push 0A ; |Timeout = 10. ms
004027B9 .6A 01 push 1 ; |TimerID = 1
004027BB .52 push edx ; |hWnd
004027BC .FF15 30934000 call [<&user32.SetTimer>] ; \SetTimer
004027C2 .5E pop esi
004027C3 .C3 retn
004027C4 >C746 60 40E20>mov dword ptr , 1E240 ;到这里就死
004027CB .5E pop esi
004027CC .C3 retn
当两步比较都过了之后,会SetTimer,每隔10ms触发一次,触发之后在这里:
004025D0 .64:A1 0000000>mov eax, fs:
004025D6 .6A FF push -1
004025D8 .68 E0864000 push 004086E0
004025DD .50 push eax
往下找,先到这里:
004025F3 .8B83 2C010000 mov eax, ;注册码
004025F9 .8DBB 2C010000 lea edi,
004025FF .8A08 mov cl,
00402601 .80F9 50 cmp cl, 50 ;P
00402604 .75 1B jnz short 00402621
00402606 .8078 01 59 cmp byte ptr , 59 ;Y
0040260A .75 15 jnz short 00402621
0040260C .8078 02 47 cmp byte ptr , 47 ;G
00402610 .75 0F jnz short 00402621
00402612 .8078 03 2D cmp byte ptr , 2D ;-
00402616 .75 09 jnz short 00402621
00402618 .C743 60 B30D2>mov dword ptr , 12F0DB3
0040261F .EB 07 jmp short 00402628
00402621 >C743 60 F1CD3>mov dword ptr , 131CDF1 ;跳到这里就死
这里,注册码前四位必须是“PYG-”,然后会把赋值为12F0DB3,也就是前面的。
继续往下看
00402628 > \55 push ebp
00402629 .56 push esi
0040262A .8DB3 30010000 lea esi,
00402630 .6A 01 push 1
00402632 .8D4424 30 lea eax,
00402636 .6A 00 push 0
00402638 .50 push eax
00402639 .8BCE mov ecx, esi
0040263B .E8 985B0000 call <jmp.&mfc42.#4278_CString::Mid>;用户名第一位
00402640 .8BE8 mov ebp, eax
00402642 .6A 01 push 1
00402644 .8D4C24 2C lea ecx,
00402648 .6A 14 push 14
0040264A .51 push ecx
0040264B .8BCF mov ecx, edi
0040264D .C74424 44 000>mov dword ptr , 0
00402655 .E8 7E5B0000 call <jmp.&mfc42.#4278_CString::Mid>;注册码第21位
0040265A .8B6D 00 mov ebp,
0040265D .8B00 mov eax,
0040265F .55 push ebp ; /s2
00402660 .8B2D D8924000 mov ebp, [<&msvcrt._mbscmp>] ; |msvcrt._mbscmp
00402666 .50 push eax ; |s1
00402667 .C64424 40 01mov byte ptr , 1 ; |
0040266C .FFD5 call ebp ; \_mbscmp
0040266E .83C4 08 add esp, 8
00402671 .85C0 test eax, eax
00402673 .0F85 BB000000 jnz 00402734 ;不等则死
这里,用户名第一位要等于注册码第21位,后面还有同样的比较,方法都一样,就不写了,还有2个地方的比较,分别是用户名第3位等于注册码第26位,用户名第5位等于注册码第37位,都过了之后来到这里:
0040275D .84C0 test al, al
0040275F .5D pop ebp
00402760 .74 07 je short 00402769
00402762 .8143 60 F1CD3>add dword ptr , 131CDF1
这里=12F0DB3+131CDF1=260DBA4,就是前面最后一个判断的地方,这里也过了就通过注册
呵呵,算法很简单吧。
btw 飘云老大的程序有一个bug,当先输入用户名,然后输入注册码,这时按OK没有显示注册通过,原因是在输入用户名的时候判断注册码的位数,不等于0x2C就不会进入SetTimer,而输入注册码的时候不会触发402790程序段的判断,这是这个CrackMe的一个小bug,呵呵。 给一组我用的用户名和注册码:
用户名:ToTToT
注册码:PYG-2679 012\45\c890T2345T7890c23456o8901234 原帖由 ToT 于 2007-2-17 22:15 发表
因为比较简单,我这样的菜鸟来献个丑,算法很简单,高手略过
PEiD侦壳,NsPack,用ESP定律轻松搞定,不说。
跟注册码算法有关一共有三个地方,先找到402490这里:
004024A5 .8378 F8 2C cmp ...
不是BUG,是打破常规次序~~ 嘘!;P
呵呵,不错!
KeyGenMe哦~~ 完成之后 加入精华! 呵呵,其实只要把4027B0那句nop掉就不会有bug了....
注册机有点懒得写了,呵呵....这个精华留给别人吧 飘过,丢个注册机
;
;不懂算法的keygen模版,欢迎随便修改
;
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\comctl32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comctl32.lib
dlgproc proto :DWORD,:DWORD,:DWORD,:DWORD
.const
.data
szName db 020h dup (0)
szSerial db "PYG-k888h888?888w888888888888888888888888888",0
szErr db "错误",0
szErr1 db "名字长度必须大于5",0
.data?
hInstance dd ?
.code
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,eax,101,NULL,offset dlgproc,0
invoke ExitProcess,NULL
dlgproc proc hWnd:DWORD,wMsg:DWORD,wParam:DWORD,lParam:DWORD
moveax,wMsg
.ifeax == WM_CLOSE
invokeEndDialog,hWnd,NULL
.elseifeax == WM_INITDIALOG
invoke LoadIcon,hInstance,1
invoke SendMessage,hWnd,WM_SETICON,0,eax
.elseifeax == WM_COMMAND
moveax,wParam
.ifeax == 1002
invokeGetDlgItemText,hWnd,1000,addr szName,11h
.if eax<6
invoke MessageBox,NULL,addr szErr1,addr szErr,MB_OK
mov eax,FALSE
ret
.endif
mov al,byte ptr ds:
mov byte ptr ds:,al
mov al,byte ptr ds:
mov byte ptr ds:,al
mov al,byte ptr ds:
mov byte ptr ds:,al
invoke SetDlgItemText,hWnd,1001,addr szSerial
.endif
.else
moveax,FALSE
ret
.endif
moveax,TRUE
ret
dlgproc endp
end start 原帖由 ToT 于 2007-2-17 23:11 发表 https://www.chinapyg.com/images/common/back.gif
呵呵,其实只要把4027B0那句nop掉就不会有bug了....
注册机有点懒得写了,呵呵....这个精华留给别人吧
这个就是PY所说的陷阱 /:017 不是BUG~~ 可惜我不会算法学习中
页:
[1]