Happytown的第18个crackme分析 注册机 ,CrackMe,happytown,加密算法 2008年06月22日 星期日 下午 11:50 【文章标题】: Happytown的第18个crackme分析 注册机 【文章作者】: kaien 【作者邮箱】: kkaien@hotmail.com 【软件名称】: CrackMe_0018.exe 【加壳方式】: 无壳 【使用工具】: OllyDbg,VC(写注册机用) 【操作平台】: winxp 本文分两部分,前半部分是算法分析;后半部分是注册机。 其实,本文的前半部分在我的另一个帖子里已经发表过了。 但是我们的happytown发话了,不写出注册机誓不罢休!- - 无奈之下,只好献丑了! 时间仓促,水平有限,错误之处在所难免,还望各位大大们手下留情 ^_^ 算法部分代码如下,很简单,看我注释: 0040117E |. 68 C9000000 push 0C9 ; /Count = C9 (201.) 00401183 |. 50 push eax ; |Buffer 00401184 |. 68 E8030000 push 3E8 ; |ControlID = 3E8 (1000.) 00401189 |. 57 push edi ; |hWnd 0040118A |. FFD5 call ebp ; \GetDlgItemTextA 0040118C |. 8BF0 mov esi,eax 0040118E |. 83FE 04 cmp esi,4 ; 用户名长度>=4 00401191 |. 0F8C CA000000 jl CrackMe_.00401261 00401197 |. 8BCE mov ecx,esi 00401199 |. 81E1 01000080 and ecx,80000001 0040119F |. 79 05 jns short CrackMe_.004011A6 004011A1 |. 49 dec ecx 004011A2 |. 83C9 FE or ecx,FFFFFFFE 004011A5 |. 41 inc ecx 004011A6 |> 0F85 B5000000 jnz CrackMe_.00401261 ; 用户名长度必须为偶数,否则就跳了 004011AC |. 8D9424 D8000000 lea edx,dword ptr ss:[esp D8] 004011B3 |. 56 push esi 004011B4 |. 52 push edx 004011B5 |. E8 B6000000 call CrackMe_.00401270 ; 小写转大写 004011BA |. 83C4 08 add esp,8 004011BD |. 85C0 test eax,eax 004011BF |. 0F84 9C000000 je CrackMe_.00401261 004011C5 |. 8D4424 10 lea eax,dword ptr ss:[esp 10] 004011C9 |. 68 C9000000 push 0C9 004011CE |. 50 push eax 004011CF |. 68 E9030000 push 3E9 004011D4 |. 57 push edi 004011D5 |. FFD5 call ebp 004011D7 |. 3BC6 cmp eax,esi 004011D9 |. 0F85 82000000 jnz CrackMe_.00401261 004011DF |. 8D4C24 10 lea ecx,dword ptr ss:[esp 10] 004011E3 |. 50 push eax 004011E4 |. 51 push ecx 004011E5 |. E8 86000000 call CrackMe_.00401270 004011EA |. 83C4 08 add esp,8 004011ED |. 85C0 test eax,eax 004011EF |. 74 70 je short CrackMe_.00401261 004011F1 |. 8BC6 mov eax,esi 004011F3 |. 33FF xor edi,edi 004011F5 |. 99 cdq 004011F6 |. 2BC2 sub eax,edx 004011F8 |. 8BE8 mov ebp,eax 004011FA |. D1FD sar ebp,1 004011FC |. 3BEB cmp ebp,ebx 004011FE |. 7E 51 jle short CrackMe_.00401251 00401200 |> 8A4C7C 11 /mov cl,byte ptr ss:[esp edi*2 11] ; 取密码第二位 00401204 |. 8A447C 10 |mov al,byte ptr ss:[esp edi*2 10] ; 取密码第一位 00401208 |. 80E9 41 |sub cl,41 ; cl= 第二位-41 0040120B |. 2C 41 |sub al,41 ; al= 第一位-41 0040120D |. 0FBEF1 |movsx esi,cl ; esi=cl 00401210 |. 0FBEC8 |movsx ecx,al ; ecx=al 00401213 |. BB 1A000000 |mov ebx,1A ; ebx=1A 00401218 |. 8D14C9 |lea edx,dword ptr ds:[ecx ecx*8] ; edx=ecx*9=(密码第一位-41)*9 0040121B |. 8D0472 |lea eax,dword ptr ds:[edx esi*2] ; eax=(密码第一位-41)*9 (密码第二位-41)*2 0040121E |. 99 |cdq ; 求余数 0040121F |. F7FB |idiv ebx ; eax=eax/ebx=eax/1A 且余数给edx 00401221 |. 0FBE847C D8000000 |movsx eax,byte ptr ss:[esp edi*2 D8] ; eax=用户名第一位 00401229 |. 83E8 41 |sub eax,41 ; eax=eax-41 0040122C |. 3BD0 |cmp edx,eax ; 比较eax和余数edx 0040122E 75 31 jnz short CrackMe_.00401261 00401230 |. 8D0476 |lea eax,dword ptr ds:[esi esi*2] ; eax=esi*3=cl*3=(密码第二位-41)*3 00401233 |. 8D0C81 |lea ecx,dword ptr ds:[ecx eax*4] ; ecx = ecx eax*4 = al eax*4 = (密码第一位-41) (密码第二位-41)*0C 00401236 |. 03C1 |add eax,ecx ; eax=eax ecx= (密码第一位-41) (密码第二位-41)*0F 00401238 |. 8BCB |mov ecx,ebx ; ecx=ebx=1A 0040123A |. 99 |cdq 0040123B |. F7F9 |idiv ecx ; eax=eax/1A 余数edx 0040123D |. 0FBE847C D9000000 |movsx eax,byte ptr ss:[esp edi*2 D9] ; eax=取用户名第二位 00401245 |. 83E8 41 |sub eax,41 ; eax=用户名第二位-41 00401248 |. 3BD0 |cmp edx,eax ; 比较eax和余数edx 0040124A |. 75 15 |jnz short CrackMe_.00401261 0040124C |. 47 |inc edi ; edi 0040124D |. 3BFD |cmp edi,ebp ; 一组一组的来,每组两个字符,所以共(用户名长度/2)组 0040124F |.^ 7C AF \jl short CrackMe_.00401200 00401251 |> 5F pop edi 00401252 |. 5E pop esi 00401253 |. 5D pop ebp 00401254 |. B8 01000000 mov eax,1 00401259 |. 5B pop ebx 0040125A |. 81C4 90010000 add esp,190 00401260 |. C3 retn 00401261 |> 5F pop edi 00401262 |. 5E pop esi 00401263 |. 5D pop ebp 00401264 |. 33C0 xor eax,eax 00401266 |. 5B pop ebx 00401267 |. 81C4 90010000 add esp,190 0040126D \. C3 retn 总结一下算法: 1。用户名和密码都必须是大小写字母(大写还是小写无关紧要) 2。用户名和密码的位数必须相同且为偶数,位数不能小于4。 算法关键是: 用户名的第一位-41H = [(密码第一位-41H)*9H (密码第二位-41H)*2H] % 1AH 用户名的第二位-41H = [(密码第一位-41H) (密码第二位-41H)*0FH] % 1AH 解上面这个方程组就行。(% 就是C里面的取余数运算) 后面的用户名和密码的3、4位;5、6位等等,都可以同样的方法算出。 我们可以看到,如果知道密码的两位来确定用户名比较好计算。因为,连续两位密码可以分别唯一的计算出两位用户名来。 ===================================================================== 下面是一个简单的注册机,C写的。 这个注册机将会根据给定的长度随机生成用户名和注册码。 鉴于大小写不是关键,所以我一律按大写算了。大家不要介意 #include #include #include #include void main() { char code1,code2,name1,name2; int length; char code[256],name[256]; //自己给定密码和用户名长度,两个的长度必须相等且为偶数。 //密码长度=用户名的长度=length*2 //length必须>=2 //如密码长度为10,即length=5 length=5; //构造随机变量 srand((unsigned)time(NULL)); for(int i=1;i<=length;i ) { //随机生成注册码 //code1和2为ASCII的65-90之间的大写字母,即A-Z。取小写字母也无妨 code1=int(((float(rand())/RAND_MAX)*26) 65); code2=int(((float(rand())/RAND_MAX)*26) 65); name1=((((code1-0x41)*9) ((code2-0x41)*2))%0x1A) 0x41; name2=(((code1-0x41) ((code2-0x41)*0xF))%0x1A) 0x41; code[i*2-2]=code1; code[i*2-1]=code2; name[i*2-2]=name1; name[i*2-1]=name2; } code[i*2-2]='\0'; name[i*2-2]='\0'; printf("用户名:\t%s\n",name); printf("密码:\t%s\n",code); } ==================================================================== 几个随机生成的结果(已验证): 长度4的 用户名: STWY 密码: IZQE 长度6的 用户名: ESKUXI 密码: ISCWXZ 长度8的 用户名: EFDDHCNO 密码: IFNIZVVD 长度10的 用户名: OTDMXGOYTM 密码: OJHJHTCYJV 长度20的 用户名: DGFDZNMXNYSOTFTFVLXU 密码: LRXQVWKNXHUKFAFALAPJ 长度60的 用户名: UVMAQYKJKZHIHDENVGREQISINPMNXIRJEGMRVUTZPOEYCYEQYURSBEXEOPVL 密码: INIWMGSPQLVNHYUDXLNPOKYSDGIJXZBEQIOVFBJIFLEKUCSMUAVFLDRNIXLA 长度100的 用户名: UVUAKPYIECREINMGMLKBBMQFSSBMAOEYVKLZVLUGPCDQWKDXPUIDZBWFORSVQPJTGVEVOMOJJRMEYVMEBLLLQNENMZFVPMLASKIV 密码: INWCOHCQKWNPOTEOSDGRXBQBAWXBIQEKDXVCLASUNBNVIORQBDMPDMUZYDYFSFPCQJGBKOMFZWOICDOIPYNMCZUDATLSPFDFOYAR |
|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )
GMT+8, 2024-9-30 03:26 , Processed in 0.260191 second(s), 12 queries , Gzip On, MemCache On.
Powered by Discuz! X3.5
© 2001-2023 Discuz! Team.