【文章标题】: 某幼儿学习软件的注册码分析
【文章作者】: pojiemyie
【软件名称】: 大家都知道的原因隐藏了
【下载地址】: 自己搜索下载
【使用工具】: PEID,OD
【操作平台】: WinXP
【软件介绍】: 幼儿学习数学的软件
【作者声明】: 给自己小孩用的,注册算法超级简单。为了邀请码,厚脸皮写这篇破文。
--------------------------------------------------------------------------------
【详细过程】
首先Peid查壳,为Microsoft Visual C++ 6.0,无壳。OD载入,发现是MFC的程序,一大堆jmp <jmp.&MFC42.#641>之类的函数,头晕。想起教程里有导入函数一说,赶紧找MFC42.lib,然后调试→选择导入库,OD重新载入程序,jmp <jmp.&MFC42.#641>之类的函数已经能识别出名称了。
F9运行,出现注册对话框,随便填入一些东西,点注册出现错误提示。关闭提示,OD中用中文搜索引擎搜索相关提示,找到错误提示处,
00406359 |> 68 38304100 push 儿童快乐.00413038 ; 注册号不正确,请重新输入! ////搜索到的错误提示
向上找跳转,发现注册关键代码如下,F8单步分析:
004061B2 |. 8B86 DC070000 mov eax,dword ptr ds:[esi+7DC]
004061B8 |. 8DAE DC070000 lea ebp,dword ptr ds:[esi+7DC]
004061BE |. 8B50 F8 mov edx,dword ptr ds:[eax-8]
004061C1 |. 83FA 1D cmp edx,1D ; 长度是否等于1D,即29位
004061C4 |. 0F85 65010000 jnz 儿童快乐.0040632F
004061CA |. 8A48 05 mov cl,byte ptr ds:[eax+5]
004061CD |. 80F9 2D cmp cl,2D
004061D0 |. 0F85 59010000 jnz 儿童快乐.0040632F
004061D6 |. 8078 0B 2D cmp byte ptr ds:[eax+B],2D
004061DA |. 0F85 4F010000 jnz 儿童快乐.0040632F
004061E0 |. 8078 11 2D cmp byte ptr ds:[eax+11],2D
004061E4 |. 0F85 45010000 jnz 儿童快乐.0040632F
004061EA |. 8078 17 2D cmp byte ptr ds:[eax+17],2D
004061EE |. 0F85 3B010000 jnz 儿童快乐.0040632F ; 判断每隔5位(第6位)是否是字符-,得注册码形式XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
004061F4 |. 55 push ebp
004061F5 |. 8D4C24 2C lea ecx,dword ptr ss:[esp+2C]
004061F9 |. E8 E4790000 call <jmp.&MFC42.#CString::CString_535>
004061FE |. 68 18394100 push 儿童快乐.00413918
00406203 |. 8D4C24 14 lea ecx,dword ptr ss:[esp+14]
00406207 |. 897C24 20 mov dword ptr ss:[esp+20],edi
0040620B |. E8 CC790000 call <jmp.&MFC42.#CString::CString_537>
00406210 |. 6A 07 push 7
00406212 |. 6A 16 push 16
00406214 |. 8D4C24 30 lea ecx,dword ptr ss:[esp+30]
00406218 |. C64424 24 01 mov byte ptr ss:[esp+24],1
0040621D |. E8 B4790000 call <jmp.&MFC42.#CString::Delete_6648> ; 删除从第16位(即22位)后的7个字符(最后7位)
00406222 |. BF 04000000 mov edi,4
00406227 |> 6A 02 /push 2
00406229 |. 57 |push edi
0040622A |. 8D4C24 30 |lea ecx,dword ptr ss:[esp+30]
0040622E |. E8 A3790000 |call <jmp.&MFC42.#CString::Delete_6648> ; 从第4位开始,每隔4位删除2个字符,即将-和前面一个字符删除
00406233 |. 83C7 04 |add edi,4
00406236 |. 83FF 10 |cmp edi,10
00406239 |.^ 7C EC \jl short 儿童快乐.00406227
0040623B |. 68 18394100 push 儿童快乐.00413918
00406240 |. 8D4C24 28 lea ecx,dword ptr ss:[esp+28]
00406244 |. E8 93790000 call <jmp.&MFC42.#CString::CString_537>
00406249 |. 8D4C24 24 lea ecx,dword ptr ss:[esp+24]
0040624D |. C64424 1C 02 mov byte ptr ss:[esp+1C],2
00406252 |. 51 push ecx
00406253 |. 8BCE mov ecx,esi
00406255 |. E8 B6720000 call 儿童快乐.0040D510 ; 获取C盘信息以便计算注册码
0040625A |. 8D5424 24 lea edx,dword ptr ss:[esp+24]
0040625E |. 8BCE mov ecx,esi
00406260 |. 52 push edx
00406261 |. E8 2A650000 call 儿童快乐.0040C790 ; 第一次计算注册码
00406266 |. 8D4424 24 lea eax,dword ptr ss:[esp+24]
0040626A |. 8BCE mov ecx,esi
0040626C |. 50 push eax
0040626D |. E8 1E650000 call 儿童快乐.0040C790 ; 第二次计算注册码
00406272 |. 8B4C24 24 mov ecx,dword ptr ss:[esp+24]
00406276 |. 8B5424 28 mov edx,dword ptr ss:[esp+28]
0040627A |. 51 push ecx ; /s2
0040627B |. 52 push edx ; |s1
0040627C |. FF15 F4024100 call dword ptr ds:[<&MSVCRT._mbscmp>] ; \_mbscmp 关键比较
00406282 |. 83C4 08 add esp,8
00406285 |. 85C0 test eax,eax
00406287 |. 6A 00 push 0
00406289 |. 68 74304100 push 儿童快乐.00413074 ; 提示
0040628E |. 75 5F jnz short 儿童快乐.004062EF
00406290 |. 68 18324100 push 儿童快乐.00413218 ; 注册成功, 谢谢使用!
00406295 |. 8BCE mov ecx,esi
00406297 |. E8 34790000 call <jmp.&MFC42.#CWnd::MessageBoxA_4224>
0040629C |. B8 01000000 mov eax,1
004062A1 |. 55 push ebp
004062A2 |. 8986 C8070000 mov dword ptr ds:[esi+7C8],eax
004062A8 |. 8986 CC070000 mov dword ptr ds:[esi+7CC],eax
004062AE |. 8D4424 10 lea eax,dword ptr ss:[esp+10]
004062B2 |. 68 54304100 push 儿童快乐.00413054 ; SERIAL=
004062B7 |. 50 push eax
004062B8 |. C786 98030000>mov dword ptr ds:[esi+398],0
004062C2 |. E8 03790000 call <jmp.&MFC42.#operator+_926>
004062C7 |. 50 push eax
004062C8 |. 8D8E C4070000 lea ecx,dword ptr ds:[esi+7C4]
004062CE |. C64424 20 03 mov byte ptr ss:[esp+20],3
004062D3 |. E8 EC780000 call <jmp.&MFC42.#CString::operator=_858>
004062D8 |. 8D4C24 0C lea ecx,dword ptr ss:[esp+C]
004062DC |. C64424 1C 02 mov byte ptr ss:[esp+1C],2
004062E1 |. E8 96780000 call <jmp.&MFC42.#CString::~CString_800>
004062E6 |. 8BCE mov ecx,esi
004062E8 |. E8 E3C4FFFF call 儿童快乐.004027D0 ; 跟进发现保存注册码保存在 DAT\diary.dat,格式SERIAL=注册码
004062ED |. EB 0C jmp short 儿童快乐.004062FB
004062EF |> 68 38304100 push 儿童快乐.00413038 ; 注册号不正确,请重新输入!
004062F4 |. 8BCE mov ecx,esi
004062F6 |. E8 D5780000 call <jmp.&MFC42.#CWnd::MessageBoxA_4224>
004062FB |> 8D4C24 24 lea ecx,dword ptr ss:[esp+24]
004062FF |. C64424 1C 01 mov byte ptr ss:[esp+1C],1
00406304 |. E8 73780000 call <jmp.&MFC42.#CString::~CString_800>
00406309 |. 8D4C24 10 lea ecx,dword ptr ss:[esp+10]
0040630D |. C64424 1C 00 mov byte ptr ss:[esp+1C],0
00406312 |. E8 65780000 call <jmp.&MFC42.#CString::~CString_800>
00406317 |. 8D4C24 28 lea ecx,dword ptr ss:[esp+28]
0040631B |. C74424 1C FFF>mov dword ptr ss:[esp+1C],-1
00406323 |. E8 54780000 call <jmp.&MFC42.#CString::~CString_800>
00406328 |. 33FF xor edi,edi
0040632A |. E9 9D000000 jmp 儿童快乐.004063CC
0040632F |> 3BD7 cmp edx,edi
00406331 |. 57 push edi
00406332 |. 68 74304100 push 儿童快乐.00413074 ; 提示
00406337 |. 75 20 jnz short 儿童快乐.00406359
00406339 |. 68 28304100 push 儿童快乐.00413028 ; 请输入注册号!
0040633E |. 8BCE mov ecx,esi
00406340 |. E8 8B780000 call <jmp.&MFC42.#CWnd::MessageBoxA_4224>
00406345 |. 5F pop edi
00406346 |. 5E pop esi
00406347 |. 5D pop ebp
00406348 |. 8B4C24 08 mov ecx,dword ptr ss:[esp+8]
0040634C |. 64:890D 00000>mov dword ptr fs:[0],ecx
00406353 |. 83C4 14 add esp,14
00406356 |. C2 0800 retn 8
00406359 |> 68 38304100 push 儿童快乐.00413038 ; 注册号不正确,请重新输入! ////搜索到的错误提示
0040635E |. 8BCE mov ecx,esi
00406360 |. E8 6B780000 call <jmp.&MFC42.#CWnd::MessageBoxA_4224>
00406365 |. 5F pop edi
00406366 |. 5E pop esi
00406367 |. 5D pop ebp
00406368 |. 8B4C24 08 mov ecx,dword ptr ss:[esp+8]
0040636C |. 64:890D 00000>mov dword ptr fs:[0],ecx
00406373 |. 83C4 14 add esp,14
00406376 |. C2 0800 retn 8
注册码的算出没有仔细跟,粗略看了一下,在以下三处(省略部分代码):
第一处:
00406255 |. E8 B6720000 call 儿童快乐.0040D510 ; 获取C盘信息以便计算注册码
F7跟进:
0040D52F |. 6A 0A push 0A ; /pFileSystemNameSize = 0000000A
0040D531 |. 50 push eax ; |pFileSystemNameBuffer
0040D532 |. 8D4424 10 lea eax,dword ptr ss:[esp+10] ; |
0040D536 |. 50 push eax ; |pFileSystemFlags
0040D537 |. 51 push ecx ; |pMaxFilenameLength
0040D538 |. 52 push edx ; |pVolumeSerialNumber
0040D539 |. 6A 0C push 0C ; |MaxVolumeNameSize = C (12.)
0040D53B |. 56 push esi ; |VolumeNameBuffer
0040D53C |. 68 F4384100 push 儿童快乐.004138F4 ; |c://
0040D541 |. FF15 60004100 call dword ptr ds:[<&KERNEL32.GetVolumeI>; \GetVolumeInformationA 获取C盘信息以便计算注册码
第二处:
00406261 |. E8 2A650000 call 儿童快乐.0040C790 ; 第一次计算注册码
F7跟进:
0040C7E3 |> /8D3C00 /lea edi,dword ptr ds:[eax+eax]
0040C7E6 |. |83FF 18 |cmp edi,18
0040C7E9 |. |7E 05 |jle short 儿童快乐.0040C7F0
0040C7EB |. |BF 18000000 |mov edi,18
0040C7F0 |> |B3 31 |mov bl,31 ; 数字1
0040C7F2 |. |BE 01000000 |mov esi,1
0040C7F7 |. |885C24 1C |mov byte ptr ss:[esp+1C],bl
0040C7FB |> |8B5424 1C |/mov edx,dword ptr ss:[esp+1C]
0040C7FF |. |8D4C24 14 ||lea ecx,dword ptr ss:[esp+14]
0040C803 |. |52 ||push edx
0040C804 |. |56 ||push esi
0040C805 |. |E8 2C140000 ||call <jmp.&MFC42.#CString::Insert_6778> ; 每隔两位插入递加数字1、2、3、4、5……
0040C80A |. |FEC3 ||inc bl ; 递加
0040C80C |. |80FB 3A ||cmp bl,3A
0040C80F |. |885C24 1C ||mov byte ptr ss:[esp+1C],bl
0040C813 |. |75 06 ||jnz short 儿童快乐.0040C81B
0040C815 |. |B3 41 ||mov bl,41
0040C817 |. |885C24 1C ||mov byte ptr ss:[esp+1C],bl
0040C81B |> |8B4424 14 ||mov eax,dword ptr ss:[esp+14]
0040C81F |. |83C6 02 ||add esi,2
0040C822 |. |8B48 F8 ||mov ecx,dword ptr ds:[eax-8]
0040C825 |. |3BCF ||cmp ecx,edi
0040C827 |.^|7C D2 |\jl short 儿童快乐.0040C7FB
0040C829 |. |8BC1 |mov eax,ecx
0040C82B |. |83F8 18 |cmp eax,18
0040C82E |.^\7C B3 \jl short 儿童快乐.0040C7E3
0040C830 |. 5F pop edi ; 经过以上计算,补足18位(即24位)字符
0040C831 |> 68 18394100 push 儿童快乐.00413918
0040C836 |. 8D4C24 10 lea ecx,dword ptr ss:[esp+10]
0040C83A |. E8 9D130000 call <jmp.&MFC42.#CString::CString_537>
0040C83F |. C64424 28 02 mov byte ptr ss:[esp+28],2
0040C844 |. 33F6 xor esi,esi
0040C846 |. BB 04000000 mov ebx,4
0040C84B |> 6A 06 push 6
0040C84D |. 8D4424 1C lea eax,dword ptr ss:[esp+1C]
0040C851 |. 56 push esi
0040C852 |. 50 push eax
0040C853 |. 8D4C24 1C lea ecx,dword ptr ss:[esp+1C]
0040C857 |. E8 D4130000 call <jmp.&MFC42.#CString::Mid_4278> ; 每6个一组取出计算注册码
0040C85C |. 50 push eax
0040C85D |. 8D4C24 10 lea ecx,dword ptr ss:[esp+10]
0040C861 |. C64424 2C 03 mov byte ptr ss:[esp+2C],3
0040C866 |. E8 59130000 call <jmp.&MFC42.#CString::operator=_858>
0040C86B |. 8D4C24 18 lea ecx,dword ptr ss:[esp+18]
0040C86F |. C64424 28 02 mov byte ptr ss:[esp+28],2
0040C874 |. E8 03130000 call <jmp.&MFC42.#CString::~CString_800>
0040C879 |. 6A 06 push 6
0040C87B |. 6A 06 push 6
0040C87D |. 8D4C24 14 lea ecx,dword ptr ss:[esp+14]
0040C881 |. E8 A4130000 call <jmp.&MFC42.#CString::GetBuffer_2915>
0040C886 |. 50 push eax
0040C887 |. 8BCD mov ecx,ebp
0040C889 |. E8 52FEFFFF call 儿童快乐.0040C6E0 ; 计算注册码,转化为字母。跟进,见下
0040C88E |. 6A FF push -1
0040C890 |. 8D4C24 10 lea ecx,dword ptr ss:[esp+10]
0040C894 |. E8 8B130000 call <jmp.&MFC42.#CString::ReleaseBuffer_557>
0040C899 |. 6A 01 push 1
0040C89B |. 53 push ebx
0040C89C |. 8D4C24 14 lea ecx,dword ptr ss:[esp+14]
0040C8A0 |. E8 31130000 call <jmp.&MFC42.#CString::Delete_6648>
0040C8A5 |. 8D4C24 0C lea ecx,dword ptr ss:[esp+C]
0040C8A9 |. 8D5424 14 lea edx,dword ptr ss:[esp+14]
0040C8AD |. 51 push ecx
0040C8AE |. 8D4424 20 lea eax,dword ptr ss:[esp+20]
0040C8B2 |. 52 push edx
0040C8B3 |. 50 push eax
0040C8B4 |. E8 65130000 call <jmp.&MFC42.#operator+_922>
0040C8B9 |. 50 push eax
0040C8BA |. 8D4C24 18 lea ecx,dword ptr ss:[esp+18]
0040C8BE |. 885C24 2C mov byte ptr ss:[esp+2C],bl
0040C8C2 |. E8 FD120000 call <jmp.&MFC42.#CString::operator=_858>
0040C8C7 |. 8D4C24 1C lea ecx,dword ptr ss:[esp+1C]
0040C8CB |. C64424 28 02 mov byte ptr ss:[esp+28],2
0040C8D0 |. E8 A7120000 call <jmp.&MFC42.#CString::~CString_800>
0040C8D5 |. 83C6 06 add esi,6
0040C8D8 |. 83FE 18 cmp esi,18
0040C8DB |.^ 0F8C 6AFFFFFF jl 儿童快乐.0040C84B ; 循环计算5次,得到5组字母,再经第二次计算即得注册码
0040C889 |. E8 52FEFFFF call 儿童快乐.0040C6E0 处跟进如下:
0040C6F9 |> /83F8 07 /cmp eax,7
0040C6FC |. |7E 02 |jle short 儿童快乐.0040C700
0040C6FE |. |33C0 |xor eax,eax
0040C700 |> |33D2 |xor edx,edx
0040C702 |. |33DB |xor ebx,ebx
0040C704 |. |8A1431 |mov dl,byte ptr ds:[ecx+esi]
0040C707 |. |8A98 A4304100 |mov bl,byte ptr ds:[eax+4130A4]
0040C70D |. |0FAFD3 |imul edx,ebx
0040C710 |. |03FA |add edi,edx
0040C712 |. |41 |inc ecx
0040C713 |. |40 |inc eax
0040C714 |. |3BCD |cmp ecx,ebp
0040C716 |.^\7C E1 \jl short 儿童快乐.0040C6F9
0040C718 |> 57 push edi ; /<%ld>
0040C719 |. 68 7C304100 push 儿童快乐.0041307C ; |%ld
0040C71E |. 56 push esi ; |s
0040C71F |. FF15 6C034100 call dword ptr ds:[<&USER32.wsprintfA>] ; \wsprintfA
0040C725 |. 8A4E 02 mov cl,byte ptr ds:[esi+2] ;
////经过以上计算转化为四位数字
0040C728 |. 8A46 03 mov al,byte ptr ds:[esi+3]
0040C72B |. 83C4 0C add esp,0C
0040C72E |. 3AC8 cmp cl,al
0040C730 |. 7D 06 jge short 儿童快乐.0040C738
0040C732 |. 8AD0 mov dl,al
0040C734 |. 2AD1 sub dl,cl
0040C736 |. EB 04 jmp short 儿童快乐.0040C73C
0040C738 |> 8AD1 mov dl,cl
0040C73A |. 2AD0 sub dl,al
0040C73C |> 8A1E mov bl,byte ptr ds:[esi]
0040C73E |. 80C1 11 add cl,11 ; 数字加11转化为字母,以下同
0040C741 |. 04 11 add al,11
0040C743 |. 02DA add bl,dl ; 加第四位与第二位差
0040C745 |. 884E 02 mov byte ptr ds:[esi+2],cl ; 所得字母填充入第三位
0040C748 |. 8846 03 mov byte ptr ds:[esi+3],al ; 所得字母填充入第四位
0040C74B |. 881E mov byte ptr ds:[esi],bl ; 填充入第一位,继续计算
0040C74D |. 8AD3 mov dl,bl
0040C74F |. 8A5E 01 mov bl,byte ptr ds:[esi+1]
0040C752 |. 80C2 11 add dl,11
0040C755 |. 0FBEC0 movsx eax,al
0040C758 |. 0FBEC9 movsx ecx,cl
0040C75B |. 80C3 11 add bl,11
0040C75E |. 03C1 add eax,ecx
0040C760 |. 0FBECB movsx ecx,bl
0040C763 |. 8816 mov byte ptr ds:[esi],dl ; 填充入第一位
0040C765 |. 03C1 add eax,ecx
0040C767 |. 0FBED2 movsx edx,dl
0040C76A |. 03C2 add eax,edx
0040C76C |. 885E 01 mov byte ptr ds:[esi+1],bl ; 填充入第二位
0040C76F |. 99 cdq
0040C770 |. 83E2 03 and edx,3
0040C773 |. C646 05 00 mov byte ptr ds:[esi+5],0
0040C777 |. 03C2 add eax,edx
0040C779 |. 5F pop edi
0040C77A |. C1F8 02 sar eax,2 ; 除以4,基本是前四位平均
0040C77D |. 8846 04 mov byte ptr ds:[esi+4],al ; 填充入第五位
0040C780 |. 5E pop esi
0040C781 |. 5D pop ebp
0040C782 |. 5B pop ebx
0040C783 \. C2 0800 retn 8
第三处:
0040626D |. E8 1E650000 call 儿童快乐.0040C790 ; 第二次计算注册码
对第一计算结果再次计算,算法完全一样,得到最终注册码。
总结:
算法非常简单,上面有分析。注册码形式为XXXXX-XXXXX-XXXXX-XXXXX-XXXXX,X全为大写字母。基本是明码比较,对输入码做了简单处理,为了方便找规律,输入ABCDE-FGHIJ-KLMNO-PQRST-UVWXY,输入码转化的规律为:
将后7位删除,每个-及前面一个字母删除,重新连接得到字符串,即得ABCDFGHIKLMNPQRS,再与真码比较。将真码每四个一组,插入一个字母和-,最后在补足7个字符即可。
从C盘获得信息得到一串字符,填充变为24位,循环取出6位,转化为四位数字,然后加11变为字母,第五位基本是前四位平均,将几组字母连接成16位字母,再算一次变成注册码。只大概看了一下,可能分析有些不准,谅解。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2011年05月02日 上午 10:11:48
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!