首页
社区
课程
招聘
[原创]自修改算法设计与实现
发表于: 2007-8-1 18:04 5956

[原创]自修改算法设计与实现

2007-8-1 18:04
5956
标题:自修改算法设计与实现
作者:壹只老虎
日期:2007-08-01
说明:转载请注明出处和保持文件完整性。
1:什么是自修改(个人定义的!嘿嘿!)
   就是程序执行的时候,某段代码可以根据某些数据(比如密钥)自行修改。

2:特点
   这种算法不同于一般的算法,一般算法的代码是静态的,人家可以打印出来慢慢分析,而这种算法在代码中保存的是加密过的代码,没有真正的密钥,是不可能解密出正确地执行代码的。
简单点说,算法等效于=>
If 注册码=不告诉你 then
   注册成功;

3:优点
   反汇编代码中保存的是加密后的代码,正确的代码不可见。

4:缺点
   密钥一旦泄漏,本算法的失去意义。为了弥补这个缺点,请务必注意注册算法的强度。

5:应用
   功能限制,注册算法等。

6:实现思路
   第一:对于被加密的程序自身而言,需要有解密被加密的代码的功能,在被加密程序中,需要设置代码开始加密偏移和结束偏移两个标记。
   第二:被加密程序根据输入的信息计算出一个解密密钥,进行代码的解密。(如果密钥和加密代码使用的密钥不同,那么不可能解密出正确的代码)。
   第三:需要一个加密程序,用来加密待加密程序中的指定数据,我们需要给加密程序提供开始加密偏移和结束加密偏移,以及密钥。
   第四:由于我们编写的代码经编译器编译后保存于代码段,但是代码段的段属性默认是读权限和可执行权限,我们的程序解密的时候需要将解密的代码写入代码段,所以,
        我们需要修改被加密程序的代码短的段属性为:读+写+可执行权限。
   第五:为了防止程序运行错误的解密后的代码的时候异常,所以我们需要对异常进行处理。
   第六:在被加密程序中,为了方便寻找要加密的代码,我们需设置一个开始标记和结束标记,我设置的为:$40484048,即inc eax;dec eax;inc eax;dec eax;当然也可以设置为:$909090909090,即nop; nop; nop; nop; nop; nop;被加密程序编译完成后,用C32ASM以16进制方式打开它,搜索16进制40484048即可定位到编译后的待加密代码开始偏移和结束偏移。

7:如何破解(个人观点,欢迎大家讨论)
  a:未知密钥,编程实现代码解密,程序自动判断解密后的代码是否正确。(难度比较大)
b:已知密钥,和普通的算法破解思路相同,因为程序会解密出正确的算法。

8:CrackMe01_Delphi源代码
{CrackMe01_DelphiReg.pas}
unit CrackMe01_DelphiReg;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, WinSkinData, jpeg, ExtCtrls,StrUtils;

type
  TForm1 = class(TForm)
    SkinData1: TSkinData;
    Label1: TLabel;
    Label2: TLabel;
    edRegName: TEdit;
    edRegCode: TEdit;
    btnReg: TButton;
    btnAbout: TButton;
    btnExit: TButton;
    Image1: TImage;
    Label3: TLabel;
    edRandom: TEdit;
    procedure btnAboutClick(Sender: TObject);
    procedure btnExitClick(Sender: TObject);
    procedure btnRegClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
     KeyTitle = '壹只老虎CrackMe01_Delphi';

var
  Form1: TForm1;

implementation

{$R *.dfm}

{十六进值字符串转换成LongInt值}
function HexStrToInt(S: String): LongInt;
var
   i:Integer;
begin
  Result := 0;
  for i := 1 to Length(S) do
    begin
      if S[i] in ['0'..'9'] then
        Result := Result * 16 + (Integer(S[i]) - 48)
      else if S[I] in ['A'..'F'] then
        Result := Result * 16 + (Ord(S[i]) - 55);
    end;
end;

{注册按钮事件处理过程}
procedure TForm1.btnRegClick(Sender: TObject);
var
   i,num:integer;
   key:integer;  {密钥}
   code,name:string;
   Label begindecrypt,enddecrypt,s0;
