加壳原理与简单实现加壳(delphi源码)

  { *****************************************************************
AddShell()源自于前一段时间有写的addsection()新增区段代码,
在增加区段代码的基础上,追加了
1.修改启动入口点位置
2.增加一段壳头xor $50的代码function AttachStart-function AttachEnd
 这一段代码是先填充,再被修改成合适原EXE的壳头
3.修改原启动代码入口点所在区段的段属性可写并进行xor $50运算加密


不支持addshell()处理已经过addshell的exe
*****************************************************************
}

unit Unit1;

interface

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

type
  TForm1 
=  class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Button2: TButton;
    Button3: TButton;
    
procedure  Button1Click(Sender: TObject);
    
procedure  Button3Click(Sender: TObject);
    
procedure  Button2Click(Sender: TObject);
  private
    
{  Private declarations  }
  public
    
{  Public declarations  }
  
end ;

var
  Form1             : TForm1;

implementation

{ $R *.dfm }
function  AttachStart: dword; stdcall;    // 我们定义的待填充数据
asm
       pushfd
       pushad
       mov eax,$
12345678        // 将会被自动计算并修改为加密初始地址
       mov ebx,$
1234            // 将会被自动计算并修改为加密大小
       mov ecx,
0
       @AA:
       xor byte ptr[eax],$
50
       inc eax
       inc ecx
       cmp ecx,ebx
       jbe @aa
       popad
       popfd
       push $
12345678          // 将会被自动计算并修改为原OEP
       ret
end ;

function  AttachEnd: dword; stdcall;
begin
end ;

{ -------------------------增加区块并实现简易加壳-------------------------------- }
procedure  AddShell(lFileName: string; lBackup: boolean);  // 打开exe文件,是否备份
var
  hFile             : THandle;          
// 文件句柄
  ImageDosHeader    : IMAGE_DOS_HEADER; 
// DOS部首
  ImageNtHeaders    : IMAGE_NT_HEADERS; 
// 映象头
  ImageSectionHeader: IMAGE_SECTION_HEADER; 
// 块表
  lPointerToRawData : dword;            
// 指向文件中的偏移
  lVirtualAddress   : dword;            
// 指向内存中的偏移
  i                 : integer;          
// 循环变量
  BytesRead, ByteSWrite: Cardinal;      
// 读写用参数
  AttachSize        : dword;            
// 附加段大小
  AttachData, ChangeData: integer;      
// 附加段填充数据
  OEP               : integer;          
// 使用过程中用到的EP
  lpBuffer          : 
array [ 0 .. 1024   *   400 of  byte;  { 待加密数据存储缓冲区 }
  nNumberOfBytesToRead, lpNumberOfBytesRead: dword; 
// 加密时用到的一些数据
  StartEN, SizeEN, StartCr: dword;      
// 加密用的开始物理地址和大小
begin

  
// 定义附加段填充数据
  AttachData :
=   0 ;

  
// 打开文件
  hFile :
=  CreateFile(PChar(lFileName), GENERIC_READ  or  GENERIC_WRITE, FILE_SHARE_READ  or  FILE_SHARE_WRITE,  nil , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,  0 );

  
// 校验
  
if  hFile  =  INVALID_HANDLE_VALUE  then
  
begin
    ShowMessage(
' 打开文件失败 ' );
    exit;
  
end ;

  
// 确认备份
  
if  lBackup  then  CopyFile(PChar(lFileName), PChar(lFileName  +   ' .bak ' ), False);
  try

    
// 读取DOS部首到ImageDosHeader
    ReadFile(hFile, ImageDosHeader, SizeOf(ImageDosHeader), BytesRead, 
nil );

    
// 校验
    
if  ImageDosHeader.e_magic  <>  IMAGE_DOS_SIGNATURE  then
    
begin
      ShowMessage(
' 不是有效的PE文件! ' );
      exit;
    
end ;

    
// 指向映象头
    SetFilePointer(hFile, ImageDosHeader._lfanew, 
nil , FILE_BEGIN);

    
// 读取映向头到ImageNtHeaders
    ReadFile(hFile, ImageNtHeaders, SizeOf(ImageNtHeaders), BytesRead, 
nil );

    
// 校验
    
if  ImageNtHeaders.Signature  <>  IMAGE_NT_SIGNATURE  then
    
begin
      ShowMessage(
' 不是有效的PE文件 ' );
      exit;
    
end ;
    
{ ******************************** }
    
{ OEP=基址+原EP }
    OEP :
=  ImageNtHeaders.OptionalHeader.ImageBase  +  ImageNtHeaders.OptionalHeader.AddressOfEntryPoint;

    
{ ******************************** }

    
// 计算加入块对齐后大小
    AttachSize :
=  ((integer(@AttachEnd)  -  integer(@AttachStart))  div  ImageNtHeaders.OptionalHeader.FileAlignment  +   1 *  ImageNtHeaders.OptionalHeader.FileAlignment;

    
// 初始化文件中偏移和映象中偏移
    lPointerToRawData :
=   0 ;
    lVirtualAddress :
=   0 ;

    
for  i : =   0   to  ImageNtHeaders.FileHeader.NumberOfSections  -   1   do
    
begin

      
// 读取块表中信息
      ReadFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), BytesRead, 
nil );

      
{ ******************************** }
       
