-
-
[分享]简单keyfile方式cm分析
-
发表于:
2010-2-22 22:28
6915
-
【文章标题】: 简单keyfile方式cm分析
【文章作者】: gtboy
【软件名称】: DueList2
【下载地址】: 网盘,http://www.rayfile.com/files/d0361838-200f-11df-9d9d-0015c55db73d/
向大家道歉,看纳米提示成功,没校验,就发上来了。这次换rayfile了,呵呵
【加壳方式】: MASM32 / TASM32
【保护方式】: 无壳,keyfile
【使用工具】: od
【操作平台】: xp sp3
【软件介绍】: 一个简单的keyfile crackme
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
过年浑浑噩噩的,啥事也没干,收集了好多教程和电子书,就是不看。图书馆借出来的纸质书都蒙了一层土了。先从下载的录像搞起。
一个keyfile的cm。没有看教程,自己分析了下,呵呵,很有成就感。建议大家先搞搞,搞不出来了再看教程,分析自己的失误,学习经验。
查壳,无壳,直接od开始分析。
下bp CreateFileA,bpx可以直接断在程序领空,但对一般程序而言,断点太多,还是bp好,可以看堆栈窗口的提示,判断是不是自己想要断下的地方。
这个cm就一个调用,开始跟。通过字符提示也可以找到。
0040105C . 6A 00 PUSH 0 ; |/hTemplateFile = NULL
0040105E . 68 6F214000 PUSH 0040216F ; ||Attributes = READONLY|HIDDEN|SYSTEM|ARCHIVE|TEMPORARY|402048
00401063 . 6A 03 PUSH 3 ; ||Mode = OPEN_EXISTING
00401065 . 6A 00 PUSH 0 ; ||pSecurity = NULL
00401067 . 6A 03 PUSH 3 ; ||ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
00401069 . 68 000000C0 PUSH C0000000 ; ||Access = GENERIC_READ|GENERIC_WRITE
0040106E . 68 79204000 PUSH 00402079 ; ||FileName = "due-cm2.dat"
00401073 . E8 0B020000 CALL <JMP.&KERNEL32.CreateFileA> ; |\CreateFileA
00401078 . 83F8 FF CMP EAX,-1 ; |CreatefileA返回-1表示失败
0040107B . 75 1D JNZ SHORT 0040109A ; |
0040107D . 6A 00 PUSH 0 ; |/Style = MB_OK|MB_APPLMODAL
0040107F . 68 01204000 PUSH 00402001 ; ||Title = "Duelist's Crackme #2"
00401084 . 68 17204000 PUSH 00402017 ; ||Text = "Your time-trial has ended... Please register and copy the keyfile sent to you to this directory!"
00401089 . 6A 00 PUSH 0 ; ||hOwner = NULL
0040108B . E8 D7020000 CALL <JMP.&USER32.MessageBoxA> ; |\MessageBoxA
00401090 . E8 24020000 CALL <JMP.&KERNEL32.ExitProcess> ; \ExitProcess
00401095 . E9 28010000 JMP 004011C2
0040109A > \6A 00 PUSH 0 ; /pOverlapped = NULL
0040109C . 68 73214000 PUSH 00402173 ; |pBytesRead = DueList2.00402173
004010A1 . 6A 46 PUSH 46 ; |BytesToRead = 46 (70.)
004010A3 . 68 1A214000 PUSH 0040211A ; |Buffer = DueList2.0040211A
004010A8 . 50 PUSH EAX ; |hFile
004010A9 . E8 2F020000 CALL <JMP.&KERNEL32.ReadFile> ; \ReadFile
004010AE . 85C0 TEST EAX,EAX
004010B0 . 75 02 JNZ SHORT 004010B4
004010B2 . EB 43 JMP SHORT 004010F7
004010B4 > 33DB XOR EBX,EBX
004010B6 . 33F6 XOR ESI,ESI
004010B8 . 833D 73214000>CMP DWORD PTR DS:[402173],12 ; 必须大于等于18位
004010BF . 7C 36 JL SHORT 004010F7
004010C1 > 8A83 1A214000 MOV AL,BYTE PTR DS:[EBX+40211A] ; 内存中为keyfile的内容
004010C7 . 3C 00 CMP AL,0 ; 至少要有两个0x1
004010C9 . 74 08 JE SHORT 004010D3 ; 0x0,字符串结束
004010CB . 3C 01 CMP AL,1 ; 0x1,不是数字1,数字1就是0x31了
004010CD . 75 01 JNZ SHORT 004010D0
004010CF . 46 INC ESI
004010D0 > 43 INC EBX
004010D1 .^ EB EE JMP SHORT 004010C1
004010D3 > 83FE 02 CMP ESI,2
004010D6 . 7C 1F JL SHORT 004010F7
004010D8 . 33F6 XOR ESI,ESI
004010DA . 33DB XOR EBX,EBX
004010DC > 8A83 1A214000 MOV AL,BYTE PTR DS:[EBX+40211A]
004010E2 . 3C 00 CMP AL,0 ; 0x0应该是字符串结束符
004010E4 . 74 09 JE SHORT 004010EF
004010E6 . 3C 01 CMP AL,1 ; 第一个0x1前的内容累加为1D5
004010E8 . 74 05 JE SHORT 004010EF
004010EA . 03F0 ADD ESI,EAX ; 第一段累加,要求等于1D5
004010EC . 43 INC EBX
004010ED .^ EB ED JMP SHORT 004010DC
004010EF > 81FE D5010000 CMP ESI,1D5
004010F5 . 74 1D JE SHORT 00401114
004010F7 > 6A 00 PUSH 0 ; |/Style = MB_OK|MB_APPLMODAL
004010F9 . 68 01204000 PUSH 00402001 ; ||Title = "Duelist's Crackme #2"
004010FE . 68 86204000 PUSH 00402086 ; ||Text = "Your current keyfile is invalid... Please obtain a valid one from the software author!"
00401103 . 6A 00 PUSH 0 ; ||hOwner = NULL
00401105 . E8 5D020000 CALL <JMP.&USER32.MessageBoxA> ; |\MessageBoxA
0040110A . E8 AA010000 CALL <JMP.&KERNEL32.ExitProcess> ; \ExitProcess
0040110F . E9 AE000000 JMP 004011C2
00401114 > 33F6 XOR ESI,ESI
00401116 > 43 INC EBX
00401117 . 8A83 1A214000 MOV AL,BYTE PTR DS:[EBX+40211A] ; 两个0x1中间的部分
0040111D . 3C 00 CMP AL,0
0040111F . 74 18 JE SHORT 00401139
00401121 . 3C 01 CMP AL,1 ; 到第二个0x1就处理第三段
00401123 . 74 14 JE SHORT 00401139
00401125 . 83FE 0F CMP ESI,0F ; 第二段长度不能超过15位,否则就死循环了。。
00401128 . 73 0F JNB SHORT 00401139
0040112A . 3286 1A214000 XOR AL,BYTE PTR DS:[ESI+40211A] ; 和第三段按顺序做异或,生成用户名
00401130 . 8986 60214000 MOV DWORD PTR DS:[ESI+402160],EAX
00401136 . 46 INC ESI
00401137 .^ EB DD JMP SHORT 00401116
00401139 > 43 INC EBX
0040113A . 33F6 XOR ESI,ESI
0040113C > 8A83 1A214000 MOV AL,BYTE PTR DS:[EBX+40211A] ; 第二个0x1后面的内容
00401142 . 3C 00 CMP AL,0
00401144 . 74 09 JE SHORT 0040114F ; 如果还有0x1则死循环,限制了用户名的位数
00401146 . 3C 01 CMP AL,1
00401148 .^ 74 F2 JE SHORT 0040113C
0040114A . 03F0 ADD ESI,EAX ; 累加到esi中
0040114C . 43 INC EBX
0040114D .^ EB ED JMP SHORT 0040113C
0040114F > 81FE B2010000 CMP ESI,1B2 ; 要求累加值为1B2
00401155 .^ 75 A0 JNZ SHORT 004010F7 ; 第一段和第三段正确就是正确的keyfile
根据上面的分析就可以算出注册码了。给出一个:123456781 VFQ[L 1234567F
sorry,0x1显示成空格了。。。。。。
教程中附带了一个注册机,有源码,一并压缩。必然不是我写的,呵呵。
因为第二段要异或产生用户名,为了方便,找下最大公约数。1B2的十进制434,最大公约数62,所以这个注册机限制成七位注册码了。不过经过测试,可以超过七位,不大于15位就行。会有乱码。。。。。
注册的漏洞有两个:
1.第二段可以为空,注册成功,只是没有注册名而已。前后两段大家随意啦。
2.死循环问题。第二段超过15个字符就死循环。原因是比较的跳转直接跳过了 inc ebx,导致在处理第二个0x1时进入死循环。
--------------------------------------------------------------------------------
【经验总结】
学习是自己的事情,要坚持。我就是太懒惰了,眼高手低,呵呵,只能捡软柿子捏了。
最近迷上打dota了,花费了很多时间。虽然在娱乐中获得很多快感,但每天晚上总感觉每天都很堕落。相信很多和我一样的
新手都是为了兴趣自学的,所以和我一样自制力比较差的同学就很难有提高了。
扯远了,呵呵。关于这个cm,挺简单的,分析的时候认真看各个参数,就可以最后得出keyfile了。
这个cm的缺陷就在于keyfile的容量过小,而且验证条件很简单,也没有隐藏啥,适合增强自信心。
ps:看到petnt的cm分析,赶紧学习。跟了半天,还是没搞懂。基础不牢啊。呵呵
--------------------------------------------------------------------------------
【版权声明】: 版权没有,大家互相交流,呵呵
2010年02月22日 22:19:41
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!