⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mainunit.pas

📁 Delphi版pe加壳程序
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit MainUnit;

interface

(*
  V2Packer
  code by tt.t with almost pure delphi
  first build @ 2006.4.15

  看到过许多别人写的壳,大多是asm,也有的是c。早就想试一试用比较“纯”的delphi
  写会是什么样子,于是就有了V2Packer。
  V2Packer断断续续写了半个月的时间,资源部分代码写的很垃圾,只算是能用。PEAnalyst类
  由于改变了思路,去掉了一些东西,现在成了PEHeader类的再包装。
  代码中的{$INCLUDE 'DePack.pas'}是因为d6的ide不支持代码折叠,就把一些代码移到了
  单独的单元。
  DePack.pas中用了一个非常简单而且不安全的anti-debug trick,很可能有危险,不过
  姑且放在那里吧。

  代码中肯定有bug,不过测试中没发现大问题,作为自娱自乐的产物就算说得过去了。

  程序写的思路比较清晰,如果对感兴趣,可以从DoPack函数看起。
  希望能对为数不多的用delphi写这累东西的初学者有一些帮助。

  !请不要将这些代码用于非法用途!

  
Todo:
  1. OverLay data                Done: 15, Apr.
  2. Add app icon                Done: 18, Apr.
  3. Move header Data
  4. Delay import support        Done: 15, Apr.
  5. Relocation support
  6. Dll support
  7. anti-debug tricks
  8. ...
*)

uses
  JwaWinnt, JwaWinBase, JwaWintype, JwaWinUser,
  Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ShellAPI, ComCtrls, StdCtrls,
  aplibu,
  PkDataQueueUnit,
  PEAnalystUnit,
  UtilUnit, Gauges, ExtCtrls, Menus;

type
  TForm1 = class(TForm)
    PB: TGauge;
    Panel1: TPanel;
    Bevel1: TBevel;
    RichEdit1: TRichEdit;
    leSrcFn: TLabeledEdit;
    GroupBox2: TGroupBox;
    cbClearImp: TCheckBox;
    cbBackup: TCheckBox;
    leSectionName: TLabeledEdit;
    imgIcon: TImage;
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private                      
    SrcFn: String;
    BackFn: String;
    PkSectionName: String;
    procedure WithDropFiles(var Msg: TMessage); message WM_DROPFILES;
    procedure ShowMsg(Msg: String);
    procedure UpdateUi;
    function BackupFile(const FileName: String): integer;
    procedure DoPack;
  public
  end;

  function CallBack(w0, w1, w2 : DWORD;cbparam : Pointer) : DWORD;cdecl;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
  PImpDir = ^TImpDir;              //壳中保存的导入表数据的结构
  TImpDir = packed record
    ThunkRVA: DWORD;
    ImpFuncCount: DWORD;
    Name: Array [0..0] of Char;
  end;
  PPkSectionDir = ^TPkSectionDir;  //壳中保存的Section数据的信息
  TPkSectionDir = packed record
    Offset: Cardinal;
    Length: Cardinal;
    RVA: Cardinal;
    VLength: Cardinal;
    Prop: Byte;
  end;
  PPkDataHeader = ^TPkDataHeader;  //壳中保存的压缩后数据的位置信息
  TPkDataHeader = packed record
    PkSectionDirCount: Cardinal;   //压缩前Section的个数
    PkSectionDirOffset: Cardinal;  //PkSectionDir数据相对PkDataHeader的偏移
    PkImpDirOffset: Cardinal;      //ImpDir数据相对PkDataHeader的偏移
    ImpSize: Cardinal;
    EPRVA: Cardinal;
    ResRVA: Cardinal;
    ResSize: Cardinal;
    DelayImpRVA: Cardinal;
    DelayImpSize: Cardinal;
  end;

  type            
    PRegs = ^TRegs;
    TRegs = record
      Edi: Cardinal;
      Esi: Cardinal;
      Ebp: Cardinal;
      Esp: Cardinal;
      Ebx: Cardinal;
      Edx: Cardinal;
      Ecx: Cardinal;
      Eax: Cardinal;
  end;

var
  SrcPE: TMemoryStream;
  PkDataQueue: TPkDataQueue;  
  PEAnalyst: TPEAnalyst;
  pPackerSection: PImageSectionHeader;
  SectionDataSize: Cardinal = 0;  
  PkImportDirLength: Cardinal;

//===========SHELLCODE==============
  
procedure StartHere;
asm
end;

function LocalVar: PDWORD;     //一些数据,保存在壳中
asm
  call @j
  dd 0              //PkDataHeaderRVA

  dd $12345678      //'GetModuleHandleA' Thunk
  dd $87654321      //'LoadLibrary' Thunk
  dd $feeffeef      //'GetProcAddress' Thunk
  dd $feeffeef      //'VirtualAlloc' Thunk
  dd $feeffeef      //'VirtualFree' Thunk
  dd $feeffeef      //'VirtualProtect' Thunk
  dd $feeffeef      //'HeapCreate' Thunk
  dd $feeffeef      //'HeapAlloc' Thunk
  dd 0              //Null
