Add New Section to PE File
Post date: Mar 16, 2010 3:30:16 PM
{
Unit: uAddSection
Author: steve10120
Description: Add a new section to a PE file.
Thanks: Nacho_dj
Website: ic0de.org
History: First try
Bugfix - SetLength(bDataBuff, dwNewSectionSize);
}
unit uAddSection;
//steve10120
interface
uses
Windows;
function AddSection(szFileName:string; szNewSectionName:string; dwNewSectionSize:DWORD; dwNewSectionCharacteristics:DWORD):Boolean;
implementation
function Align(dwValue:DWORD; dwAlign:DWORD):DWORD;
begin
if dwAlign <> 0 then
begin
if dwValue mod dwAlign <> 0 then
begin
Result := (dwValue + dwAlign) - (dwValue mod dwAlign);
Exit;
end;
end;
Result := dwValue;
end;
function LastSectionRaw(Sections: array of TImageSectionHeader):DWORD;
var
i: integer;
Ret: DWORD;
begin
Ret := 0;
for i := Low(Sections) to High(Sections) do
begin
if Sections[i].SizeOfRawData + Sections[i].PointerToRawData > Ret then
Ret := Sections[i].SizeOfRawData + Sections[i].PointerToRawData;
end;
Result := Ret;
end;
function LastSectionVirtual(Sections: array of TImageSectionHeader):DWORD;
var
i: integer;
Ret: DWORD;
begin
Ret := 0;
for i := Low(Sections) to High(Sections) do
begin
if Sections[i].Misc.VirtualSize + Sections[i].VirtualAddress > Ret then
Ret := Sections[i].Misc.VirtualSize + Sections[i].VirtualAddress;
end;
Result := Ret;
end;
function AddSection(szFileName:string; szNewSectionName:string; dwNewSectionSize:DWORD; dwNewSectionCharacteristics:DWORD):Boolean;
var
hFile: DWORD;
x, i, k: integer;
IDH: TImageDosHeader;
INH: TImageNtHeaders;
Sections: array of TImageSectionHeader;
dwRead: DWORD;
bDataBuff: array of Byte;
const
szError: string = 'Add Section Error';
begin
Result := FALSE;
if Length(szNewSectionName) > 1 then
begin
if Length(szNewSectionName) > 8 then
szNewSectionName := Copy(szNewSectionName, 1, 8);
hFile := CreateFile(PChar(szFileName), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if hFile <> INVALID_HANDLE_VALUE then
begin
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
ReadFile(hFile, IDH, 64, dwRead, nil);
if IDH.e_magic = IMAGE_DOS_SIGNATURE then
begin
SetFilePointer(hFile, IDH._lfanew, nil, FILE_BEGIN);
ReadFile(hFile, INH, 248, dwRead, nil);
if INH.Signature = IMAGE_NT_SIGNATURE then
begin
k := INH.FileHeader.NumberOfSections;
SetLength(Sections, k);
x := IDH._lfanew + 24 + INH.FileHeader.SizeOfOptionalHeader;
for i := Low(Sections) to High(Sections) do
begin
SetFilePointer(hFile, x, nil, FILE_BEGIN);
ReadFile(hFile, Sections[i], 40, dwRead, nil);
Inc(x, 40);
end;
if INH.OptionalHeader.SizeOfHeaders >= (x + 40) then
begin
Inc(INH.FileHeader.NumberOfSections, 1);
SetLength(Sections, INH.FileHeader.NumberOfSections);
with Sections[INH.FileHeader.NumberOfSections - 1] do
begin
CopyMemory(@Name[0], @szNewSectionName[1], 8);
Characteristics := dwNewSectionCharacteristics;
PointerToRawData := Align(LastSectionRaw(Sections), INH.OptionalHeader.FileAlignment);
SizeOfRawData := Align(dwNewSectionSize, INH.OptionalHeader.FileAlignment);
VirtualAddress := Align(LastSectionVirtual(Sections), INH.OptionalHeader.SectionAlignment);
Misc.VirtualSize := Align(dwNewSectionSize, INH.OptionalHeader.SectionAlignment);
end;
INH.OptionalHeader.DataDirectory[11].VirtualAddress := 0;
INH.OptionalHeader.DataDirectory[11].Size := 0;
Inc(INH.OptionalHeader.SizeOfImage, Sections[INH.FileHeader.NumberOfSections - 1].Misc.VirtualSize);
SetFilePointer(hFile, IDH._lfanew, nil, FILE_BEGIN);
WriteFile(hFile, INH, 248, dwRead, nil);
SetFilePointer(hFile, x, nil, FILE_BEGIN);
WriteFile(hFile, Sections[INH.FileHeader.NumberOfSections - 1], 40, dwRead, nil);
SetLength(Sections, 0);
dwNewSectionSize := Align(dwNewSectionSize, INH.OptionalHeader.FileAlignment);
SetLength(bDataBuff, dwNewSectionSize);
SetFilePointer(hFile, 0, nil, FILE_END);
WriteFile(hFile, bDataBuff[0], dwNewSectionSize, dwRead, nil);
CloseHandle(hFile);
Result := TRUE;
end;
end
else
MessageBox(0, PChar('Bad PE signature.'), PChar(szError), MB_ICONEXCLAMATION);
end
else
MessageBox(0, PChar('Bad MZ signature.'), PChar(szError), MB_ICONEXCLAMATION);
end
else
MessageBox(0, PChar('Error opening file.'), PChar(szError), MB_ICONEXCLAMATION);
end;
end;
end.
Usage:
if AddSection('hellovb6.exe', '.test', 100, IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE) then
MessageBox(0, PChar('Section added successfully.'), PChar('Success'), MB_ICONINFORMATION);