首页
社区
课程
招聘
[原创][看雪读书月]vxin的[学习心得]软件加密保护演示 算法分析
发表于: 2008-7-18 13:35 9101

[原创][看雪读书月]vxin的[学习心得]软件加密保护演示 算法分析

2008-7-18 13:35
9101

看到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>
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

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 7
支持
分享
最新回复 (9)
雪    币: 372
活跃值: (31)
能力值: ( LV12,RANK:410 )
在线值:
发帖
回帖
粉丝
2
强,学习,一会源码放在你的源子后面。。。

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.
2008-7-18 14:31
0
雪    币: 207
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
看到vxin说这个CM应该比较有意思的,刚好有空,拿来XX一下

虐待
2008-7-18 14:47
0
雪    币: 561
活跃值: (124)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
不错值得研究
2008-7-18 15:31
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
思路解决问题,前面的所有部分,昨天看的时候一下就过了,开始就困在了 keyfile 的内容上面

到底如何建立一个这样的图像文件而止步了,(后来看到你的附件后才解决了问题)

想不到的是,你把 xor 后的内容自己建立一个  keyfile ,而且加上了 头部 ,佩服
2008-7-18 15:42
0
雪    币: 136
活跃值: (120)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
6
嘿嘿黑色就是不一般
2008-7-19 22:59
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
好东西!值得研究
2008-7-20 18:04
0
雪    币: 6051
活跃值: (1441)
能力值: ( LV15,RANK:1473 )
在线值:
发帖
回帖
粉丝
8
看到0047F72A  call    00402B84                    ;  sum=sum*8088405+1,al=sum高8位
这个地方时我迷惑了很长时间,按这个CALL的位置来看应该是一个系统函数,可是只是简单的一个算术运算,不理解什么系统函数会只是一个简单的算术运算呢?

看了源代码才知道,原来是Random函数,呵呵~

看来DEDE没把这个Random函数给逆出来啊~还好我没钻牛角尖~
2008-7-20 21:21
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
Random,随机
2008-7-20 23:45
0
雪    币: 372
活跃值: (31)
能力值: ( LV12,RANK:410 )
在线值:
发帖
回帖
粉丝
10
我的CM2已经制作完毕了,适当时机放出来与大家见面~~
2008-7-28 14:41
0
游客
登录 | 注册 方可回帖
返回
//