|
看到vxin说这个CM应该比较有意思的,刚好有空,拿来XX一下
原程序请看:http://bbs.pediy.com/showthread.php?t=68698
先PEiD一下,DELPHI的程序,再用DEDE看一下,居然没有Anti DeDe,于是祭出OD,在OD里对比着DEDE看源代码,怎一个爽字了得!
在DEDE里看程序的过程,除了FormShow外只有一个Button1Click:0047F89C,直奔OD里的0047F89C处下断,F9运行后输入用户名:lelfei注册码:14141414,确定后中断下来了!
提示:注意对比DEDE看CALL过程的作用~~
代码:
0047F8CA lea edx, dword ptr [ebp-4]
0047F8CD mov eax, dword ptr [ebx+308]
0047F8D3 call <GetText> ; Edit_Name.GetText
0047F8D8 mov eax, dword ptr [ebp-4]
0047F8DB call <StrLen> ; 用户名长度必须大于2
0047F8E0 cmp eax, 2
0047F8E3 jle 0047F9F8
0047F8E9 mov eax, 0047FA7C ; ASCII "3w.bmp"
0047F8EE call <FileExists> ; 检测KeyFile是否存在
0047F8F3 test al, al
0047F8F5 je 0047F9F8
0047F8FB lea edx, dword ptr [ebp-C]
0047F8FE mov eax, dword ptr [ebx+310]
0047F904 call <GetText> ; Edit_Code.GetText
0047F909 mov eax, dword ptr [ebp-C]
0047F90C lea edx, dword ptr [ebp-8]
0047F90F call 0047F520 ; -----------@1,Code转换为16进制
0047F914 mov eax, dword ptr [ebp-8]
0047F917 push eax
0047F918 lea edx, dword ptr [ebp-10]
0047F91B mov eax, dword ptr [ebx+308]
0047F921 call <GetText> ; Edit_Name.GetText
0047F926 mov edx, dword ptr [ebp-10]
0047F929 pop eax
0047F92A call <StrCmp> ; 比较Name与处理后的Code
0047F92F jnz 0047F9F8
0047F935 mov eax, dword ptr [ebx+304]
0047F93B mov eax, dword ptr [eax+168]
0047F941 mov edx, 0047FA7C ; ASCII "3w.bmp"
0047F946 call <LoadFromFile> ; 载入KeyFile文件
0047F94B call 0047F34C ; ------------@2,获取硬盘SN
0047F950 lea edx, dword ptr [ebp-18]
0047F953 call <FixFileName> ; 修复字符串
0047F958 mov eax, dword ptr [ebp-18]
0047F95B lea edx, dword ptr [ebp-14]
0047F95E call <Trim> ; 去除空格
0047F963 mov eax, dword ptr [ebp-14]
0047F966 call 0047F4BC ; ------------@3,累加硬盘SN的ASC码
0047F96B push eax
0047F96C mov eax, dword ptr [ebx+304]
0047F972 mov eax, dword ptr [eax+168]
0047F978 call <GetBitmap> ; Image2.GetBitmap
0047F97D pop edx
0047F97E call 0047F684 ; -------------@4,用累加的ASC码对图片XOR解密
0047F983 mov eax, dword ptr [ebx+304]
0047F989 call 004350D4 ; Image2.PaintRequest
0047F98E mov eax, dword ptr [ebx+304]
0047F994 mov eax, dword ptr [eax+168]
0047F99A call <GetBitmap> ; Image2.GetBitmap
0047F99F push eax
0047F9A0 mov eax, dword ptr [ebx+2FC]
0047F9A6 mov eax, dword ptr [eax+168]
0047F9AC call <GetBitmap> ; Image1.GetBitmap
0047F9B1 pop edx
0047F9B2 call 0047F758 ; -------------@5,比较图片内容
0047F9B7 test al, al
0047F9B9 je short 0047FA10
0047F9BB push 40
0047F9BD lea edx, dword ptr [ebp-20]
0047F9C0 mov eax, dword ptr [ebx+308]
0047F9C6 call <GetText> ; Edit_Name.GetText
0047F9CB mov ecx, dword ptr [ebp-20]
0047F9CE lea eax, dword ptr [ebp-1C]
0047F9D1 mov edx, 0047FA8C ; '注册成功!正式授权给:'
0047F9D6 call <StrCat>
0047F9DB mov eax, dword ptr [ebp-1C]
0047F9DE call <StrToChar>
0047F9E3 mov edx, eax
0047F9E5 mov ecx, 0047FAA4
0047F9EA mov eax, dword ptr [4812F4]
0047F9EF mov eax, dword ptr [eax]
0047F9F1 call <MessageBox>
0047F9F6 jmp short 0047FA10
0047F9F8 push 40
0047F9FA mov ecx, 0047FAAC
0047F9FF mov edx, 0047FAB4
0047FA04 mov eax, dword ptr [4812F4]
0047FA09 mov eax, dword ptr [eax] ; '非法用户!请与软件开发商联系。'
0047FA0B call <MessageBox>
可以看出这个过程大部分都是调用系统过程,只有标注的@1--@5这5个CALL不知道用途。下面分别分析每个CALL的作用:
第一个CALL 0047F520代码就不贴了,主要作用是把用户输入的Code转换为16进制值,比如我输入的Code='14141414',输出结果=0x14141414,然后与用户名的ASC码逐位比较。这就是说只需要把用户名的ASC码连接成字符串就是注册码了。
第二个call 0047F34C作用为读取硬盘序列号:
代码:
0047F34C push ebp
0047F34D mov ebp, esp
0047F34F add esp, -23C
0047F355 push ebx
0047F356 mov ebx, 0047F494
0047F35B mov eax, dword ptr [481468]
0047F360 cmp dword ptr [eax], 2 ; 判断操作系统
0047F363 jnz short 0047F386
0047F365 push 0 ; /hTemplateFile = NULL
0047F367 push 0 ; |Attributes = 0
0047F369 push 3 ; |Mode = OPEN_EXISTING
0047F36B push 0 ; |pSecurity = NULL
0047F36D push 3 ; |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
0047F36F push C0000000 ; |Access = GENERIC_READ|GENERIC_WRITE
0047F374 push 0047F498 ; |FileName = "\\.\PhysicalDrive0"
0047F379 call <jmp.&kernel32.CreateFileA> ; \CreateFileA
0047F37E mov dword ptr [ebp-214], eax ; 连接第1个物理硬盘
0047F384 jmp short 0047F3A2
0047F386 push 0 ; /hTemplateFile = NULL
0047F388 push 0 ; |Attributes = 0
0047F38A push 1 ; |Mode = CREATE_NEW
0047F38C push 0 ; |pSecurity = NULL
0047F38E push 0 ; |ShareMode = 0
0047F390 push 0 ; |Access = 0
0047F392 push 0047F4AC ; |FileName = "\\.\SMARTVSD"
0047F397 call <jmp.&kernel32.CreateFileA> ; \CreateFileA
0047F39C mov dword ptr [ebp-214], eax
0047F3A2 cmp dword ptr [ebp-214], -1
0047F3A9 je 0047F48B
0047F3AF xor eax, eax
0047F3B1 push ebp
0047F3B2 push 0047F463
0047F3B7 push dword ptr fs:[eax]
0047F3BA mov dword ptr fs:[eax], esp
0047F3BD lea eax, dword ptr [ebp-239]
0047F3C3 xor ecx, ecx
0047F3C5 mov edx, 20 ; Clear InBuffer=20
0047F3CA call <FillChar>
0047F3CF lea eax, dword ptr [ebp-210]
0047F3D5 xor ecx, ecx
0047F3D7 mov edx, 210
0047F3DC call <FillChar> ; Clear OutBuffer=210
0047F3E1 xor eax, eax
0047F3E3 mov dword ptr [ebp-218], eax
0047F3E9 mov dword ptr [ebp-239], 200
0047F3F3 mov byte ptr [ebp-234], 1
0047F3FA mov byte ptr [ebp-233], 1
0047F401 mov byte ptr [ebp-230], 0A0
0047F408 mov byte ptr [ebp-22F], 0EC
0047F40F push 0 ; /pOverlapped = NULL
0047F411 lea eax, dword ptr [ebp-218] ; |
0047F417 push eax ; |pBytesReturned
0047F418 push 210 ; |OutBufferSize = 210 (528.)
0047F41D lea eax, dword ptr [ebp-210] ; |
0047F423 push eax ; |OutBuffer
0047F424 push 20 ; |InBufferSize = 20 (32.)
0047F426 lea eax, dword ptr [ebp-239] ; |
0047F42C push eax ; |InBuffer
0047F42D push 7C088 ; |IoControlCode = SMART_RCV_DRIVE_DATA
0047F432 mov eax, dword ptr [ebp-214] ; |
0047F438 push eax ; |hDevice
0047F439 call <jmp.&kernel32.DeviceIoContro>; \DeviceIoControl
0047F43E test eax, eax ; 读取硬盘驱动数据
0047F440 jnz short 0047F449
0047F442 call 0040399C
0047F447 jmp short 0047F48B
0047F449 xor eax, eax
0047F44B pop edx
0047F44C pop ecx
0047F44D pop ecx
0047F44E mov dword ptr fs:[eax], edx
0047F451 push 0047F46A
0047F456 mov eax, dword ptr [ebp-214]
0047F45C push eax ; /hObject
0047F45D call <jmp.&kernel32.CloseHandle> ; \CloseHandle
获取硬盘数据后会先用FixFileName修复一下字符串,再Trim去除空格,然后进行第3个CALL进行处理。
第三个call 0047F4BC跟进后只是简单的对硬盘序列号累加,结果记为sum,代码也不贴了。
第四个call 0047F684作用是用sum对一幅图片进行解密:
代码:
0047F684 push ebp
0047F685 mov ebp, esp
0047F687 add esp, -10
0047F68A push ebx
0047F68B push esi
0047F68C push edi
0047F68D mov ebx, edx
0047F68F mov dword ptr [ebp-4], eax
0047F692 xor eax, eax
0047F694 push ebp
0047F695 push 0047F6CE
0047F69A push dword ptr fs:[eax]
0047F69D mov dword ptr fs:[eax], esp
0047F6A0 mov edx, 1
0047F6A5 mov eax, dword ptr [ebp-4]
0047F6A8 call <GetScanline> ; 获取图片第1线数据
0047F6AD push eax
0047F6AE xor edx, edx
0047F6B0 mov eax, dword ptr [ebp-4]
0047F6B3 call <GetScanline> ; 获取图片第0线数据
0047F6B8 pop edx
0047F6B9 xchg eax, edx
0047F6BA sub eax, edx
0047F6BC cdq
0047F6BD xor eax, edx
0047F6BF sub eax, edx
0047F6C1 mov dword ptr [ebp-8], eax ; 相减得到每一线数据长度
0047F6C4 xor eax, eax
0047F6C6 pop edx
0047F6C7 pop ecx
0047F6C8 pop ecx
0047F6C9 mov dword ptr fs:[eax], edx
0047F6CC jmp short 0047F6EE
……异常处理
0047F6EE mov eax, dword ptr [48140C]
0047F6F3 mov dword ptr [eax], ebx ; 保存累加结果sum
0047F6F5 mov eax, dword ptr [ebp-4]
0047F6F8 mov edx, dword ptr [eax]
0047F6FA call dword ptr [edx+20] ; 图片高度
0047F6FD dec eax
0047F6FE test eax, eax
0047F700 jl short 0047F73E
0047F702 inc eax
0047F703 mov dword ptr [ebp-10], eax
0047F706 mov dword ptr [ebp-C], 0 ; i=0
0047F70D mov edx, dword ptr [ebp-C] ; ----循环开始
0047F710 mov eax, dword ptr [ebp-4]
0047F713 call <GetScanline> ; 获取图片每一线数据
0047F718 mov edi, eax
0047F71A mov ebx, dword ptr [ebp-8] ; 取每一线数据长度
0047F71D dec ebx
0047F71E test ebx, ebx
0047F720 jl short 0047F736
0047F722 inc ebx
0047F723 xor esi, esi
0047F725 mov eax, 100
0047F72A call 00402B84 ; sum=sum*8088405+1,al=sum高8位
0047F72F xor byte ptr [edi+esi], al ; 对数据进行XOR解密
0047F732 inc esi
0047F733 dec ebx
0047F734 jnz short 0047F725 ; 对每一线的每一字节解密
0047F736 inc dword ptr [ebp-C] ; i=i+1
0047F739 dec dword ptr [ebp-10] ; 取下一线
0047F73C jnz short 0047F70D ; 循环结束----
0047F73E pop edi
0047F73F pop esi
0047F740 pop ebx
0047F741 mov esp, ebp
0047F743 pop ebp
0047F744 retn
可以看出对图片数据的每一字节都进行了XOR加密了。
最后一个call 0047F758就是比较图片内容了:
代码:
0047F758 push ebp
0047F759 mov ebp, esp
0047F75B add esp, -1C
0047F75E push ebx
0047F75F push esi
0047F760 push edi
0047F761 mov edi, edx
0047F763 mov esi, eax
0047F765 mov byte ptr [ebp-1], 0
0047F769 mov eax, esi
0047F76B mov edx, dword ptr [eax]
0047F76D call dword ptr [edx+20] ; Image2.GetImageHeight
0047F770 mov ebx, eax
0047F772 mov eax, edi
0047F774 mov edx, dword ptr [eax]
0047F776 call dword ptr [edx+20] ; Image1.GetImageHeight=5B
0047F779 cmp ebx, eax
0047F77B jnz 0047F892 ; 高度是否相同?
0047F781 mov eax, esi
0047F783 mov edx, dword ptr [eax]
0047F785 call dword ptr [edx+2C] ; Image2.GetImageWidth
0047F788 mov ebx, eax
0047F78A mov eax, edi
0047F78C mov edx, dword ptr [eax]
0047F78E call dword ptr [edx+2C] ; Image.GetImageWidth=157
0047F791 cmp ebx, eax
0047F793 jnz 0047F892 ; 宽度是否相同?
0047F799 mov dl, 1
0047F79B mov eax, dword ptr [41C194]
0047F7A0 call <CreateBitmap>
0047F7A5 mov dword ptr [ebp-10], eax
0047F7A8 mov dl, 1
0047F7AA mov eax, dword ptr [41C194]
0047F7AF call <CreateBitmap>
0047F7B4 mov dword ptr [ebp-14], eax
0047F7B7 xor ecx, ecx
0047F7B9 push ebp
0047F7BA push 0047F88B
0047F7BF push dword ptr fs:[ecx]
0047F7C2 mov dword ptr fs:[ecx], esp
0047F7C5 mov edx, esi
0047F7C7 mov eax, dword ptr [ebp-10]
0047F7CA mov ecx, dword ptr [eax]
0047F7CC call dword ptr [ecx+8] ; Bitmap.Assign
0047F7CF mov edx, edi
0047F7D1 mov eax, dword ptr [ebp-14]
0047F7D4 mov ecx, dword ptr [eax]
0047F7D6 call dword ptr [ecx+8] ; Bitmap.Assign
0047F7D9 mov dl, 6
0047F7DB mov eax, dword ptr [ebp-10]
0047F7DE call <SetPixelFormat>
0047F7E3 mov dl, 6
0047F7E5 mov eax, dword ptr [ebp-14]
0047F7E8 call <SetPixelFormat>
0047F7ED mov eax, dword ptr [ebp-10]
0047F7F0 mov edx, dword ptr [eax]
0047F7F2 call dword ptr [edx+20] ; GetImageHeight
0047F7F5 dec eax
0047F7F6 test eax, eax
0047F7F8 jl short 0047F86D
0047F7FA inc eax
0047F7FB mov dword ptr [ebp-18], eax
0047F7FE mov dword ptr [ebp-8], 0
0047F805 mov edx, dword ptr [ebp-8] ; 循环开始====
0047F808 mov eax, dword ptr [ebp-10]
0047F80B call <GetScanline> ; 获取Image1的每一线
0047F810 mov ebx, eax
0047F812 mov edx, dword ptr [ebp-8]
0047F815 mov eax, dword ptr [ebp-14]
0047F818 call <GetScanline> ; 获取Image2的每一线
0047F81D mov dword ptr [ebp-C], eax
0047F820 mov eax, dword ptr [ebp-10]
0047F823 mov edx, dword ptr [eax]
0047F825 call dword ptr [edx+2C] ; GetImageWidth
0047F828 dec eax
0047F829 test eax, eax
0047F82B jl short 0047F865
0047F82D inc eax
0047F82E mov dword ptr [ebp-1C], eax
0047F831 xor eax, eax
0047F833 lea edx, dword ptr [eax+eax*2] ; 循环开始----每次取3位
0047F836 mov cl, byte ptr [ebx+edx]
0047F839 mov esi, dword ptr [ebp-C]
0047F83C cmp cl, byte ptr [esi+edx] ; 比较第1位
0047F83F jnz short 0047F865
0047F841 mov cl, byte ptr [ebx+edx+1]
0047F845 mov esi, dword ptr [ebp-C]
0047F848 cmp cl, byte ptr [esi+edx+1] ; 比较第2位
0047F84C jnz short 0047F865
0047F84E mov cl, byte ptr [ebx+edx+2]
0047F852 mov esi, dword ptr [ebp-C]
0047F855 cmp cl, byte ptr [esi+edx+2] ; 比较第3位
0047F859 jnz short 0047F865
0047F85B mov byte ptr [ebp-1], 1 ; 当3位都相同时置标志位
0047F85F inc eax
0047F860 dec dword ptr [ebp-1C]
0047F863 jnz short 0047F833 ; 继续循环----
0047F865 inc dword ptr [ebp-8]
0047F868 dec dword ptr [ebp-18]
0047F86B jnz short 0047F805 ; 继续循环====取下一位
0047F86D xor eax, eax
0047F86F pop edx
0047F870 pop ecx
0047F871 pop ecx
0047F872 mov dword ptr fs:[eax], edx
0047F875 push 0047F892
0047F87A mov eax, dword ptr [ebp-10]
0047F87D call 00403164
0047F882 mov eax, dword ptr [ebp-14]
0047F885 call 00403164
0047F88A retn
0047F88B jmp 004038B8
0047F890 jmp short 0047F87A
0047F892 mov al, byte ptr [ebp-1] ; 取标志位
0047F895 pop edi
0047F896 pop esi
0047F897 pop ebx
0047F898 mov esp, ebp
0047F89A pop ebp
0047F89B retn
从这个CALL返回后就直接判断AL值,并判断注册是否成功的对话框。
由于是用XOR进行加密的,只需要把Image1的图片数据另存出来就可以作为KeyFile使用了。注意存出来后要加上一个Bitmap的头格式,先自己用画图程序建立一个343*91*24b大小的图片(如何知道长宽和色深?在比较图片数据时可以得到长与宽,色深就是在用工具查看程序资源Image1和Image2时得到的),把前0x36字节的头格式附到图片数据前就OK了。建议用010Editor进行查看,会自动把头格式用其他颜色标记出来。
如果要做注册机的话,可以自己获取到硬盘SN后累加ASC值,用累加结果sum*8088405+1取高位后,对得到的KeyFile进行XOR操作,只需要得到前3字节就OK了。在此略过注册机了,反正vxin要开放源代码了~~~~
PS:这个CM界面不错~~~~
lelfei
6C656C666569
- 标 题:答复
- 作 者:vxin
- 时 间:2008-07-18 14:31
强,学习,一会源码放在你的源子后面。。。
代码:
unit Unit1;
{=====================================
软件保护思路 :
KeyFile验证而且是利用图片加密比较
by:VxinLv
HomePage:www.3WorkRoom.cn
=====================================}
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,Registry, WinSkinData, StdCtrls, ExtCtrls, Mask;
type
TForm1 = class(TForm)
Button1: TButton;
Image1: TImage;
SkinData1: TSkinData;
Image2: TImage;
Edit_Name: TEdit;
Label1: TLabel;
Edit_Code: TEdit;
Label3: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetIdeSerialNumber: pchar; //=============获取硬盘的出厂系列号
const IDENTIFY_BUFFER_SIZE = 512;
type
TIDERegs = packed record
bFeaturesReg: BYTE;
bSectorCountReg: BYTE;
bSectorNumberReg: BYTE;
bCylLowReg: BYTE;
bCylHighReg: BYTE;
bDriveHeadReg: BYTE;
bCommandReg: BYTE;
bReserved: BYTE;
end;
TSendCmdInParams = packed record
cBufferSize: DWORD;
irDriveRegs: TIDERegs;
bDriveNumber: BYTE;
bReserved: array[0..2] of Byte;
dwReserved: array[0..3] of DWORD;
bBuffer: array[0..0] of Byte;
end;
TIdSector = packed record
wGenConfig: Word;
wNumCyls: Word;
wReserved: Word;
wNumHeads: Word;
wBytesPerTrack: Word;
wBytesPerSector: Word;
wSectorsPerTrack: Word;
wVendorUnique: array[0..2] of Word;
sSerialNumber: array[0..19] of CHAR;
wBufferType: Word;
wBufferSize: Word;
wECCSize: Word;
sFirmwareRev: array[0..7] of Char;
sModelNumber: array[0..39] of Char;
wMoreVendorUnique: Word;
wDoubleWordIO: Word;
wCapabilities: Word;
wReserved1: Word;
wPIOTiming: Word;
wDMATiming: Word;
wBS: Word;
wNumCurrentCyls: Word;
wNumCurrentHeads: Word;
wNumCurrentSectorsPerTrack: Word;
ulCurrentSectorCapacity: DWORD;
wMultSectorStuff: Word;
ulTotalAddressableSectors: DWORD;
wSingleWordDMA: Word;
wMultiWordDMA: Word;
bReserved: array[0..127] of BYTE;
end;
PIdSector = ^TIdSector;
TDriverStatus = packed record
bDriverError: Byte;
bIDEStatus: Byte;
bReserved: array[0..1] of Byte;
dwReserved: array[0..1] of DWORD;
end;
TSendCmdOutParams = packed record
cBufferSize: DWORD;
DriverStatus: TDriverStatus;
bBuffer: array[0..0] of BYTE;
end;
var
hDevice: Thandle;
cbBytesReturned: DWORD;
SCIP: TSendCmdInParams;
aIdOutCmd: array[0..(SizeOf(TSendCmdOutParams) + IDENTIFY_BUFFER_SIZE-1)-1] of Byte;
IdOutCmd: TSendCmdOutParams absolute aIdOutCmd;
procedure ChangeByteOrder(var Data; Size: Integer);
var
ptr: Pchar;
i: Integer;
c: Char;
begin
ptr := @Data;
for I := 0 to (Size shr 1) - 1 do begin
c := ptr^;
ptr^ := (ptr + 1)^;
(ptr + 1)^ := c;
Inc(ptr, 2);
end;
end;
begin
Result := '';
if SysUtils.Win32Platform = VER_PLATFORM_WIN32_NT then begin // Windows NT, Windows 2000
hDevice := CreateFile('\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
end else // Version Windows 95 OSR2, Windows 98
hDevice := CreateFile('\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0);
if hDevice = INVALID_HANDLE_VALUE then Exit;
try
FillChar(SCIP, SizeOf(TSendCmdInParams) - 1, #0);
FillChar(aIdOutCmd, SizeOf(aIdOutCmd), #0);
cbBytesReturned := 0;
with SCIP do begin
cBufferSize := IDENTIFY_BUFFER_SIZE;
with irDriveRegs do begin
bSectorCountReg := 1;
bSectorNumberReg := 1;
bDriveHeadReg := $A0;
bCommandReg := $EC;
end;
end;
if not DeviceIoControl(hDevice, $0007C088, @SCIP, SizeOf(TSendCmdInParams) - 1,
@aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil) then Exit;
finally
CloseHandle(hDevice);
end;
with PIdSector(@IdOutCmd.bBuffer)^ do begin
ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));
(Pchar(@sSerialNumber) + SizeOf(sSerialNumber))^:= #0;
Result := Pchar(@sSerialNumber);
end;
end;
function ASCII10ADD(s: string): Integer; //=============取10进制累加值
var i,sum:integer;
begin
sum:=0; for i:=1 to length(s) do
begin
sum:=sum+ord(s[i]);
end;
Result :=sum;
end;
function myHextoStr(S: string): string; //=============16进制字符串转原字符串
var hexS,tmpstr:string;
i:integer;
a:byte;
begin
hexS :=s;//应该是该字符串
if length(hexS) mod 2=1 then
begin
hexS:=hexS+'0';
end;
tmpstr:='';
for i:=1 to (length(hexS) div 2) do
begin
a:=strtoint('$'+hexS[2*i-1]+hexS[2*i]);
tmpstr := tmpstr+chr(a);
end;
result :=tmpstr;
end;
procedure EncryptBMP(const BMP: TBitmap; Key: Integer); //=============加密图片
var
BytesPorScan: Integer;
w, h: integer;
p: pByteArray;
begin
try
BytesPorScan := Abs(Integer(BMP.ScanLine[1]) -
Integer(BMP.ScanLine[0]));
except
raise Exception.Create('Error');
end;
RandSeed := Key;
for h := 0 to BMP.Height - 1 do
begin
P := BMP.ScanLine[h];
for w := 0 to BytesPorScan - 1 do
P^[w] := P^[w] xor Random(256);
end;
end;
function IsHomology(bmp1, bmp2: TbitMap): boolean; //=============图片验证
type
PRGBTripleArray = ^TRGBTripleArray;
TRGBTripleArray = array[0..32767] of TRGBTriple;
var
x, y: integer;
p0, p1: PRGBTripleArray;
sBmp, dBmp: TBitMap;
begin
Result := False;
if (bmp1.Height <> bmp2.Height) or
(bmp1.Width <> bmp2.Width) then
begin
Exit;
end;
sBmp := TBitmap.Create;
dBmp := TBitmap.Create;
try
sBmp.Assign(bmp1);
dBmp.Assign(bmp2);
sBmp.PixelFormat := pf24bit;
dBmp.PixelFormat := pf24bit;
for y := 0 to sBmp.Height - 1 do
begin
p0 := sBmp.ScanLine[y];
p1 := dBmp.ScanLine[y];
for x := 0 to sBmp.Width - 1 do
if (p0[x].rgbtBlue = p1[x].rgbtBlue) and
(p0[x].rgbtGreen = p1[x].rgbtGreen) and
(p0[x].rgbtRed = p1[x].rgbtRed) then
begin
Result := True;
end
else
begin
Break;
end;
end;
finally
sBmp.Free;
dBmp.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
try
if (Length(Edit_Name.Text)>2) and (FileExists('3w.bmp')) //=========忽悠一下Cracker
and (myHextoStr(Edit_Code.Text)=Edit_Name.Text) then //====重点就是验证图片
begin
Image2.Picture.LoadFromFile('3w.bmp'); //=========载入图片
EncryptBMP(Image2.Picture.Bitmap, ASCII10ADD(Trim(strpas(GetIdeSerialNumber)))); //===恢复加密过的图片
Image2.Refresh;
if IsHomology(Image1.Picture.Bitmap,Image2.Picture.Bitmap) then //============验证图片
begin
Application.MessageBox(PChar('注册成功!正式授权给:'+Edit_name.text),'提示',MB_OK+64);
end;
end
else
Application.MessageBox(PChar('非法用户!请与软件开发商联系。'),'错误',MB_OK+64);
except
end;
end;
procedure TForm1.FormShow(Sender: TObject);
begin
Edit_Name.SetFocus;
end;
end.
|