【文章作者】: 网络断魂
【软件名称】: Xnview v1.93.1
【下载地址】: http://www.crsky.com/soft/1187.html
【加壳方式】: ASPack 2.12b -> Alexey Solodovnikov
【保护方式】: 序列号
【编写语言】: Microsoft Visual C++ 6.0
【使用工具】: PEID,OD,
【操作平台】: XP SP3,
【软件介绍】: 国外软件,非常棒的图像查看程序。支持150种图片格式, 除一般的查看、浏览、幻灯显示等功能外,还自带30多面滤镜,方便编辑修改; 可以批量转换文件格式
,创建缩略图并生成网页,还可自己制作GIF, 小巧实用。
【作者声明】: 菜鸟学习算法,失误之处敬请诸位大侠赐教!
一、ESP定律脱壳,由消息断点找到关键函数
00566BA0 . 81EC 68010000 sub esp, 168
00566BA6 . 8D4424 68 lea eax, dword ptr [esp+68]
00566BAA . 56 push esi
00566BAB . 8BB424 700100>mov esi, dword ptr [esp+170]
00566BB2 . 57 push edi
00566BB3 . 8B3D EC966A00 mov edi, dword ptr [<&user32.GetDlgI>; USER32.GetDlgItemTextA
00566BB9 . 68 00010000 push 100 ; /Count = 100 (256.)
00566BBE . 50 push eax ; |Buffer
00566BBF . 68 D0070000 push 7D0 ; |ControlID = 7D0 (2000.)
00566BC4 . 56 push esi ; |hWnd
00566BC5 . FFD7 call edi ; \GetDlgItemTextA
00566BC7 . 8D4C24 10 lea ecx, dword ptr [esp+10]
00566BCB . 6A 20 push 20 ; /Count = 20 (32.)
00566BCD . 51 push ecx ; |Buffer
00566BCE . 68 D1070000 push 7D1 ; |ControlID = 7D1 (2001.)
00566BD3 . 56 push esi ; |hWnd
00566BD4 . FFD7 call edi ; \GetDlgItemTextA
00566BD6 . 8A4424 70 mov al, byte ptr [esp+70] ; //送用户名第一位
00566BDA . 84C0 test al, al ; //较验用户名是否为空
00566BDC . 0F84 3A010000 je 00566D1C ; //为空则跳,跳往注册失败
00566BE2 . 8A4424 10 mov al, byte ptr [esp+10] ; //送假码第一位
00566BE6 . 84C0 test al, al ; //较验注册码是否为空
00566BE8 . 0F84 2E010000 je 00566D1C ; //为空则跳,跳往注册失败
00566BEE . 8D5424 08 lea edx, dword ptr [esp+8] ; //F5A0堆栈送给EDX
00566BF2 . 8D4424 70 lea eax, dword ptr [esp+70] ; //用户名送给EAX,(堆栈F608)
00566BF6 . 52 push edx ; //EDX入栈
00566BF7 . 50 push eax ; //EAX入栈(用户名入栈,准备参于运算了)
00566BF8 . E8 B3B5F9FF call 005021B0 ; //关键CALL,跟进
00566BFD . 8D4C24 18 lea ecx, dword ptr [esp+18] ; //注册码送给ECX(堆栈F5A8)
00566C01 . 51 push ecx ; //入栈
00566C02 . E8 7CB60200 call 00592283 ; //注册码转换为十六进制值
00566C07 . 8B4C24 14 mov ecx, dword ptr [esp+14] ; //用户名计算值送给ECX
00566C0B . 83C4 0C add esp, 0C
00566C0E . 3BC8 cmp ecx, eax ; //关键比较,
00566C10 74 5D je short 00566C6F ; //相等则跳往注册成功,(这里必须跳,不跳则错误)
00566C12 . A1 086E7300 mov eax, dword ptr [736E08]
00566C17 . 8D5424 30 lea edx, dword ptr [esp+30]
00566C1B . 6A 40 push 40 ; /Count = 40 (64.)
00566C1D . 52 push edx ; |Buffer
00566C1E . 68 93130000 push 1393 ; |RsrcID = STRING "Invalid registration"
00566C23 . 50 push eax ; |hInst => 00F60000
00566C24 . FF15 7C976A00 call dword ptr [<&user32.LoadStringA>>; \LoadStringA
00566C2A . 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00566C2C . 8D4C24 34 lea ecx, dword ptr [esp+34] ; |
00566C30 . 68 6CEA7200 push 0072EA6C ; |Title = ""
00566C35 . 51 push ecx ; |Text
00566C36 . 56 push esi ; |hOwner
00566C37 . FF15 0C976A00 call dword ptr [<&user32.MessageBoxA>>; \MessageBoxA
00566C3D . 68 D0070000 push 7D0 ; /ControlID = 7D0 (2000.)
00566C42 . 56 push esi ; |hWnd
00566C43 . FF15 04976A00 call dword ptr [<&user32.GetDlgItem>] ; \GetDlgItem
00566C49 . 50 push eax ; /hWnd
00566C4A . FF15 48976A00 call dword ptr [<&user32.SetFocus>] ; \SetFocus
00566C50 . 68 6CEA7200 push 0072EA6C ; /Text = ""
00566C55 . 68 D1070000 push 7D1 ; |ControlID = 7D1 (2001.)
00566C5A . 56 push esi ; |hWnd
00566C5B . FF15 00976A00 call dword ptr [<&user32.SetDlgItemTe>; \SetDlgItemTextA
00566C61 . 5F pop edi
00566C62 . B8 01000000 mov eax, 1
00566C67 . 5E pop esi
00566C68 . 81C4 68010000 add esp, 168
00566C6E . C3 retn
00566C6F > 8D5424 70 lea edx, dword ptr [esp+70]
00566C73 . 68 00010000 push 100
00566C78 . 52 push edx
00566C79 . 68 D0070000 push 7D0
00566C7E . 56 push esi
00566C7F . FFD7 call edi
00566C81 . 8D4424 10 lea eax, dword ptr [esp+10]
00566C85 . 6A 20 push 20
00566C87 . 50 push eax
00566C88 . 68 D1070000 push 7D1
00566C8D . 56 push esi
00566C8E . FFD7 call edi
00566C90 . 8D4C24 70 lea ecx, dword ptr [esp+70]
00566C94 . 51 push ecx
00566C95 . 68 DC957000 push 007095DC ; licensename
00566C9A . 6A 00 push 0
00566C9C . E8 4F37F7FF call 004DA3F0
00566CA1 . 8D5424 1C lea edx, dword ptr [esp+1C]
00566CA5 . 52 push edx
00566CA6 . 68 CC957000 push 007095CC ; licensenumber
00566CAB . 6A 00 push 0
00566CAD . E8 3E37F7FF call 004DA3F0
00566CB2 . A1 106E7300 mov eax, dword ptr [736E10]
00566CB7 . 83C4 18 add esp, 18
00566CBA . C705 286E7300>mov dword ptr [736E28], 1
00566CC4 . 6A 01 push 1 ; /Flags = MF_BYCOMMAND|MF_GRAYED|MF_STRING
00566CC6 . 68 F2000000 push 0F2 ; |ItemID = F2 (242.)
00566CCB . 50 push eax ; |/hWnd => 001D0884 ('XnView - [浏览器 - F:\下载\Xn...',class='XmainClass')
00566CCC . FF15 F0956A00 call dword ptr [<&user32.GetMenu>] ; |\GetMenu
00566CD2 . 50 push eax ; |hMenu
00566CD3 . FF15 5C976A00 call dword ptr [<&user32.EnableMenuIt>; \EnableMenuItem
00566CD9 . 8B15 086E7300 mov edx, dword ptr [736E08] ; xnviewzh.00F60000
00566CDF . 8D4C24 30 lea ecx, dword ptr [esp+30]
00566CE3 . 6A 40 push 40 ; /Count = 40 (64.)
00566CE5 . 51 push ecx ; |Buffer
00566CE6 . 68 94130000 push 1394 ; |RsrcID = STRING "Registration successful.
Thank you for purchasing XnView."
00566CEB . 52 push edx ; |hInst => 00F60000
00566CEC . FF15 7C976A00 call dword ptr [<&user32.LoadStringA>>; \LoadStringA
00566CF2 . 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00566CF4 . 8D4424 34 lea eax, dword ptr [esp+34] ; |
00566CF8 . 68 6CEA7200 push 0072EA6C ; |Title = ""
00566CFD . 50 push eax ; |Text
00566CFE . 56 push esi ; |hOwner
00566CFF . FF15 0C976A00 call dword ptr [<&user32.MessageBoxA>>; \MessageBoxA
00566D05 . 6A 00 push 0 ; /Result = 0
00566D07 . 56 push esi ; |hWnd
00566D08 . FF15 F0966A00 call dword ptr [<&user32.EndDialog>] ; \EndDialog
00566D0E . 5F pop edi
00566D0F . B8 01000000 mov eax, 1
00566D14 . 5E pop esi
00566D15 . 81C4 68010000 add esp, 168
00566D1B . C3 retn
00566D1C > 8B15 086E7300 mov edx, dword ptr [736E08] ; xnviewzh.00F60000
00566D22 . 8D4C24 30 lea ecx, dword ptr [esp+30]
00566D26 . 6A 40 push 40 ; /Count = 40 (64.)
00566D28 . 51 push ecx ; |Buffer
00566D29 . 68 93130000 push 1393 ; |RsrcID = STRING "Invalid registration"
00566D2E . 52 push edx ; |hInst => 00F60000
00566D2F . FF15 7C976A00 call dword ptr [<&user32.LoadStringA>>; \LoadStringA
00566D35 . 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00566D37 . 8D4424 34 lea eax, dword ptr [esp+34] ; |
00566D3B . 68 6CEA7200 push 0072EA6C ; |Title = ""
00566D40 . 50 push eax ; |Text
00566D41 . 56 push esi ; |hOwner
00566D42 . FF15 0C976A00 call dword ptr [<&user32.MessageBoxA>>; \MessageBoxA
00566D48 . 5F pop edi
00566D49 . B8 01000000 mov eax, 1
00566D4E . 5E pop esi
00566D4F . 81C4 68010000 add esp, 168
00566D55 . C3 retn
二、由00566BF8 call 005021B0 ; //关键CALL,跟进来到:(这里是用户名计算部份)
005021B0 /$ 8B5424 04 mov edx, dword ptr [esp+4] ; //用户名送给EDX
005021B4 |. 53 push ebx
005021B5 |. 55 push ebp
005021B6 |. 56 push esi
005021B7 |. 57 push edi
005021B8 |. 8BFA mov edi, edx ; //用户名送给EDI
005021BA |. 83C9 FF or ecx, FFFFFFFF ; //ECX=FFFFFFFF
005021BD |. 33C0 xor eax, eax ; //EAX清零(用于搜索用户名中是否有0)
005021BF |. F2:AE repne scas byte ptr es:[edi] ; //循环搜索字符
005021C1 |. F7D1 not ecx ; //ECX取反,得出(用户名长度+1)的值
005021C3 |. 49 dec ecx ; //ECX-1,得到用户名长度
005021C4 |. BE 188A7000 mov esi, 00708A18 ; //ESI=00708A18
005021C9 |. 8BE9 mov ebp, ecx ; //用户名长度送给EBP
005021CB |. B9 05000000 mov ecx, 5 ; //ECX=5
005021D0 |. BF 90087300 mov edi, 00730890 ; //EDI=00730890
005021D5 |. F3:A5 rep movs dword ptr es:[edi], dword p>; //00708A18中的内容(密码表)送给00730890地址中
005021D7 |. 8BF0 mov esi, eax ; //ESI=EAX=0
005021D9 |. 74 21 je short 005021FC
005021DB |> 8A0C16 /mov cl, byte ptr [esi+edx] ; //依次送用户名的ASCII值给CL
005021DE |. 8AD9 |mov bl, cl ; //ASCII值送给BL
005021E0 |. 3298 90087300 |xor bl, byte ptr [eax+730890] ; //ASCII值与相应位数上的固定值异或运算
005021E6 |. 40 |inc eax ; //EAX+1,用于比较是否到第五位
005021E7 |. 83F8 05 |cmp eax, 5 ; //EAX与5比较,(看来第5位是特殊)
005021EA |. 881C16 |mov byte ptr [esi+edx], bl ; //异或值替换ASCII值
005021ED |. 8888 8F087300 |mov byte ptr [eax+73088F], cl ; //ASCII值替换固定值,这两行就是字符交换
005021F3 |. 75 02 |jnz short 005021F7 ; //不等则跳,
005021F5 |. 33C0 |xor eax, eax ; //若EAX=5即第五位时,EAX清零,进行第二轮交换
005021F7 |> 46 |inc esi ; //标志位+1,用于取下一位
005021F8 |. 3BF5 |cmp esi, ebp ; //标志位与长度比较,看是否循环完
005021FA |.^ 72 DF \jb short 005021DB ; //小于则跳,未完继续(循环1)
005021FC |> 33FF xor edi, edi ; //EDI清零
005021FE |. 33C9 xor ecx, ecx ; //ECX清零
00502200 |. 85ED test ebp, ebp ; //较验用户名长度是否为空
00502202 |. 76 26 jbe short 0050222A ; //为空则跳(标志小于等于0则跳)
00502204 |> 8A9F 95087300 /mov bl, byte ptr [edi+730895] ; //依次取固定值给BL(从第六位固定值开始取)
0050220A |. 8BF5 |mov esi, ebp ; //用户名长度送给ESI
0050220C |. 2BF1 |sub esi, ecx ; //长度-ECX(ECX初值为0)
0050220E |. 4E |dec esi ; //再-1,这三行代码用来从倒数第一位依次往前取值
0050220F |. 8A0416 |mov al, byte ptr [esi+edx] ; //第一次循环交换后的用户名倒数第一位开始依次送给AL,
00502212 |. 32D8 |xor bl, al ; //与固定值异或运算
00502214 |. 47 |inc edi ; //EDI+1,比较是否到了第五位
00502215 |. 881C16 |mov byte ptr [esi+edx], bl
00502218 |. 8887 94087300 |mov byte ptr [edi+730894], al ; //这两行也是字符交换
0050221E |. 83FF 05 |cmp edi, 5 ; //EDI与5比较,看是否为第5位
00502221 |. 75 02 |jnz short 00502225 ; //不是则跳
00502223 |. 33FF |xor edi, edi ; //是第5位则EDI清零,进行第二轮交换
00502225 |> 41 |inc ecx ; //标志位加1,
00502226 |. 3BCD |cmp ecx, ebp ; //标志位与长度比较,看是否取完
00502228 |.^ 72 DA \jb short 00502204 ; //未完继续(循环2)
0050222A |> 33F6 xor esi, esi ; //ESI清零
0050222C |. 33FF xor edi, edi ; //EDI清零
0050222E |. 85ED test ebp, ebp ; //用户名是否为空
00502230 |. 76 21 jbe short 00502253 ; //为空则跳
00502232 |> 8A0417 /mov al, byte ptr [edi+edx] ; //循环二交换后的用户名ASCII值依次送给AL
00502235 |. 8A8E 9A087300 |mov cl, byte ptr [esi+73089A] ; //依次取固定值送给CL,第11位固定值开始取值
0050223B |. 32C8 |xor cl, al ; //固定值与ASCII值异或运算
0050223D |. 46 |inc esi ; //ESI+1,用来比较是否到了第5位,(第二轮较换)
0050223E |. 880C17 |mov byte ptr [edi+edx], cl
00502241 |. 8886 99087300 |mov byte ptr [esi+730899], al ; //这两行代码交换值
00502247 |. 83FE 05 |cmp esi, 5 ; //ESI与5比较
0050224A |. 75 02 |jnz short 0050224E ; //不等则跳,
0050224C |. 33F6 |xor esi, esi ; //若相等则ESI清零,进行第二轮交换
0050224E |> 47 |inc edi ; //EDI+1
0050224F |. 3BFD |cmp edi, ebp ; //标志位与用户名长度比较,
00502251 |.^ 72 DF \jb short 00502232 ; //此循环(循环3)功能同循环1,从固定值的第11位开始替换
00502253 |> 33FF xor edi, edi ; //EDI清零
00502255 |. 33C9 xor ecx, ecx ; //ECX清零
00502257 |. 85ED test ebp, ebp ; //用户名是否为空
00502259 |. 76 26 jbe short 00502281 ; //为空则跳
0050225B |> 8A9F 9F087300 /mov bl, byte ptr [edi+73089F] ; //依次取固定值送给BL,从固定值第16位开始取值
00502261 |. 8BF5 |mov esi, ebp ; //用户名长度送给ESI
00502263 |. 2BF1 |sub esi, ecx ; //ESI-EBP,EBP初始值为零
00502265 |. 4E |dec esi ; //再-1,这三行代码用来从倒数第一位依次往前取值
00502266 |. 8A0416 |mov al, byte ptr [esi+edx] ; //依次取循环3后的用户名ASCII值送给AL,从后往前取值
00502269 |. 32D8 |xor bl, al ; //ASCII值与固定值异或运算
0050226B |. 47 |inc edi ; //EDI+1,用于比较是否到了第五位以便进行第二轮交换
0050226C |. 881C16 |mov byte ptr [esi+edx], bl
0050226F |. 8887 9E087300 |mov byte ptr [edi+73089E], al ; //这两行代码进行值的交换
00502275 |. 83FF 05 |cmp edi, 5 ; //EDI与5比较,
00502278 |. 75 02 |jnz short 0050227C ; //不等则跳,
0050227A |. 33FF |xor edi, edi ; //若相等则EDI清零,进行第二轮交换
0050227C |> 41 |inc ecx ; //ECX+1
0050227D |. 3BCD |cmp ecx, ebp ; //与长度比较
0050227F |.^ 72 DA \jb short 0050225B ; //此循环(循环4)功能同循环2,从固定值第16位开始交换
00502281 |> 8B7C24 18 mov edi, dword ptr [esp+18] ; //堆栈地址F5A0送给EDI
00502285 |. 33C0 xor eax, eax ; //EAX清零
00502287 |. 85ED test ebp, ebp ; //较验用户名是否为空
00502289 |. C707 00000000 mov dword ptr [edi], 0 ; //堆栈清零,用于存储4次循环后的 前4位值的 累加值
0050228F |. 76 17 jbe short 005022A8 ; //为空则跳
00502291 |> 8BC8 /mov ecx, eax ; //ECX=EAX(标志位)
00502293 |. 83E1 03 |and ecx, 3 ; // ECX AND 3,(4位一循环)
00502296 |. 8A1C39 |mov bl, byte ptr [ecx+edi] ; //依次送每一位累加值给BL
00502299 |. 8D3439 |lea esi, dword ptr [ecx+edi] ; //存储地址送给ESI
0050229C |. 8A0C10 |mov cl, byte ptr [eax+edx] ; //依次取用户名4次循环交换后的值给CL
0050229F |. 02D9 |add bl, cl ; //累加
005022A1 |. 40 |inc eax ; //EAX+1,用于取下一位
005022A2 |. 3BC5 |cmp eax, ebp ; //与用户名比较
005022A4 |. 881E |mov byte ptr [esi], bl ; //相加值送入堆栈中
005022A6 |.^ 72 E9 \jb short 00502291 ; //未完继续(4位一循环,对前面几次循环的值进行累加)
005022A8 |> 5F pop edi
005022A9 |. 5E pop esi
005022AA |. 5D pop ebp
005022AB |. 5B pop ebx
005022AC \. C3 retn
三、由00566C02 call 00592283 ; //注册码转换为十六进制值函数
00592283 /$ 53 push ebx ; //这个函数用于将注册码转换为十六进制值
00592284 |. 55 push ebp
00592285 |. 56 push esi
00592286 |. 57 push edi
00592287 |. 8B7C24 14 mov edi, dword ptr [esp+14] ; //注册码送给EDI
0059228B |> 833D 8C727100>/cmp dword ptr [71728C], 1 ; //[71728C]中的值(初值为1)与1比较
00592292 |. 7E 0F |jle short 005922A3 ; //小于等于则跳
00592294 |. 0FB607 |movzx eax, byte ptr [edi]
00592297 |. 6A 08 |push 8
00592299 |. 50 |push eax
0059229A |. E8 7C240000 |call 0059471B
0059229F |. 59 |pop ecx
005922A0 |. 59 |pop ecx
005922A1 |. EB 0F |jmp short 005922B2
005922A3 |> 0FB607 |movzx eax, byte ptr [edi] ; //依次取注册码ASCII值送给EAX
005922A6 |. 8B0D 80707100 |mov ecx, dword ptr [717080] ; //[717080]中的值(字符表地址)送给ECX
005922AC |. 8A0441 |mov al, byte ptr [ecx+eax*2] ; //取字符表中的值送给AL
005922AF |. 83E0 08 |and eax, 8 ; //EAX AND 8(无效地址:709C-90A4、70CA)
005922B2 |> 85C0 |test eax, eax ; //是否为空(无效ASCII值为9-D、20)
005922B4 |. 74 03 |je short 005922B9 ; //为空则跳(只要第一个为有效字符就跳出循环,否则清除)
005922B6 |. 47 |inc edi ; //取下一位
005922B7 |.^ EB D2 \jmp short 0059228B ; //这一个循环是较验注册码字符的有效性,把开始处的无效字符清除
005922B9 |> 0FB637 movzx esi, byte ptr [edi] ; //取注册码第一位ASCII值送给ESI
005922BC |. 47 inc edi ; //EDI加1
005922BD |. 83FE 2D cmp esi, 2D ; //ASCII值与2D(-)比较
005922C0 |. 8BEE mov ebp, esi ; //ASCII值送给EBP
005922C2 |. 74 05 je short 005922C9 ; //相等则跳
005922C4 |. 83FE 2B cmp esi, 2B ; //ASCII值与2B(+)比较
005922C7 |. 75 04 jnz short 005922CD ; //不等则跳
005922C9 |> 0FB637 movzx esi, byte ptr [edi] ; //若相等,则ASCII值送给ESI
005922CC |. 47 inc edi ; //EDI+1,取下一位
005922CD |> 33DB xor ebx, ebx ; //不为(+)号跳来此处,EBX清零
005922CF |> 833D 8C727100>/cmp dword ptr [71728C], 1 ; //[71728C]中的值(初值为1)与1比较
005922D6 |. 7E 0C |jle short 005922E4 ; //小于等于则跳
005922D8 |. 6A 04 |push 4
005922DA |. 56 |push esi
005922DB |. E8 3B240000 |call 0059471B
005922E0 |. 59 |pop ecx
005922E1 |. 59 |pop ecx
005922E2 |. EB 0B |jmp short 005922EF
005922E4 |> A1 80707100 |mov eax, dword ptr [717080] ; //[717080]中的值(固定值)送给EAX
005922E9 |. 8A0470 |mov al, byte ptr [eax+esi*2] ; //字符表中的值送给AL
005922EC |. 83E0 04 |and eax, 4 ; //EAX AND 4(有效字符表:70EA-70FC)
005922EF |> 85C0 |test eax, eax ; //是否为空(有效ASCII值:30-39,说明注册码必为数字)
005922F1 |. 74 0D |je short 00592300 ; //为空则跳,跳了就挂了
005922F3 |. 8D049B |lea eax, dword ptr [ebx+ebx*4] ; //EAX=EBX*5(EBX初始值为0)
005922F6 |. 8D5C46 D0 |lea ebx, dword ptr [esi+eax*2-30] ; //EBX=ESI+EAX*2-30 (ESI为注册码的ASCII值)
005922FA |. 0FB637 |movzx esi, byte ptr [edi] ; //注册码ASCII值送给ESI
005922FD |. 47 |inc edi ; //EDI+1,取下一位注册码
005922FE |.^ EB CF \jmp short 005922CF ; //字符串有效性较验的循环
00592300 |> 83FD 2D cmp ebp, 2D ; //ASCII值与2D(-)比较
00592303 |. 8BC3 mov eax, ebx ; //EAX=EBX=0
00592305 |. 75 02 jnz short 00592309 ; //不等则跳
00592307 |. F7D8 neg eax ; //若相等则EAX取补,为FFFFFFFF
00592309 |> 5F pop edi
0059230A |. 5E pop esi
0059230B |. 5D pop ebp
0059230C |. 5B pop ebx
0059230D \. C3 retn
四、软件运用到的几个表:
(1)、字符有效性较验用到的表:
0071708A 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 . . . . . . . .
0071709A 20 00 28 00 28 00 28 00 28 00 28 00 20 00 20 00 .(.(.(.(.(. . .
007170AA 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 . . . . . . . .
007170BA 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 . . . . . . . .
007170CA 48 00 10 00 10 00 10 00 10 00 10 00 10 00 10 00 H........
007170DA 10 00 10 00 10 00 10 00 10 00 10 00 10 00 10 00 ........
007170EA 84 00 84 00 84 00 84 00 84 00 84 00 84 00 84 00 ????????
007170FA 84 00 84 00 10 00 10 00 10 00 10 00 10 00 10 00 ??......
0071710A 10 00 81 00 81 00 81 00 81 00 81 00 81 00 01 00 .??????.
0071711A 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 ........
0071712A 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 ........
0071713A 01 00 01 00 01 00 10 00 10 00 10 00 10 00 10 00 ........
0071714A 10 00 82 00 82 00 82 00 82 00 82 00 82 00 02 00 .??????.
0071715A 02 00 02 00 02 00 02 00 02 00 02 00 02 00 02 00 ........
0071716A 02 00 02 00 02 00 02 00 02 00 02 00 02 00 02 00 ........
0071717A 02 00 02 00 02 00 10 00 10 00 10 00 10 00 20 00 ....... .
(2)、用户名循环计算时用到的表:(4个循环,每个循环用到5个数值)
00708A18 AA 89 C4 FE 46 78 F0 D0 03 E7 F7 FD F4 E7 B9 B5 獕宁Fx鹦琪绻
00708A28 1B C9 50 73 蒔s.
五、算法总结:
1、循环1:
依次取用户名ASCII值与密码表1-5位(AA 89 C4 FE 46 )对应值进行异或,异或后的值替换用户名的ASCII值,同时用户名的ASCII值替换对应位置的固定值,每五位一次循环,直
到用户名计算完。
2、循环2:
依次取循环1计算后的用户名值(从倒数第一位开始依次往前取)与密码表第6-10位(78 F0 D0 03 E7)对应值进行异或,异或后的值替换用户名值,用户名值替换对应位置的固定
值,每五位一次循环,直到用户名计算完。
3、循环3:
依次取循环2计算后的用户名值与密码表第11-15位(F7 FD F4 E7 B9)对应值进行异或,异或后的值替换用户名值,用户名值替换对应位置的固定值,每五位一次循环,直到用户
名计算完。
4、循环4:
依次取循环3计算后的用户名值(从倒数第一位开始依次往前取)与密码表第16-20位(B5 1B C9 50 73)对应值进行异或,异或后的值替换用户名值,用户名值替换对应位置的固
定值,每五位一次循环,直到用户名计算完。
5、循环5
依次取循环4计算后用户名值进行累加,1、5、9、13、……位相加作为累加值的第一位;2、6、10、14、……位相加作为累加值第二位;3、7、11、15、……位相加作为累加值的
第3位;4、8、12、16、……位相加作为累加值的第4位;(每4位一循环);累加值作为一个数值(从高到低排),计作A1。A1转换为十进数就是真码!
6、关键比较:注册码转换为十六进制值记作Y; A1==Y 则注册成功,否则注册失败!
六:注册机源码(代码写的太土了,各位大侠不要见笑)复制内容到剪贴板代码:
void C测试Dlg::OnBnClickedOk()
{
CString Yhm,Zcm,ZcmTemp; //定义用户名、注册码字符串
_int64 ZcmInt1 = 0; //定义大整数
CString str1,str2,str3,str4; //定义4个字符串,用来将循环5中的4个值转换为16进制字符串
int biao1[5] = {0xAA,0x89,0xC4,0xFE,0x46};//密码表1
int biao2[5] = {0x78,0xF0,0xD0,0x03,0xE7};//密码表2
int biao3[5] = {0xF7,0xFD,0xF4,0xE7,0xB9};//密码表3
int biao4[5] = {0xB5,0x1B,0xC9,0x50,0x73};//密码表4
int YhmLength = 0; //定义用户名长度
int YhmAscii[100] = {0}; //定义用户名ASCII值表,长度100,
GetDlgItemText(IDC_EDIT1,Yhm); //从输入框1中获取输入的用户名
YhmLength = Yhm.GetLength(); //取用户名长度
if (YhmLength<1) //若用户名长度小于1,则提示,
{
MessageBox("请输入用户名!");
return;
}
if (YhmLength>99) //若用户名长度大于99,则超出用户名ASCII值表,提示,
{
MessageBox("你的用户名不用这么长吧?");
return;
}
for (int i = 0;i<YhmLength;i++) //循环将用户名转换为ASCII值,存入用户名ASCII值表中
{
YhmAscii[i] = (int)Yhm[i];
}
for (int i = 0;i < YhmLength;i++) //循环1
{
int temp = YhmAscii[i];
YhmAscii[i] = biao1[i%5]^YhmAscii[i];
YhmAscii[i] = LOBYTE(YhmAscii[i]);
biao1[i%5] = temp;
}
for (int i = YhmLength;i>0;i--) //循环2
{
int temp = YhmAscii[i-1];
YhmAscii[i-1] = biao2[(YhmLength-i)%5]^YhmAscii[i-1];
YhmAscii[i-1] = LOBYTE(YhmAscii[i-1]);
biao2[(YhmLength-i)%5] = temp;
}
for (int i = 0;i < YhmLength;i++) //循环3
{
int temp = YhmAscii[i];
YhmAscii[i] = biao3[i%5]^YhmAscii[i];
YhmAscii[i] = LOBYTE(YhmAscii[i]);
biao3[i%5] = temp;
}
for (int i = YhmLength;i>0;i--) //循环4
{
int temp = YhmAscii[i-1];
YhmAscii[i-1] = biao4[(YhmLength-i)%5]^YhmAscii[i-1];
YhmAscii[i-1] = LOBYTE(YhmAscii[i-1]);
biao4[(YhmLength-i)%5] = temp;
}
int YhmAscii2[4] = {0}; //定义一个4位的整数数组,用于存储累加值
for (int i = 0;i<YhmLength;i++) //循环5
{
YhmAscii2[i%4] = YhmAscii2[i%4] + YhmAscii[i];
YhmAscii2[i%4] = LOBYTE(YhmAscii2[i%4]);
}
str1.Format("%.2x",YhmAscii2[0]);
str2.Format("%.2x",YhmAscii2[1]);
str3.Format("%.2x",YhmAscii2[2]);
str4.Format("%.2x",YhmAscii2[3]);
ZcmTemp = str4 + str3 + str2 + str1; //从高位到低位拼接字符串
ZcmInt1 = strtoul(ZcmTemp, NULL, 16); //将16进制字符串转换为大整数
Zcm.Format("%I64d",ZcmInt1);
SetDlgItemText(IDC_EDIT2,Zcm); //输出注册码
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!