【破文标题】光驱伴侣的注册算法分析及简单的分析一下程序
【破文作者】小娃崽[DFCG]
【作者邮箱】wanzailuan@yahoo.com.cn
【作者主页】
【破解工具】OD
【破解平台】XP+SP2
【软件名称】光驱伴侣V1.2
【软件大小】68.0 KB
【原版下载】不记得了
【保护方式】序列号
【软件简介】无
------------------------------------------------------------------------
<pre>
004045BC . 68 0C934000 push 0040930C ; /IniFileName = "C:\Doc
004045C1 . 8D4424 0C lea eax, dword ptr [esp+C] ; |
004045C5 . 6A 15 push 15 ; |BufSize = 15 (21.)
004045C7 . 50 push eax ; |ReturnBuffer
004045C8 . 68 10944000 push 00409410 ; |Default = ""
004045CD . 68 28914000 push 00409128 ; |licensecode
004045D2 . 68 20914000 push 00409120 ; |license
004045D7 . FF15 54604000 call dword ptr [<&KERNEL32.GetPrivateP>; \GetPrivateProfileStringA
//取得当前目录下CDPartner.ini中[License]
//LicenseCode的内容
004045DD . 8D4C24 08 lea ecx, dword ptr [esp+8]
004045E1 . 51 push ecx ; /Arg1=LicenseCode的内容
004045E2 . 8D4C24 08 lea ecx, dword ptr [esp+8] ; |
004045E6 . E8 95F5FFFF call 00403B80 ; \cdpartne.00403B80
//关键的call,跟进
004045EB . 85C0 test eax, eax
004045ED . 75 07 jnz short 004045F6 //爆破点
跟进关键call
00403B80 /$ 83EC 18 sub esp, 18
00403B83 |. 8D4424 00 lea eax, dword ptr [esp]
00403B87 |. 53 push ebx
00403B88 |. 55 push ebp
00403B89 |. 56 push esi
00403B8A |. 57 push edi
00403B8B |. 50 push eax
00403B8C |. E8 2FFFFFFF call 00403AC0
00403B91 |. 8B7C24 2C mov edi, dword ptr [esp+2C] ; 注册码到EDI
00403B95 |. 57 push edi ; /String
00403B96 |. FF15 64604000 call dword ptr [<&KERNEL32.lstrlenA>] ; \lstrlenA
00403B9C |. 83F8 14 cmp eax, 14 ; 注册码要等于14(20)位
00403B9F 0F85 AB000000 jnz 00403C50
00403BA5 |. 8A07 mov al, byte ptr [edi] ; 注册码第1位到al
00403BA7 |. 3C 44 cmp al, 44
//注册码第一位等于D吗?
00403BA9 |. 75 04 jnz short 00403BAF
//不等跳到 00403BAF
00403BAB |. 33ED xor ebp, ebp
//等于的话EBP清零
00403BAD |. EB 23 jmp short 00403BD2
//然后跳到00403BD2
00403BAF |> 3C 39 cmp al, 39
//第一位不等于D跳到这里比较是不是等于9
00403BB1 |. 75 07 jnz short 00403BBA
//不等于跳到00403BBA
00403BB3 |. BD 01000000 mov ebp, 1
//等于的话EBP置1
00403BB8 |. EB 18 jmp short 00403BD2
//然后跳到00403BD2继续执行
00403BBA |> 3C 41 cmp al, 41
//不等于D,9跳到这里比较是不是等于A
00403BBC |. 75 07 jnz short 00403BC5
//不等于跳到00403BC5
00403BBE |. BD 02000000 mov ebp, 2
//等于的话EBP=2
00403BC3 |. EB 0D jmp short 00403BD2
//然后跳到00403BD2继续执行
00403BC5 |> 3C 35 cmp al, 35
//不等于D,9,A跳到这里比较是不是等于5
00403BC7 |. 0F85 83000000 jnz 00403C50
//不等于跳到00403C50(会注册失败哦,不能跳)~
00403BCD |. BD 03000000 mov ebp, 3
等于EBP=3
//以上分析告诉我们,注册码第一位要等于D,9,A,或者5 ,等于D时EBP=0;等于9时,EBP=1;等于A时,EBP=2,等于5时,EBP=3
/////////////////////////////////////////一个循环////////////////////////////////////////////////////
00403BD2 |> 33DB xor ebx, ebx
00403BD4 |. BE 01000000 mov esi, 1 ; ESI置1
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00403BD9 |> 8A143E /mov dl, byte ptr [esi+edi] ;注册码第[esi]位到DL
00403BDC |. 33C9 |xor ecx, ecx ;ECX被清零
00403BDE |> 3891 EC914000 |/cmp byte ptr [ecx+4091EC], dl
//到这里D 004091EC一下查看是什么数据
004091EC 30 31 32 33 34 35 36 37 01234567
004091F4 38 39 41 42 43 44 45 46 89ABCDEF
原来是0123456789ABCDEF
00403BE4 |. 74 06 ||je short 00403BEC
相等了跳到 00403BEC
00403BE6 |. 41 ||inc ecx
00403BE7 |. 83F9 10 ||cmp ecx, 10
00403BEA |.^ 7C F2 |\jl short 00403BDE
//这个小循环的作用是比较注册码第ESI位等于几
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00403BEC |> 83F9 10 |cmp ecx, 10
//测试ECX=10(16)吗,也就是注册码第ESI位要在0――F之间,要不就注册失败哦
//ECX返回的结果其实等于CODE[ESI]
00403BEF |. 74 5F |je short 00403C50
//等于就注册失败了,所以这里不能跳
00403BF1 |. 8D04EB |lea eax, dword ptr [ebx+ebp*8]
//EAX=[EBX+EBP*8],观察发现是这样的结果
00403BF4 |. 3B3485 6C9140>|cmp esi, dword ptr [eax*4+40916C]
//D一下40916C看看,很明显的哦
0040916C 01 00 00 00 04 00 00 00 ......
00409174 07 00 00 00 08 00 00 00 ......
0040917C 09 00 00 00 0E 00 00 00 .......
00409184 11 00 00 00 13 00 00 00 ......
0040918C 03 00 00 00 05 00 00 00 ......
00409194 07 00 00 00 09 00 00 00 .......
0040919C 0A 00 00 00 0D 00 00 00 ........
004091A4 10 00 00 00 12 00 00 00 ......
004091AC 02 00 00 00 03 00 00 00 ......
004091B4 06 00 00 00 08 00 00 00 ......
004091BC 09 00 00 00 0B 00 00 00 .......
004091C4 0F 00 00 00 11 00 00 00 ......
004091CC 05 00 00 00 06 00 00 00 ......
004091D4 09 00 00 00 0C 00 00 00 ........
004091DC 0F 00 00 00 10 00 00 00 ......
004091E4 12 00 00 00 13 00 00 00 ......
//S[]={1,4,7,8,9,E,11,13,,3,5,7,9,a,d,,10,12,2,3,6,8,9,b,f,11,5,6,9,c,f,10,12,13}
//下标:(EBX+EBP*8)+1
00403BFB |. 75 29 |jnz short 00403C26
//不相等跳到00403C26
00403BFD |. 8A543E FF |mov dl, byte ptr [esi+edi-1]
//注册码第[ESI-1]位到dl
00403C01 |. 33C0 |xor eax, eax //EAX=0
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00403C03 |> 3890 EC914000 |/cmp byte ptr [eax+4091EC], dl
00403C09 |. 74 06 ||je short 00403C11
00403C0B |. 40 ||inc eax
00403C0C |. 83F8 10 ||cmp eax, 10
00403C0F |.^ 7C F2 |\jl short 00403C03
//这个小循环的作用同上!
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00403C11 |> 03C6 |add eax, esi
//EAX其实等于CODE[ESI-1]
//EAX=EAX+ESI
00403C13 |. 25 0F000080 |and eax, 8000000F
//于8000000F进行与运算
00403C18 |. 79 05 |jns short 00403C1F
//SF=0跳,也就是EAX返回正值跳
00403C1A |. 48 |dec eax
//不跳EAX-1
00403C1B |. 83C8 F0 |or eax, FFFFFFF0
//再or FFFFFFF0
00403C1E |. 40 |inc eax
//最后EAX+1
00403C1F |> 3BC8 |cmp ecx, eax
//比较EAX与ECX
00403C21 |. 75 2D |jnz short 00403C50
不相等注册失败!
00403C23 |. 43 |inc ebx //EBX=EBX+1,在EAX=ECX的情况下才++的哦
00403C24 |. EB 15 |jmp short 00403C3B
00403C26 |> 33C0 |xor eax, eax
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00403C28 |> 3890 EC914000 |/cmp byte ptr [eax+4091EC], dl
00403C2E |. 74 06 ||je short 00403C36
00403C30 |. 40 ||inc eax
00403C31 |. 83F8 10 ||cmp eax, 10
00403C34 |.^ 7C F2 |\jl short 00403C28
//这个小循环的作用同上!
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00403C36 |> 83F8 10 |cmp eax, 10
00403C39 |. 74 15 |je short 00403C50
00403C3B |> 46 |inc esi //ESI=ESI+1,作用是指向注册码下一位拉!
00403C3C |. 83FE 14 |cmp esi, 14 //和注册码位数20比较
00403C3F |.^ 7C 98 \jl short 00403BD9 //小于20继续循环
//////////////////////////////////////////一个循环////////////////////////////////////////////////////////
00403C41 |. 5F pop edi
00403C42 |. 5E pop esi
00403C43 |. 5D pop ebp
00403C44 |. B8 01000000 mov eax, 1 ;注册成功的标志
00403C49 |. 5B pop ebx
00403C4A |. 83C4 18 add esp, 18
00403C4D |. C2 0400 retn 4
00403C50 |> 5F pop edi ; Default case of switch 00403BA7
00403C51 |. 5E pop esi
00403C52 |. 5D pop ebp
00403C53 |. 33C0 xor eax, eax ;注册失败的标志
00403C55 |. 5B pop ebx
00403C56 |. 83C4 18 add esp, 18
00403C59 \. C2 0400 retn 4
算法总结:
ECX=CODE[ESI] //ESI从零开始,CODE[ESI]指注册码第ESI位
EAX=CODE[ESI-1]+ESI AND 8000000F
若EAX为负,那么再让EAX=(EAX-1) OR or FFFFFFF0 +1
让第0位=5,那么EBP=3;也就是ESI=5,6,9,C,F,10,12,13时比较EAX,ECX
让第4位=1;ESI=5; 那么第5位=(1+esi) AND 8000000F=6
ESI=6 ;那么第6位=(6+6) AND 8000000F=C
esi=9; 那么第9位=(1+9) and 8000000f=A //让第8位=1
ESI=C; 那么第C位=(1+c) and 8000000f=D //让第B位=1
ESI=F; 那么第F位=(1+f) and 8000000f=0 //让第E位=1
ESI=10,那么第10位=(0+10) AND 8000000F=0
ESI=12,那么第12位=(1+12) and 8000000f=3 //让第11位=1
ESI=13,那么第13位=(3+13) and 8000000f= 6
最后我们得到5???16c?1a?1d?100136? ?表示0--F任意的一个,注意要大写!!
比如我们输入:522216C21A21D21001362,程序就会提示你注册成功!
------------------------------------------------------------------------
------------------------------------------------------------------------
程序代码分析:
我关心的只是打开以及关闭光驱的代码,这个软件其实提供的也只有这两个功能而已!
=======================================打开光驱的子函数=================================================================
004010C0 /$ 81EC CC000000 sub esp, 0CC ;为函数开辟堆栈空间
004010C6 |. 8A8424 D00000>mov al, byte ptr [esp+D0] ; [esp+d0]指向的内容就是你的光驱,比如'G'
004010CD |. 56 push esi
004010CE |. 6A 64 push 64 ; /n = 64 (100.)
004010D0 |. 8D4C24 0C lea ecx, dword ptr [esp+C] ; |
004010D4 |. 68 50904000 push 00409050 ; |open
004010D9 |. 51 push ecx ; |String1
004010DA |. 884424 10 mov byte ptr [esp+10], al ; |
004010DE |. C64424 11 3A mov byte ptr [esp+11], 3A ; |
004010E3 |. C64424 12 00 mov byte ptr [esp+12], 0 ; |
004010E8 |. FF15 6C604000 call dword ptr [<&KERNEL32.lstrcpynA>>; \lstrcpynA
//复制这个"open"
004010EE |. 8B35 70604000 mov esi, dword ptr [<&KERNEL32.lstrc>; kernel32.lstrcatA
//esi=lstrcatA,call esi=call lstrcatA
004010F4 |. 8D5424 04 lea edx, dword ptr [esp+4] ;光驱盘符到EDX
004010F8 |. 8D4424 08 lea eax, dword ptr [esp+8] ;'open'到EAX
004010FC |. 52 push edx ; /StringToAdd
004010FD |. 50 push eax ; |ConcatString
004010FE |. FFD6 call esi ; \lstrcatA
//调用lstrcatA连接两个字符串!
00401100 |. 8D4C24 08 lea ecx, dword ptr [esp+8]
[esp+8]的内容就是连接好的字符串-->ecx,我这里是ECX="open G:"
00401104 |. 68 38904000 push 00409038 ; / "type cdaudio alias x"
00401109 |. 51 push ecx ; |ConcatString
0040110A |. FFD6 call esi ; \lstrcatA
//将"open G:"与"type cdaudio alias x"连接在一起
0040110C |. 8B35 CC634000 mov esi, dword ptr [<&WINMM.mciSendS>; WINMM.mciSendStringA
//ESI=mciSendStringA
00401112 |. 6A 00 push 0
00401114 |. 8D5424 70 lea edx, dword ptr [esp+70]
00401118 |. 6A 64 push 64
0040111A |. 8D4424 10 lea eax, dword ptr [esp+10] //[ESP+10]="open G: type cdaudio alias x"
0040111E |. 52 push edx
0040111F |. 50 push eax
00401120 |. FFD6 call esi ; <&WINMM.mciSendStringA>
//CALL mciSendStringA( "open G: type cdaudio alias x,[esp+70],64,0")
00401122 |. 6A 00 push 0
00401124 |. 8D4C24 70 lea ecx, dword ptr [esp+70]
00401128 |. 6A 64 push 64
0040112A |. 51 push ecx
0040112B |. 68 28904000 push 00409028 ; set x door open
00401130 |. FFD6 call esi
// mciSendStringA( "set x door open",[esp+70],64,0),到这里我的光驱打开了,真讨厌
00401132 |. 6A 00 push 0
00401134 |. 8D5424 70 lea edx, dword ptr [esp+70]
00401138 |. 6A 64 push 64
0040113A |. 52 push edx
0040113B |. 68 20904000 push 00409020 ; close x
00401140 |. FFD6 call esi
//mciSendStringA("close x ,[esp+70],64,0" )
00401142 |. 5E pop esi
00401143 |. 81C4 CC000000 add esp, 0CC
00401149 \. C2 0400 retn 4
===============================================================================================================
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$关闭光驱的子函数$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
00401150 /$ 81EC CC000000 sub esp, 0CC ;为函数开辟堆栈空间
00401156 |. 8A8424 D00000>mov al, byte ptr [esp+D0] ;[esp+D0]指向光驱,比如'G'
0040115D |. 56 push esi
0040115E |. 6A 64 push 64 ; /n = 64 (100.)
00401160 |. 8D4C24 0C lea ecx, dword ptr [esp+C] ; |
00401164 |. 68 50904000 push 00409050 ; |open
00401169 |. 51 push ecx ; |String1
0040116A |. 884424 10 mov byte ptr [esp+10], al ; |
0040116E |. C64424 11 3A mov byte ptr [esp+11], 3A ; |
00401173 |. C64424 12 00 mov byte ptr [esp+12], 0 ; |
00401178 |. FF15 6C604000 call dword ptr [<&KERNEL32.lstrcpynA>>; \lstrcpynA
0040117E |. 8B35 70604000 mov esi, dword ptr [<&KERNEL32.lstrc>; kernel32.lstrcatA
//复制这个"open"
00401184 |. 8D5424 04 lea edx, dword ptr [esp+4] ;光驱盘符到EDX
00401188 |. 8D4424 08 lea eax, dword ptr [esp+8] 'open'到EAX
0040118C |. 52 push edx ; /StringToAdd
0040118D |. 50 push eax ; |ConcatString
0040118E |. FFD6 call esi ; \lstrcatA
//连接"open"+"G:"
00401190 |. 8D4C24 08 lea ecx, dword ptr [esp+8]
00401194 |. 68 38904000 push 00409038 ; / type cdaudio alias x
00401199 |. 51 push ecx ; |ConcatString
0040119A |. FFD6 call esi ; \lstrcatA
//连接"open G:"与"type cdaudio alias x"
0040119C |. 8B35 CC634000 mov esi, dword ptr [<&WINMM.mciSendS>; WINMM.mciSendStringA
004011A2 |. 6A 00 push 0
004011A4 |. 8D5424 70 lea edx, dword ptr [esp+70]
004011A8 |. 6A 64 push 64
004011AA |. 8D4424 10 lea eax, dword ptr [esp+10] ;[ESP+10]的内容是"open G: type cdaudio alias x"
004011AE |. 52 push edx
004011AF |. 50 push eax
004011B0 |. FFD6 call esi ; <&WINMM.mciSendStringA>
//mciSendStringA("open G: type cdaudio alias x",[esp+70],64,0)
004011B2 |. 6A 00 push 0
004011B4 |. 8D4C24 70 lea ecx, dword ptr [esp+70]
004011B8 |. 6A 64 push 64
004011BA |. 51 push ecx
004011BB |. 68 58904000 push 00409058 ; set x door closed
004011C0 |. FFD6 call esi
//mciSendStringA("set x door closed",[esp+70],64,0),到这里我的光驱就关闭了
004011C2 |. 6A 00 push 0
004011C4 |. 8D5424 70 lea edx, dword ptr [esp+70]
004011C8 |. 6A 64 push 64
004011CA |. 52 push edx
004011CB |. 68 20904000 push 00409020 ; close x
004011D0 |. FFD6 call esi
//mciSendStringA("close x",[esp+70],64,0)
004011D2 |. 5E pop esi
004011D3 |. 81C4 CC000000 add esp, 0CC
004011D9 \. C2 0400 retn 4
判断是不是光驱的我们可以用GetDriveTypeA,用类似下面的代码检测就可以了,作者也是这样的,代码在0040105B---004010A0之间,就不具体
分析了,主要是获得思路。
for(drive='c';drive<'z';drive++)
{
if GetDriveTypeA(drive)==5
s=drive; //最好用一个数组来接受,有些用户可能有多个光驱
return;
}
简单的分析了一下代码,这其实是我第4次这样分析别人的程序了,为什么呢!因为当初学习C的时候感觉只能用来写算术题,写不出什么好的
应用程序来,所以后来就不学了!现在认识到要做高手必须得掌握一门编程语言(我的好友觉悟更高:高手也要吃饭!~_~),我的目的就是想看
看人家是怎样写出自己的程序的!
这个程序我还是留到等我学会编程了再写!^_^
【版权声明】"破"文一篇,随意转载,但请保持文章的完整性
[注意]APP应用上架合规检测服务,协助应用顺利上架!