第15课keymake算法注册机技巧文档格式.docx
《第15课keymake算法注册机技巧文档格式.docx》由会员分享,可在线阅读,更多相关《第15课keymake算法注册机技巧文档格式.docx(24页珍藏版)》请在冰点文库上搜索。
moveax,a2
addeax,edx
mova2,eax
shlecx,8
movedx,a2
xoredx,ecx
mova2,edx
addeax,1
movecx,len
imulecx,a1
notecx
imuleax,ecx
imuledx,eax
jmpn2
n1:
invokewsprintf,addrszBuffer,addrszHex,a2
leaeax,szBuffer
说明:
将dwordptrss:
[ebp-10]定义为a2,用a2替换
dwordptrss:
[ebp-20]定义为a1,用a1替换
[ebp-1C]定义为len,用len替换,表征姓名字符串的长度
注意:
在程序的反汇编代码中寻找a1、a2的初始值。
假设你看不懂算法,乱七八糟的一堆汇编代码,依然可以写出它的注册机。
二、keymake使用说明:
keymake程序初始时,默认的是,令EAX指向第一个编辑框(也就是输入序列号的窗口)收到用户输入的数据;
令EBX指向第二个编辑框收到用户输入的数据;
令ECX指向第三个编辑框收到用户输入的数据。
你如果要对用户输入的序列号或用户名等信息进行操作,那么可以就对EAX、EBX、ECX进行操作。
在keymake目录EXAMPLE下有一个例子程序,主要用来举例说明这个程序的使用(我先假设自己并不太懂Win32汇编)。
1.通过动态调试或反汇编例子程序可以得到以下注册码的计算过程(它不是根据你的序列号来计算注册码):
xxxx:
00401077CALLGetCommandLineA
0040107CCMP BYTEPTR[EAX],22
0040107FJNZ 401082
00401081INC EAX
00401082MOV CX,WORDPTR[EAX]
00401085MOV WORDPTR[0040306C],CX
0040108CMOV WORDPTR[0040306E],5C
00401095PUSH0
00401097PUSH0
00401099PUSH0
0040109BPUSH0
0040109DPUSHDWORD00403058
004010A2PUSH0
004010A4PUSH0
004010A6PUSHDWORD0040306C
004010ABCALLGetVolumeInformationA
………… …………
………… …………0040112F0040305C0040113C
40306C
40305C
种算注册码的方法不是直接从用户所输入的序列号来计算注册码的,所以并不适用于所有情况。
有时我们可能需要根据用户所填入的序列号来计算注册码。
下面的代码是本例根据用户所填入的序列号来计算注册码的方法:
MOVECX,EAX
;
EAX指向用户输入的八位序列号,现在暂将它移动到ECX寄存器
XOREBX,EBX;
EBX清零
以下是一段典型的将内存中的ASCII码转换为十六进制代码。
MOVZXEAX,BYTEPTR[ECX]
ORAL,AL
JZn3
CMPAL,3Ah
JCn2
SUBAL,7
SUBAL,30h
SHLEBX,4
ADDEBX,EAX
INCECX
JMPn1
我想以上的一段代码应该懂汇编就能写的出(如果不是很明白,那么你对我编写好的注册机用ollydbg调试一次就知道了)。
PUSHEBX
最后的十六进制结果都保存在寄存器EBX中
将EBX入栈,这是为了将EBX寄存器的数据保存起来。
因为经过CPUID这个指令后EBX的值将被修改。
然后后面就和上面一样照抄程序中的指令。
以下计算注册码的方法很简短。
但在实际的破解过程中,程序的算法可能会相当复杂。
这就需要你通过调试或反汇编将关键的运算指令都找出来,再写进来。
MOV EAX,1
CPUID
POPECX
恢复EBX的值到ECX寄存器,开始计算注册码
XOR EDX,EDX
MUL ECX
ADD EAX,EDX
下面的指令指的是输出格式,除了“%lX”可以修改,其他的请照抄
PUSHEAX
LEA EAX,a3
令EAX指向a3,也就是指向字符“%lX”。
%lX"
指的是输出数据的格式,你会C语言就肯定懂了
LEA EAX,a4
CALLwsprintfA
LEAEAX,a4
令EAX指向a4。
因为程序最后显示的就是EAX寄存器所指向的内存地址的数据。
以下几个是进制转换函数和我加入的部分自定义函数,你也可以在编写注册机的过程中调用它们(使用时千万不要把大小写弄错了)。
atodw 将十进制的内存ASCII数值转换为数据元素
使用格式:
invokeatodw,指向存放内存数值的缓冲区
htodw 将十六进制的内存ASCII数值转换为数据元素
invokehtodw,指向存放内存数值的缓冲区
MakeCrypt 对内存缓冲区数据进行加密
invokeMakeCrypt,指向要加密的字符缓冲区,指向接收加密后的字符缓冲区
UnMakeCrypt 对内存缓冲区数据进行解密
invokeUnMakeCrypt,指向要解密的字符缓冲区,指向接收解密后的字符缓冲区
wsprintf 使用给定格式格式化数据元素
invokewsprintf,指向存储输出的字符缓冲区,指向以空值结尾的包含格式化选项的字符串,指向一个数据元素列表
数据格式化选项:
%d,%i 有符号十进制数值;
%ld,%li 长的有符号十进制整数值;
%u 无符号十进制整数值;
%lu 长的无符号十进制整数值;
%x,%X 十六进制整数值,%x输出小写,%X输出大写;
%lx,%lX 长的十六进制整数值,%lx输出小写,%lX输出大写;
# 0x字符串的前缀数据,一般在显示十六进制值时使用。
精度修饰符——小数点后跟一个数,指定复制到输出缓冲区数字的最小数目。
如果给定数字位数小于精度指定位数,域中用0填充,默认情况从左边填充。
假如给定精度“.10”,数“”复制到输出缓冲区后变为“”
如无特别说明或已经指定了输出位置,在Win32程序中所有的结果都返回在eax中。
使用举例一:
比如要将内存中的十进制数值“”转换为十六进制,输出结果以0x为前缀,再进行加密。
数据区:
szXor16db"
%#lX"
szNum10db"
szOutMemdb50dup(0)
代码区:
invokeatodw,addrszNum10 ;
这一句是将内存中的数值当做十进制转换为数据元素,返回的结果在eax中,那么eax=bc614e
invokewsprintf,addrszBuffer,addrszXor16,eax ;
这一句是将eax中的值以十六进制大写输出到内存szBuffer位置。
invokeMakeCrypt,addrszBuffer,addrszOutMem ;
这一句是将指向内存szBuffer的数据加密后输出到内存szOutMem的位置。
使用举例二:
比如要将内存中的十六进制数值“ABCDEF”转换为十进制,输出长度为20位数,再进行解密。
szXor10db"
%"
szNum16db"
ABCDEF"
invokehtodw,addrszNum16 ;
这一句是将内存中的数值ABCDEF当做十六进制转换为数据元素,返回的结果在eax中,那么eax=abcdef
invokewsprintf,addrszBuffer,addrszXor10,eax ;
这一句是将eax中的值以十进制输出到内存szBuffer位置。
invokeUnMakeCrypt,addrszBuffer,addrszOutMem ;
这一句是将指向内存szBuffer的数据解密后输出到内存szOutMem的位置。
=====以上部分摘自keymake的说明书======
〔例2〕某软件:
小护士,注册算法为:
注册码=机器码XOR78AB1234
的十进制值!
显然,78AB1234为16进制数。
根据上面学的,用atodw函数
输入的机器码不正确!
szFMTdb"
%d"
szBufferdb30dup(0)
invokeatodw,eax
xoreax,78AB1234h
invokewsprintf,addrszBuffer,addrszFMT,eax
〔例3〕象棋桥
关键代码如下:
004846B733C9xorecx,ecx
004846B98A08movcl,byteptrds:
[eax]
004846BB8B45F4moveax,dwordptrss:
[ebp-C]
004846BE33DBxorebx,ebx
004846C08A5801movbl,byteptrds:
[eax+1]
004846C38B45F4moveax,dwordptrss:
004846C60FB67002movzxesi,byteptrds:
[eax+2]
004846CA8B45F4moveax,dwordptrss:
004846CD0FB67803movzxedi,byteptrds:
[eax+3]
004846D18B45F4moveax,dwordptrss:
004846D40FB64004movzxeax,byteptrds:
[eax+4]
004846D88945F0movdwordptrss:
[ebp-10],eax
004846DB8D040Bleaeax,dwordptrds:
[ebx+ecx]
004846DE03FEaddedi,esi
004846E0F7EFimuledi
004846E2F76DF0imuldwordptrss:
[ebp-10]
004846E5B9A0860100movecx,186A0
004846EA99cdq
004846EBF7F9idivecx
004846ED8BDAmovebx,edx
004846EF8D55F4leaedx,dwordptrss:
输入的序列号不正确!
TempBufferdb100dup(0)
CCB21R-%lu"
xorecx,ecx
movcl,byteptr[eax]
xorebx,ebx
movbl,byteptr[eax+1]
movzxesi,byteptr[eax+2]
movzxedi,byteptr[eax+3]
movzxeax,byteptr[eax+4]
mova1,eax
leaeax,dwordptr[ebx+ecx]
addedi,esi
imuledi
imula1
movecx,000186A0h
cdq
idivecx
movebx,edx
invokewsprintf,addrTempBuffer,addrszHex,ebx
leaeax,TempBuffer
留意红色字体的部分
〔例4〕Flash注册算法
关键代码(企业版)如下:
:
005168E1BBDB070000movebx,000007DB
005168E68B45FCmoveax,dwordptr[ebp-04]
005168E9E832D8EEFFcall00404120
005168EE8BF0movesi,eax
005168F085F6testesi,esi
005168F27E4Ajle0051693E
005168F4BF01000000movedi,00000001
*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:
|:
0051693C(C)
|
005168F98B45FCmoveax,dwordptr[ebp-04]
005168FC8A4C38FFmovcl,byteptr[eax+edi-01]
0051690033C0xoreax,eax
005169028AC1moval,cl
005169048D570Dleaedx,dwordptr[edi+0D]
00516907F7EAimuledx
0051690903D8addebx,eax
0051690B8BC3moveax,ebx
0051690DBBFFC99A3Bmovebx,3B9AC9FF
0051691299cdq
00516913F7FBidivebx
005169158BDAmovebx,edx
005169178B45FCmoveax,dwordptr[ebp-04]
0051691A80F145xorcl,45
0051691D33C0xoreax,eax
0051691F8AC1moval,cl
00516921F76DF8imul[ebp-08]
0051692403D8addebx,eax
005169268BC3moveax,ebx
00516928B9FFC99A3Bmovecx,3B9AC9FF
0051692D99cdq
0051692EF7F9idivecx
005169308BDAmovebx,edx
0051693269C72B300600imuleax,edi,0006302B
0051693803D8addebx,eax
0051693A47incedi
0051693B4Edecesi
0051693C75BBjne005168F9
005168F2(C)
0051693E8BC3moveax,ebx
00516940B9FFE0F505movecx,05F5E0FF
0051694599cdq
00516946F7F9idivecx
005169488BDAmovebx,edx
0051694A8BC3moveax,ebx
0051694CB0movecx,00000006
0051695199cdq
00516952F7F9idivecx
0051695483C241addedx,00000041
005169578855F3movbyteptr[ebp-0D],dl
0051695A895DECmovdwordptr[ebp-14],ebx
0051695DDB45ECfilddwordptr[ebp-14]
0051696083C4F4addesp,FFFFFFF4
00516963DB3C24fstptbyteptr[esp]
005169669Bwait
005169678D45E8leaeax,dwordptr[ebp-18]
0051696A8A55F3movdl,byteptr[ebp-0D]
0051696DE8D6D6EEFFcall00404048
005169728D45E8leaeax,dwordptr[ebp-18]
*PossibleStringDataReffromCodeObj->
00-000-000"
|
00516975BAC0695100movedx,005169C0
其文件如下:
0
没输入姓名!
szFmtdb"
szTempdb10dup(0)
szCodedb14dup(0)
a1dd147h
movebx,7DBh
invokelstrlen,eax
movesi,eax
movedi,1
leaeax,hInput1
movcl,byteptr[eax+edi-1]
xoreax,eax
moval,cl
leaedx,dwordptr[edi+0Dh]
imuledx
addebx,eax
moveax,ebx
movebx,3B9AC9FFh
cdq
idivebx
movebx,edx
xorcl,45h
imula1
movecx,3B9AC9FFh
idivecx
imuleax,edi,0006302Bh
incedi
decesi
jnen1
movecx,05F5E0FFh
movecx,6
addedx,41h
movbyteptrszTemp,dl
invokewsprintf,addrszTemp+1,addrszFmt,ebx
movedx,3
leaesi,szTemp
leaedi,szCode
movecx,3
repmovsb
mov[edi],byteptr"
-"
decedx
jnzn2
mov[edi-1],byteptr0
leaeax,szCode
注意其中的红色的部分。
〔例5〕k4n2的注册算法(KEYGENNING4NEWBIES#2)
此软件有bug。
注册码的计算中涉及到一个edi的初值。
不同的机器是不同的。
无法制作通用在任何机器上的注册机。
但作为教学来说,还是一个很不错的例子。
可以制作针对本机的注册机。
我机器的edi初值为12F55C。
004010F733D2xoredx,edx
004010F933DBxorebx,ebx
004010FB8B55D4movedx,dwordptrss:
[ebp-2C]
004010FE0155C4adddwordptrss:
[ebp-3C],edx
004011010155C4adddwordptrss:
004011048BC2moveax,edx
0040110683C005addeax,5
004011098945B8movdwordptrss:
[ebp-48],eax
0040110C33C0xoreax,eax
0040110E8BCFmovecx,edi
0040111083C104addecx,4
00401113894DB4movdwordptrss:
[ebp-4C],ecx
0040111633C9xorecx,ecx
004011180155BCadd