既然大家都不屑于写 就有我这个小菜鸟开个头吧.
根据搜索字符串可断到这里
00401748 . 33D2 XOR EDX,EDX
0040174A . 33C9 XOR ECX,ECX
0040174C . 85DB TEST EBX,EBX
0040174E . 7E 2E JLE SHORT crackme_.0040177E
00401750 > 8A440C 10 MOV AL,BYTE PTR SS:[ESP+ECX+10]
00401754 . 3C 30 CMP AL,30
00401756 . 7C 04 JL SHORT crackme_.0040175C
00401758 . 3C 39 CMP AL,39
0040175A . 7E 18 JLE SHORT crackme_.00401774
0040175C > 3C 41 CMP AL,41
0040175E . 7C 04 JL SHORT crackme_.00401764 ; 限制用户名是a-z,0-9,A-Z之间的字符
00401760 . 3C 5A CMP AL,5A
00401762 . 7E 10 JLE SHORT crackme_.00401774
00401764 > 3C 61 CMP AL,61
00401766 . 0F8C B8000000 JL crackme_.00401824
0040176C . 3C 7A CMP AL,7A
0040176E . 0F8F B0000000 JG crackme_.00401824
00401774 > 0FBEC0 MOVSX EAX,AL
00401777 . 03D0 ADD EDX,EAX ; 用户名每一位相加=x
00401779 . 41 INC ECX
0040177A . 3BCB CMP ECX,EBX
0040177C .^ 7C D2 JL SHORT crackme_.00401750
0040177E > 42 INC EDX
0040177F . 81FA 801B0000 CMP EDX,1B80 ; x+1 与1B80比较
00401785 . 7E 0B JLE SHORT crackme_.00401792
00401787 > C1FA 02 SAR EDX,2
0040178A . 81FA 801B0000 CMP EDX,1B80
00401790 .^ 7F F5 JG SHORT crackme_.00401787
00401792 > 83FD 27 CMP EBP,27 ; SN长度看是否是39
00401795 . 8915 B0AA4000 MOV DWORD PTR DS:[40AAB0],EDX
0040179B . 0F85 B4000000 JNZ crackme_.00401855
004017A1 . 8A0D 08AA4000 MOV CL,BYTE PTR DS:[40AA08]
004017A7 . B0 2D MOV AL,2D
004017A9 . 3AC8 CMP CL,AL
004017AB . 0F85 A4000000 JNZ crackme_.00401855
004017B1 . 3805 0DAA4000 CMP BYTE PTR DS:[40AA0D],AL
004017B7 . 0F85 98000000 JNZ crackme_.00401855
004017BD . 3805 12AA4000 CMP BYTE PTR DS:[40AA12],AL
004017C3 . 0F85 8C000000 JNZ crackme_.00401855
004017C9 . 3805 17AA4000 CMP BYTE PTR DS:[40AA17],AL
004017CF . 0F85 80000000 JNZ crackme_.00401855
004017D5 . 3805 1CAA4000 CMP BYTE PTR DS:[40AA1C],AL
004017DB . 75 78 JNZ SHORT crackme_.00401855
004017DD . 3805 21AA4000 CMP BYTE PTR DS:[40AA21],AL
004017E3 . 75 70 JNZ SHORT crackme_.00401855
004017E5 . 3805 26AA4000 CMP BYTE PTR DS:[40AA26],AL
004017EB . 75 68 JNZ SHORT crackme_.00401855 ; 以上验证SN的格式,每各4位要用-连接
004017ED . E8 4EFEFFFF CALL crackme_.00401640 ; 关键CALL
004017F2 . A1 B0AA4000 MOV EAX,DWORD PTR DS:[40AAB0]
004017F7 . 8B0D 5CAB4000 MOV ECX,DWORD PTR DS:[40AB5C]
004017FD . 3BC1 CMP EAX,ECX ;DS:[40AAB0]与DS:[40AB5C]里面的值相等即可注册成功
004017FF . 74 31 JE SHORT crackme_.00401832
00401801 . 8B0D 00AA4000 MOV ECX,DWORD PTR DS:[40AA00]
00401807 . 6A 10 PUSH 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401809 . 68 D8804000 PUSH crackme_.004080D8 ; |sorry
0040180E . 68 BC804000 PUSH crackme_.004080BC ; |try again,never give up!
00401813 . 51 PUSH ECX ; |hOwner => 000806F4 ('Crackme by topmint',class='#32770')
00401814 . FF15 D0704000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
0040181A . A1 68AA4000 MOV EAX,DWORD PTR DS:[40AA68]
0040181F . 6A 01 PUSH 1
00401821 . 50 PUSH EAX
00401822 . EB 53 JMP SHORT crackme_.00401877
00401824 > 6A 10 PUSH 10
00401826 . 68 24814000 PUSH crackme_.00408124 ; error
0040182B . 68 94804000 PUSH crackme_.00408094 ; the name contains invalid ascii char!
00401830 . EB 2F JMP SHORT crackme_.00401861
00401832 > 8B15 00AA4000 MOV EDX,DWORD PTR DS:[40AA00]
00401838 . 6A 40 PUSH 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
0040183A . 68 8C804000 PUSH crackme_.0040808C ; |welcome
0040183F . 68 74804000 PUSH crackme_.00408074 ; |welcome to harbin :)
00401844 . 52 PUSH EDX ; |hOwner => 000806F4 ('Crackme by topmint',class='#32770')
00401845 . FF15 D0704000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
那个关键call进入后是这样
00401640 /$ E8 BBF9FFFF CALL crackme_.00401000
;初始化,把40aab4 40aa6c 40ab5c 都填0
00401645 |. 6A 01 PUSH 1
00401647 |. E8 64FFFFFF CALL crackme_.004015B0
0040164C |. 59 POP ECX
0040164D \. C3 RET
下面进入CALL crackme_.004015B0
004015b0里面关键CALL是00401030 f7进入看看
00401030 /$ 81EC A4000000 SUB ESP,0A4
00401036 |. A1 5CAB4000 MOV EAX,DWORD PTR DS:[40AB5C] ; ds;[40ab5c]中开始是被填0
0040103B |. 40 INC EAX ; 可知运行到这个CALL一次ds:[40ab5c]中就加1
0040103C |. A3 5CAB4000 MOV DWORD PTR DS:[40AB5C],EAX ; 因此由最后可知 只要运行到这CALL里面x+1次就OK了
; x=用户名的每一位相加
00401041 |. 33C0 XOR EAX,EAX
00401043 |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX
00401047 |. 33C9 XOR ECX,ECX
00401049 |. 894424 08 MOV DWORD PTR SS:[ESP+8],EAX
0040104D |. 894424 0C MOV DWORD PTR SS:[ESP+C],EAX
00401051 |. 894424 10 MOV DWORD PTR SS:[ESP+10],EAX
00401055 |. 884424 14 MOV BYTE PTR SS:[ESP+14],AL
00401059 |. B8 6CAA4000 MOV EAX,crackme_.0040AA6C
0040105E |> 8A10 /MOV DL,BYTE PTR DS:[EAX] ; 取40aa6c到dl
00401060 |. 83C0 04 |ADD EAX,4
00401063 |. 80C2 41 |ADD DL,41
00401066 |. 88540C 04 |MOV BYTE PTR SS:[ESP+ECX+4],DL
0040106A |. 41 |INC ECX
0040106B |. 3D ACAA4000 |CMP EAX,crackme_.0040AAAC
00401070 |.^ 7E EC \JLE SHORT crackme_.0040105E
00401072 |. 53 PUSH EBX
00401073 |. 55 PUSH EBP
00401074 |. 56 PUSH ESI
00401075 |. 8D4424 58 LEA EAX,DWORD PTR SS:[ESP+58]
00401079 |. 57 PUSH EDI
0040107A |. 50 PUSH EAX
0040107B |. E8 30090000 CALL crackme_.004019B0 ; md5初始化
00401080 |. 8D4C24 18 LEA ECX,DWORD PTR SS:[ESP+18]
00401084 |. 6A 11 PUSH 11
00401086 |. 8D5424 64 LEA EDX,DWORD PTR SS:[ESP+64]
0040108A |. 51 PUSH ECX
0040108B |. 52 PUSH EDX
0040108C |. E8 4F090000 CALL crackme_.004019E0 ; MD5_update()
00401091 |. 8D4424 38 LEA EAX,DWORD PTR SS:[ESP+38]
00401095 |. 8D4C24 6C LEA ECX,DWORD PTR SS:[ESP+6C]
00401099 |. 50 PUSH EAX
0040109A |. 51 PUSH ECX
0040109B |. E8 D0130000 CALL crackme_.00402470 ; MD5_Final()
004010A0 |. 83C4 18 ADD ESP,18
004010A3 |. 33F6 XOR ESI,ESI
004010A5 |. 8D7C24 38 LEA EDI,DWORD PTR SS:[ESP+38] ; md5(esp+4)
004010A9 |> 33D2 /XOR EDX,EDX
004010AB |. 8A5434 28 |MOV DL,BYTE PTR SS:[ESP+ESI+28]
004010AF |. 52 |PUSH EDX
004010B0 |. 68 30804000 |PUSH crackme_.00408030 ; %02x
004010B5 |. 6A 02 |PUSH 2
004010B7 |. 57 |PUSH EDI
004010B8 |. E8 33140000 |CALL crackme_.004024F0
004010BD |. 83C4 10 |ADD ESP,10
004010C0 |. 46 |INC ESI
004010C1 |. 83C7 02 |ADD EDI,2
004010C4 |. 83FE 10 |CMP ESI,10
004010C7 |.^ 7C E0 \JL SHORT crackme_.004010A9 ; 把16进制的MD5结果转为ASCII码到esp+38中
004010C9 |. BA 04000000 MOV EDX,4
004010CE |. 8D7424 38 LEA ESI,DWORD PTR SS:[ESP+38]
004010D2 |. 33C0 XOR EAX,EAX
004010D4 |. 33ED XOR EBP,EBP
004010D6 |. B9 19000000 MOV ECX,19
004010DB |. BF F8AA4000 MOV EDI,crackme_.0040AAF8
004010E0 |. 2BF2 SUB ESI,EDX
004010E2 |. C64424 58 00 MOV BYTE PTR SS:[ESP+58],0
004010E7 |. F3:AB REP STOS DWORD PTR ES:[EDI]
004010E9 |. 897424 10 MOV DWORD PTR SS:[ESP+10],ESI
004010ED |> 8D42 FC /LEA EAX,DWORD PTR DS:[EDX-4]
004010F0 |. 3BC2 |CMP EAX,EDX
004010F2 |. 7D 23 |JGE SHORT crackme_.00401117
004010F4 |. B8 04000000 |MOV EAX,4
004010F9 |. 8DBD F8AA4000 |LEA EDI,DWORD PTR SS:[EBP+40AAF8]
004010FF |. 8BC8 |MOV ECX,EAX
00401101 |. 03F2 |ADD ESI,EDX
00401103 |. 8BD9 |MOV EBX,ECX
00401105 |. C1E9 02 |SHR ECX,2
00401108 |. F3:A5 |REP MOVS DWORD PTR ES:[EDI],DWORD PTR D>
0040110A |. 8BCB |MOV ECX,EBX
0040110C |. 83E1 03 |AND ECX,3
0040110F |. 03E8 |ADD EBP,EAX
00401111 |. F3:A4 |REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:>
00401113 |. 8B7424 10 |MOV ESI,DWORD PTR SS:[ESP+10]
00401117 |> 83FA 20 |CMP EDX,20
0040111A |. 7D 08 |JGE SHORT crackme_.00401124
0040111C |. C685 F8AA4000>|MOV BYTE PTR SS:[EBP+40AAF8],2D
00401123 |. 45 |INC EBP
00401124 |> 83C2 04 |ADD EDX,4
; 把转化后的MD5的ascii码转为xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx种形式
00401127 |. 83FA 24 |CMP EDX,24
0040112A |.^ 7C C1 \JL SHORT crackme_.004010ED
0040112C |. 68 04AA4000 PUSH crackme_.0040AA04
; /String2 = "1234-5678-90AB-CDEF-ABCD-EF12-3456-7890"
00401131 |. 68 F8AA4000 PUSH crackme_.0040AAF8 ; |String1 = ""
00401136 |. FF15 00704000 CALL DWORD PTR DS:[<&KERNEL32.lstrcmpA>] ; \lstrcmpA
; 这里有个比较函数。就是在走进这个CALL最后一次时只要相等即可。
0040113C |. F7D8 NEG EAX
0040113E |. 1BC0 SBB EAX,EAX
00401140 |. 5F POP EDI
00401141 |. 40 INC EAX
00401142 |. 5E POP ESI
00401143 |. 5D POP EBP
00401144 |. A3 60AB4000 MOV DWORD PTR DS:[40AB60],EAX
00401149 |. 5B POP EBX
0040114A |. 81C4 A4000000 ADD ESP,0A4
00401150 \. C3 RET
从这个CALL可知,每进入这个CALL一次DS:[40AB5C]会加1,而它最后是和x+1(用户名每一位相加之和+1)比较。
每进来一次要经过一次md5运算。那个参数是40aa6c到40aaac之间的值有关。
所以最关键是找到 每次进入这个CALL时看40aa6c到40aaac之间的值是如何变化的即可。
从这里可以看出
004015B0 /$ A1 60AB4000 MOV EAX,DWORD PTR DS:[40AB60]
004015B5 |. 57 PUSH EDI
004015B6 |. 85C0 TEST EAX,EAX
004015B8 |. 75 7D JNZ SHORT crackme_.00401637
004015BA |. 8B7C24 08 MOV EDI,DWORD PTR SS:[ESP+8]
004015BE |. 83FF 10 CMP EDI,10
004015C1 |. 7E 07 JLE SHORT crackme_.004015CA
004015C3 |. E8 68FAFFFF CALL crackme_.00401030
004015C8 |. 5F POP EDI
004015C9 |. C3 RET
要能进入CALL crackme_.00401030 参数必须大于10。所以找到第x+1次参数大于10时的40aa6c到40aaac之间的值就OK了。
然而这个参数的变化 进入到一个递归 算法还是比较复杂。
关键的函数是call 00401250
这个CALL里面根据参数的值分了6种情况来改变40aa6c到40aaac之间的值。
我简单看了下 说下大致情况
设
0040AA6C = z1
0040AA70 =z2
0040AA74 =z3
0040AA78 = z4
0040AA7C = z5
0040AA80 =z6
0040AA84 = z7
0040AA88 =z8
0040AA8C =z9
0040AA90 =z10
0040AA94 =z11
0040AA98 =z12
0040AA9C =z13
0040AAA0 =z14
0040AAA4 = z15
0040AAA8 =z16
0040AAAC = z17
参数设为z
当z<3时 则返回值eax=1
当z=3时 又几种情况
1, 22-z4-z3-z2如果为负 则返回值eax=0
2, 22-z4-z3-z2>10 则返回值eax=0
3,第22-z4-z3-z2位=1 则返回值eax=0
4,22-z4-z3-z2=z5 返回值eax=第22-z4-z3-z2位
当z=4,5,6,8,a时 返回值eax=1
当z=7,9,b 时 和z=3大同小异 只不过分别换成22-x8-x7-x6, 22-x2-x6-x10, 22-x12-x8-x4来再分别判断 从而得到返回值。
因为这个CRACKEME不需要求逆,至于中间值如何改变可不必深究。
最简单的办法是
到地址00401136处,SHIFT+F2设条件断点:[0040AB5C]==x+1,断下来后就能看到正确的注册码了
给一组
user:kyo327
sn:F7AD-9E78-15A5-2CFA-FA43-54BF-4128-B714
晚上睡不着 实在无聊 才写了上面一点。主要是为了响应某些人, 让大家有劲头写这次比赛的CRACKEME破解文章 。我就先开个头了。
至于那个40aa6c到40aaac之间的值正向分析得到的算法,还是请大牛们来写吧!
上面都是随手匆匆写的 不对之处 还望大家指出。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课