黑夜彩虹CM3的算法分析和注册机
- 自从论坛开了股市以来,我快破产了,看来不想办法捞点UB是不行的了,看着看着就看见老黑的CrackMe3也挂了好几天,地址:
自从论坛开了股市以来,我快破产了,看来不想办法捞点UB是不行的了,看着看着就看见老黑的CrackMe3也挂了好几天,地址:
http://www.unpack.cn/thread-14671-1-1.html
我想怎么高手都去哪里了,不会都躲去炒股了吧,于是菜鸟的我就抄刀跳上去,定睛一看,哇anti
DEDE,听小子说还加了CRC,这可惨了,顿时一身冷汗,不管了,脱了衣服,翻出OD,立马挂上去,然后用罗聪大牛的插件来查找ASCII,定位到这里:
超级字串参考
地址 反汇编 文本字串
0045474C MOV EAX,CrackMe3.00454820 .
00454FE0 PUSH CrackMe3.004550AC hookdll
00454FE5 PUSH CrackMe3.004550B4 RC_Dll
00455002 MOV EDX,CrackMe3.00456DF4 RegCheck
00455035 PUSH CrackMe3.004550C4 师付又教了一种加密方法,拿出来试试
00455101 MOV EAX,CrackMe3.00456DF4 RegCheck
没有什么有用的信息,定睛一看,“RegCheck”!
好,注册检查,双击这里
00455002 MOV EDX,CrackMe3.00456DF4 RegCheck
然后F2 下断,为了保险,也下这里,双击这里
00455101 MOV EAX,CrackMe3.00456DF4 RegCheck
然后F2 下断,按F9运行,
输入注册信息,我的:
Name:langhai
Code:123456 (注意,Code只能是数字,字母不行,因为计算问题,详情看下面)
点击Check,OD立刻断下来,如下:
00455002 . BA F46D4500 MOV EDX,CrackMe3.00456DF4 ;RegCheck
//断在这里,下面有很多垃圾代码,我就不分析了,直接看有注释的就行!
00455007 . 8B46 04 MOV EAX,DWORD PTR DS:[ESI+4]
//将DS:[ESI+4]传给EAX,这里是MZP,就是EXE文件的开头字节
0045500A . 33C9 XOR ECX,ECX
0045500C . E8 BBFAFFFF CALL CrackMe3.00454ACC
//不太懂,貌似在自效验,请高手指点 !
00455011 . 8D55 EC LEA EDX,DWORD PTR SS:[EBP-14]
00455014 . 8B83 08030000 MOV EAX,DWORD PTR DS:[EBX+308]
0045501A . E8 9DE2FDFF CALL CrackMe3.004332BC
0045501F . 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14]
00455022 . 50 PUSH EAX
00455023 . 8D55 E8 LEA EDX,DWORD PTR SS:[EBP-18]
00455026 . 8B83 04030000 MOV EAX,DWORD PTR DS:[EBX+304]
0045502C . E8 8BE2FDFF CALL CrackMe3.004332BC
00455031 . 8B45 E8 MOV EAX,DWORD PTR SS:[EBP-18]
//将SS:[EBP-18]放进EAX,就是将假码放进EAX
00455034 . 50 PUSH EAX
//EAX入栈
00455035 . 68 C4504500 PUSHCrackMe3.004550C4;师付又教了一种加密方法,拿出来试试
//将004550C4处的字符串“师付又教了一种加密方法,拿出来试试”压入堆栈,注意这里,这个字符串是有用的,等看到下面就知道了。
0045503A . 8D55 E4 LEA EDX,DWORD PTR SS:[EBP-1C]
0045503D . 8B83 00030000 MOV EAX,DWORD PTR DS:[EBX+300]
00455043 . E8 74E2FDFF CALL CrackMe3.004332BC
00455048 . 8B45 E4 MOV EAX,DWORD PTR SS:[EBP-1C]
//将用户名放进EAX
0045504B . 50 PUSH EAX
//EAX压入堆栈
0045504C . FF15 DC8B4500 CALL DWORD PTR DS:[458BDC]
//注意这里,算法Call,F7 跟进去!
由上面0045504C按F7 进到这里:
01B82048 55 PUSH EBP
//来到这里,这里是算法Call的空间,F8 往下走
01B82049 8BEC MOV EBP,ESP
01B8204B 6A 00 PUSH 0
01B8204D 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
//将SS:[EBP+8]传给EAX,就是用户名。
01B82050 E8 2F23FBFF CALL 01B34384
//验证用户名是否为空
01B82055 8B45 0C MOV EAX,DWORD PTR SS:[EBP+C]
//将刚才的字符串传给EAX
01B82058 E8 2723FBFF CALL 01B34384
//验证字符串是否为空
01B8205D 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
//将注册码传给EAX
01B82060 E8 1F23FBFF CALL 01B34384
//验证注册码是否为空
01B82065 8B45 14 MOV EAX,DWORD PTR SS:[EBP+14]
//将SS:[EBP+14]传给EAX,里面是字符串“OK”
01B82068 E8 1723FBFF CALL 01B34384
//验证字符串“OK”是否为空
01B8206D 33C0 XOR EAX,EAX
//EAX清零
01B8206F 55 PUSH EBP
01B82070 68 CC20B801 PUSH 1B820CC
01B82075 64:FF30 PUSH DWORD PTR FS:[EAX]
01B82078 64:8920 MOV DWORD PTR FS:[EAX],ESP
01B8207B 8D4D FC LEA ECX,DWORD PTR SS:[EBP-4]
01B8207E 8B55 0C MOV EDX,DWORD PTR SS:[EBP+C]
01B82081 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
//将注册码传给EAX
01B82084 E8 E7FDFFFF CALL 01B81E70
//计算注册码的算法Call,非常重要,F7 跟进去!
由上面的01B82084按F7来到这里(注意,下面的注释都是根据第一次循环而写的,为了照顾像我一样的菜鸟,我会根据我的注册码长度,将每次的循环都写出来):
01B81E70 55 PUSH EBP
//来到这里,这里是计算注册码的算法Call的空间,F8 往下走,下面有很多垃圾代码,我就不分析了,直接看有注释的就行!
01B81E71 8BEC MOV EBP,ESP
01B81E73 51 PUSH ECX
01B81E74 B9 06000000 MOV ECX,6
//将固定的数值6传给ECX
01B81E79 6A 00 PUSH 0
01B81E7B 6A 00 PUSH 0
01B81E7D 49 DEC ECX
//ECX减一
01B81E7E ^ 75 F9 JNZ SHORT 01B81E79
//不为零就跳,这是一个循环,将数值0压进堆栈12次,不知有什么作用,请高手指点!
01B81E80 51 PUSH ECX
//ECX入栈。ECX=0
01B81E81 874D FC XCHG DWORD PTR SS:[EBP-4],ECX
//ECX与SS:[EBP-4]交换
01B81E84 53 PUSH EBX
01B81E85 56 PUSH ESI
01B81E86 57 PUSH EDI
01B81E87 894D F4 MOV DWORD PTR SS:[EBP-C],ECX
01B81E8A 8955 F8 MOV DWORD PTR SS:[EBP-8],EDX
01B81E8D 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
//将EAX传给SS:[EBP-4]备用,就是将注册码传给SS:[EBP-4]
01B81E90 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
//将SS:[EBP-4]回传给EAX
01B81E93 E8 EC24FBFF CALL 01B34384
//检查EAX
01B81E98 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
01B81E9B E8 E424FBFF CALL 01B34384
01B81EA0 33C0 XOR EAX,EAX
01B81EA2 55 PUSH EBP
01B81EA3 68 F41FB801 PUSH 1B81FF4
01B81EA8 64:FF30 PUSH DWORD PTR FS:[EAX]
01B81EAB 64:8920 MOV DWORD PTR FS:[EAX],ESP
01B81EAE 8D45 E0 LEA EAX,DWORD PTR SS:[EBP-20]
01B81EB1 BA 0C20B801 MOV EDX,1B8200C ; ASCII "VM_begin"
01B81EB6 E8 B120FBFF CALL 01B33F6C
01B81EBB 837D FC 00 CMP DWORD PTR SS:[EBP-4],0
//将SS:[EBP-4]内存里的注册码与0比较
01B81EBF 75 0D JNZ SHORT 01B81ECE
//不等于就跳,不跳就Over
01B81EC1 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C]
01B81EC4 E8 0B20FBFF CALL 01B33ED4
01B81EC9 E9 F6000000 JMP 01B81FC4
01B81ECE 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
01B81ED1 E8 BE22FBFF CALL 01B34194
//这个CALL是将刚才那个中文的字符串的十六进制值的长度(注意,每两位十六进制值就为算是一位)压进EAX,
那个字符串的长度刚好是33,所以33的十六进制就是21
01B81ED6 8945 F0 MOV DWORD PTR SS:[EBP-10],EAX
//将EAX传给SS:[EBP-10],EAX=21H
01B81ED9 837D F0 00 CMP DWORD PTR SS:[EBP-10],0
// SS:[EBP-10]的值与0比较
01B81EDD 75 0D JNZ SHORT 01B81EEC
//不为零就跳,不跳就Over
01B81EDF 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
01B81EE2 BA 2020B801 MOV EDX,1B82020 ; ASCII "Think Space"
01B81EE7 E8 8020FBFF CALL 01B33F6C
01B81EEC 33FF XOR EDI,EDI
01B81EEE 8D45 D4 LEA EAX,DWORD PTR SS:[EBP-2C]
01B81EF1 50 PUSH EAX
01B81EF2 B9 02000000 MOV ECX,2
01B81EF7 BA 01000000 MOV EDX,1
01B81EFC 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
//将SS:[EBP-4]传给EAX,就是注册码啦
01B81EFF E8 F024FBFF CALL 01B343F4
//取这册码的前两位
01B81F04 8B4D D4 MOV ECX,DWORD PTR SS:[EBP-2C]
将这册码的前两位传给ECX
01B81F07 8D45 D8 LEA EAX,DWORD PTR SS:[EBP-28]
01B81F0A BA 3420B801 MOV EDX,1B82034
01B81F0F E8 CC22FBFF CALL 01B341E0
01B81F14 8B45 D8 MOV EAX,DWORD PTR SS:[EBP-28]
01B81F17 E8 705FFBFF CALL 01B37E8C
01B81F1C 8945 EC MOV DWORD PTR SS:[EBP-14],EAX
//将EAX传给SS:[EBP-14],EAX为注册码的前两位
01B81F1F BE 03000000 MOV ESI,3
//ESI为3
01B81F24 8D45 CC LEA EAX,DWORD PTR SS:[EBP-34]
01B81F27 50 PUSH EAX
01B81F28 B9 02000000 MOV ECX,2
01B81F2D 8BD6 MOV EDX,ESI
01B81F2F 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
//将注册码传给EAX
01B81F32 E8 BD24FBFF CALL 01B343F4
//取注册码的第3,第4位
01B81F37 8B4D CC MOV ECX,DWORD PTR SS:[EBP-34]
//将注册码的第3,第4位存进ECX
01B81F3A 8D45 D0 LEA EAX,DWORD PTR SS:[EBP-30]
01B81F3D BA 3420B801 MOV EDX,1B82034
01B81F42 E8 9922FBFF CALL 01B341E0
01B81F47 8B45 D0 MOV EAX,DWORD PTR SS:[EBP-30]
01B81F4A E8 3D5FFBFF CALL 01B37E8C
01B81F4F 8945 E4 MOV DWORD PTR SS:[EBP-1C],EAX
//将EAX存进SS:[EBP-1C],EAX为注册码的第3,第4位
01B81F52 3B7D F0 CMP EDI,DWORD PTR SS:[EBP-10]
//将EDI与SS:[EBP-10]比较,SS:[EBP-10]是固定值21,就是说,注册码的位数只能小于或等于42,因为程序是每次取两位注册码
01B81F55 7D 03 JGE SHORT 01B81F5A
//EDI大于或等于SS:[EBP-10]就跳
01B81F57 47 INC EDI
//EDI加1
01B81F58 EB 05 JMP SHORT 01B81F5F
//无条件跳转
01B81F5A BF 01000000 MOV EDI,1
01B81F5F 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
01B81F62 33DB XOR EBX,EBX
01B81F64 8A5C38 FF MOV BL,BYTE PTR DS:[EAX+EDI-1]
//取刚才中文的字符串十六进制值,第一次循环就取第一个两位值,第二次就取第二个两位值,依次类推
01B81F68 335D E4 XOR EBX,DWORD PTR SS:[EBP-1C]
//将SS:[EBP-1C]与EBX做xor运算,还记得SS:[EBP-1C]吗,就是刚才注册码的第三,第四位,此时,SS:[EBP-1C]=34,根据我输入的信息,就是CA XOR 34 = FE
01B81F6B 3B5D EC CMP EBX,DWORD PTR SS:[EBP-14]
//将EBX与SS:[EBP-14]比较,EBX就是上面做完xor后的值FE,而SS:[EBP-14]就是注册码的第一,第二位。根据我输入的信息,即是12
01B81F6E 7F 0B JG SHORT 01B81F7B
//若EBX大于SS:[EBP-14],就跳。根据我输入的信息,这里是跳的哦
01B81F70 81C3 FF000000 ADD EBX,0FF
//EBX加上FF,并存回EBX
01B81F76 2B5D EC SUB EBX,DWORD PTR SS:[EBP-14]
//EBX减去SS:[EBP-14],得到的值并存回EBX
01B81F79 EB 03 JMP SHORT 01B81F7E
01B81F7B 2B5D EC SUB EBX,DWORD PTR SS:[EBP-14]
//从刚才01B81F6E 跳到这里,EBX减去SS:[EBP-14],得到的值并存回EBX,根据我输入的信息,就是FE -12=EC , 记住这个数,等下有用,终极代码!
01B81F7E 8D45 C8 LEA EAX,DWORD PTR SS:[EBP-38]
01B81F81 8BD3 MOV EDX,EBX
//将EBX传给EDX,就是EDX=EC
01B81F83 E8 3421FBFF CALL 01B340BC
01B81F88 8B55 C8 MOV EDX,DWORD PTR SS:[EBP-38]
01B81F8B 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
01B81F8E E8 0922FBFF CALL 01B3419C
01B81F93 8B45 E4 MOV EAX,DWORD PTR SS:[EBP-1C]
01B81F96 8945 EC MOV DWORD PTR SS:[EBP-14],EAX
01B81F99 83C6 02 ADD ESI,2
//ESI加 2,刚才ESI=3,此时加2就等于5
01B81F9C 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
//将SS:[EBP-4]传给EAX,就是注册码啦
01B81F9F E8 F021FBFF CALL 01B34194
//验证EAX,并取注册码的位数存入EAX
01B81FA4 3BF0 CMP ESI,EAX
//ESI与EAX比较,我输入的注册码是六位,而ESI现在只是5位。
01B81FA6 ^ 0F8C 78FFFFFF JL 01B81F24
//小于就跳,这是循环的结束,如果注册码还没取完,就继续去取。根据我输入的信息,这里是跳的哦。
-
TAGS:
- 作者:管理员 时间:2009-6-21 来源:网络 人气: