Description
This Delphi unit demonstrate how to manipulate EOF Data of a Valid Microsoft Windows Portable Executable (PE) File.
EOF (End Of File) is often used by Malware authors to offer their Malware users a way to edit Malware payload configuration (Ex: C2 informations) without having access to source code.
You often encounter such techniques in:
- Remote Access Tool/Trojan (RAT)
- File Wrapper / Binder
- Downloader
- Loader / Botnets
Tiny snippet to know whether or not target process id is running under 32bit or 64bit architecture.
If result is True
, target process is running under 64bit architecture.
If result is False
, target process is running under 32bit architecture.
// ...
uses Windows, SysUtils;
// ...
type
TArchitecture = (x86, x64, xUnknown);
// ...
function IsProcessX64(AProcessId : Cardinal) : TArchitecture;
var AProcHandle : THandle;
AWow64Process : bool;
begin
result := xUnknown;
///
{
If we are not in a 64Bit system then we are for sure in a 32Bit system
}
if (TOSVersion.Architecture = arIntelX86) then
Exit();
///
AProcHandle := OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, AProcessId);
if AProcHandle = 0 then
Exit;
try
isWow64Process(AProcHandle, AWow64Process);
///
if AWow64Process then
result := x86
else
result := x64;
finally
CloseHandle(AProcHandle);
end;
end;
Read more...
This is one of the most famous method to enumerate running process on Windows.
If AFilterSameArch
is set to True
, only processes running with same architecture as current process will be listed.
{
Jean-Pierre LESUEUR (@DarkCoderSc)
Example:
...
var AProcessName : String;
AProcessId : Cardinal;
AProcessList : TDictionary<Integer, String>;
begin
AProcessList := EnumProcess(True);
try
for AProcessId in AProcessList.Keys do begin
if NOT AProcessList.TryGetValue(AProcessId, AProcessName) then
continue;
///
...
end;
finally
if Assigned(AProcessList) then
FreeAndNil(AProcessList);
end;
end;
}
//...
uses tlhelp32, SysUtils, Windows, Generics.Collections;
//...
function EnumProcess(AFilterSameArch : Boolean = False) : TDictionary<Integer {Process Id}, String {Process Name}>;
var ASnap : THandle;
AProcessEntry : TProcessEntry32;
AProcessName : String;
procedure AppendEntry();
begin
if AFilterSameArch and ((IsProcessX64(GetCurrentProcessId())) <> (IsProcessX64(AProcessEntry.th32ProcessID))) then
Exit();
///
result.Add(AProcessEntry.th32ProcessID, AProcessEntry.szExeFile);
end;
begin
result := TDictionary<Integer, String>.Create();
///
ASnap := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if ASnap = INVALID_HANDLE_VALUE then
Exit();
try
ZeroMemory(@AProcessEntry, SizeOf(TProcessEntry32));
///
AProcessEntry.dwSize := SizeOf(TProcessEntry32);
if NOT Process32First(ASnap, AProcessEntry) then
Exit();
AppendEntry();
while True do begin
ZeroMemory(@AProcessEntry, SizeOf(TProcessEntry32));
///
AProcessEntry.dwSize := SizeOf(TProcessEntry32);
if NOT Process32Next(ASnap, AProcessEntry) then
break;
AppendEntry();
end;
finally
CloseHandle(ASnap);
end;
end;
Read more...
You will find below 4 different techniques to close/kill/terminate Windows process in pure WinAPI.
Techniques
TerminateProcess()
: Classic method.ExitProcess()
: via Code Injection (32bit to 32bit ; 64bit to 64bit).Crash Process
: Inject code that will crash the process (32bit to 32bit ; 64bit to 64bit).CTRL_CLOSE_EVENT
/WM_CLOSE
: Send "close" messages to target process windows.
TerminateAProcess()
Method
Kill target process id following desired method : tmpAll
, tpmTerminateProcess
, tpmExitProcess
, tpmCrash
, tpmMessage
tmpAll
attempt to kill process from cleanest way to dirtiest way until it succeed.
You will find below an example of how to enumerate process modules using the well known Windows API CreateToolHelp32Snapshot()
, I will cover additional methods soon.
You may notice that when using CreateToolHelp32Snapshot()
, first result (row) is generally the Image Path of the process owning module. I ignore that row by checking the value of szExePath
with owner process image path.
GetProcessName()
is compatible since Windows Vista. It is possible to support Windows XP and below but not in this example.
You will find GetProcessName()
and alternatives in separated snippets threads.
This one possible technique (through QueryFullProcessImageNameW
) to get process image path from it id.
This example support Windows Vista to latest Windows version (Actually Windows 10)
I will cover other example progressively and compatible with Windows XP and below.
// Jean-Pierre LESUEUR (@DarkCoderSc)
//...
uses Windows, SysUtils;
//...
function GetProcessName(AProcessID : Cardinal) : String;
var hProc : THandle;
ALength : DWORD;
hDLL : THandle;
QueryFullProcessImageNameW : function(
AProcess: THANDLE;
AFlags: DWORD;
AFileName: PWideChar;
var ASize: DWORD): BOOL; stdcall;
const PROCESS_QUERY_LIMITED_INFORMATION = $00001000;
begin
result := '';
///
if (TOSVersion.Major < 6) then
Exit();
///
QueryFullProcessImageNameW := nil;
hDLL := LoadLibrary('kernel32.dll');
if hDLL = 0 then
Exit();
try
@QueryFullProcessImageNameW := GetProcAddress(hDLL, 'QueryFullProcessImageNameW');
///
if Assigned(QueryFullProcessImageNameW) then begin
hProc := OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, AProcessID);
if hProc = 0 then exit;
try
ALength := (MAX_PATH * 2);
SetLength(result, ALength);
if NOT QueryFullProcessImageNameW(hProc, 0, @result[1], ALength) then
Exit();
SetLength(result, ALength); // Get rid of extra junk
finally
CloseHandle(hProc);
end;
end;
finally
FreeLibrary(hDLL);
end;
end;
Read more...
This unit demonstrate how to enumerate DLL exported functions through PE Header manipulation.
Features
- Support both 32 and 64bit DLL's.
- Identify exported function names.
- Identify exported function ordinal value.
- Support and resolve forwarded function.
- Identify export function address and relative address.
In the past two days, I released examples about how to enumerate DLL export table through the PE Header.
We will see one concreate example of using the UntEnumDLLExport.pas library to dynamically load API without using the famous Windows API > GetProcAddress()
This technique is quite known and often used by some Malware, to mask which API's they are dynamically loading and avoid Antivirus detection.
Read more...This very small snippet is an adaptation of the previously released unit > UntEnumDLLExport.pas with just one goal, retrieve an exported function address by its name from any DLL (both 32 and 64bit).
This adaptation is also interesting because it remove the need of having both heavy units Generics.Collections
and SysUtils
to have a smaller binary.
Finally it is also quite interesting for tweaking our GetProcAddress
alternative (you will find here) and only have the necesarry code.
As promised, we will adapt our previous code grab an exported function directly from memory.
Serious advantage of this technique:
- We don't have to use
CreateToolHelp32Snapshot
anymore to enumerate modules and catch target module base address. - We don't need to parse PE Header from disk anymore, we will parse PE Header directly from memory.
LoadLibrary
API to load desired DLL in memory. An alternative of LoadLibrary
would be to create our own PE Loader. We will cover that subject in a near future.