{ 查找原EP所在区段(原EP所在区段),记录物理偏移(加密用初始地址),物理大小(加密用长度) }
      
if  LPCSTR(@ImageSectionHeader.Name[ 0 ])  =   ' .EN '   then
      
begin
        ShowMessage(
' 已经过本addshell处理! ' );
        exit;
      
end ;

      
if  ImageNtHeaders.OptionalHeader.AddressOfEntryPoint  >  ImageSectionHeader.VirtualAddress  then
      
begin
        StartEN :
=  ImageSectionHeader.PointerToRawData;
        SizeEN :
=  ImageSectionHeader.SizeOfRawData;
        StartCr :
=  ImageNtHeaders.OptionalHeader.ImageBase  +  ImageSectionHeader.VirtualAddress;
      
end ;

      
{ ******************************** }

      
// 计算文件中偏移
      
if  lPointerToRawData  <  ImageSectionHeader.PointerToRawData  +  ImageSectionHeader.SizeOfRawData  then
        lPointerToRawData :
=  ImageSectionHeader.PointerToRawData  +  ImageSectionHeader.SizeOfRawData;

      
// 计算映象中偏移
      
if  lVirtualAddress  <  ImageSectionHeader.VirtualAddress  +  ImageSectionHeader.Misc.VirtualSize  then
        lVirtualAddress :
=  ImageSectionHeader.VirtualAddress  +  ImageSectionHeader.Misc.VirtualSize;
    
