Created
December 19, 2024 10:19
-
-
Save erdesigns-eu/dba4e9a6839e56c80ba6db4484b5e1df to your computer and use it in GitHub Desktop.
Cross-Platform System Call Executor (x86, x64, ARM) in Delphi
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
unit SysCallExecutor; | |
interface | |
uses | |
Windows, SysUtils; | |
type | |
TSysCallExecutor = class | |
private | |
function GetSysCallNumber(const FunctionName: string): Cardinal; | |
function GetProcAddressEx(const ModuleName, FunctionName: string): Pointer; | |
public | |
function ExecuteSysCall(SysCallNumber: Cardinal; Parameters: array of Pointer): Integer; | |
function ExecuteFunctionByName(const FunctionName: string; Parameters: array of Pointer): Integer; | |
end; | |
implementation | |
function TSysCallExecutor.GetProcAddressEx(const ModuleName, FunctionName: string): Pointer; | |
var | |
ModuleHandle: HMODULE; | |
begin | |
ModuleHandle := GetModuleHandle(PChar(ModuleName)); | |
if ModuleHandle = 0 then | |
raise Exception.CreateFmt('Module not found: %s', [ModuleName]); | |
Result := GetProcAddress(ModuleHandle, PChar(FunctionName)); | |
if not Assigned(Result) then | |
raise Exception.CreateFmt('Function not found: %s in module %s', [FunctionName, ModuleName]); | |
end; | |
function TSysCallExecutor.GetSysCallNumber(const FunctionName: string): Cardinal; | |
var | |
NtFunction: Pointer; | |
begin | |
NtFunction := GetProcAddressEx('ntdll.dll', FunctionName); | |
if not Assigned(NtFunction) then | |
raise Exception.CreateFmt('Failed to locate function: %s', [FunctionName]); | |
Result := PCardinal(Cardinal(NtFunction) + 1)^; // Syscall number is located at +1 offset | |
end; | |
function TSysCallExecutor.ExecuteSysCall(SysCallNumber: Cardinal; Parameters: array of Pointer): Integer; | |
{$IFDEF WIN32} | |
asm | |
// Save state | |
pushad | |
pushfd | |
// Load syscall number | |
mov eax, SysCallNumber | |
// Load parameters into registers | |
mov ecx, Parameters | |
// Execute syscall | |
int $2E // System call interrupt for 32-bit systems | |
// Store result in EAX | |
mov @Result, eax | |
// Restore state | |
popfd | |
popad | |
end; | |
{$ELSEIF Defined(WIN64)} | |
asm | |
// x64 uses the syscall instruction | |
mov r10, rcx // First parameter in rcx | |
mov eax, SysCallNumber | |
syscall // Invoke syscall | |
mov @Result, eax // Return value in eax | |
end; | |
{$ELSEIF Defined(ARM)} | |
asm | |
// ARM architecture uses SVC (Supervisor Call) for syscalls | |
mov w8, SysCallNumber // Load syscall number into w8 (ARM convention) | |
svc #0 // Supervisor call | |
mov @Result, w0 // Store the result from x0 (ARM convention) | |
end; | |
{$ELSE} | |
{$ERROR Unsupported architecture} | |
{$ENDIF} | |
function TSysCallExecutor.ExecuteFunctionByName(const FunctionName: string; Parameters: array of Pointer): Integer; | |
var | |
SysCallNumber: Cardinal; | |
begin | |
SysCallNumber := GetSysCallNumber(FunctionName); | |
Result := ExecuteSysCall(SysCallNumber, Parameters); | |
end; | |
end. |
Author
erdesigns-eu
commented
Dec 19, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment