【文章标题】: 一个程序有两种注册方式
【文章作者】: rdsnow[BCG][PYG][D.4s]
【作者邮箱】: [email]rdsnow@163.com[/email]
【作者主页】: http://rdsnow.ys168.com
【作者QQ号】: 83757177
【下载地址】: 主页:http://www.wizissoft.com
【使用工具】: OllyICE
【软件介绍】: 网文×× V4.361
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
【文章简介】
这个程序有两种注册方式,但是均比较简单:
1、在程序目录下建立"oem.ini"文件,输入以下内容则可变成 OEM 版
[Common]
Name=成都铁路局基层工会资料管理系统
这也算个最简单的keyfile吧!
2、使用简单算法得到符合条件的注册码注册成个人版:
注册码的形式为:XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
下面的注释中给各段取名:szRegCode1-szRegCode2-szRegCode3-szRegCode4-szRegCode5
(其实中间不一定用"-",任何字符都可以通过,只是验证时没有用到这几位,所以用"-"替代了)
算法中使用到了修改了加法常数的 MD5 运算。
--------------------------------------------------------------------------------
【破解过程】
程序在输入注册码后会关闭程序,在重启后验证注册码,输入假码:
98765-56789-54321-12345-ABCDE
监视程序保存注册码,发现假码保存在文件
"C:\Documents and Settings\Administrator\Application Data\CyberArticle\CyberArticle.ini"中:
内容如下:
[UserInfo]
SerialNo=BFIXU-LMFJV-NUENK-GTZYA-PMRSW
Name=rdsnow[BCG][PYG][D.4s]
典型的ini的格式。可以通过字符串"UserInfo"查找关键点下断:
断到这里:
004F366C |. 51 push ecx
004F366D |. BA 1E586600 mov edx,Cyber.0066581E ; ASCII "UserInfo"
004F3672 |. 8D45 FC lea eax,dword ptr ss:[ebp-4]
004F3675 |. E8 8A611000 call Cyber.005F9804
F8单步跟代码,return 后来到:
0040761A |. FF45 EC inc dword ptr ss:[ebp-14]
0040761D |. E8 FEBF0E00 call Cyber.WaGetSN ; 读取注册码
00407622 |. 8D55 F8 lea edx,dword ptr ss:[ebp-8]
00407625 |. 52 push edx
00407626 |. BA 350D6000 mov edx,Cyber.00600D35 ; ASCII ""
0040762B |. 8D45 FC lea eax,dword ptr ss:[ebp-4]
0040762E |. E8 D1211F00 call Cyber.005F9804
00407633 |. FF45 EC inc dword ptr ss:[ebp-14]
00407636 |. 5A pop edx
00407637 |. 59 pop ecx
00407638 |. E8 2F241F00 call Cyber.005F9A6C
0040763D |. 8D45 F4 lea eax,dword ptr ss:[ebp-C]
00407640 |. 8B00 mov eax,dword ptr ds:[eax]
00407642 |. E8 ADC00E00 call Cyber.WaDownloadImageFile ; 关键 Call
00407647 |. 50 push eax ; 返回值压栈
………………
(中间有许多Call,用于销毁局部变量,所以就省了)
………………
00407678 |. 59 pop ecx ; 弹出返回值
00407679 |. 84C9 test cl,cl
0040767B |. 74 11 je short Cyber.0040768E ; 若返回 1 则注册成功
0040767D |. 33C0 xor eax,eax
0040767F |. 8B55 D0 mov edx,dword ptr ss:[ebp-30]
00407682 |. 64:8915 00000>mov dword ptr fs:[0],edx
00407689 |. E9 C4000000 jmp Cyber.00407752
程序有意将关键 Call 和关键 JUMP 拉远距离,不多说了,赶快进去看看吧:
004F3753 |. 50 push eax
004F3754 |. FF45 8C inc dword ptr ss:[ebp-74]
004F3757 |. BA 30586600 mov edx,Cyber.00665830 ; ASCII "oem.ini"
004F375C |. 8D45 F0 lea eax,dword ptr ss:[ebp-10]
004F375F |. E8 A0601000 call Cyber.005F9804
004F3764 |. FF45 8C inc dword ptr ss:[ebp-74]
004F3767 |. 8D55 F0 lea edx,dword ptr ss:[ebp-10]
004F376A |. 52 push edx
004F376B |. 8D45 F4 lea eax,dword ptr ss:[ebp-C]
004F376E |. E8 ED3CF1FF call Cyber.00407460
004F3773 |. FF45 8C inc dword ptr ss:[ebp-74]
004F3776 |. E8 F9C5FFFF call Cyber.WaGetAppPath ; 获取程序路径
004F377B |. 8D45 F4 lea eax,dword ptr ss:[ebp-C]
004F377E |. 5A pop edx
004F377F |. 59 pop ecx
004F3780 |. E8 E7621000 call Cyber.005F9A6C ; 连接程序路径和"oem.ini"
004F3785 |. 8D45 EC lea eax,dword ptr ss:[ebp-14]
004F3788 |. 50 push eax
004F3789 |. BA 3F586600 mov edx,Cyber.0066583F ; ASCII "Name"
004F378E |. 8D45 E4 lea eax,dword ptr ss:[ebp-1C]
004F3791 |. E8 6E601000 call Cyber.005F9804
004F3796 |. FF45 8C inc dword ptr ss:[ebp-74]
004F3799 |. 8D55 E4 lea edx,dword ptr ss:[ebp-1C]
004F379C |. 52 push edx
004F379D |. BA 38586600 mov edx,Cyber.00665838 ; ASCII "Common"
004F37A2 |. 8D45 E8 lea eax,dword ptr ss:[ebp-18]
004F37A5 |. E8 5A601000 call Cyber.005F9804
004F37AA |. FF45 8C inc dword ptr ss:[ebp-74] ; |
004F37AD |. 8D55 E8 lea edx,dword ptr ss:[ebp-18] ; |
004F37B0 |. 59 pop ecx ; |
004F37B1 |. 58 pop eax ; |
004F37B2 |. E8 A9A4FBFF call Cyber.WizReadStrFromConfig ; \读取 oem.ini 内的信息
004F37B7 |. 8D45 DC lea eax,dword ptr ss:[ebp-24]
004F37BA |. 50 push eax
004F37BB |. BA 45586600 mov edx,Cyber.00665845
004F37C0 |. 8D45 D8 lea eax,dword ptr ss:[ebp-28]
004F37C3 |. E8 3C601000 call Cyber.005F9804
004F37C8 |. FF45 8C inc dword ptr ss:[ebp-74]
004F37CB |. 8D55 D8 lea edx,dword ptr ss:[ebp-28]
004F37CE |. 58 pop eax
004F37CF |. E8 24631000 call Cyber.005F9AF8 ; 判断是不是 OEM 版
看下程序所在目录根本没有 oem.ini 文件,伪造一个吧,ini格式的文件是最容易伪造的了,根据上面代码文件内容应是:
[Common]
Name=XXXXXXXXXXXXXXXXXXXXXXX
oem.ini 造好后,跟进判断是不是 OEM 版的 Call:
005F9AF8 /$ 55 push ebp
005F9AF9 |. 8BEC mov ebp,esp
005F9AFB |. 53 push ebx
005F9AF8 /$ 55 push ebp
005F9AF9 |. 8BEC mov ebp,esp
005F9AFB |. 53 push ebx
005F9AFC |. 8B00 mov eax,dword ptr ds:[eax] ; ASCII "XXXXXXXXXXXXXXXXXXXXXXX"
005F9AFE |. 8B12 mov edx,dword ptr ds:[edx] ; ASCII "成都铁路局基层工会资料管理系统"
005F9B00 |. E8 3F71FCFF call Cyber.005C0C44 ; 这个当然是比较字符串了
005F9B05 |. 0F94C0 sete al
005F9B08 |. 83E0 01 and eax,1
005F9B0B |. 5B pop ebx
005F9B0C |. 5D pop ebp
005F9B0D \. C3 retn
赶快将 oem.ini 文件中的XXX换成"成都…………",重启程序,果然变成"成都铁路局基层工会(100套授权)"
不要满足,程序并没有处理我们输入的注册码,关键 Call 直接返回1了,删掉 oem.ini,继续跟:
下面同样有很多 Call 用于销毁局部变量,走了好远,来到:
004F38B6 |. 8D45 FC lea eax,dword ptr ss:[ebp-4]
004F38B9 |. E8 1E4EF1FF call Cyber.004086DC ; 取得注册码的长度
004F38BE |. 83F8 1D cmp eax,1D ; if(strlen(szRegCode)>29) bRegLog=1
004F38C1 |. 0F9FC2 setg dl
004F38C4 |. 83E2 01 and edx,1
004F38C7 |. 8895 6FFFFFFF mov byte ptr ss:[ebp-91],dl ; 保存 bRegLog
004F38CD |. 66:C745 80 08>mov word ptr ss:[ebp-80],8
004F38D3 |. 66:C745 80 2C>mov word ptr ss:[ebp-80],2C
004F38D9 |. 8D55 FC lea edx,dword ptr ss:[ebp-4]
004F38DC |. 8D45 F8 lea eax,dword ptr ss:[ebp-8]
004F38DF |. E8 585F1000 call Cyber.005F983C
004F38E4 |. FF45 8C inc dword ptr ss:[ebp-74]
004F38E7 |. 66:C745 80 08>mov word ptr ss:[ebp-80],8
004F38ED |. 80BD 6FFFFFFF>cmp byte ptr ss:[ebp-91],0
004F38F4 |. 0F84 9E050000 je Cyber.004F3E98 ; if( bRegLog==0 ) 跳下去继续验证
bRegLog=1 时,程序没有直接跳向返回 0,作者跟你开了个玩笑,大概过程是这样的:
if(szRegCode==szStr1){
if(szRegCode==szStr2){
if(szRegCode==szStr3){
if(szRegCode==szStr4){
if(szRegCode==szStr5){
if(szRegCode==szStr6){
if(szRegCode==szStr7)
CheckCode( );
}
}
}
}
}
}
return false;
如果你跟下去,你就会发现上当了:注册码怎么可能同时等于7个不同的字符串呢?即使相等,最后还是去验证注册码。
004F3E98 |> \8D45 F8 lea eax,dword ptr ss:[ebp-8]
004F3E9B |. E8 283CF1FF call Cyber.00407AC8
004F3EA0 |. 50 push eax ; /Arg1
004F3EA1 |. E8 6E000000 call Cyber.004F3F14 ; \CheckCode( )
004F3EA6 |. 59 pop ecx
004F3EA7 |. 84C0 test al,al
004F3EA9 |. 75 33 jnz short Cyber.004F3EDE ; if(CheckCode( )==true) return true;
004F3EAB |. 33C0 xor eax,eax ; return false
………………
004F3EDC |. EB 31 jmp short Cyber.004F3F0F ; JUMP TO:return false
004F3EDE |> B0 01 mov al,1 ; return true
………………
004F3F0F |> 8BE5 mov esp,ebp
004F3F11 |. 5D pop ebp
004F3F12 \. C3 retn
CheckCode( )当然是关键了,继续跟进这个关键:
004F3F14 /$ 55 push ebp
004F3F15 |. 8BEC mov ebp,esp
004F3F17 |. 83C4 C4 add esp,-3C
004F3F1A |. C645 DE 00 mov byte ptr ss:[ebp-22],0
004F3F1E |. 6A 05 push 5 ; /Arg3 = 00000005
004F3F20 |. FF75 08 push dword ptr ss:[ebp+8] ; |Arg2
004F3F23 |. 8D45 D4 lea eax,dword ptr ss:[ebp-2C] ; |
004F3F26 |. 50 push eax ; |Arg1
004F3F27 |. E8 F00C0D00 call Cyber.005C4C1C ; \取 szRegCode 的第1段 szRegCode1
004F3F2C |. 83C4 0C add esp,0C
004F3F2F |. 6A 05 push 5 ; /Arg3 = 00000005
004F3F31 |. 8B55 08 mov edx,dword ptr ss:[ebp+8] ; |
004F3F34 |. 83C2 06 add edx,6 ; |
004F3F37 |. 52 push edx ; |Arg2
004F3F38 |. 8D4D D9 lea ecx,dword ptr ss:[ebp-27] ; |
004F3F3B |. 51 push ecx ; |Arg1
004F3F3C |. E8 DB0C0D00 call Cyber.005C4C1C ; \取 szRegCode 的第2段 szRegCode2
004F3F41 |. 83C4 0C add esp,0C
004F3F44 |. 8D45 C4 lea eax,dword ptr ss:[ebp-3C]
004F3F47 |. 50 push eax ; /Arg3
004F3F48 |. 6A 0A push 0A ; |Arg2 = 0000000A
004F3F4A |. 8D55 D4 lea edx,dword ptr ss:[ebp-2C] ; |
004F3F4D |. 52 push edx ; |Arg1
004F3F4E |. E8 812A0000 call Cyber.004F69D4 ; \用szRegCode1 和 szRegCode2 生成 bMd5Result[16]
004F3F53 |. 83C4 0C add esp,0C
004F3F56 |. 33C9 xor ecx,ecx
004F3F58 |. 894D FC mov dword ptr ss:[ebp-4],ecx
004F3F5B |> 8B45 FC /mov eax,dword ptr ss:[ebp-4]
004F3F5E |. 33D2 |xor edx,edx
004F3F60 |. 8A5405 C4 |mov dl,byte ptr ss:[ebp+eax-3C] ; bMd5Result[i]
004F3F64 |. 8955 F8 |mov dword ptr ss:[ebp-8],edx
004F3F67 |. 8B4D 08 |mov ecx,dword ptr ss:[ebp+8]
004F3F6A |. 8B45 FC |mov eax,dword ptr ss:[ebp-4]
004F3F6D |. 8A5401 0C |mov dl,byte ptr ds:[ecx+eax+C] ; szRegCode3[i]
004F3F71 |. 8855 F7 |mov byte ptr ss:[ebp-9],dl
004F3F74 |. 8B45 F8 |mov eax,dword ptr ss:[ebp-8]
004F3F77 |. B9 1A000000 |mov ecx,1A ; bMd5Result[i] % 26
004F3F7C |. 33D2 |xor edx,edx
004F3F7E |. F7F1 |div ecx
004F3F80 |. 80C2 41 |add dl,41 ; result = bMd5Result[i] % 26 + 0x41
004F3F83 |. 3A55 F7 |cmp dl,byte ptr ss:[ebp-9]
004F3F86 |. 74 07 |je short Cyber.004F3F8F ; if (szRegCode3[i]!=result) retrun false
004F3F88 |. 33C0 |xor eax,eax
004F3F8A |. E9 8D000000 |jmp Cyber.004F401C
004F3F8F |> FF45 FC |inc dword ptr ss:[ebp-4]
004F3F92 |. 837D FC 05 |cmp dword ptr ss:[ebp-4],5
004F3F96 |.^ 7C C3 \jl short Cyber.004F3F5B
004F3F98 |. C745 F0 05000>mov dword ptr ss:[ebp-10],5
004F3F9F |> 8B55 F0 /mov edx,dword ptr ss:[ebp-10]
004F3FA2 |. 33C9 |xor ecx,ecx
004F3FA4 |. 8A4C15 C4 |mov cl,byte ptr ss:[ebp+edx-3C] ; bMd5Result[i+5]
004F3FA8 |. 894D EC |mov dword ptr ss:[ebp-14],ecx
004F3FAB |. 8B45 08 |mov eax,dword ptr ss:[ebp+8]
004F3FAE |. 8B55 F0 |mov edx,dword ptr ss:[ebp-10]
004F3FB1 |. 8A4C10 0D |mov cl,byte ptr ds:[eax+edx+D] ; szRegCode4[i]
004F3FB5 |. 884D EB |mov byte ptr ss:[ebp-15],cl
004F3FB8 |. 8B45 EC |mov eax,dword ptr ss:[ebp-14]
004F3FBB |. B9 1A000000 |mov ecx,1A
004F3FC0 |. 33D2 |xor edx,edx
004F3FC2 |. F7F1 |div ecx ; bMd5Result[i+5] % 26
004F3FC4 |. 80C2 41 |add dl,41 ; result = bMd5Result[i] % 26 + 0x41
004F3FC7 |. 3A55 EB |cmp dl,byte ptr ss:[ebp-15]
004F3FCA |. 74 04 |je short Cyber.004F3FD0 ; if (szRegCode4[0]!=result) retrun false
004F3FCC |. 33C0 |xor eax,eax
004F3FCE |. EB 4C |jmp short Cyber.004F401C
004F3FD0 |> FF45 F0 |inc dword ptr ss:[ebp-10]
004F3FD3 |. 837D F0 0A |cmp dword ptr ss:[ebp-10],0A
004F3FD7 |.^ 7C C6 \jl short Cyber.004F3F9F
004F3FD9 |. C745 E4 0A000>mov dword ptr ss:[ebp-1C],0A
004F3FE0 |> 8B55 E4 /mov edx,dword ptr ss:[ebp-1C]
004F3FE3 |. 33C9 |xor ecx,ecx
004F3FE5 |. 8A4C15 C4 |mov cl,byte ptr ss:[ebp+edx-3C] ; bMd5Result[i+10]
004F3FE9 |. 894D E0 |mov dword ptr ss:[ebp-20],ecx
004F3FEC |. 8B45 08 |mov eax,dword ptr ss:[ebp+8]
004F3FEF |. 8B55 E4 |mov edx,dword ptr ss:[ebp-1C]
004F3FF2 |. 8A4C10 0E |mov cl,byte ptr ds:[eax+edx+E] ; szRegCode5[i]
004F3FF6 |. 884D DF |mov byte ptr ss:[ebp-21],cl
004F3FF9 |. 8B45 E0 |mov eax,dword ptr ss:[ebp-20]
004F3FFC |. B9 1A000000 |mov ecx,1A
004F4001 |. 33D2 |xor edx,edx
004F4003 |. F7F1 |div ecx ; bMd5Result[i+10] % 26
004F4005 |. 80C2 41 |add dl,41 ; result = bMd5Result[i+10] % 26 + 0x41
004F4008 |. 3A55 DF |cmp dl,byte ptr ss:[ebp-21]
004F400B |. 74 04 |je short Cyber.004F4011 ; if (szRegCode5[0]!=result) retrun false
004F400D |. 33C0 |xor eax,eax
004F400F |. EB 0B |jmp short Cyber.004F401C
004F4011 |> FF45 E4 |inc dword ptr ss:[ebp-1C]
004F4014 |. 837D E4 0F |cmp dword ptr ss:[ebp-1C],0F
004F4018 |.^ 7C C6 \jl short Cyber.004F3FE0
004F401A |. B0 01 mov al,1
004F401C |> 8BE5 mov esp,ebp
004F401E |. 5D pop ebp
004F401F \. C3 retn
将bMd5Result[16]中前 15 个 byte 对 26 取余,再加 0x41 就得到组成szRegCode3、4、5 的 15 个字符
程序将 szRegCode1="98765" 和 szRegCode2="56789"连接得到"9876556789"
bMd5Result[16],正是对 "9876556789" 后的字符串MD5运算的结果,跟进
004F3F4E |. E8 812A0000 call Cyber.004F69D4 ; \用szRegCode1 和 szRegCode2 生成 bMd5Result[16]
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课