end ;

    
{ 增加块,定义块各项属性 }

    Move(
' .EN ' # 0 , ImageSectionHeader.Name[ 0 ],  5 );

    
// 设置初始属性
    ImageSectionHeader.Misc.VirtualSize :
=  AttachSize;
    ImageSectionHeader.VirtualAddress :
=  lVirtualAddress;
    ImageSectionHeader.SizeOfRawData :
=  AttachSize;
    ImageSectionHeader.PointerToRawData :
=  lPointerToRawData;
    ImageSectionHeader.PointerToRelocations :
=   0 ;
    ImageSectionHeader.PointerToLinenumbers :
=   0 ;
    ImageSectionHeader.NumberOfRelocations :
=   0 ;

    
// 校正新节物理偏移(物理区块对齐)
    
if  ImageSectionHeader.VirtualAddress  mod  ImageNtHeaders.OptionalHeader.SectionAlignment  >   0   then
      ImageSectionHeader.VirtualAddress :
=  (ImageSectionHeader.VirtualAddress  div  ImageNtHeaders.OptionalHeader.SectionAlignment  +   1 *  ImageNtHeaders.OptionalHeader.SectionAlignment;

    
// 校正新节映象偏移(映象中区块对齐)
    
if  ImageSectionHeader.Misc.VirtualSize  mod  ImageNtHeaders.OptionalHeader.SectionAlignment  >   0   then
      ImageSectionHeader.Misc.VirtualSize :
=  (ImageSectionHeader.Misc.VirtualSize  div  ImageNtHeaders.OptionalHeader.SectionAlignment  +   1 *  ImageNtHeaders.OptionalHeader.SectionAlignment;

    
// 设置区块属性
    ImageSectionHeader.Characteristics :
=  $E00000E0;

    
// 保存区块信息
    WriteFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), ByteSWrite, 
nil );

    
// 校正内存映象大小
    ImageNtHeaders.OptionalHeader.SizeOfImage :
=  ImageNtHeaders.OptionalHeader.SizeOfImage  +  ImageSectionHeader.Misc.VirtualSize;
    
// 更新OEP
    ImageNtHeaders.OptionalHeader.AddressOfEntryPoint :
=  ImageSectionHeader.VirtualAddress;

    
// 校正块数目
    Inc(ImageNtHeaders.FileHeader.NumberOfSections);

    
// 定位到映象头
    SetFilePointer(hFile, ImageDosHeader._lfanew, 
nil , FILE_BEGIN);

    
// 保存校正过的映象头
    WriteFile(hFile, ImageNtHeaders, SizeOf(ImageNtHeaders), ByteSWrite, 
nil );

    
// 定位到新节开始处
    SetFilePointer(hFile, ImageSectionHeader.PointerToRawData, 
nil , FILE_BEGIN);

    
// 用00数据填充满新节
    
for  i : =   1   to  AttachSize  do
    
begin
      WriteFile(hFile, PByte(@AttachData)^, 
1 , ByteSWrite,  nil );
    
end ;

    
{ 填充自定义数据 }
      
// 指向新节开始处
    SetFilePointer(hFile, ImageSectionHeader.PointerToRawData, 
nil , FILE_BEGIN);

    
// 填充我们定义的数据
    WriteFile(hFile, PByte(@AttachStart)^, integer(@AttachEnd) 
-  integer(@AttachStart), ByteSWrite,  nil );
    
{ ******************************** }
    
// 修改所谓的外壳处大量数据
    ChangeData :
=  ImageSectionHeader.PointerToRawData  +   3 ;
    SetFilePointer(hFile, ChangeData, 
nil , FILE_BEGIN);
    WriteFile(hFile, StartCr, 
4 , ByteSWrite,  nil );  // 开始加密地址
    ChangeData :
=  ChangeData  +   5 ;
    SetFilePointer(hFile, ChangeData, 
nil , FILE_BEGIN);
    WriteFile(hFile, SizeEN, 
4 , ByteSWrite,  nil );  // 大小
    ChangeData :
=  ChangeData  +   21 ;
    SetFilePointer(hFile, ChangeData, 
nil , FILE_BEGIN);
    WriteFile(hFile, OEP, 
4 , ByteSWrite,  nil );  // 跳回OEP

    
{ ******************************** }
    
// 没有异常,显示增加区块成功!
    ShowMessage(
' 增加区块成功! ' );


    SetFilePointer(hFile, StartEN, 
nil , FILE_BEGIN);
    ReadFile(hFile, lpBuffer, SizeEN, BytesRead, 
nil );
    
for  i : =   0   to  SizeEN  -   1   do
    
begin
      byte(pointer(integer(@lpBuffer) 
+  i)^) : =  byte(pointer(integer(@lpBuffer)  +  i)^) xor $ 50 ;
    
end ;
    SetFilePointer(hFile, StartEN, 
nil , FILE_BEGIN);
    WriteFile(hFile, lpBuffer, SizeEN, ByteSWrite, 
nil );
    
// 没有异常,显示变换成功!
    ShowMessage(
' 变换数据成功! ' );



    
{ ******************************** }
    SetFilePointer(hFile, (ImageDosHeader._lfanew 
+  SizeOf(ImageNtHeaders)),  nil , FILE_BEGIN);

    
for  i : =   0   to  ImageNtHeaders.FileHeader.NumberOfSections  -   1   do
    
begin

      
// 读取块表中信息
      ReadFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), BytesRead, 
nil );
      
if  ImageSectionHeader.PointerToRawData  =  StartEN  then
      
begin
        ImageSectionHeader.Characteristics :
=  $E00000E0;
        SetFilePointer(hFile, 
- SizeOf(ImageSectionHeader),  nil , FILE_CURRENT);
        
// 保存区块信息
        WriteFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), ByteSWrite, 
nil );
        Break;
      
end ;
    
end ;
    ShowMessage(
' 修改区段属性成功! ' );
    
{ ******************************** }


  finally

    
{ 8.退出 }
        
// 关闭文件
    CloseHandle(hFile);
  
end ;

end ;
{ *************************Func end********************************* }

procedure  TForm1.Button1Click(Sender: TObject); // addshell
begin

  AddShell(Edit1.text, true);
end ;

procedure  TForm1.Button3Click(Sender: TObject); // browser
begin
  
with  TOpenDialog.Create(Self)  do
  try
    Filter :
=   ' 可执行文件 (*.exe)|*.exe ' ;
    
if  Execute  then
    
begin
      Edit1.text :
=  FileName;
    
end ;
  finally
    Free;
  
end ;
end ;

procedure  TForm1.Button2Click(Sender: TObject); // exit
begin
  close;
end ;

end .
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值