来自:
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
.
转载于:https://www.cnblogs.com/iinsnian/archive/2008/06/10/1216579.html