@j:
  pop result
end;

{$INCLUDE 'DePack.pas'}

procedure NewEnteryPoint;        //壳的EP
asm
  pushad
  call DelphiEP
end;

procedure EndHere;
asm
end;
//===========SHELLCODE==============













procedure AssembleImpTab;
//组装壳的导入表
const
  DllName: PChar = 'kernel32.dll';
  FuncName: Array [1..8] of PChar = ('GetModuleHandleA', 'LoadLibraryA',
    'GetProcAddress', 'VirtualAlloc', 'VirtualFree', 'VirtualProtect', 'HeapCreate',
    'HeapAlloc');
  //壳需要导入的函数
var
  PEImpPtr: Pointer;
  PkData: PPkData;

  PEImpPtrLen: Cardinal;
  PEImpDir: PImageImportDecriptor;
  pFuncName: PImageImportByName;
  pDllName: PChar;

  lImpDir, lDllName, lFuncName: Cardinal;
  pThunk: PDWORD;

  i, FuncCount, l, l2: Cardinal;
begin
  lImpDir := SizeOf(TImageImportDecriptor) * 2;      
  lDllName := Length(DllName) + 1;
  lFuncName := 0;
  FuncCount := High(FuncName) - Low(FuncName) + 1;
  for i := Low(FuncName) to High(FuncName) do
    Inc(lFuncName, Length(FuncName[i]) + 1);
  PEImpPtrLen := lImpDir + lDllName + lFuncName +
                 (SizeOf(WORD))* FuncCount +
                 SizeOf(DWORD) * (FuncCount + 1);

  PEImpPtr := AllocMem(PEImpPtrLen);

  PEImpDir := PEImpPtr;
  PEImpDir^.Union.OriginalFirstThunk := 0;
  PEImpDir^.TimeDateStamp := $FFFFFFFF;
  PEImpDir^.ForwarderChain := $FFFFFFFF;
  PEImpDir^.Name := lImpDir + SizeOf(DWORD) * (FuncCount + 1);
  PEImpDir^.FirstThunk := lImpDir;
  //Name, FirstThunk的值是Offset,不是RVA!

  pDllName := PtrAdd(PEImpDir, PEImpDir^.Name);
  CopyMemory(pDllName, DllName, lDllName);

  pThunk := PtrAdd(PEImpDir, PEImpDir^.FirstThunk);
  pFuncName := PtrAdd(pDllName, lDllName);
  l := lImpDir + SizeOf(DWORD) * (FuncCount + 1) + lDllName;
  for i := Low(FuncName) to High(FuncName) do
  begin
    pThunk^ := l;
    //pThunk的值是Offset,不是RVA!
    Inc(pThunk);
    pFuncName^.Hint := 0;
    CopyMemory(@pFuncName^.Name[0], FuncName[i], Length(FuncName[i]));
    l2 := Length(FuncName[i]) + SizeOf(TImageImportByName) - 1;
    pFuncName := PtrAdd(pFuncName, l2);
    Inc(l, l2);
  end;

  PkData := PkDataQueue.Get('ImpTab');  //存入列表
  PkData^.Ptr := PEImpPtr;
  PkData^.Len := PEImpPtrLen;
end;



procedure FixImpRVA(pImpDir: PImageImportDecriptor; BaseRVA: Cardinal);
//将Name, FirstThunk, pThunk值修正为RVA!
//BaseRVA: 导入表的RVA
//pImpDir: 指向导入表的指针
var
  pThunk: PDWORD;
begin
  Inc(pImpDir^.Name, BaseRVA);
  Inc(pImpDir^.FirstThunk, BaseRVA);
  pThunk := PtrAdd(pImpDir, SizeOf(TImageImportDecriptor) * 2 );
  while pThunk^ <> 0 do
  begin
    Inc(pThunk^, BaseRVA);
    Inc(pThunk);
  end;
end;

procedure FixImpThunk(pImpDir: PImageImportDecriptor; NewThunk: Cardinal);
//将导入表的FirstThunk指向LocalVar相应变量在加壳后程序中的RVA
//NewThunk: LocalVar第一个变量的RVA
//pImpDir: 指向导入表的指针
var
  pThunk: PDWORD;
  pLocalVar: PDWORD;
begin
  pLocalVar := LocalVar;
  Inc(pLocalVar);
  pThunk := PtrAdd(pImpDir, SizeOf(TImageImportDecriptor) * 2 );
  pImpDir^.FirstThunk := NewThunk;
  while pThunk^ <> 0 do
  begin
    pLocalVar^ := pThunk^;  //更新LocalVar相应变量的值=pThunk的RVA
    Inc(pThunk);
    Inc(pLocalVar);
  end;
