您的位置:首页 > 编程语言 > Delphi

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

2008-06-10 11:31 555 查看
来自:http://bbs.pediy.com/showthread.php?t=57671

{*****************************************************************

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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: