来自: 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 .
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 .