我不是高手,只是把自己的一点经验写出来与大家一起分享。
制做注册机,关键是要找到
加密运算的逆运算。破解一个程序时,反汇编代码是极容易得到的,而且我们必须通过分析反汇编代码来了解程序用了什么算法。当我们弄清了它的算法的时候,这些反汇编代码往往已经被我们熟知了。这时我们要求它的逆运算,我看还是修改反汇编代码最为直接。这样那些利用了寄存器特性的指令也可以很方便地求出逆运算。对原程序的成熟代码要尽可能利用,如果原代码太繁琐,在了解了其功能以后也可以自编代码。
要想把反汇编代码修改成注册机源代码,首先必须获得加密运算中用到的所有代码包括所有子程序。然后要把反汇编代码分析透彻,知道它是一种什么算法,才能有针对性地求逆运算。这很重要,因为有的算法是无法直接得到逆运算的,如RSA,它的特点是,加密和
解密可以用同一个函数,但所用的密钥不同,我们要求出解密密钥。
Windows优化大师对申请码和第二、六注册码的计算及比较如下:
0167:0061422E LEA EAX,[EBP-04]<- 申请码
0167:00614231 MOV EDX,00614394<- '1234567'的地址
0167:00614236 CALL 00612F7C<- 通过跟踪观察,可知这个子程序是把两个字符串相连接。
0167:0061423B MOV EAX,[EBP-04]
0167:0061423E CALL 00612F74<- 执行完后eax=d,可见此call是求字符串长度
0167:00614243 TEST EAX,EAXcall 612f74是求字符串长度
0167:00614245 JNS 0061424A<- 跳
0167:00614247 ADD EAX,BYTE +07
0167:0061424A SAR EAX,03<- 右移三位得1
0167:0061424D MOV EDX,EAX
0167:0061424F SHL EDX,03<- 左移三位得8
0167:00614252 LEA EAX,[EBP-04]<- [ebp-04]为2240020,这个地址处是'9787811234567'
0167:00614255 CALL 00613008<- 联系上下文,可知这个子程序是把字符串截成8位
0167:0061425A XOR ESI,ESI
0167:0061425C LEA EAX,[EBP-04]<- [ebp-04]为2240020,这个地址处'97878112'
0167:0061425F CALL 00612FD0 <- 意义不明,但无影响
通过分析可知,优化大师把申请码用"1234567"的前几位补成成8位,这一段再加上子程序会很长,在我们的注册机中不必完全照抄这些代码,自编出代码完成此功能即可,我编的代码如下,也可以完成此功能:
lea eax,APPH;申请码的地址
bits:inc ecx;
mov bl,BYTE ptr [eax+ecx]
test bl,bl
jnz bits;这段循环查看申请码的位数
cmp ecx,8;位数是否8?
jge app_cal
mov bl,31h;不足8位,用“1234567”的前几位来补足8位
add_bit:mov BYTE ptr [eax+ecx],bl
inc bl
inc ecx
cmp ecx,8
jl add_bit
继续向下,主要的计算及比较如下:
0167:0061427F MOV EDX,EBX<- EBX中是“You are big pig”的地址,
0167:00614281 LEA EAX,[EBP-1C]<- 这就是刚移出的“申请号97878112”
0167:00614284 CALL 00614170<- 根据“申请号”计算
...........
0167:006142B8 MOV EAX,[EBP-10]<- 由第二注册码变来的16进制数
0167:006142BB XOR EDX,EDX
0167:006142BD PUSH EDX<- 0
0167:006142BE PUSH EAX<- 由第二注册码变来的16进制数
0167:006142BF PUSH DWORD [006150D0]<- 0
0167:006142C5 PUSH DWORD [006150CC]<- 常数3b442af9
0167:006142CB PUSH DWORD [006150D8]<- 0
0167:006142D1 PUSH DWORD [006150D4]<- 常数69aaa0e3
0167:006142D7 CALL 006140B8<- 进行rsa计算
0167:006142DC SUB EAX,BYTE +02<- 结果减2
0167:006142DF MOV [EBP-24],EAX<- 存入内存,设为数2
0167:006142E2 MOV EAX,[EBP-0C]<- 由第六注册码变来的16进制数
0167:006142E5 XOR EDX,EDX
0167:006142E7 PUSH EDX<- 0
0167:006142E8 PUSH EAX<- 由第六注册码变来的16进制数
0167:006142E9 PUSH DWORD [006150D0]<- 0
0167:006142EF PUSH DWORD [006150CC]<- 常数3b442af9
0167:006142F5 PUSH DWORD [006150D8]<- 0
0167:006142FB PUSH DWORD [006150D4]<- 常数69aaa0e3
0167:00614301 CALL 006140B8<- 进行rsa计算
0167:00614306 SUB EAX,BYTE +02<- 结果减2
0167:00614309 MOV [EBP-20],EAX<- 存入内存
0167:0061430C SHL DWORD [EBP-24],02<- 数2左移2位
0167:00614310 LEA ECX,[EBP-24]<- 数2的地址
0167:00614313 MOV EAX,[ECX]<- 取出数2
0167:00614315 MOV EDX,[ECX+04]<- 取出数3
0167:00614318 SHRD EAX,EDX,02<- 数2、数3联合移位,数2改变,数3不变
0167:0061431C SHR EDX,02<- 数3右移2位
0167:0061431F MOV [ECX],EAX<- 数2放入内存
0167:00614321 MOV [ECX+04],EDX<- 数3放入内存
0167:00614324 MOV EAX,[EBP-24]<- 取出数2
0167:00614327 CMP EAX,[EBP-1C]<- 与根据申请码计算的数1的低32位比较
0167:0061432A JZ 00614330<- 相等时跳转,去取出数3的低16位存在一个地方(83f30a)
0167:0061432C XOR EBX,EBX;移位结果可使第二注册码结果的最低两位替换第一注册码结果的最高两位,第二注册码结果右移两位,高位补0
0167:0061432E JMP SHORT 00614341
0167:00614330 MOV AX,[EBP-20]<- 取出数3的低16位,返回上一级子程序后比较它是否14H。
通过分析,这一段求逆不是很困难,我编的逆运算如下:
app_cal:lea eax,APPH;装入申请码的地址
call appcode;对申请码计算,结果存在申请码处
mov eax,APPH;申请码计算结果的高32位
mov edx,14h
shld edx,eax,2;联合左移,edx变,eax不变,eax的最高两位移到edx的最低两位,edx中原数顺次左移两位
shl eax,2;
shr eax,2;先左移1位,再右移1位也行,目的是把最高位即符号位清0
add eax,2
add edx,2
mov DWORD ptr REG2,eax;这两个数再进行rsa计算就是注册码了
mov DWORD ptr REG6,edx;
MOV EAX,DWORD PTR REG2 ;由申请码算出的未进行rsa计算的第二注册码
XOR EDX,EDX
PUSH EDX
PUSH EAX
PUSH 0
PUSH 2C86F9h;解密密钥d;加密密钥为3b442af9h
PUSH 0;解密密钥是另外编程求出的。
PUSH 69aaa0e3h;密钥n
CALL rsa;进行rsa计算
MOV DWORD PTR REG2,EAX;保存第一注册码
MOV EAX,DWORD PTR REG6;由申请码算出的未进行rsa计算的第六注册码
XOR EDX,EDX
PUSH EDX
PUSH EAX
PUSH 0
PUSH 2C86F9h;解密密钥d;加密密钥为33b442af9h
PUSH 0
PUSH 69aaa0e3h;密钥n
CALL rsa;进行rsa计算
MOV DWORD PTR REG6,EAX;保存第二注册码
Windows优化大师对跟进申请码进行计算的子程序,直接dump出的代码如下:
00614170 PUSH EBX
00614171 PUSH ESI
00614172 PUSH EDI
00614173 PUSH ECX
00614174 MOV DWORD PTR SS:[ESP],EAX
00614177 MOV EAX,20
0061417C MOV ECX,DWORD PTR SS:[ESP]
0061417F MOV ECX,DWORD PTR DS:[ECX]
00614181 MOV EBX,DWORD PTR SS:[ESP]
00614184 MOV EBX,DWORD PTR DS:[EBX+4]
00614187 XOR ESI,ESI
00614189 DEC EAX
0061418A ADD ESI,DWORD PTR DS:[6150C8]
00614190 MOV EDI,EBX
00614192 SHL EDI,4
00614195 ADD ECX,EDI
00614197 MOV EDI,DWORD PTR DS:[EDX]
00614199 XOR EDI,EBX
0061419B ADD ECX,EDI
0061419D MOV EDI,EBX
0061419F SHR EDI,5
006141A2 XOR EDI,ESI
006141A4 ADD ECX,EDI
006141A6 ADD ECX,DWORD PTR DS:[EDX+4]
006141A9 MOV EDI,ECX
006141AB SHL EDI,4
006141AE ADD EBX,EDI
006141B0 MOV EDI,DWORD PTR DS:[EDX+8]
006141B3 XOR EDI,ECX
006141B5 ADD EBX,EDI
006141B7 MOV EDI,ECX
006141B9 SHR EDI,5
006141BC XOR EDI,ESI
006141BE ADD EBX,EDI
006141C0 ADD EBX,DWORD PTR DS:[EDX+C]
006141C3 TEST EAX,EAX
006141C5 JA SHORT 00614189
006141C7 MOV EAX,DWORD PTR SS:[ESP]
006141CA MOV DWORD PTR DS:[EAX],ECX
006141CC MOV EAX,DWORD PTR SS:[ESP]
006141CF MOV DWORD PTR DS:[EAX+4],EBX
006141D2 POP EDX
006141D3 POP EDI
006141D4 POP ESI
006141D5 POP EBX
006141D6 RETN
这段代码不用求逆,其是0061418A行用到了直接寻址方式,我们把它改作立即数,修改后的代码如下:
appcode:PUSH EBX
PUSH ESI
PUSH EDI
PUSH ECX
lea edx,STRING;"You are big pig."的地址
MOV DWORD PTR SS:[ESP],EAX
MOV EAX,20h
MOV ECX,DWORD PTR SS:[ESP];申请码地址放入ecx
MOV ECX,DWORD PTR DS:[ECX];申请码前4位放入ecx
MOV EBX,DWORD PTR SS:[ESP];申请码地址放入ebx
MOV EBX,DWORD PTR DS:[EBX+4];申请码后4位放入ebx
XOR ESI,ESI
j614189:DEC EAX
ADD ESI,9e3779b9h;DWORD PTR DS:[6150C8]
MOV EDI,EBX
SHL EDI,4
ADD ECX,EDI
MOV EDI,DWORD PTR DS:[EDX]
XOR EDI,EBX
ADD ECX,EDI
MOV EDI,EBX
SHR EDI,5
XOR EDI,ESI
ADD ECX,EDI
ADD ECX,DWORD PTR DS:[EDX+4]
MOV EDI,ECX
SHL EDI,4
ADD EBX,EDI
MOV EDI,DWORD PTR DS:[EDX+8]
XOR EDI,ECX
ADD EBX,EDI
MOV EDI,ECX
SHR EDI,5
XOR EDI,ESI
ADD EBX,EDI
ADD EBX,DWORD PTR DS:[EDX+0Ch]
TEST EAX,EAX
JA j614189
MOV EAX,DWORD PTR SS:[ESP]
MOV DWORD PTR DS:[EAX],ECX
MOV EAX,DWORD PTR SS:[ESP]
MOV DWORD PTR DS:[EAX+4],EBX
POP EDX
POP EDI
POP ESI
POP EBX
RETN
对注册码使用了RSA算法,它有个特点,加密和解密可以用同一个函数。这样实现RSA算法的代码我们就不用编了,直接“以子之矛,攻子之盾”,我们只需把关键的密钥算出来代入即可。因此RSA运算的代码完全取自Windows优化大师,只做标号和个别语法的修改即可。(代码较长,此处略)
对另四个码的运算如下:
004E99C1 |.>MOV EAX,DWORD PTR DS:[EDI+CC] 8E4B1B2B
004E99C7 |.>SUB DWORD PTR SS:[ESP+C],EAX 第3码-8E4B1B2B
004E99CB |.>MOV EAX,DWORD PTR DS:[EDI+C8] AC0AF08E
004E99D1 |.>SUB DWORD PTR SS:[ESP+4],EAX 第1码-AC0AF08E
004E99D5 |.>MOV ESI,14 设定循环次数
004E99DA |>>/MOV EBX,DWORD PTR SS:[ESP+4]
004E99DE |.>|MOV EAX,DWORD PTR SS:[ESP+10]
004E99E2 |.>|MOV DWORD PTR SS:[ESP+4],EAX 第4码代替第1码
004E99E6 |.>|MOV EAX,DWORD PTR SS:[ESP+C]
004E99EA |.>|MOV DWORD PTR SS:[ESP+10],EAX 第3码代替第4码
004E99EE |.>|MOV EAX,DWORD PTR SS:[ESP+8]
004E99F2 |.>|MOV DWORD PTR SS:[ESP+C],EAX 第2码代替第3码
004E99F6 |.>|MOV DWORD PTR SS:[ESP+8],EBX 第1码代替第2码
004E99FA |.>|MOV EAX,DWORD PTR SS:[ESP+10]
004E99FE |.>|ADD EAX,EAX 第4码乘以2
004E9A00 |.>|INC EAX 再加1
004E9A01 |.>|IMUL DWORD PTR SS:[ESP+10] 再乘以第4码
004E9A05 |.>|MOV EDX,5
004E9A0A |.>|CALL WIN优化?004E9744 带进位循环左移
004E9A0F |.>|MOV EBP,EAX 结果暂存到ebp
004E9A11 |.>|MOV EAX,DWORD PTR SS:[ESP+8]
004E9A15 |.>|ADD EAX,EAX 第2码乘以2
004E9A17 |.>|INC EAX 再加1
004E9A18 |.>|IMUL DWORD PTR SS:[ESP+8] 再乘以第2码
004E9A1C |.>|MOV EDX,5
004E9A21 |.>|CALL WIN优化?004E9744 带进位循环左移
004E9A26 |.>|MOV EBX,EAX 结果暂存到ebx
004E9A28 |.>|M