一个crackme的分析+注册机编写全过程!
【文章标题】: 软件破解学习笔记(算法分析8)【文章作者】: 壹只老虎
【软件名称】: _UnPackedCrack.exe
【软件大小】: 24kb
【下载地址】: http://bbs.pediy.com/attachment.php?s=&attachmentid=2576
【加壳方式】: 无壳
【保护方式】: 序列号+注册码
【编写语言】: LCC Win32 1.x -> Jacob Navia
【使用工具】: od+peid+ windows计算器
【操作平台】: xp
【软件介绍】: 看雪的找的一个crackme,算法有点复杂!
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
看雪的找的一个crackme,算法有点复杂!不过还是挺锻炼的!嗬嗬!!!!!!!!!!!!!
声明一下!这个东西在看雪已经有人写了文章了!我自己分析之后也去看了下这片文章!写的不错!
我仔细分析了下算法!顺便写了注册机!(delphi原代码!)!写的不好!就当灌水!
感谢原作者jdxyw 提供 creakme!
1:PEID查壳,LCC Win32 1.x -> Jacob Navia,无壳,这个不是壳哈!
2:运行程序,填写注册资料:序列号:123456,注册码:11111111,注册,没反应,晕!
3:OD载入,不想了看看api断点行不行!
ok!下GetDlgItemTextA断点!可以了!(其实有正确的字符串的!个人比较习惯api断点来段!嘿嘿!)
4:具体的分析过程:写的比较详细的!
第一部分:
00401533 |.50 push eax ; |Buffer
00401534 |.6A 65 push 65 ; |ControlID = 65 (101.)
00401536 |.FF75 08 push dword ptr ss: ; |hWnd
下GetDlgItemTextA断点,在这里会断下来
00401539 |.E8 FA010000 call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
0040153E |.89C3 mov ebx,eax ;eax=ebx=注册名长度
00401540 |.09DB or ebx,ebx
00401542 |.75 04 jnz short _UnPacke.00401548 ;ebx不等于0就跳
00401544 |.31C0 xor eax,eax
00401546 |.EB 50 jmp short _UnPacke.00401598 ;跳失败
00401548 |>BF BC020000 mov edi,2BC ;edi=700
0040154D |.BE 30000000 mov esi,30 ;esi=48
00401552 |.B8 48000000 mov eax,48 ;eax=72
00401557 |.99 cdq
00401558 |.F7FB idiv ebx ;eax=eax div ebx
0040155A |.29C6 sub esi,eax ;esi=esi-eax
0040155C |.8D34B6 lea esi,dword ptr ds: ;esi=5*esi
0040155F |.29F7 sub edi,esi ;edi=edi-esi
00401561 |.6BFF 6B imul edi,edi,6B ;edi=edi*107
00401564 |.81EF 6CCF00>sub edi,0CF6C ;edi=edi-53100
0040156A |.81FF 002300>cmp edi,2300 ;edi和8960比较
00401570 |.7F 08 jg short _UnPacke.0040157A ;>就跳,失败了
00401572 |.81FF 900100>cmp edi,190 ;和400比较
00401578 |.7D 04 jge short _UnPacke.0040157E ;大于等于就跳
0040157A |>31C0 xor eax,eax ;eax=0
0040157C |.EB 1A jmp short _UnPacke.00401598 ;跳出去,失败
0040157E |>8D85 00FFFF>lea eax,dword ptr ss: ;eax=注册名字符串
00401584 |.50 push eax ;注册名压栈
00401585 |.53 push ebx ;注册名长度压栈
00401586 |.FF75 08 push dword ptr ss:
上面这一段分析一下:要想不跳失败:那么
条件如下:
1:注册名长度不等于0
2:((700-(48-(72 div 注册名长度))*5)*107-53100)>8960或者<400就失败,
等价于--->嘿嘿,借不等式,大家都会把!!
注册名长度<3或者>9就失败
00401589 |.E8 77FDFFFF call _UnPacke.00401305 ;进去看看
0040158E |.83C4 0C add esp,0C
00401591 |.09C0 or eax,eax
00401593 |.74 03 je short _UnPacke.00401598 ;eax=0就跳,失败
00401595 |.31C0 xor eax,eax
00401597 |.40 inc eax ;eax=1成功
00401598 |>5F pop edi
00401599 |.5E pop esi
0040159A |.5B pop ebx
0040159B |.C9 leave
0040159C \.C3 retn返回到0040162A(主函数体)
第二部分:
00401589 |.E8 77FDFFFF call _UnPacke.00401305 ;进去看看
00401305 /$55 push ebp
00401306 |.89E5 mov ebp,esp
00401308 |.81EC 2C0400>sub esp,42C
0040130E |.53 push ebx
0040130F |.56 push esi
00401310 |.57 push edi
00401311 |.8DBD FCFEFF>lea edi,dword ptr ss:
00401317 |.8D35 382040>lea esi,dword ptr ds:
0040131D |.B9 40000000 mov ecx,40
00401322 |.F3:A5 rep movs dword ptr es:,dword ptr >
00401324 |.8DBD E1FBFF>lea edi,dword ptr ss:
0040132A |.8D35 382140>lea esi,dword ptr ds:
00401330 |.B9 40000000 mov ecx,40
00401335 |.F3:A5 rep movs dword ptr es:,dword ptr >
00401337 |.8DBD E1FDFF>lea edi,dword ptr ss:
0040133D |.8D35 382240>lea esi,dword ptr ds:
00401343 |.B9 40000000 mov ecx,40
00401348 |.F3:A5 rep movs dword ptr es:,dword ptr >
0040134A |.8DBD E1FCFF>lea edi,dword ptr ss:
00401350 |.8D35 382340>lea esi,dword ptr ds:
00401356 |.B9 40000000 mov ecx,40
0040135B |.F3:A5 rep movs dword ptr es:,dword ptr >
0040135D |.8DBD DCFBFF>lea edi,dword ptr ss:
00401363 |.8D35 382440>lea esi,dword ptr ds:
00401369 |.B9 05000000 mov ecx,5
0040136E |.F3:A4 rep movs byte ptr es:,byte ptr ds>
00401370 |.8DBD D6FBFF>lea edi,dword ptr ss:
00401376 |.8D35 3D2440>lea esi,dword ptr ds:
0040137C |.B9 03000000 mov ecx,3
00401381 |.F3:66:A5 rep movs word ptr es:,word ptr ds>
00401384 |.8DBD E1FEFF>lea edi,dword ptr ss:
0040138A |.8D35 432440>lea esi,dword ptr ds:
00401390 |.B9 1B000000 mov ecx,1B
00401395 |.F3:A4 rep movs byte ptr es:,byte ptr ds>
00401397 |.C745 FC 000>mov dword ptr ss:,0
0040139E |.68 00010000 push 100 ; /Count = 100 (256.)
004013A3 |.8D85 E1FCFF>lea eax,dword ptr ss: ; |
004013A9 |.50 push eax ; |Buffer
004013AA |.6A 66 push 66 ; |ControlID = 66 (102.)
004013AC |.FF75 08 push dword ptr ss: ; |hWnd
004013AF |.E8 84030000 call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
004013B4 |.09C0 or eax,eax ;eax=注册码长度
004013B6 |.0F84 480100>je _UnPacke.00401504
004013BC |.B8 CF110000 mov eax,11CF ;eax=4559
004013C1 |.0FB68D E1FC>movzx ecx,byte ptr ss: ;ecx=注册码第一位ascoii码
004013C8 |.99 cdq
004013C9 |.F7F9 idiv ecx ;ecx=eax div ecx
004013CB |.83FA 17 cmp edx,17 ;(余数)edx=23?
这里分析一下:要想跳走,余数edx必须=23
所以我们就需要构造数据来进行调试分析:这个数据随便大家挑
挑选方法如下:
4559 mod 注册码第一位ascoii码=23;都可以的
等价于
4559-注册码第一位ascoii码*N=23;
注册码第一位ascoii码*N=4536=2*2*2*3*3*3*3*7;这里随便构造就可以了
我开始的时候选的'6'=54,'T'也可以
004013CE |.74 07 je short _UnPacke.004013D7 ;等于就跳(这里必须跳走)
004013D0 |.31C0 xor eax,eax ;eax=0
004013D2 |.E9 2D010000 jmp _UnPacke.00401504 ;跳出去了,失败了
004013D7 |>31DB xor ebx,ebx ;ebx=0
这里是一个循环
004013D9 |.EB 0B jmp short _UnPacke.004013E6 ;小跳,开始循环了
004013DB |>8B45 10 /mov eax,dword ptr ss:
004013DE |.0FBE0418 |movsx eax,byte ptr ds: ;eax=按位取注册名ascii码
004013E2 |.0145 FC |add dword ptr ss:,eax ;eax累加到0012f9ac
004013E5 |.43 |inc ebx
004013E6 |>3B5D 0C cmp ebx,dword ptr ss: ;循环是否结束
004013E9 |.^ 7C F0 \jl short _UnPacke.004013DB ;这个循环把注册名数据各位的ascii码和防到0012f9ac
循环的分析:这个循环把注册名数据各位的ascii码和防到0012f9ac
下面又是一个循环
004013EB |.31DB xor ebx,ebx ;ebx=0
004013ED |.E9 83000000 jmp _UnPacke.00401475 ;循环一个
004013F2 |>8B55 10 /mov edx,dword ptr ss: ;ebx为计数器
004013F5 |.0FBE3C1A |movsx edi,byte ptr ds: ;edi=按位取注册名ascii码
004013F9 |.8B75 FC |mov esi,dword ptr ss: ;esi=0012f9ac的数据(上次的循环结果)
004013FC |.89D9 |mov ecx,ebx ;ecx=ebx
004013FE |.C1E1 02 |shl ecx,2 ;ecx=ecx*4
00401401 |.89DA |mov edx,ebx ;edx=ebx
00401403 |.42 |inc edx ;edx+1
00401404 |.29D1 |sub ecx,edx ;ecx=ecx-edx
00401406 |.0FB68C0D E1>|movzx ecx,byte ptr ss: ;ecx=这里根到内存里面去看看有张表(.ABCDEFGHI...XYZ)
0040140E |.89FA |mov edx,edi ;edx=edi
00401410 |.31CA |xor edx,ecx ;edx=edx xor ecx
00401412 |.89F1 |mov ecx,esi ;ecx=esi
00401414 |.0FAFCB |imul ecx,ebx ;ecx=ecx*ebx
00401417 |.29F1 |sub ecx,esi ;ecx=ecx-esi
00401419 |.89CE |mov esi,ecx ;esi=ecx
0040141B |.83F6 FF |xor esi,FFFFFFFF ;esi=esi xor ffffffff
0040141E |.8DB432 4D01>|lea esi,dword ptr ds: ;esi=esi+edx+333
00401425 |.8B4D 0C |mov ecx,dword ptr ss: ;ecx=注册名长度
00401428 |.89DA |mov edx,ebx ;edx=ebx
0040142A |.83C2 03 |add edx,3 ;edx=edx+3
0040142D |.0FAFCA |imul ecx,edx ;ecx=ecx*edx
00401430 |.0FAFCF |imul ecx,edi ;ecx=ecx*edi
00401433 |.89F0 |mov eax,esi ;eax=esi
00401435 |.01C8 |add eax,ecx ;eax=eax+ecx
00401437 |.B9 0A000000 |mov ecx,0A ;ecx=10
0040143C |.31D2 |xor edx,edx ;edx=0
0040143E |.F7F1 |div ecx ;eax=eax div ecx
00401440 |.83C2 30 |add edx,30 ;edx=余数+48
00401443 |.88941D FCFE>|mov byte ptr ss:,dl ;dl存入0012f8ac开始的地址范围(后面会替换的)
0040144A |.0FB6BC1D FC>|movzx edi,byte ptr ss: ;edi=dl
00401452 |.81F7 ACAD00>|xor edi,0ADAC ;edi=edi xor 44460
00401458 |.89DE |mov esi,ebx ;esi=ebx
0040145A |.83C6 02 |add esi,2 ;esi=esi+2
0040145D |.89F8 |mov eax,edi ;eax=edi
0040145F |.0FAFC6 |imul eax,esi ;eax=eax*esi
00401462 |.B9 0A000000 |mov ecx,0A ;ecx=10
00401467 |.99 |cdq
00401468 |.F7F9 |idiv ecx ;eax=eax div ecx
0040146A |.83C2 30 |add edx,30 ;edx=余数+48
0040146D |.88941D FCFE>|mov byte ptr ss:,dl ;dl-->0012f8ac开始的地质(注意这里是替换本次循环得到的这个位置的数据)
00401474 |.43 |inc ebx ;ebx+1
00401475 |>3B5D 0C cmp ebx,dword ptr ss: ;循环是否结束(次数为注册名长度)
00401478 |.^ 0F8C 74FFFF>\jl _UnPacke.004013F2
这里分析下这个循环的作用
循环注册名长度的次数,每次计算出一个值,放到0012f8ac开始的地址里面
具体算法如下:
/********************************************************************/
var
str,code:string;
str:="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
code:='';
for ebx:=0 to length(name)-1 do
begin
edi:=ord(name);
esi=0012f9ac的数据(上次的循环结果);
ecx=ebx*4-(ebx+1);
ecx=ord(str);
edx=edi xor ecx;
esi=esi*ebx-esi;
esi=esi xor ffffffff;
esi=esi+edx+333;
ecx=注册名长度*(ebx+3)*edi;
eax=esi+ecx;
ecx=eax;
eax=eax div 10;
edi=(ecx mod 10)+48;
edi=edi xor 44460;
esi=ebx+2;
eax=edi*esi;
ecx=eax;
eax=eax div 10;
edx=(ecx mod 10)+48;;
code:=chr(edx);
end;
/********************************************************************/
0040147E |.8D85 FCFEFF>lea eax,dword ptr ss: ;这是上个循环得到的数据的字符串
00401484 |.50 push eax ;存入eax并压栈
00401485 |.6A 54 push 54 ;压入84
84就表示T的意思
00401487 |.8D85 DCFBFF>lea eax,dword ptr ss:
0040148D |.50 push eax ; |Format
0040148E |.8D85 E1FBFF>lea eax,dword ptr ss: ; |
00401494 |.50 push eax ; |s
00401495 |.E8 CE020000 call <jmp.&USER32.wsprintfA> ; \在上面的字符串前面加个T
0040149A |.8B7D 0C mov edi,dword ptr ss: ;edi=注册名长度
0040149D |.89F8 mov eax,edi ;eax=注册名长度
0040149F |.0FAF45 FC imul eax,dword ptr ss: ;eax=第一个循环的结果*eax
004014A3 |.B9 64000000 mov ecx,64 ;ecx=100
004014A8 |.99 cdq
004014A9 |.F7F9 idiv ecx ;eax=eax div 100
004014AB |.89D7 mov edi,edx ;edi=余数
004014AD |.83C7 30 add edi,30 ;edi=edi+48
004014B0 |.57 push edi ;edi压栈(设为num)
分析一下这个num的来由:(注册名数据各位的ascii码和*注册名长度 mod 100)+48
004014B1 |.8DBD E1FBFF>lea edi,dword ptr ss: ;edi存入上面得到的字符串
004014B7 |.57 push edi ;edi压栈
004014B8 |.8DBD D6FBFF>lea edi,dword ptr ss: ;%s-%d
004014BE |.57 push edi ; |Format
004014BF |.8DBD E1FDFF>lea edi,dword ptr ss: ; |
004014C5 |.57 push edi ; |s
004014C6 |.E8 9D020000 call <jmp.&USER32.wsprintfA> ; \上面的字符串+'-'+num(10)
004014CB |.83C4 20 add esp,20
004014CE |.8D8D E1FDFF>lea ecx,dword ptr ss: ;ecx存入上面得到的字符串
004014D4 |.83C8 FF or eax,FFFFFFFF
004014D7 |>40 /inc eax
004014D8 |.803C01 00 |cmp byte ptr ds:,0
004014DC |.^\75 F9 \jnz short _UnPacke.004014D7 ;eax=上面得到的字符串长度
004014DE |.50 push eax ; /eax压栈
004014DF |.8D85 E1FCFF>lea eax,dword ptr ss: ; |eax=假码字符串
004014E5 |.50 push eax ; |eax压栈
004014E6 |.8D85 E1FDFF>lea eax,dword ptr ss: ; |eax=上面得到的字符串长度
004014EC |.50 push eax ; |eax压栈
004014ED |.E8 D0FDFFFF call _UnPacke.004012C2 ; \_UnPacke.004012C2 进去看看
004014F2 |.83C4 0C add esp,0C
004014F5 83F8 00 cmp eax,0 ;失败没有,=0表示失败
004014F8 |.75 07 jnz short _UnPacke.00401501
004014FA |.B8 00000000 mov eax,0 ;eax=0
004014FF |.EB 03 jmp short _UnPacke.00401504 ;跳出
00401501 |>31C0 xor eax,eax
00401503 |.40 inc eax ;eax=1表示成功
00401504 |>5F pop edi
00401505 |.5E pop esi
00401506 |.5B pop ebx
00401507 |.C9 leave
00401508 \.C3 retn
第三部分:
004014ED |.E8 D0FDFFFF call _UnPacke.004012C2 ; \_UnPacke.004012C2 进去看看
004012C2 /$55 push ebp
004012C3 |.89E5 mov ebp,esp
004012C5 |.53 push ebx
004012C6 |.56 push esi
004012C7 |.57 push edi
004012C8 |.8B5D 10 mov ebx,dword ptr ss: ;ebx=上面得到的字符串长度
004012CB |.31F6 xor esi,esi ;esi=0
004012CD |.46 inc esi ;esi+1
004012CE |.EB 29 jmp short _UnPacke.004012F9 ;又是一个循环
下面是个循环
004012D0 |>8B55 08 /mov edx,dword ptr ss: ;edx=上面得到的字符串
004012D3 |.0FBE3C32 |movsx edi,byte ptr ds: ;edi=从第2位开始取上面得到的字符串数据的ascii码
004012D7 |.89F8 |mov eax,edi ;eax=edi
004012D9 |.83F0 20 |xor eax,20 ;eax=eax xor 32
004012DC |.B9 0A000000 |mov ecx,0A ;ecx=10
004012E1 |.99 |cdq
004012E2 |.F7F9 |idiv ecx ;eax=eax div 10
004012E4 |.89D7 |mov edi,edx
004012E6 |.83C7 30 |add edi,30 ;edi=余数+48
004012E9 |.8B55 0C |mov edx,dword ptr ss: ;edx=假码
004012EC |.0FBE1432 |movsx edx,byte ptr ds: ;从第2位开始取
004012F0 |.39D7 |cmp edi,edx ;相等
004012F2 |.74 04 |je short _UnPacke.004012F8 ;继续
004012F4 |.31C0 |xor eax,eax ;不等则eax=0,失败
004012F6 |.EB 08 |jmp short _UnPacke.00401300 ;跳出
004012F8 |>46 |inc esi
004012F9 |>39DE cmp esi,ebx ;esi是计数器
004012FB |.^ 7C D3 \jl short _UnPacke.004012D0
分析下这个循环的作用:
这里就是注册码的真假的比较了,但是注意!绝对不是直接比较的!
这里还进行了一些运算!
看看算法:------------>
/*********************************************/
str=上面得到的字符串;
realcode:string//真码
realcode:='6';//T也可以!就是前面写了的对于第一位的要求
for esi:=2 to length(str) do
begin
eax:=ord(str) xor 32;
edi:=(eax mod 10)+48;
realcode:=chr(edi);
end;
/*********************************************/
004012FD |.31C0 xor eax,eax
004012FF |.40 inc eax ;eax=1
00401300 |>5F pop edi
00401301 |.5E pop esi
00401302 |.5B pop ebx
00401303 |.5D pop ebp
00401304 \.C3 retn
第四部分:(主程序体部分)
返回到这里
0040162A |.59 pop ecx ;00130698
0040162B |.09C0 or eax,eax ;关键比较哦
0040162D |.74 53 je short _UnPacke.00401682 ;关键跳转
0040162F |.6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401631 |.8D45 C7 lea eax,dword ptr ss: ; |
00401634 |.50 push eax ; |Title
00401635 |.8D45 D3 lea eax,dword ptr ss: ; |
00401638 |.50 push eax ; |Text
00401639 |.FF75 08 push dword ptr ss: ; |hOwner
0040163C |.E8 1B010000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA 正确了
00401641 |.EB 3D jmp short _UnPacke.00401680
00401643 |>8D05 0E2640>lea eax,dword ptr ds:
00401649 |.8945 F8 mov dword ptr ss:,eax
0040164C |.8D05 932540>lea eax,dword ptr ds:
00401652 |.8945 F4 mov dword ptr ss:,eax
00401655 |.6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401657 |.FF75 F8 push dword ptr ss: ; |Title
0040165A |.50 push eax ; |Text => "You have to make an own working keygen!
Send the solutions to: [email protected]
Patching is not allowed!
Enjoy !"
0040165B |.FF75 08 push dword ptr ss: ; |hOwner
0040165E |.E8 F9000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
00401663 |.EB 1B jmp short _UnPacke.00401680
00401665 |>6A 01 push 1 ; /Result = 1
00401667 |.FF75 08 push dword ptr ss: ; |hWnd
0040166A |.E8 B1000000 call <jmp.&USER32.EndDialog> ; \EndDialog
0040166F |.EB 0F jmp short _UnPacke.00401680
00401671 |>6A 00 push 0 ; /Result = 0
00401673 |.FF75 08 push dword ptr ss: ; |hWnd
00401676 |.E8 A5000000 call <jmp.&USER32.EndDialog> ; \EndDialog
0040167B |.31C0 xor eax,eax
0040167D |.40 inc eax
0040167E |.EB 02 jmp short _UnPacke.00401682
00401680 |>31C0 xor eax,eax
00401682 |>5F pop edi
00401683 |.5E pop esi
00401684 |.5B pop ebx
00401685 |.C9 leave
00401686 \.C2 1000 retn 10
5:算法分析:上面都写得很清楚了!这里就不说了
6:注册机编写如下:
procedure TForm1.Button1Click(Sender: TObject);
var
name_asc:integer;
i,edi,esi,ecx,edx,ebx,eax:integer;
name,code,table,realcode:string;
begin
name:=edit1.Text;
if (length(name)<3)or(length(name)>9) then
begin
showmessage('注册名长度必须大于2小于10');
exit;
end;
code:='6';
name_asc:=0;
for i:=1 to length(name) do
name_asc:=name_asc+ord(name);
table:='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
for ebx:=0 to length(name)-1 do
begin
edi:=ord(name);
esi:=name_asc;
ecx:=ebx*4-(ebx+1);
ecx:=ord(table);
edx:=edi xor ecx;
esi:=esi*ebx-esi;
esi:=esi xor -1;
esi:=esi+edx+333;
ecx:=length(name)*(ebx+3)*edi;
eax:=esi+ecx;
edi:=(eax mod 10)+48;
edi:=edi xor 44460;
eax:=edi*(ebx+2);
edx:=(eax mod 10)+48;;
code:=code+chr(edx);
end;
code:=code+'-'+inttostr(((length(name)*name_asc)mod 100)+48);
realcode:='6';
for esi:=2 to length(code) do
begin
eax:=ord(code) xor 32;
edi:=(eax mod 10)+48;
realcode:=realcode+chr(edi);
end;
edit2.Text:=realcode+' BY:壹只老虎2006-8-25';
end;
嘿嘿!说明一下!这个注册码只要前面参加运算的几位比较正确了!后面你随便写什么都可以!嘿嘿
比如说!
123456-->68921253768 BY:壹只老虎2006-8-25
123456-->68921253768 也可以的!嘿嘿!
好了就这样了!大家破解愉快!
--------------------------------------------------------------------------------
【经验总结】
坚持就是胜利!睡觉去了!!!!!!!!!!!
--------------------------------------------------------------------------------
【版权声明】: BY:壹只老虎
2006年08月25日 10:39:17
[ 本帖最后由 风飘雪 于 2007-1-13 21:13 编辑 ] 正点的算法.支持一下拉登兄弟! 太强了!好文,学习了 兄弟好强,学习滴说~ 嘿嘿,又一delphi的兄弟~~,支持 收下啦~~呵呵 唉,跟了一阵,把头都跟昏了,不过,一定要学会! 嘿嘿!谢谢兄弟们支持哈!我会加油的!! /:D 终于跟完了,最后得到这样一个注册码:用户名:zyh;注册码:T480-89,可惜的是,一点反应也没有,不知道到底是哪个地方出了问题! 6046345 BY:壹只老虎2006-8-25
这是zyh对应的正确的注册码
你仔细看看,别看花眼了!