【破解作者】 qfejj
【作者邮箱】 qfejj@163.com
【使用工具】 OllyDbgv1.10;PEIDv0.93;MASM32
【破解平台】 WindowsXP
【软件名称】 维克仓库管理系统2.7(build20050530)
【下载地址】 http://crc.onlinedown.net:82/files/vkck.exe
【软件简介】 帮助用户 管理出入库业务
【软件大小】 3.2
【加壳方式】 无
【破解声明】 本人破解软件无任何商业目的,纯粹兴趣使然
--------------------------------------------------------------------------------
【破解内容】
维克仓库管理系统2.7单机板,5月30号的新版本。修改别人的软件总是不好的,再说这个软件好歹也是我们杭州人自己写的,我总不能不给他们面子。所以软件我是绝对不会去改的,但写个注册机却也无妨。
软件马马虎虎,加密形同虚设。
软件是delphi写的(没有加壳,有点失败!),这也太自信了吧?
还是简单说一下软件的加密算法(明文比较,有点失败!),至于怎么找到算法部分我就不说了。
大致过程如下:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
换算 以前面得到的地址,从固定字串中取出一个值,作为注册码
用户名-------->得到结果,参与字串的取值运算----------------------------------------------------->注册码
其中,固定字串 ASCII "1B2D3F4H5J6L7N8P9R8T7V6X5Z41W3F5Y7R9Q1C2E3G4I5K6M7B8Q7SYU5W8Y9",我写注册机时定义在了常量中,这个字串在调试时会明文出现。
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
要获得注册码,关键是获得定位固定字串元素的地址,用户名换算用了很多不同的算法,根据用户输入的序列号分别采用不同的运算,输入的序列号位数不同,算法就不同。不过都是大同小异,调试时跟着慢走,就全都清晰了。
注释中005A7C84固定字串附近都是计算注册码的计算过程,视输入的序列号不同来选择不同的计算过程。每次取固定字串前的运算都是为了获得指向字串元素的地址。(我写的注册机里没有使用软件全部的注册算法,为了能使最后的注册码结果正确,我自做主张地把用户名转化得到固定位数的序列号,实际情况并不是一个用户名对应一个序列号,要是换了其他的序列号,只要能和注册码对应起来,一样可以完成注册)
下面是算法的简单分析,算法不难,看我的注册机源码会觉得更简单(函数GetRegistKey proc,至于前面的花哨东西大可不去理会)。如果要自己写注册机,mov edx,005A7C84 这句前面的代码几乎是不用修改就可以拿来用,当然了,变量还是要重设的,我自己倒是改了点。
;----------------------------------------------------------------------------------------------------------
...
005A7AA7 lea edx,dword ptr ds:[ebx+ebx*2] ;初始值为0,我注册机里设为变量CmpTime
005A7AAA mov eax,edx
005A7AAC add eax,3
005A7AAF cmp eax,dword ptr ss:[ebp-C]
005A7AB2 jg vkckmini.005A7B52
005A7AB8 mov eax,edx
005A7ABA inc eax
005A7ABB mov ecx,dword ptr ss:[ebp-4] ; 堆栈的地址是输入的序列号存放处的地址
005A7ABE movzx eax,byte ptr ds:[ecx+eax-1] ; 取出注册码值(ASCII)
005A7AC3 shr eax,2 ; 逻辑右移,后面取值要用到
005A7AC6 mov ecx,vkckmini.005A7C84 ; 005A7C84是固定字串的地址
005A7ACB mov al,byte ptr ds:[ecx+eax] ; 取固定字串中的一个值,地址由前面ecx和eax决定
005A7ACE mov byte ptr ss:[ebp-D],al ; 保存结果作为注册码的其中一位
005A7AD1 lea eax,dword ptr ds:[ebx+ebx*2]
005A7AD4 inc eax
005A7AD5 mov ecx,dword ptr ss:[ebp-4] ; 堆栈的地址是输入的序列号存放处的地址
005A7AD8 mov al,byte ptr ds:[ecx+eax-1] ; 取单个注册码ASCII值
005A7ADC shl eax,4
005A7ADF and al,30
005A7AE1 add edx,2
005A7AE4 mov ecx,dword ptr ss:[ebp-4] ; 堆栈的地址是输入的序列号存放处的地址
005A7AE7 movzx edx,byte ptr ds:[ecx+edx-1] ; 取单个注册码ASCII值
005A7AEC shr edx,4 ;
005A7AEF or al,dl
005A7AF1 and eax,0FF ; 后面取值要用到eax
005A7AF6 mov edx,vkckmini.005A7C84 ; 005A7C84是固定字串的地址
005A7AFB mov al,byte ptr ds:[edx+eax] ; 取固定字串中的一个值
005A7AFE mov byte ptr ss:[ebp-E],al ; 保存结果作为注册码的其中一位
005A7B01 lea eax,dword ptr ds:[ebx+ebx*2]
005A7B04 add eax,2
005A7B07 mov edx,dword ptr ss:[ebp-4] ; 堆栈的地址是输入的序列号存放处的地址
005A7B0A mov al,byte ptr ds:[edx+eax-1] ; 取出单个注册码值(ASCII)
005A7B0E shl eax,2 ;
005A7B11 and al,3C
005A7B13 lea edx,dword ptr ds:[ebx+ebx*2] ;
005A7B16 add edx,3
005A7B19 mov ecx,dword ptr ss:[ebp-4] ; 堆栈的地址是输入的序列号存放处的地址
005A7B1C mov dl,byte ptr ds:[ecx+edx-1]
005A7B20 xor ecx,ecx
005A7B22 mov cl,dl
005A7B24 shr ecx,6
005A7B27 or al,cl
005A7B29 and eax,0FF
005A7B2E mov ecx,vkckmini.005A7C84 ; 005A7C84是固定字串的地址
005A7B33 mov al,byte ptr ds:[ecx+eax] ; 取固定字串中的一个值
005A7B36 mov byte ptr ss:[ebp-F],al ; 保存结果作为注册码的其中一位
005A7B39 mov eax,edx
005A7B3B and al,3F
005A7B3D and eax,0FF
005A7B42 mov edx,vkckmini.005A7C84 ; 005A7C84是固定字串的地址
005A7B47 mov al,byte ptr ds:[edx+eax] ; 取固定字串中的一个值
005A7B4A mov byte ptr ss:[ebp-10],al ; 保存结果作为注册码的其中一位
005A7B4D jmp vkckmini.005A7BF9
005A7B52 mov eax,edx
005A7B54 add eax,2
005A7B57 cmp eax,dword ptr ss:[ebp-C]
005A7B5A jg short vkckmini.005A7BC2
005A7B5C inc edx
005A7B5D mov eax,dword ptr ss:[ebp-4]
005A7B60 movzx eax,byte ptr ds:[eax+edx-1]
005A7B65 shr eax,2
005A7B68 mov edx,vkckmini.005A7C84 ; 005A7C84是固定字串的地址
005A7B6D mov al,byte ptr ds:[edx+eax] ; 取固定字串中的一个值
005A7B70 mov byte ptr ss:[ebp-D],al ; 保存结果作为注册码的其中一位
005A7B73 lea eax,dword ptr ds:[ebx+ebx*2]
005A7B76 inc eax
005A7B77 mov edx,dword ptr ss:[ebp-4]
005A7B7A mov al,byte ptr ds:[edx+eax-1]
005A7B7E shl eax,4
005A7B81 and al,30
005A7B83 lea edx,dword ptr ds:[ebx+ebx*2]
005A7B86 add edx,2
005A7B89 mov ecx,dword ptr ss:[ebp-4]
005A7B8C mov dl,byte ptr ds:[ecx+edx-1]
005A7B90 xor ecx,ecx
005A7B92 mov cl,dl
005A7B94 shr ecx,4
005A7B97 or al,cl
005A7B99 and eax,0FF
005A7B9E mov ecx,vkckmini.005A7C84 ; 005A7C84是固定字串的地址
005A7BA3 mov al,byte ptr ds:[ecx+eax] ; 取固定字串中的一个值
005A7BA6 mov byte ptr ss:[ebp-E],al ; 保存结果作为注册码的其中一位
005A7BA9 mov eax,edx
005A7BAB shl eax,2
005A7BAE and al,3C
005A7BB0 and eax,0FF
005A7BB5 mov edx,vkckmini.005A7C84 ; 005A7C84是固定字串的地址
005A7BBA mov al,byte ptr ds:[edx+eax] ; 取固定字串中的一个值
005A7BBD mov byte ptr ss:[ebp-F],al ; 保存结果作为注册码的其中一位
005A7BC0 jmp short vkckmini.005A7BF9
005A7BC2 inc edx
005A7BC3 mov eax,dword ptr ss:[ebp-4]
005A7BC6 movzx eax,byte ptr ds:[eax+edx-1]
005A7BCB shr eax,2
005A7BCE mov edx,vkckmini.005A7C84 ; 005A7C84是固定字串的地址
005A7BD3 mov al,byte ptr ds:[edx+eax] ; 取固定字串中的一个值
005A7BD6 mov byte ptr ss:[ebp-D],al ; 保存结果作为注册码的其中一位
005A7BD9 lea eax,dword ptr ds:[ebx+ebx*2]
005A7BDC inc eax
005A7BDD mov edx,dword ptr ss:[ebp-4]
005A7BE0 mov al,byte ptr ds:[edx+eax-1]
005A7BE4 shl eax,4
005A7BE7 and al,30
005A7BE9 and eax,0FF
005A7BEE mov edx,vkckmini.005A7C84 ; 005A7C84是固定字串的地址
005A7BF3 mov al,byte ptr ds:[edx+eax] ; 取固定字串中的一个值
005A7BF6 mov byte ptr ss:[ebp-E],al ; 保存结果作为注册码的其中一位
005A7BF9 mov eax,dword ptr ss:[ebp-8] ; 下面的代码不在算法中,不必理会
005A7BFC push dword ptr ds:[eax]
005A7BFE lea eax,dword ptr ss:[ebp-14]
005A7C01 mov dl,byte ptr ss:[ebp-D]
005A7C04 call vkckmini.00404E5C
005A7C09 push dword ptr ss:[ebp-14]
005A7C0C lea eax,dword ptr ss:[ebp-18]
005A7C0F mov dl,byte ptr ss:[ebp-E]
005A7C12 call vkckmini.00404E5C
005A7C17 push dword ptr ss:[ebp-18]
005A7C1A lea eax,dword ptr ss:[ebp-1C]
005A7C1D mov dl,byte ptr ss:[ebp-F]
005A7C20 call vkckmini.00404E5C
005A7C25 push dword ptr ss:[ebp-1C]
005A7C28 lea eax,dword ptr ss:[ebp-20]
005A7C2B mov dl,byte ptr ss:[ebp-10]
005A7C2E call vkckmini.00404E5C
005A7C33 push dword ptr ss:[ebp-20]
005A7C36 mov eax,dword ptr ss:[ebp-8]
005A7C39 mov edx,5
005A7C3E call vkckmini.00404FF4
005A7C43 inc ebx
005A7C44 dec esi
005A7C45 jnz vkckmini.005A7AA7
...
附上注册机源码,以供参考。不当之处,请各位指正!
--------------------------------------------------------------------------------
【汇编注册机】
;-------------------------------------------------------------------------------
;编译命令:
;ml /c /coff keygen,asm
;rc keygen.rc
;link /subsystem:windows keygen.obj keygen.res
;-------------------------------------------------------------------------------
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>> keygen.asm >>
;>> Coded by qfejj >>
;>> Email :qfejj@163.com >>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.586
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include kernel32.inc
include user32.inc
include gdi32.inc
include comctl32.inc
includelib kernel32.lib
includelib user32.lib
includelib gdi32.lib
includelib comctl32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
MANIFEST equ 24
IDD_MAINDLG equ 1000
IDOK equ 1
IDC_EDT1 equ 1004
IDC_EDT2 equ 1005
IDC_EDT3 equ 1006
IDC_GRP1 equ 1007
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Windowproc proto :HWND,:UINT,:WPARAM,:LPARAM
GetRegistKey proto
Color macro Red,Green,Blue ;宏,方便后面颜色设置
xor eax,eax
mov ah,Blue
shl eax,8
mov ah,Green
mov al,Red
endm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
MsgBoxText db '用户名怎么可以为空呢?',0
MsgBoxCaption db 'Warning',0
String db '======Keygen For VKSOFT====== ',0dh,0ah
db ' This Keygen Is Designed By qfejj',0dh,0ah
db ' Contact Email: qfejj@163.com ',0dh,0ah
db '============================= ',0dh,0ah,0
SerialString db 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h
String1 db 31h,42h,32h,44h,33h,46h,34h,48h,35h,4Ah,36h,4Ch,37h,4Eh,38h,50h
String2 db 39h,52h,38h,54h,37h,56h,36h,58h,35h,5Ah,34h,31h,57h,33h,46h,35h
String3 db 59h,37h,52h,39h,51h,31h,43h,32h,45h,33h,47h,34h,49h,35h,4Bh,36h
String4 db 4Dh,37h,42h,38h,51h,37h,53h,59h,55h,35h,57h,38h,59h,39h
.data?
hInstance HINSTANCE ?
hWnd HINSTANCE ?
hDc DWORD ?
hMDc1 DWORD ?
hMDc2 DWORD ?
hBrush DWORD ?
TextOutX DWORD ?
TextOutY DWORD ?
TextOutCY DWORD ?
LogFont LOGFONT <?>
;-------------------------------------------------
NameBuffer db 20 dup(?)
SerialBuffer db 16 dup(?)
KeyBuffer db 24 dup(?)
ConvertString db 64 dup(?)
KeyOut db 30 dup(?)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
start:
invoke InitCommonControls
invoke GetModuleHandle,0
mov hInstance,eax
invoke DialogBoxParam,hInstance,IDD_MAINDLG,0,offset Windowproc,0
invoke ExitProcess,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Windowproc PROC hWin:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hBitMapMDc:HDC
LOCAL ps:PAINTSTRUCT
LOCAL rect:RECT
LOCAL TextSizeCX:dword
LOCAL TextSizeCY:dword
mov eax,uMsg
.if eax == WM_PAINT
invoke BeginPaint,hWin,addr ps
mov hDc,eax
invoke BitBlt,hDc,0h,0h,120h,40h,hMDc1,0,0,0cc0020h
invoke EndPaint,hWin,addr ps
.elseif eax == WM_INITDIALOG
invoke SetTimer,hWin,200h,45h,NULL
invoke GetDC,hWin
mov hDc,eax
invoke CreateCompatibleDC,hDc
mov hMDc1,eax
invoke CreateCompatibleBitmap,hDc,120h,40h
mov hBitMapMDc,eax
invoke SelectObject,hMDc1,hBitMapMDc
Color 0,0,0
invoke CreateSolidBrush,eax
mov hBrush,eax
mov rect.top,0h
mov rect.left,0h
mov rect.right,120h
mov rect.bottom,100h
invoke FillRect,hMDc1,addr rect,hBrush
invoke DeleteObject,hBrush
invoke CreateCompatibleDC,hDc
mov hMDc2,eax
Color 0,255,0
invoke SetTextColor,hMDc2,eax
invoke SetBkMode,hMDc2,TRANSPARENT
invoke CreateFontIndirect,addr LogFont
invoke SelectObject,hMDc2,eax
invoke CreateCompatibleBitmap,hDc,120h,80h
invoke SelectObject,hMDc2,eax
Color 0,0,0
invoke CreateSolidBrush,eax
mov hBrush,eax
mov rect.top,0h
mov rect.left,0h
mov rect.right,120h
mov rect.bottom,100h
invoke FillRect,hMDc2,addr rect,hBrush
invoke DeleteObject,hBrush
mov TextOutX,25h
mov TextOutY,30h
lea esi,String
mov al,byte ptr [esi]
.while al
.if al == 0dh
add TextOutY,10h
mov TextOutX,25h
add esi,2h
.else
invoke GetTextExtentPoint32,hMDc2,esi,1,addr TextSizeCX
invoke TextOut,hMDc2,TextOutX,TextOutY,esi,1h
mov eax,TextSizeCX
add TextOutX,eax
inc esi
.endif
mov al,byte ptr [esi]
.endw
invoke ReleaseDC,hWin,hDc
.elseif eax == WM_TIMER
invoke GetDC,hWin
mov hDc,eax
invoke BitBlt,hMDc1,0h,8h,120h,40h,hMDc2,0,TextOutCY,0cc0020h
inc TextOutCY
.if TextOutCY == 70h
mov TextOutCY,0
.endif
invoke BitBlt,hDc,0h,0h,120h,38h,hMDc1,0,0,0cc0020h
invoke ReleaseDC,hWin,hDc
.elseif eax == WM_CLOSE
invoke EndDialog,hWin,0
.elseif eax == WM_COMMAND
mov eax,wParam
.if eax ==IDOK
push hWin
pop hWnd
invoke GetDlgItemText,hWin,IDC_EDT1,addr NameBuffer,20
.if eax==0
invoke MessageBox,hWin,addr MsgBoxText,addr MsgBoxCaption,MB_OK
.else
invoke GetRegistKey ;注册码计算函数
invoke SetDlgItemText,hWin,IDC_EDT2,addr SerialBuffer
invoke SetDlgItemText,hWin,IDC_EDT3,addr KeyOut
.endif
.endif
.else
mov eax,0
ret
.endif
mov eax,1
ret
Windowproc endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
GetRegistKey proc
LOCAL CmpTime:dword
invoke lstrcat,offset ConvertString,offset String1
invoke lstrcat,offset ConvertString,offset String2
invoke lstrcat,offset ConvertString,offset String3
invoke lstrcat,offset ConvertString,offset String4
;--------------
; 计算序列号
;--------------
xor edi,edi
GetCode1:
mov dl,byte ptr[NameBuffer+edi]
inc edx
add edx,edx
and edx,7
mov al,byte ptr[SerialString+edx] ;取单个序列号
mov byte ptr[SerialBuffer+edi],al
inc edi
cmp edi,8
jl GetCode1
xor edi,edi
GetCode2:
mov dl,byte ptr[NameBuffer+edi]
add edx,7h
and edx,7
mov al,byte ptr[SerialString+edx] ;取单个序列号
mov byte ptr[SerialBuffer+7+edi],al
inc edi
cmp edi,8
jl GetCode2
;---------------
; 计算注册码
;---------------
xor edi,edi
mov CmpTime,0
@1:
mov edx,CmpTime
mov eax,CmpTime
add eax,3
mov eax,edx
inc eax
movzx eax,byte ptr[SerialBuffer+eax-1]
shr eax,2
mov al,byte ptr[ConvertString+eax]
mov byte ptr[KeyBuffer+edi],al
mov eax,CmpTime
inc eax
mov al,byte ptr[SerialBuffer+eax-1]
shl eax,4
and al,30h
add edx,2
movzx edx,byte ptr[SerialBuffer+edx-1]
shr edx,4
or al,dl
and eax,0FFh
mov al,byte ptr[ConvertString+eax]
mov byte ptr[KeyBuffer+edi+1],al
mov eax,CmpTime
add eax,2
mov al,byte ptr[SerialBuffer+eax-1]
shl eax,2
and eax,3Ch
mov edx,CmpTime
add edx,3
mov dl,byte ptr[SerialBuffer+edx-1]
xor ecx,ecx
mov cl,dl
shr ecx,6
or al,cl
and eax,0FFh
mov al,byte ptr[ConvertString+eax]
mov byte ptr[KeyBuffer+edi+2],al
mov eax,edx
and al,3Fh
and eax,0FFh
mov al,byte ptr[ConvertString+eax]
mov byte ptr[KeyBuffer+edi+3],al
add CmpTime,3
add edi,4
cmp edi,20
jl @1
mov byte ptr[KeyBuffer+21],0
;-------------
; 准备输出
;-------------
xor edi,edi
@2:
mov al,byte ptr[KeyBuffer+edi]
mov byte ptr[KeyOut+edi],al
mov byte ptr[KeyOut+5],2Dh
mov al,byte ptr[KeyBuffer+5+edi]
mov byte ptr[KeyOut+6+edi],al
mov byte ptr[KeyOut+11],2Dh
mov al,byte ptr[KeyBuffer+10+edi]
mov byte ptr[KeyOut+12+edi],al
mov byte ptr[KeyOut+17],2Dh
mov al,byte ptr[KeyBuffer+15+edi]
mov byte ptr[KeyOut+18+edi],al
mov byte ptr[KeyOut+23],0
inc edi
cmp edi,5
jl @2
ret
GetRegistKey endp
end start
;--------------------------------------------------------------------------------------------------
;>>>>>>>>>>>>>>>>>>>>>>>>>
;>> keygen.rc >>>>>>>>
;>>>>>>>>>>>>>>>>>>>>>>>>>
#define MANIFEST 24
#define IDD_MAINDLG 1000
#define IDC_GRP1 1007
#define IDOK 1
#define IDC_EDT1 1004
#define IDC_EDT2 1005
#define IDC_STC1 1001
#define IDC_STC2 1002
#define IDC_STC3 1003
#define IDC_EDT3 1006
IDD_MAINDLG DIALOGEX 4,4,159,129
CAPTION "维克仓库管理系统2.7-Keygen"
FONT 10,"宋体"
STYLE 0x10CA0880
EXSTYLE 0x00000001
BEGIN
CONTROL "计算",IDOK,"Button",0x50010000,57,108,42,15,0x00000000
CONTROL "",IDC_EDT1,"Edit",0x50010000,40,49,105,12,0x00000200
CONTROL "",IDC_EDT2,"Edit",0x50010800,40,67,105,12,0x00000200
CONTROL "注册者:",IDC_STC1,"Static",0x50000201,9,49,30,12,0x00000000
CONTROL "",IDC_GRP1,"Button",0x50000007,1,40,156,63,0x00000000
CONTROL "序列号:",IDC_STC2,"Static",0x50000201,9,66,30,12,0x00000000
CONTROL "注册码:",IDC_STC3,"Static",0x50000201,9,82,30,12,0x00000000
CONTROL "",IDC_EDT3,"Edit",0x50010800,40,82,105,12,0x00000200
END
--------------------------------------------------------------------------------
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课