004043B7|. 99 |CDQ <--扩展...
004043B8|. F7FD |IDIV EBP <--EAX中装的机器码的第1 or 2 or 3 or 4位与1500的和与62相除
004043BA|. 0FBE440C 54 |MOVSX EAX,BYTE PTR SS: <--ESP+ECX+54得到机器码的第5位(还记的ESP+ECX+50中装的是第一位吗?首次执行到这里明ECX为0,得到的就是机器码的第5位,第二次到这里时ECX会加上1,得到的是第6位...)
004043BF|. 03C6 |ADD EAX,ESI <--同样加上1500
004043C1|. 8A92 E4704000|MOV DL,BYTE PTR DS: <--重要的地方来了!此时EDX中装的是前面的第1 or 2 or 3 or 4位机器码加上1500后再除以62的余数,那4070E4处是什么呢?如果在TRW2000中,我们用d 004070E4就可以看到,在Ollydbg中,我们可以在左下角处按Ctrl+G来输入相应的内存地址,这样的话就可以看到了。我们会发现从4070E4开始,装的是一串字符,依次是0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ。呵呵明白什么意思了吗?4070E4处指的是0,那4070E4加上edx中装的余数后的内存地址中装的便是当前机器码所对应的注册码。(如余数为5,那么从4070E4处的0开始往后数第5个字符就是了)该条指令执行过后就会把相应的注册码装入dl中
004043C7|. 88540C 30 |MOV BYTE PTR SS:,DL <--将机器码的第1 or 2 or 3 or 4所对应的注册码装入ESP+ECX+30处
004043CB|. 99 |CDQ <--前边儿得到的第5 or 6 or 7 or 8位机器码扩展
004043CC|. F7FD |IDIV EBP <--同样除以62
004043CE|. 8A82 E4704000|MOV AL,BYTE PTR DS: <--与004043C1处作用相同,不用我多说了吧,就是得到当前机器码的对应注册码
004043D4|. 88440C 38 |MOV BYTE PTR SS:,AL <--装入ESP+ECX+38处
004043D8|. 0FBE440C 58 |MOVSX EAX,BYTE PTR SS: <--得到机器码的第9 or 10 or 11 or 12位
004043DD|. 03C6 |ADD EAX,ESI <--与1500相加
004043DF|. 99 |CDQ <--扩展....
004043E0|. F7FD |IDIV EBP <--除以62
004043E2|. 0FBE440C 5C |MOVSX EAX,BYTE PTR SS: <--得到机器码的第13 or 14 or 15 or 16位
004043E7|. 03C6 |ADD EAX,ESI <--与1500相加
004043E9|. 8A92 E4704000|MOV DL,BYTE PTR DS: <--前边的第9 or 10 or 11 or 12位所对应的注册码
004043EF|. 88540C 40 |MOV BYTE PTR SS:,DL <--装入ESP+ECX+40处
004043F3|. 99 |CDQ <--扩展
004043F4|. F7FD |IDIV EBP <--除以62
004043F6|. 41 |INC ECX <--ECX加1
004043F7|. 83F9 04 |CMP ECX,4 <--看ECX是否为4(前边儿是一次计算四位的嘛,第一次计算第1、5、9、13位,第二次是2、6、10、14...)
004043FA|. 8A82 E4704000|MOV AL,BYTE PTR DS: <--得到前边的第13 or 14 or 15 or 16位机器码所对应的注册码
00404400|. 88440C 47 |MOV BYTE PTR SS:,AL <--装入ESP+ECX+47处
00404404|.^7C A5 \\JL SHORT LIAOCACH.004043AB <--ECX小于4就从头再来一遍(直到16位机器码都计算完为止)
00404406|. 8B35 AC524000MOV ESI,DWORD PTR DS:[<&MSVCRT.atoi>] ;MSVCRT.atoi
0040440C|. 8D4C24 10 LEA ECX,DWORD PTR SS:
00404410|. 51 PUSH ECX ; /s
00404411|. 885C24 38 MOV BYTE PTR SS:,BL ; |
00404415|. 885C24 40 MOV BYTE PTR SS:,BL ; |
00404419|. 885C24 48 MOV BYTE PTR SS:,BL ; |
0040441D|. 885C24 50 MOV BYTE PTR SS:,BL ; |
00404421|. FFD6 , ;CALL ESI ; \\atoi
00404423|. 83C4 04 ADD ESP,4
00404426|. 83F8 01 CMP EAX,1
00404429|. 75 3C JNZ SHORT LIAOCACH.00404467
0040442B|. 8D5424 18 LEA EDX,DWORD PTR SS:
0040442F|. 52 PUSH EDX
00404430|. FFD6 CALL ESI
00404432|. 83C4 04 ADD ESP,4
00404435|. 83F8 01 CMP EAX,1
00404438|. 75 2D JNZ SHORT LIAOCACH.00404467
0040443A|. 8D4424 20 LEA EAX,DWORD PTR SS:
0040443E|. 50 PUSH EAX
0040443F|. FFD6 CALL ESI
00404441|. 83C4 04 ADD ESP,4
00404444|. 83F8 01 CMP EAX,1
00404447|. 75 1E JNZ SHORT LIAOCACH.00404467
00404449|. 8D4C24 28 LEA ECX,DWORD PTR SS:
0040444D|. 51 PUSH ECX
0040444E|. FFD6 CALL ESI
00404450|. 83C4 04 ADD ESP,4
00404453|. 83F8 01 CMP EAX,1
00404456|. 75 0F JNZ SHORT LIAOCACH.00404467
00404458|. 5F POP EDI
00404459|. 5E POP ESI
0040445A|. 5D POP EBP
0040445B|. B8 FEFFFFFF MOV EAX,-2
00404460|. 5B POP EBX
00404461|. 83C4 54 ADD ESP,54
00404464|. C2 0400 RETN 4
00404467|> 8D7424 30 LEA ESI,DWORD PTR SS: <--正确的注册码的前4位的地址装入ESI中,嘿嘿,执行到这里时我们就可以看到正确的注册的前4位了,在TRW2000 or SoftICE中可以用d ESP+30来查看而在Ollydbg中什么都不用做就可以在左上方反汇编代码区与左下内存区中间的那个小窗体中看见在TRW2000中下过D指令后按Alt+上下键翻几下,就可以看到所有的注册码了(它们并没有分太开嘛0063F5E0-0063F5E3是前4位,0063F5E8-0063F5EB是5-8位,0063F5F0-0063F5F3是9-12位,0063F5F8-0063F5FB是最后4位,而你输入的注册码的内存地址:0063F5C0-0063F5C3是前4位,0063F5C8-0063F5CB是5-8位,0063F5D0-0063F5D3是9-12位,0063F5D8-0063F5DB是最后4位,机器码存放的地址是0063F6000-0063F60F)
0040446B|. 8D4424 10 LEA EAX,DWORD PTR SS: <--你输入的注册码的前4位的地址装入EAX中
0040446F|> 8A10 /MOV DL,BYTE PTR DS: <--得到你输入的注册码的第1位或第3位(EAX中的值到了后边儿会加上2,这样再执行到这里时得到的就是第3位了)
00404471|. 8ACA |MOV CL,DL <--传入cl中
00404473|. 3A16 |CMP DL,BYTE PTR DS: <--与正确的注册码的第1位或第3位比较(ESI中的值会与EAX中的值一起改变)
00404475|. 75 1C |JNZ SHORT LIAOCACH.00404493 <--不相等就跳走
00404477|. 3ACB |CMP CL,BL <--CL与BL比较,BL中的值为00000000(也就是空啦),这条指令有什么用呢?其实很简单了,每4位注册码的后面都会再跟一个空值,也就是如你在内存中可以看到1234.那个.就是空值,明白过来了吧,等到前4位都被测试过了,cl中就会装入.也就是00000000,到时就可以在后面跳走了
00404479|. 74 14 |JE SHORT LIAOCACH.0040448F <--如果CL中的值为零(即4位已经全部比较过了),就跳走
0040447B|. 8A50 01 |MOV DL,BYTE PTR DS: <--EAX+1后得到的会是你输入的注册码的第2位或者第4位(视EAX的值而定)
0040447E|. 8ACA |MOV CL,DL <--传入CL
00404480|. 3A56 01 |CMP DL,BYTE PTR DS: <--与正确的注册码的第2位或第4位比较(ESI的值会与EAX一起改变)
00404483|. 75 0E |JNZ SHORT LIAOCACH.00404493 <--不相等就跳走
00404485|. 83C0 02 |ADD EAX,2 <--EAX加上2,这样的话待会儿再跳到0040446F处时,再得到的就是你输入的注册码的第3位了
00404488|. 83C6 02 |ADD ESI,2 <--同上,ESI加上2后再跳到0040446F处重新再来一遍时就会得到正确的注册码的第3位
0040448B|. 3ACB |CMP CL,BL <--再次比较CL是否为空
0040448D|.^75 E0 \\JNZ SHORT LIAOCACH.0040446F <--不为空就再跳到0040446F处,来继续比较前4位中的1、3两位
0040448F|> 33C0 XOR EAX,EAX <--1-4位全部比较完后会跳到这里
00404491|. EB 05 JMP SHORT LIAOCACH.00404498
00404493|> 1BC0 SBB EAX,EAX
00404495|. 83D8 FF SBB EAX,-1
00404498|> 3BC3 CMP EAX,EBX
0040449A|. 0F85 AB000000JNZ LIAOCACH.0040454B
004044A0|. 8D7424 38 LEA ESI,DWORD PTR SS: <--与上面的大体相同嘛,将正确注册码的5-8位的内存地址装入ESI中
004044A4|. 8D4424 18 LEA EAX,DWORD PTR SS: <--你输入的注册码的5-8位的内存地址装入EAX中
004044A8|> 8A10 /MOV DL,BYTE PTR DS: <--得到你输入的注册码的第5 or 7位(道理我相信你一定已经明白了)
004044AA|. 8ACA |MOV CL,DL <--再装入CL中
004044AC|. 3A16 |CMP DL,BYTE PTR DS: <--与正确的注册码的第5 or 7位比较
004044AE|. 75 1C |JNZ SHORT LIAOCACH.004044CC <--不相等就跳走
004044B0|. 3ACB |CMP CL,BL <--与BL中的00000000比较,看5-8位是否已经全部比较完毕
004044B2|. 74 14 |JE SHORT LIAOCACH.004044C8 <--是的话就跳走
004044B4|. 8A50 01 |MOV DL,BYTE PTR DS: <--得到你输入的注册码的第6 or 8位
004044B7|. 8ACA |MOV CL,DL <--装入CL
004044B9|. 3A56 01 |CMP DL,BYTE PTR DS: <--与正确的注册码的第6 or 8位比较
004044BC|. 75 0E |JNZ SHORT LIAOCACH.004044CC <--不正确就跳走
004044BE|. 83C0 02 |ADD EAX,2 <--EAX加2,这样做的目的相信你已经知道了吧
004044C1|. 83C6 02 |ADD ESI,2 <--ESI也加上2
004044C4|. 3ACB |CMP CL,BL <--比较CL是否为空
004044C6|.^75 E0 \\JNZ SHORT LIAOCACH.004044A8 <--不是就跳回去再来一遍
004044C8|> 33C0 XOR EAX,EAX <--5-8位全部比较完后全跳到这里
004044CA|. EB 05 JMP SHORT LIAOCACH.004044D1
004044CC|> 1BC0 SBB EAX,EAX
004044CE|. 83D8 FF SBB EAX,-1
004044D1|> 3BC3 CMP EAX,EBX
004044D3|. 75 76 JNZ SHORT LIAOCACH.0040454B
004044D5|. 8D7424 40 LEA ESI,DWORD PTR SS: <--将正确的注册码的9-12位的内存地址装入ESI
004044D9|. 8D4424 20 LEA EAX,DWORD PTR SS: <--你输入的
004044DD|> 8A10 /MOV DL,BYTE PTR DS: <--得到你输入的注册码的第9 or 11位
004044DF|. 8ACA |MOV CL,DL <--装入CL
004044E1|. 3A16 |CMP DL,BYTE PTR DS: <--与正确的注册码的第9 or 11位比较
004044E3|. 75 1C |JNZ SHORT LIAOCACH.00404501 <--不对便跳走
004044E5|. 3ACB |CMP CL,BL <--看CL是否为空,即看9-12位是否全部比较完毕
004044E7|. 74 14 |JE SHORT LIAOCACH.004044FD <--是的话跳走
004044E9|. 8A50 01 |MOV DL,BYTE PTR DS: <--得到你输入的注册码的第10 or 12位
004044EC|. 8ACA |MOV CL,DL <--装入CL
004044EE|. 3A56 01 |CMP DL,BYTE PTR DS: <--与正确的注册码的第10 or 12位比较
004044F1|. 75 0E |JNZ SHORT LIAOCACH.00404501 <--不相等就跳走
004044F3|. 83C0 02 |ADD EAX,2 <--EAX加2
004044F6|. 83C6 02 |ADD ESI,2 <--ESI加2
004044F9|. 3ACB |CMP CL,BL <--看是否全部比较完毕
004044FB|.^75 E0 \\JNZ SHORT LIAOCACH.004044DD <--没有就跳回去再来一遍
004044FD|> 33C0 XOR EAX,EAX <--9-12位全部比较完毕后会跳到这里
004044FF|. EB 05 JMP SHORT LIAOCACH.00404506
00404501|> 1BC0 SBB EAX,EAX
00404503|. 83D8 FF SBB EAX,-1
00404506|> 3BC3 CMP EAX,EBX
00404508|. 75 41 JNZ SHORT LIAOCACH.0040454B
0040450A|. 8D7424 48 LEA ESI,DWORD PTR SS: <--嘿嘿,都讲了三遍了,你一定明白了吧,所以我把这最后一段留给你自己来看吧,从这里到00404530处我相信你猜也猜的出来(众人:鄙视你!)
0040450E|. 8D4424 28 LEA EAX,DWORD PTR SS:
00404512|> 8A10 /MOV DL,BYTE PTR DS:
00404514|. 8ACA |MOV CL,DL
00404516|. 3A16 |CMP DL,BYTE PTR DS:
00404518|. 75 1C |JNZ SHORT LIAOCACH.00404536
0040451A|. 3ACB |CMP CL,BL
0040451C|. 74 14 |JE SHORT LIAOCACH.00404532
0040451E|. 8A50 01 |MOV DL,BYTE PTR DS:
00404521|. 8ACA |MOV CL,DL
00404523|. 3A56 01 |CMP DL,BYTE PTR DS:
00404526|. 75 0E |JNZ SHORT LIAOCACH.00404536
00404528|. 83C0 02 |ADD EAX,2
0040452B|. 83C6 02 |ADD ESI,2
0040452E|. 3ACB |CMP CL,BL
00404530|.^75 E0 \\JNZ SHORT LIAOCACH.00404512
00404532|> 33C0 XOR EAX,EAX <--全部通过后来到这里
00404534|. EB 05 JMP SHORT LIAOCACH.0040453B
00404536|> 1BC0 SBB EAX,EAX
00404538|. 83D8 FF SBB EAX,-1
0040453B|> 3BC3 CMP EAX,EBX
0040453D|. 75 0C JNZ SHORT LIAOCACH.0040454B
0040453F|. 8BC7 MOV EAX,EDI
00404541|. 5F POP EDI
00404542|. 5E POP ESI
00404543|. 5D POP EBP
00404544|. 5B POP EBX
00404545|. 83C4 54 ADD ESP,54
00404548|. C2 0400 RETN 4
我的注释写的还算清楚吧 ^_^,我再大概给你讲解一下:
软件的注册码是这样计算出来的,机器码中的各个字符的ASCII码加上1500后除以62的余数在密码表中对应的字符,就是相应的注册码。
比如说我这里的机器码为xn2urkeUMwpNv5xZ,x的ASCII码为78(十进制120) 78+5DC的值为654(即1620) 接着用1620除以3E(62)得商26余8,好的,我们从“密码表”0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ的开始处向后数8下,就会到了8这个字符,嘿嘿,这就是x对应的注册码。
好的,我给出Delphi的注册机(我仍将其写为函数的形式):
function KeyGen(Name: String): String;
var
S:String;
P:String;
Key:String;
i,N,Z:integer;
begin
P:='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
if Length(Name)<16 then
Result:='机器码必须为16位...'
else
begin
S:=Name;
for i:=1 to 16 do
begin
N:=Ord(S);
N:=N+1500;
Z:= N mod 62;
Z:=Z+1;
Key:=Key+P;
end;
Result:=Key;
end;
end;
呵呵,这一章就是最后一章了,现在也写完了.... 打个Kiss~~
<本章完>
写在最后
这篇教程到目前算是全部写完了,呵呵,我不知道它对你是否有帮助...但你肯赏个面子把它看完,偶在此还是要感谢一下的嘛 嘿嘿,点名感谢版主zmworm老哥,没有他,你们看到的这篇文章中会有N多错字
我写这篇教程的目的,除了给那些初学Crack的新手讲解一下大概的方法外,另一个目的就是想告诉你:Crack一点儿也不神秘.....只要你有信心,不久的将来,你一定有成为老鸟的一天.....
我不知道你是否看懂了这篇教程,如果你没看懂,那么也不要失去信心,造成这样的原因,除多数是因为本人水平有限外,还有一小小小小部分是因为你的基础知识没有打好,建议你先花一些时间把那些基础知识给打好再过来学Crack...刚才看到看雪老哥这样回复一位网友的贴子:
初学者我是这样定义的:掌握了汇编、至少掌握了一门编程语言(当然最好得掌握Win32编程)。
一些读者什么基础都没有,就来学习加解密,刚开始可能还好,但到了一定程度是提高不了的。到时,不得不回过头再来学习汇编、编程,反而浪费时间和精力。
加密技术发展很快的,像以前改一、二个跳转就能爆破、明码比较的时代要过去了。所以想学,就得有扎实的基本功。
了解?
总而言之言而总之一句话,基础知识--------一定要掌握......否则的话没人能帮你!
前天在红盟看到狮子在主页上写了这样一段话:
有一天,在QQ上挂着,突然收到一个消息
(2002-12-03 23:16:04) 无敌小子
我打算入侵美国白宫的主页.
我现在有个软件叫流光,但是可我不会用.
你能教我吗?
呵呵,他的用意很明显,是想告诫那些Hack初学者......
学人家出来Hacking,连最基本的扫描器都不会用,就想去Hacking白宫的首页?这就好比连调试器都不会用就想把iPB的CrackMe给拿下一样....
勿在浮沙筑高台!