begin
    name:=edRegName.Text;         {取得注册名}
    code:=edRegCode.Text;          {取得注册码}
    num:=strToint(edRandom.Text);   {取得随机数}
    try
      key:=num xor HexStrToInt(LeftStr(code,8)); {根据注册码和随机数计算密钥}
    except
      Close;
    end;
    {解密代码}
    asm
       mov ebx,offset begindecrypt        {开始解密偏移}
       mov eax,offset enddecrypt          {结束解密偏移}
       sub eax,ebx                      {计算解密数据大小}
       mov edx,0
       mov ecx,4
       div ecx
       mov ecx,eax                        {ecx=解密数据大小 div 4}
       mov esi,ebx                        {esi=开始解密偏移}
    s0:{解密循环,每次处理一个dword}
       mov eax,[esi]
       xor eax,key
       mov [esi],eax
       add esi,4
       loop s0
    end;
    {采用异常处理设计}
    try
    {为方便寻找开始解密标记编写的代码,对应16进制为:$40484048}
    asm
       inc eax;
       dec eax;
       inc eax;
       dec eax;
    end;
    begindecrypt:     {注册算法的开始标记}
    num:=0;
    if length(name)<6 then
      begin
        Application.MessageBox('Name is Too Short','no!no!no!',MB_ICONINFORMATION+MB_OK);
        Close;
      end;
    for i:=1 to length(name) do
      num:=num+i*ord(name[i]);
    try
      num:=num-StrToInt(RightStr(code,6));
      if num=0 then
        Application.MessageBox('Good Job!','heihei',MB_ICONINFORMATION+MB_OK)
      else
        Application.MessageBox('it is too false!','no!no!no!',MB_ICONINFORMATION+MB_OK);
      Close;
    except
      Close;
    end;
    {保留4字节,用来填充注册算法长度<>4得倍数的长度}
    asm
       nop
       nop
       nop
       nop
    end;
    enddecrypt:   {注册算法的结束始标记}
    {为方便寻找结束解密标记编写的代码,对应16进制为:$40484048}
    asm
       inc eax;
       dec eax;
       inc eax;
       dec eax;
    end;
    except
       {代码解密错误,则会异常退出}
       Close;
    end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
    Application.Title:=KeyTitle;
    Form1.Caption:=KeyTitle;
    Randomize;
    {产生随机数显示}
    edRandom.Text:=inttostr(Random(80000000)+12345678);
end;

procedure TForm1.btnAboutClick(Sender: TObject);
begin
      Application.MessageBox('   本CrackMe由 壹只老虎 制作! '+#13#10+#13#10+
                             '   Email:tiger..tiger@163.com'+#13#10+#13#10+
                             '         2007-08-01','关于',MB_ICONINFORMATION+MB_OK);
end;

procedure TForm1.btnExitClick(Sender: TObject);
begin
     Close;
end;

end.


9:加密工具源代码(我这里只是个半自动的加密工具,回头写个全自动的)

unit EncryptCodeSource;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, WinSkinData, jpeg, ExtCtrls;

type
  TForm1 = class(TForm)
    SkinData1: TSkinData;
    Label1: TLabel;
    edKey: TEdit;
    btnEncrypt: TButton;
    btnAttrib: TButton;
    btnExit: TButton;
    Image1: TImage;
    Label3: TLabel;
    edFilePath: TEdit;
    btnView: TButton;
    Label2: TLabel;
    edStartAddress: TEdit;
    edEndAddress: TEdit;
    Label4: TLabel;
    ofd: TOpenDialog;
    procedure btnAttribClick(Sender: TObject);
    procedure btnExitClick(Sender: TObject);
    procedure btnEncryptClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btnViewClick(Sender: TObject);
    procedure edStartAddressKeyPress(Sender: TObject; var Key: Char);
    procedure edEndAddressKeyPress(Sender: TObject; var Key: Char);
    procedure edKeyKeyPress(Sender: TObject; var Key: Char);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
     KeyTitle = '壹只老虎代码加密工具';

var
  Form1: TForm1;
implementation

{$R *.dfm}

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//> 函数说明:十六进值字符串转换成LongInt值
//> Made  by:壹只老虎
//> 日    期:2007-8-1
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
function HexStrToInt(S: String): LongInt;
var
   i: Integer;
begin
     Result := 0;
     for i := 1 to Length(S) do
        begin
            if S[i] in ['0'..'9'] then
               Result := Result * 16 + (Integer(S[i]) - 48)
            else if S[I] in ['A'..'F'] then
               Result := Result * 16 + (Ord(S[i]) - 55);
        end;
end;

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//> 函数说明:获取文件大小
//> Made  by:壹只老虎
//> 日    期:2007-8-1
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
function GetFileSize(const FileName: string): LongInt;
var
SearchRec: TSearchRec;
begin
 try
   if FindFirst(ExpandFileName(FileName), faAnyFile, SearchRec) = 0 then
      Result := SearchRec.Size
   else
      Result := -1;
  finally
      FindClose(SearchRec);
  end;
end;

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//> 函数说明:设置strFileName文件的CODE段的属性为;读+写+可执行
//> Made  by:壹只老虎
//> 日    期:2007-8-1
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
function SetSectionAttrib(strFileName:string):Boolean;
var
   dwBuffer:DWORD;                    {文件读取缓冲区}
   pe_header:IMAGE_NT_HEADERS;        {PE文件头指针}
   iNumberOfSections:Integer;         {保存区块数目}
   dwSecTableBase:DWORD;              {保存区块头文件首址}
   dwPEHeaderBase:DWORD;              {保存PE文件头文件首址}
   iLoop:Integer;                     {循环变量}
   pSectionTable:IMAGE_SECTION_HEADER;{保存各区块表指针}
   dwSectionAttrib:DWORD;             {保存段属性}
   fsWrite:TFileStream;               {写文件文件流}
begin
     {以读写方式建立文件流}
     fsWrite:=TFileStream.Create(strFileName,fmOpenReadWrite);
     {文件流指针移动到新EXE头部字段}
     fsWrite.Seek($3C,soFromBeginning);
     dwBuffer:=0;
     {读取PE文件头文件地址}
     fsWrite.ReadBuffer(dwBuffer,4);
     dwPEHeaderBase:=dwBuffer;
     {文件指针指向PE 文件头}
     fsWrite.Seek(dwBuffer,soFromBeginning);
     {读入pe文件头到内存}
     fsWrite.ReadBuffer(pe_header,SizeOf(IMAGE_NT_HEADERS));
     {取区块数目}
     iNumberOfSections:=pe_header.FileHeader.NumberOfSections;
     {获取区块表头文件地址:}
      dwSecTableBase:=dwPEHeaderBase+SizeOf(IMAGE_NT_HEADERS);
      {分别读取各个区块的信息到内存}
      for iLoop:=0 to iNumberOfSections-1 do
        begin
            {文件指针指向第iLoop区块表}
            fsWrite.Seek(dwSecTableBase,soFromBeginning);
            {读入区块表信息}
            fsWrite.ReadBuffer(pSectionTable,SizeOf(IMAGE_SECTION_HEADER));
            {读取区块数据文件地址}
            if LPCSTR(@pSectionTable.Name[0])='CODE' then
              begin
                    fsWrite.Seek(dwSecTableBase+36,soFromBeginning);
                    dwSectionAttrib:=$E0000020;
                    fsWrite.WriteBuffer(dwSectionAttrib,SizeOf(DWORD));
                    fsWrite.Free;
                    break;
             end;
            {文件指针移动}
            dwSecTableBase:=dwSecTableBase+SizeOf(IMAGE_SECTION_HEADER);
        end;                                                      
     Result:=True;
end;

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//> 函数说明:数据加密过程
//> Made  by:壹只老虎
//> 日    期:2007-8-1
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
procedure TForm1.btnEncryptClick(Sender: TObject);
var
   iKey:integer;
   fsWrite:TFileStream;
   iStartAddress,iEndAddress,iDataSize:Integer;
   bBuffer:array[0..1024*400]of byte;       {待加密数据存储缓冲区}
   pBuffer:Pointer;
   Label s0;
