算法难的不会搞,只能拿简单的来试手了:-),也算是开始学用IDA分析东西了
【目 标】:diablo2002’s crackme1
【工 具】:IDA 4.7
【任 务】:算法分析
【操作平台】:Windows 2003 server
【作 者】: LOVEBOOM[DFCG][FCG][US]
【相关链接】: 附件
【简要说明】: 一个非常简单的CrackMe入门级的,以前没有试过用ida分析东西,今天开始试着用IDA分析。
【详细过程】:
该CRACKME是masm32写的,所以非常直观的找到关键处,直接静态分析就可以写出注册机的,分析如下:
.text:00401227 jnz loc_4013BB
.text:0040122D mov eax, [ebp+wParam] ; Case EAX==WM_COMMAND
.text:00401230 cmp ax, 3
.text:00401234 jnz loc_4013D0
.text:0040123A shr eax, 10h
.text:0040123D or ax, ax
.text:00401240 jnz loc_4013B9
.text:00401246 xor eax, eax ; 准备获取用户名
.text:00401248 push 28h ; nMaxCount
.text:0040124A push offset name_szBuffer ; lpString
.text:0040124F push 2 ; nIDDlgItem
.text:00401251 push [ebp+hWnd] ; hDlg
.text:00401254 call GetDlgItemTextA
.text:00401259 test al, al
.text:0040125B jz Name_isEmpty ; 比较用户名是长是否为0
.text:00401261 cmp al, 20h ; 用户名长度是否大于20H
.text:00401263 jg Name_ToLong
.text:00401269 cmp al, 5 ; 比较用户名长度是否小于5
.text:0040126B jl Name_IsToShort
.text:00401271 lea ebx, ds:40318Ch ; 取出保存用户名的地址到EBX中
.text:00401277 xor ecx, ecx
.text:00401279 mov al, 5 ; 开始计算KEY1
.text:0040127B xor edx, edx ; EDX清0
.text:0040127D
.text:0040127D Loop_Key1: ; CODE XREF: sub_401109+19B j
.text:0040127D mov cl, [edx+ebx] ; 取出用户名的每一位
.text:00401280 xor cl, 29h ; KEY=用户名xor 29h
.text:00401283 add cl, al ; KEY=Key add len(UerName)
.text:00401285 cmp cl, 41h ; 如果相加后的KEY小于41h,则key=52H,key=key add len(userName)
.text:00401288 jl short Mov_CL_52h
.text:0040128A cmp cl, 5Ah ; 如果相加后的KEY大于5Ah,则key=52H,key=key add len(userName)
.text:0040128D jg short Mov_CL_52h
.text:0040128F
.text:0040128F loc_40128F: ; CODE XREF: sub_401109+1A1 j
.text:0040128F mov SaveKey1[edx], cl ; 计算后的值保存在40313C处
.text:00401295 mov byte_40313D[edx], 0
.text:0040129C inc dl
.text:0040129E dec al
.text:004012A0 cmp al, 0
.text:004012A2 jz short jmp_next ; 开始计算KEY2
.text:004012A4 jmp short Loop_Key1
.text:004012A6 ; ----------------------------------------------------------------------------
.text:004012A6
.text:004012A6 Mov_CL_52h: ; CODE XREF: sub_401109+17F j
.text:004012A6 ; sub_401109+184 j
.text:004012A6 mov cl, 52h
.text:004012A8 add cl, al
.text:004012AA jmp short loc_40128F ; 计算后的值保存在40313C处
.text:004012AC ; ----------------------------------------------------------------------------
.text:004012AC
.text:004012AC jmp_next: ; CODE XREF: sub_401109+199 j
.text:004012AC xor edx, edx ; 开始计算KEY2
.text:004012AE mov eax, 5
.text:004012B3
.text:004012B3 Loop_key2: ; CODE XREF: sub_401109+1D4 j
.text:004012B3 mov cl, [edx+ebx] ; 取出用户名的每一位tmpkey=asc(mid(username,i,1)
.text:004012B6 xor cl, 27h ; tmpkey=tmpkey xor &H27
.text:004012B9 add cl, al ; tmpkey=tmpkey add loopval(al)
.text:004012BB add cl, 1 ; tmpkey=tmpkey+1
.text:004012BE cmp cl, 41h ; if tmpkey<&H41 then tmpkey=&H4D add loopval
.text:004012C1 jl short Mov_CL_4DH
.text:004012C3 cmp cl, 5Ah
.text:004012C6 jg short Mov_CL_4DH ; if tmpkey >&H5A then tmpkey=&H4D add loopval
.text:004012C8
.text:004012C8 loc_4012C8: ; CODE XREF: sub_401109+1DA j
.text:004012C8 mov SaveKey2[edx], cl
.text:004012CE mov byte_403142[edx], 0
.text:004012D5 inc dl
.text:004012D7 dec al
.text:004012D9 cmp al, 0
.text:004012DB jz short Jmp_next1 ; 准备获取注册码
.text:004012DD jmp short Loop_key2 ; 取出用户名的每一位tmpkey=asc(mid(username,i,1)
.text:004012DF ; ----------------------------------------------------------------------------
.text:004012DF
.text:004012DF Mov_CL_4DH: ; CODE XREF: sub_401109+1B8 j
.text:004012DF ; sub_401109+1BD j
.text:004012DF mov cl, 4Dh
.text:004012E1 add cl, al
.text:004012E3 jmp short loc_4012C8
.text:004012E5 ; ----------------------------------------------------------------------------
.text:004012E5
.text:004012E5 Jmp_next1: ; CODE XREF: sub_401109+1D2 j
.text:004012E5 xor eax, eax ; 准备获取注册码
.text:004012E7 push 28h ; nMaxCount
.text:004012E9 push offset Key_szBuffer ; lpString
.text:004012EE push 4 ; nIDDlgItem
.text:004012F0 push [ebp+hWnd] ; hDlg
.text:004012F3 call GetDlgItemTextA
.text:004012F8 test ax, ax
.text:004012FB jz short Invalid_Key ; 如果注册码为空则OVER
.text:004012FD cmp ax, 0Ah
.text:00401301 jg short Invalid_Key ; 如果注册码长度不为10则over
.text:00401303 jl short Invalid_Key
.text:00401305 xor eax, eax
.text:00401307 xor ebx, ebx
.text:00401309 xor ecx, ecx
.text:0040130B xor edx, edx
.text:0040130D lea eax, ds:4031B4h
.text:00401313
.text:00401313 loop_compareKey: ; CODE XREF: sub_401109+234 j
.text:00401313 mov bl, [ecx+eax]
.text:00401316 mov dl, SaveKey1[ecx]
.text:0040131C cmp bl, 0
.text:0040131F jz Correct_Key
.text:00401325 add dl, 5 ; 再次取计算后的KEY,如果值+5大于5A的话,值-0D
.text:00401328 cmp dl, 5Ah
.text:0040132B jg short Sub_DL_0D
.text:0040132D
.text:0040132D loc_40132D: ; CODE XREF: sub_401109+23B j
.text:0040132D xor dl, 0Ch ; if key<&H41 then key=&H4B +loopVal
.text:00401330 cmp dl, 41h
.text:00401333 jl short ADDMOV_DL_4B
.text:00401335 cmp dl, 5Ah ; if Key>&H5A then key=&h4B - LoopVal
.text:00401338 jg short subMov_dl_4b
.text:0040133A
.text:0040133A loc_40133A: ; CODE XREF: sub_401109+241 j
.text:0040133A ; sub_401109+247 j
.text:0040133A inc ecx
.text:0040133B cmp dl, bl ; 如果结果不相等则OVER
.text:0040133D jz short loop_compareKey
.text:0040133F jmp short Invalid_Key
.text:00401341 ; ----------------------------------------------------------------------------
.text:00401341
.text:00401341 Sub_DL_0D: ; CODE XREF: sub_401109+222 j
.text:00401341 sub dl, 0Dh
.text:00401344 jmp short loc_40132D ; if key<&H41 then key=&H4B +loopVal
.text:00401346 ; ----------------------------------------------------------------------------
.text:00401346
.text:00401346 ADDMOV_DL_4B: ; CODE XREF: sub_401109+22A j
.text:00401346 mov dl, 4Bh
.text:00401348 add dl, cl
.text:0040134A jmp short loc_40133A
.text:0040134C ; ----------------------------------------------------------------------------
.text:0040134C
.text:0040134C subMov_dl_4b: ; CODE XREF: sub_401109+22F j
.text:0040134C mov dl, 4Bh
.text:0040134E sub dl, cl
.text:00401350 jmp short loc_40133A
.text:00401352 ; ----------------------------------------------------------------------------
.text:00401352
.text:00401352 Invalid_Key: ; CODE XREF: sub_401109+1F2 j
.text:00401352 ; sub_401109+1F8 j ...
.text:00401352 push 0 ; uType
.text:00401354 push offset Caption ; lpCaption
.text:00401359 push offset Text ; lpText
.text:0040135E push 0 ; hWnd
.text:00401360 call MessageBoxA
.text:00401365 jmp short loc_4013B9
.text:00401367 ; ----------------------------------------------------------------------------
.text:00401367
.text:00401367 Name_isEmpty: ; CODE XREF: sub_401109+152 j
.text:00401367 push 0 ; uType
.text:00401369 push offset aSorry___ ; lpCaption
.text:0040136E push offset aEnterName_0 ; lpText
.text:00401373 push 0 ; hWnd
.text:00401375 call MessageBoxA
.text:0040137A jmp short loc_4013B9
.text:0040137C ; ----------------------------------------------------------------------------
.text:0040137C
.text:0040137C Name_ToLong: ; CODE XREF: sub_401109+15A j
.text:0040137C push 0 ; uType
.text:0040137E push offset aSorry___ ; lpCaption
.text:00401383 push offset aNameCanBeMax32 ; lpText
.text:00401388 push 0 ; hWnd
.text:0040138A call MessageBoxA
.text:0040138F jmp short loc_4013B9
.text:00401391 ; ----------------------------------------------------------------------------
.text:00401391
.text:00401391 Name_IsToShort: ; CODE XREF: sub_401109+162 j
.text:00401391 push 0 ; uType
.text:00401393 push offset aSorry___ ; lpCaption
.text:00401398 push offset aNameMustBeMin5 ; lpText
.text:0040139D push 0 ; hWnd
.text:0040139F call MessageBoxA
.text:004013A4 jmp short loc_4013B9
.text:004013A6 ; ----------------------------------------------------------------------------
.text:004013A6
.text:004013A6 Correct_Key: ; CODE XREF: sub_401109+216 j
.text:004013A6 push 0 ; uType
.text:004013A8 push offset aGoodCracker ; lpCaption
.text:004013AD push offset aSerialIsCorrec ; lpText
.text:004013B2 push 0 ; hWnd
.text:004013B4 call MessageBoxA
.text:004013B9
.text:004013B9 loc_4013B9: ; CODE XREF: sub_401109+137 j
.text:004013B9 ; sub_401109+25C j ...
.text:004013B9 jmp short loc_4013D0
总结一下算法为:
只用注册名的前五位参与运算。共分为三个部分
第一部分:
count1=5
取用户名的每一位nameval1
nameval1 异或29h加上循环值count1
运算后的值小于41h或大于5ah则nameval1=52h + count1
count1-1,直到count1为0结束第一部分key1
第二部分:
count2=5
取用户名的每一位nameval2
nameval2异或27加上循环值加上1
运算后的值如果小于41h或大于5ah则nameval2=4dh+count2
count2=count2-1直到count2为0结束第二部分key2
第三部分:
count3=0
tmpkey=key1+key2
取tmpkey的每一位keyval
keyval加上5
运算后的值如果大于5ah则keyval=keyval-0d
keyval异或0ch
如果异或后的值小于41则keyval=4b加上count3
如果异或后的值大于5ah则keyval=4bh减去count3
循环10次,得出正确注册码。
附件里有asm和 VB版的注册机J
Greetz:
Fly.Jingulong,yock,tDasm.David.hexer,hmimys,ahao.UFO(brother).alan(sister).all of my friends and you!
By loveboom[DFCG][FCG][US]
http://blog.csdn.net/bmd2chen
Email:loveboom#163.com
Date:2005-6-12 13:49
附:VB+asm注册机源码:-)
附件:cr1kg.rar
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!