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

http://hi.baidu.com/broland/blog/item/0a051c25c4321c23d4074223.html

 

[code]{*****************************************************************
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.

[code]

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值