begin
    {打开文件}
     iStartAddress:=HexStrToInt(edStartAddress.text);  {取开始加密偏移}
     iEndAddress:=HexStrToInt(edEndAddress.text);      {取结束加密偏移}
     iKey:=StrToInt(edKey.text);                       {取密钥}
     iDataSize:= iEndAddress-iStartAddress;            {取加密数据大小}
     if iStartAddress>=iEndAddress-3 then
       begin
          Showmessage('结束地址必须>=开始地址+4');
          exit;
       end;
     if iEndAddress>GetFileSize(edFilePath.Text)then
       begin
          Showmessage('结束地址不能大于文件大小');
          exit;
       end;
     if iKey<100 then
       begin
          Showmessage('密钥至少为3位');
          exit;
       end;
     fsWrite:=TFileStream.Create(edFilePath.Text,fmOpenReadWrite);
     fsWrite.Seek(iStartAddress,soFromBeginning);
     iDataSize:=(iDataSize div 4)*4;
     fsWrite.ReadBuffer(bBuffer,iDataSize);
     pBuffer:=@bBuffer;
    {解密代码}
    asm
       pushad
       mov eax,iDataSize
       mov edx,0
       mov ecx,4
       div ecx
       mov ecx,eax
       mov esi,0
    s0:
       mov ebx,[pBuffer]
       mov eax,[ebx];
       xor eax,iKey
       mov [ebx],eax
       add pBuffer,4
       loop s0
       popad
    end;

    fsWrite.Seek(iStartAddress,soFromBeginning);
    fsWrite.WriteBuffer(bBuffer,iDataSize);
    fsWrite.Free;
    showmessage('代码加密完成');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
    Application.Title:=KeyTitle;
    Form1.Caption:=KeyTitle;
end;

procedure TForm1.btnViewClick(Sender: TObject);
begin
     if ofd.Execute then
       edFilePath.Text:=ofd.FileName;
end;

procedure TForm1.edStartAddressKeyPress(Sender: TObject; var Key: Char);
begin
     if not (key in ['0'..'9',chr(VK_BACK),'a'..'f','A'..'F']) then
       key:=#0;
end;

procedure TForm1.edEndAddressKeyPress(Sender: TObject; var Key: Char);
begin
    if not (key in ['0'..'9',chr(VK_BACK),'a'..'f','A'..'F']) then
       key:=#0;
end;

procedure TForm1.edKeyKeyPress(Sender: TObject; var Key: Char);
begin
    if not (key in ['0'..'9',chr(VK_BACK)]) then
       key:=#0;
end;

procedure TForm1.btnAttribClick(Sender: TObject);
begin
   if SetSectionAttrib(edFilePath.Text) then
     showmessage('代码段添加可写属性成功')
   else
     showmessage('代码段添加可写属性失败');
end;

procedure TForm1.btnExitClick(Sender: TObject);
begin
     Close;
end;

end.


作者:壹只老虎
日期:2007-08-01

[培训]科锐逆向工程师培训第53期2025年7月8日开班!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
2
八月一号建军节之大作,
支持了再看``顶`
2007-8-1 18:05
0
雪    币: 2134
活跃值: (14)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
3
抢.....................不早点提醒我
2007-8-1 18:07
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
没有看明白,先收藏了
2007-8-1 21:47
0
雪    币: 1505
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
5
哈哈 顶你老虎
2007-8-1 22:38
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
不错,顶一下老虎
2007-8-1 23:01
0
雪    币: 1946
活跃值: (303)
能力值: (RANK:330 )
在线值:
发帖
回帖
粉丝
7
发贴重复.网络原因,不能怪我
2007-8-2 04:16
0
雪    币: 1946
活跃值: (303)
能力值: (RANK:330 )
在线值:
发帖
回帖
粉丝
8
大半夜的突然兴起来研究你的这个cm.原来是self modify.更没想到的是你把源代码都贴上来了却给我个exe.
没啥搞的了,提供一组注册码就挂了.
2007-8-2 04:17
0
雪    币: 112
活跃值: (16)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
9
嘿嘿!大忽悠!
2007-8-2 05:08
0
游客
登录 | 注册 方可回帖
返回