end;

procedure PackSection(SrcPEPtr: Pointer);
//压缩section数据
//SrcPEPtr: 指向PE文件指针
var
  i, l: Cardinal;
  PkData: PPkData;
  PkSectionBuf: Pointer;
  PkSectionDir: PPkSectionDir;
  FirstPkSectionDir: PPkSectionDir;
  SectionCount: Cardinal;
  Source, WorkMem: Pointer;
  SourceLength: Cardinal;
  SourceSectionSize: Cardinal;
  PkDataOffset: Cardinal;        
  PkSectionDataSize: Cardinal;
begin
  SectionCount := PEAnalyst.SectionCount;

  SourceSectionSize := 0;
  for i := 0 to SectionCount - 1 do
    inc(SourceSectionSize, PEAnalyst.SectionHeaders[i]^.SizeOfRawData);
  SourceSectionSize := _aP_max_packed_size(SourceSectionSize);
  GetMem(PkSectionBuf, SizeOf(TPkDataHeader) + SectionCount * SizeOf(TPkSectionDir) +
    SourceSectionSize);
  GetMem(WorkMem, _aP_workmem_size(SourceSectionSize));
  PkSectionDir := PkSectionBuf;
  FirstPkSectionDir := PkSectionDir;
  PkDataOffset := SectionCount * SizeOf(TPkSectionDir);
  for i := 0 to SectionCount - 1 do
  begin
    Source := PtrAdd(SrcPEPtr, PEAnalyst.SectionHeaders[i]^.PointerToRawData);
    SourceLength := PEAnalyst.SectionHeaders[i]^.SizeOfRawData;
    Inc(PkSectionDataSize, SourceLength);
    l := _aP_pack(Source^, PtrAdd(FirstPkSectionDir, PkDataOffset)^, SourceLength, WorkMem^, CallBack, @PkSectionDataSize);
    PkSectionDir^.Length := SourceLength;
    PkSectionDir^.Offset := PkDataOffset;
    PkSectionDir^.RVA := PEAnalyst.SectionHeaders[i]^.VirtualAddress;
    PkSectionDir^.VLength := PEAnalyst.SectionHeaders[i]^.Misc.VirtualSize;
    PkSectionDir^.Prop := PAGE_EXECUTE_READWRITE;               //保存section header的信息
    Inc(PkDataOffset, l);
    Inc(PkSectionDir);
  end;
  FreeMem(WorkMem);
  PkData := PkDataQueue.Get('PkSectionData');    //存入列表
  PkData^.Ptr := PkSectionBuf;
  PkData^.Len := PkDataOffset;
end;

procedure PackImports(SrcPEPtr: Pointer; ClearImp: Bool);
//转换导入表为简单格式,然后压缩
//SrcPEPtr: 指向PE文件指针
var
  PkData: PPkData;

  PkImportBuf: Pointer;
  PkImportDir: PImpDir;
  PEImpDir: PImageImportDecriptor;
  pFuncName: PImageImportByName;
  pThunk: PDWORD;
  pDllName: PChar;
  pName: PChar;
  lDll: DWORD;  
  lFunc: DWORD;
  l: Cardinal;

  PkImportTab, WorkMem: Pointer;  
  PkLen: Cardinal;
begin
  PEImpDir := PtrAdd(SrcPEPtr, PEAnalyst.RVAtoOffset(PEAnalyst.DataDirectorys[IMAGE_DIRECTORY_ENTRY_IMPORT]^.VirtualAddress));
  PkImportBuf := AllocMem(500 * 1024);  //临时缓冲区,保存简单格式
  PkImportDir := PkImportBuf;
  PkImportDirLength := 0;
  while PEImpDir^.FirstThunk <> 0 do
  begin
    pDllName := PtrAdd(SrcPEPtr, PEAnalyst.RVAtoOffset(PEImpDir^.Name));
    lDll := Length(pDllName) + 1;
    pName := @PkImportDir^.Name[0];
    CopyMemory(pName, pDllName, lDll);
    if ClearImp then
      ZeroMemory(pDllName, lDll);                       //清除原导入表数据
    PkImportDir^.ThunkRVA := PEImpDir^.FirstThunk;
    if PEImpDir^.Union.OriginalFirstThunk <> 0 then
      pThunk := PtrAdd(SrcPEPtr, PEAnalyst.RVAtoOffset(PEImpDir^.Union.OriginalFirstThunk))
    else
      pThunk := PtrAdd(SrcPEPtr, PEAnalyst.RVAtoOffset(PEImpDir^.FirstThunk));
    pName := PtrAdd(pName, lDll);
    lFunc := 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -