added Linux distinction and pragmas together with new platform functions

This commit is contained in:
maxraulea 2026-06-08 17:15:14 +02:00 committed by Sina Karvandi
parent 0e39c24f28
commit 9c3e0ed23b
12 changed files with 470 additions and 86 deletions

View file

@ -72,7 +72,8 @@ typedef wchar_t WCHAR;
typedef void VOID;
typedef size_t SIZE_T;
typedef size_t SIZE_T;
typedef SIZE_T * PSIZE_T;
typedef signed long long INT64, *PINT64;
typedef unsigned long long UINT64, *PUINT64;
@ -83,6 +84,13 @@ typedef unsigned long long DWORD64, *PDWORD64;
typedef unsigned long long ULONGLONG;
typedef unsigned long long ULONG_PTR, *PULONG_PTR;
typedef INT64 LONGLONG;
typedef union _LARGE_INTEGER {
struct { DWORD LowPart; LONG HighPart; };
LONGLONG QuadPart;
} LARGE_INTEGER, *PLARGE_INTEGER;
//
// To be fixed later, linux wchar_t is 4 bytes, but windows wchar_t is 2 bytes
//

View file

@ -11,7 +11,9 @@
*/
#pragma once
/*
#ifndef _WIN32
// On Windows these are provided by winnt.h; define them here for other platforms.
typedef struct _IMAGE_DOS_HEADER
{ // DOS .EXE header
WORD e_magic; // Magic number
@ -46,7 +48,7 @@ typedef struct _IMAGE_FILE_HEADER
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
#define IMAGE_SIZEOF_SHORT_NAME 8
# define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_SECTION_HEADER
{
@ -66,7 +68,7 @@ typedef struct _IMAGE_SECTION_HEADER
DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
*/
#endif // _WIN32
typedef struct _PE_IMAGE_READER
{

View file

@ -32,9 +32,45 @@
// Windows source annotation language (SAL) not present in Linux, so defining them here for the compiler
#ifdef HYPERDBG_ENV_LINUX
// SAL annotations
# define _In_
# define _Out_
# define _Inout_
#endif
# define _In_opt_
# define _Out_opt_
# define _In_z_
# define _Outptr_
# define _In_reads_bytes_(x)
# define _Out_writes_bytes_(x)
# define _Inout_updates_bytes_all_(x)
// wchar_t is a C++ built-in but needs this header in C
# include <wchar.h>
// Windows string/char types
typedef char TCHAR;
typedef char * LPTSTR;
typedef const char * LPCTSTR;
typedef const char * LPCSTR;
typedef char * LPSTR;
typedef const char * PCSTR;
typedef char * PSTR;
typedef wchar_t * PWCHAR;
// Windows socket type (Linux sockets are plain int)
typedef int SOCKET;
# define INVALID_SOCKET ((SOCKET)(-1))
# define SOCKET_ERROR (-1)
// Windows calling convention (no-op on Linux)
# define WINAPI
// Windows module handle (equivalent to dlopen's void * on Linux)
typedef void * HMODULE;
// Misc Windows macros
# define UNREFERENCED_PARAMETER(P) ((void)(P))
#endif // HYPERDBG_ENV_LINUX

View file

@ -83,10 +83,32 @@ CpuReadTsc(VOID)
// Misc Instructions //
//////////////////////////////////////////////////
/**
* @brief Read Time-Stamp Counter (serializing)
*
* @param Aux processor ID output (may be NULL)
* @return UINT64
*/
UINT64
CpuReadTscp(UINT32 * Aux)
{
#if defined(_WIN32) || defined(_WIN64)
return __rdtscp(Aux);
#elif defined(__linux__)
UINT32 __lo, __hi, __aux;
__asm__ __volatile__("rdtscp" : "=a"(__lo), "=d"(__hi), "=c"(__aux));
if (Aux)
*Aux = __aux;
return ((UINT64)__hi << 32) | __lo;
#else
# error "Unsupported platform"
#endif
}
/**
* @brief Execute PAUSE (spin-wait hint)
*/
VOID
VOID
CpuPause(VOID)
{
#if defined(_WIN32) || defined(_WIN64)
@ -97,3 +119,83 @@ CpuPause(VOID)
# error "Unsupported platform"
#endif
}
//////////////////////////////////////////////////
// Interlocked (Atomic) Operations //
//////////////////////////////////////////////////
INT64
CpuInterlockedExchange64(INT64 volatile * Target, INT64 Value)
{
#if defined(_WIN32) || defined(_WIN64)
return InterlockedExchange64(Target, Value);
#elif defined(__linux__)
return __atomic_exchange_n(Target, Value, __ATOMIC_SEQ_CST);
#else
# error "Unsupported platform"
#endif
}
INT64
CpuInterlockedExchangeAdd64(INT64 volatile * Addend, INT64 Value)
{
#if defined(_WIN32) || defined(_WIN64)
return InterlockedExchangeAdd64(Addend, Value);
#elif defined(__linux__)
return __atomic_fetch_add(Addend, Value, __ATOMIC_SEQ_CST);
#else
# error "Unsupported platform"
#endif
}
INT64
CpuInterlockedIncrement64(INT64 volatile * Addend)
{
#if defined(_WIN32) || defined(_WIN64)
return InterlockedIncrement64(Addend);
#elif defined(__linux__)
return __atomic_add_fetch(Addend, 1LL, __ATOMIC_SEQ_CST);
#else
# error "Unsupported platform"
#endif
}
INT64
CpuInterlockedDecrement64(INT64 volatile * Addend)
{
#if defined(_WIN32) || defined(_WIN64)
return InterlockedDecrement64(Addend);
#elif defined(__linux__)
return __atomic_sub_fetch(Addend, 1LL, __ATOMIC_SEQ_CST);
#else
# error "Unsupported platform"
#endif
}
INT64
CpuInterlockedCompareExchange64(INT64 volatile * Destination, INT64 ExChange, INT64 Comparand)
{
#if defined(_WIN32) || defined(_WIN64)
return InterlockedCompareExchange64(Destination, ExChange, Comparand);
#elif defined(__linux__)
INT64 Expected = Comparand;
__atomic_compare_exchange_n(Destination, &Expected, ExChange, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return Expected;
#else
# error "Unsupported platform"
#endif
}
UCHAR
CpuInterlockedBitTestAndSet(volatile LONG * Base, LONG Bit)
{
#if defined(_WIN32) || defined(_WIN64)
return _interlockedbittestandset(Base, Bit);
#elif defined(__linux__)
LONG Mask = (1L << Bit);
LONG Old = __atomic_fetch_or(Base, Mask, __ATOMIC_SEQ_CST);
return (UCHAR)((Old >> Bit) & 1);
#else
# error "Unsupported platform"
#endif
}

View file

@ -13,6 +13,9 @@
#if defined(__linux__)
# include "../header/platform-lib-calls.h"
# include <unistd.h>
# include <sched.h>
# include <sys/syscall.h>
#endif // defined(__linux__)
/**
@ -71,3 +74,169 @@ PlatformZeroMemory(PVOID Buffer, SIZE_T Size)
# error "Unsupported platform"
#endif
}
/**
* @brief Platform independent wrapper for QueryPerformanceFrequency
*
* @param Frequency output ticks per second
* @return BOOLEAN TRUE on success
*/
BOOLEAN
PlatformQueryPerformanceFrequency(LARGE_INTEGER * Frequency)
{
#if defined(_WIN32)
return (BOOLEAN)QueryPerformanceFrequency((LARGE_INTEGER *)Frequency);
#elif defined(__linux__)
Frequency->QuadPart = 1000000000LL; // clock_gettime gives nanosecond resolution
return TRUE;
#else
# error "Unsupported platform"
#endif
}
/**
* @brief Platform independent wrapper for QueryPerformanceCounter
*
* @param Count output current tick count
* @return BOOLEAN TRUE on success
*/
BOOLEAN
PlatformQueryPerformanceCounter(LARGE_INTEGER * Count)
{
#if defined(_WIN32)
return (BOOLEAN)QueryPerformanceCounter((LARGE_INTEGER *)Count);
#elif defined(__linux__)
struct timespec Ts;
clock_gettime(CLOCK_MONOTONIC, &Ts);
Count->QuadPart = (INT64)Ts.tv_sec * 1000000000LL + Ts.tv_nsec;
return TRUE;
#else
# error "Unsupported platform"
#endif
}
/**
* @brief Platform independent wrapper for sprintf_s / snprintf
*
* @param Buffer output buffer
* @param BufferSize size of the output buffer
* @param Format format string
* @return INT number of characters written, or -1 on error
*/
INT
PlatformSprintf(char * Buffer, SIZE_T BufferSize, const char * Format, ...)
{
va_list Args;
va_start(Args, Format);
INT Result;
#if defined(_WIN32)
Result = vsprintf_s(Buffer, BufferSize, Format, Args);
#elif defined(__linux__)
Result = vsnprintf(Buffer, BufferSize, Format, Args);
#else
# error "Unsupported platform"
#endif
va_end(Args);
return Result;
}
/**
* @brief Platform independent wrapper for GetCurrentThreadId / gettid
*
* @return UINT32 thread ID of the calling thread
*/
UINT32
PlatformGetCurrentThreadId(VOID)
{
#if defined(_WIN32)
return (UINT32)GetCurrentThreadId();
#elif defined(__linux__)
return (UINT32)syscall(SYS_gettid);
#else
# error "Unsupported platform"
#endif
}
/**
* @brief Platform independent wrapper for GetCurrentProcessorNumber / sched_getcpu
*
* @return UINT32 logical processor index the calling thread is running on
*/
UINT32
PlatformGetCurrentProcessorNumber(VOID)
{
#if defined(_WIN32)
return (UINT32)GetCurrentProcessorNumber();
#elif defined(__linux__)
return (UINT32)sched_getcpu();
#else
# error "Unsupported platform"
#endif
}
/**
* @brief Platform independent wrapper for GetCurrentProcessId / getpid
*
* @return UINT32 PID of the calling process
*/
UINT32
PlatformGetCurrentProcessId(VOID)
{
#if defined(_WIN32)
return (UINT32)GetCurrentProcessId();
#elif defined(__linux__)
return (UINT32)getpid();
#else
# error "Unsupported platform"
#endif
}
/**
* @brief Platform independent wrapper to get the current process name
*
* @return CHAR* pointer to a static buffer holding the process name, or NULL on failure
*/
CHAR *
PlatformGetCurrentProcessName(VOID)
{
static CHAR ProcessNameBuf[MAX_PATH] = {0};
#if defined(_WIN32)
HANDLE Handle = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
GetCurrentProcessId());
if (Handle)
{
CHAR ModulePath[MAX_PATH] = {0};
if (GetModuleFileNameEx(Handle, 0, ModulePath, MAX_PATH))
{
CloseHandle(Handle);
strncpy(ProcessNameBuf, PathFindFileNameA(ModulePath), MAX_PATH - 1);
ProcessNameBuf[MAX_PATH - 1] = '\0';
return ProcessNameBuf;
}
CloseHandle(Handle);
}
return NULL;
#elif defined(__linux__)
FILE * f = fopen("/proc/self/comm", "r");
if (f)
{
if (fgets(ProcessNameBuf, sizeof(ProcessNameBuf), f))
{
size_t Len = strlen(ProcessNameBuf);
if (Len > 0 && ProcessNameBuf[Len - 1] == '\n')
ProcessNameBuf[Len - 1] = '\0';
}
fclose(f);
return ProcessNameBuf;
}
return NULL;
#else
# error "Unsupported platform"
#endif
}

View file

@ -41,6 +41,12 @@ CpuCpuIdEx(INT32 * CpuInfo, INT32 FunctionId, INT32 SubFunctionId);
UINT64
CpuReadTsc(VOID);
//
// RDTSCP
//
UINT64
CpuReadTscp(UINT32 * Aux);
//////////////////////////////////////////////////
// Misc Instructions //
//////////////////////////////////////////////////
@ -49,4 +55,26 @@ CpuReadTsc(VOID);
// PAUSE
//
VOID
CpuPause(VOID);
CpuPause(VOID);
//////////////////////////////////////////////////
// Interlocked (Atomic) Operations //
//////////////////////////////////////////////////
INT64
CpuInterlockedExchange64(INT64 volatile * Target, INT64 Value);
INT64
CpuInterlockedExchangeAdd64(INT64 volatile * Addend, INT64 Value);
INT64
CpuInterlockedIncrement64(INT64 volatile * Addend);
INT64
CpuInterlockedDecrement64(INT64 volatile * Addend);
INT64
CpuInterlockedCompareExchange64(INT64 volatile * Destination, INT64 ExChange, INT64 Comparand);
UCHAR
CpuInterlockedBitTestAndSet(volatile LONG * Base, LONG Bit);

View file

@ -35,3 +35,33 @@ PlatformStrDup(const char * Str);
//
VOID
PlatformZeroMemory(PVOID Buffer, SIZE_T Size);
//
// SPRINTF
//
INT
PlatformSprintf(char * Buffer, SIZE_T BufferSize, const char * Format, ...);
//
// HIGH-RESOLUTION PERFORMANCE COUNTER
//
BOOLEAN
PlatformQueryPerformanceFrequency(LARGE_INTEGER * Frequency);
BOOLEAN
PlatformQueryPerformanceCounter(LARGE_INTEGER * Count);
//
// PROCESS / THREAD IDENTITY
//
UINT32
PlatformGetCurrentThreadId(VOID);
UINT32
PlatformGetCurrentProcessorNumber(VOID);
UINT32
PlatformGetCurrentProcessId(VOID);
CHAR *
PlatformGetCurrentProcessName(VOID);

View file

@ -103,7 +103,7 @@ ShowMessages(const CHAR * Fmt, ...)
va_start(ArgList, Fmt);
INT SprintfResult = vsprintf_s(TempMessage, Fmt, ArgList);
INT SprintfResult = PlatformVsnprintf(TempMessage, sizeof(TempMessage), Fmt, ArgList);
va_end(ArgList);

View file

@ -40,7 +40,7 @@ static UINT32 MaxWait = 65536;
BOOLEAN
SpinlockTryLock(volatile LONG * Lock)
{
return (!(*Lock) && !_interlockedbittestandset(Lock, 0));
return (!(*Lock) && !CpuInterlockedBitTestAndSet(Lock, 0));
}
/**

View file

@ -41,6 +41,8 @@ typedef RFLAGS * PRFLAGS;
#define USE_NATIVE_SDK_HEADERS
#define _AMD64_
#ifdef _WIN32
#if defined(USE__NATIVE_PHNT_HEADERS)
//
@ -64,18 +66,22 @@ typedef const wchar_t *LPCWCHAR, *PCWCHAR;
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <strsafe.h>
#include <shlobj.h>
#include <tchar.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <VersionHelpers.h>
#include <psapi.h>
#endif //_WIN32
#ifdef _WIN32
# include <winsock2.h>
# include <ws2tcpip.h>
# include <strsafe.h>
# include <shlobj.h>
# include <tchar.h>
# include <tlhelp32.h>
# include <shlwapi.h>
# include <VersionHelpers.h>
# include <psapi.h>
# include <conio.h>
# include <intrin.h>
#endif
#include <time.h>
#include <conio.h>
#include <intrin.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
@ -117,11 +123,6 @@ typedef const wchar_t *LPCWCHAR, *PCWCHAR;
# define NDEBUG
#endif // !NDEBUG
//
// Keystone
//
#include "keystone/keystone.h"
//
// HyperDbg defined headers
//
@ -129,6 +130,11 @@ typedef const wchar_t *LPCWCHAR, *PCWCHAR;
#include "config/Definition.h"
#include "SDK/HyperDbgSdk.h"
//
// Keystone
//
#include "keystone/keystone.h"
//
// Script-engine
//
@ -141,10 +147,21 @@ typedef const wchar_t *LPCWCHAR, *PCWCHAR;
#include "SDK/imports/user/HyperDbgLibImports.h"
//
// Platform-specific intrinsics
// Platform lib calls (cross-platform wrappers)
//
#include "platform/user/header/platform-lib-calls.h"
//
// Platform intrinsics (cross-platform CPU instructions and atomic ops)
//
#include "platform/user/header/platform-intrinsics.h"
#include "platform/user/header/windows-only/windows-privilege.h"
//
// Platform-specific intrinsics
//
#ifdef _WIN32
# include "platform/user/header/windows-only/windows-privilege.h"
#endif
//
// PCI IDs
@ -159,11 +176,15 @@ typedef const wchar_t *LPCWCHAR, *PCWCHAR;
#include "header/inipp.h"
#include "header/commands.h"
#include "header/common.h"
#include "header/symbol.h"
#ifdef _WIN32
# include "header/symbol.h"
#endif
#include "header/debugger.h"
#include "header/script-engine.h"
#include "header/help.h"
#include "header/install.h"
#ifdef _WIN32
# include "header/install.h"
#endif
#include "header/list.h"
#include "header/tests.h"
#include "header/messaging.h"
@ -172,7 +193,15 @@ typedef const wchar_t *LPCWCHAR, *PCWCHAR;
#include "header/communication.h"
#include "header/namedpipe.h"
#include "header/forwarding.h"
#include "header/kd.h"
#ifdef _WIN32
# include "header/kd.h"
#endif
//
// Components
//
#include "../include/components/pe/header/pe-image-reader.h"
#include "header/pe-parser.h"
#include "header/ud.h"
#include "header/objects.h"
@ -180,11 +209,6 @@ typedef const wchar_t *LPCWCHAR, *PCWCHAR;
#include "header/rev-ctrl.h"
#include "header/assembler.h"
//
// Components
//
#include "../include/components/pe/header/pe-image-reader.h"
//
// hwdbg
//

View file

@ -797,16 +797,16 @@ VOID
UserModeMicroSleep(UINT64 Us)
{
LARGE_INTEGER Start, End, Frequency;
QueryPerformanceFrequency(&Frequency);
PlatformQueryPerformanceFrequency(&Frequency);
LONGLONG TickPerUs = Frequency.QuadPart / 1000000;
LONGLONG Ticks = TickPerUs * Us;
QueryPerformanceCounter(&Start);
PlatformQueryPerformanceCounter(&Start);
while (TRUE)
{
QueryPerformanceCounter(&End);
PlatformQueryPerformanceCounter(&End);
if (End.QuadPart - Start.QuadPart > Ticks)
{
@ -840,7 +840,7 @@ ScriptEngineFunctionMicroSleep(UINT64 Us)
UINT64
ScriptEngineFunctionRdtsc()
{
return __rdtsc();
return CpuReadTsc();
}
/**
@ -850,8 +850,8 @@ ScriptEngineFunctionRdtsc()
UINT64
ScriptEngineFunctionRdtscp()
{
unsigned int Aux;
return __rdtscp(&Aux);
UINT32 Aux;
return CpuReadTscp(&Aux);
}
/**
@ -879,7 +879,7 @@ ScriptEngineFunctionInterlockedExchange(long long volatile * Target,
#endif // SCRIPT_ENGINE_KERNEL_MODE
Result = InterlockedExchange64(Target, Value);
Result = CpuInterlockedExchange64(Target, Value);
return Result;
}
@ -909,7 +909,7 @@ ScriptEngineFunctionInterlockedExchangeAdd(long long volatile * Addend,
#endif // SCRIPT_ENGINE_KERNEL_MODE
Result = InterlockedExchangeAdd64(Addend, Value);
Result = CpuInterlockedExchangeAdd64(Addend, Value);
return Result;
}
@ -937,7 +937,7 @@ ScriptEngineFunctionInterlockedIncrement(long long volatile * Addend,
#endif // SCRIPT_ENGINE_KERNEL_MODE
Result = InterlockedIncrement64(Addend);
Result = CpuInterlockedIncrement64(Addend);
return Result;
}
@ -965,7 +965,7 @@ ScriptEngineFunctionInterlockedDecrement(long long volatile * Addend,
#endif // SCRIPT_ENGINE_KERNEL_MODE
Result = InterlockedDecrement64(Addend);
Result = CpuInterlockedDecrement64(Addend);
return Result;
}
@ -998,7 +998,7 @@ ScriptEngineFunctionInterlockedCompareExchange(
#endif // SCRIPT_ENGINE_KERNEL_MODE
Result = InterlockedCompareExchange64(Destination, ExChange, Comperand);
Result = CpuInterlockedCompareExchange64(Destination, ExChange, Comperand);
return Result;
}
@ -1338,7 +1338,7 @@ ApplyFormatSpecifier(const CHAR * CurrentSpecifier, CHAR * FinalBuffer, PUINT32
*CurrentProcessedPositionFromStartOfFormat =
*CurrentProcessedPositionFromStartOfFormat + (UINT32)strlen(CurrentSpecifier);
sprintf_s(TempBuffer, sizeof(TempBuffer), CurrentSpecifier, Val);
PlatformSprintf(TempBuffer, sizeof(TempBuffer), CurrentSpecifier, Val);
TempBufferLen = (UINT32)strlen(TempBuffer);
//
@ -1473,8 +1473,8 @@ ApplyStringFormatSpecifier(const CHAR * CurrentSpecifier, CHAR * FinalBuffer, PU
//
// Zero the buffers
//
RtlZeroMemory(WstrBuffer, sizeof(WstrBuffer));
RtlZeroMemory(AsciiBuffer, sizeof(AsciiBuffer));
PlatformZeroMemory(WstrBuffer, sizeof(WstrBuffer));
PlatformZeroMemory(AsciiBuffer, sizeof(AsciiBuffer));
//
// Check for the last block

View file

@ -25,7 +25,7 @@ UINT64
ScriptEnginePseudoRegGetTid()
{
#ifdef SCRIPT_ENGINE_USER_MODE
return (UINT64)GetCurrentThreadId();
return (UINT64)PlatformGetCurrentThreadId();
#endif // SCRIPT_ENGINE_USER_MODE
#ifdef SCRIPT_ENGINE_KERNEL_MODE
@ -42,7 +42,7 @@ UINT64
ScriptEnginePseudoRegGetCore()
{
#ifdef SCRIPT_ENGINE_USER_MODE
return (UINT64)GetCurrentProcessorNumber();
return (UINT64)PlatformGetCurrentProcessorNumber();
#endif // SCRIPT_ENGINE_USER_MODE
#ifdef SCRIPT_ENGINE_KERNEL_MODE
@ -59,7 +59,7 @@ UINT64
ScriptEnginePseudoRegGetPid()
{
#ifdef SCRIPT_ENGINE_USER_MODE
return (UINT64)GetCurrentProcessId();
return (UINT64)PlatformGetCurrentProcessId();
#endif // SCRIPT_ENGINE_USER_MODE
#ifdef SCRIPT_ENGINE_KERNEL_MODE
@ -76,39 +76,7 @@ CHAR *
ScriptEnginePseudoRegGetPname()
{
#ifdef SCRIPT_ENGINE_USER_MODE
HANDLE Handle = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
GetCurrentProcessId() /* Current process */
);
if (Handle)
{
CHAR CurrentModulePath[MAX_PATH] = {0};
if (GetModuleFileNameEx(Handle, 0, CurrentModulePath, MAX_PATH))
{
//
// At this point, buffer contains the full path to the executable
//
CloseHandle(Handle);
return PathFindFileNameA(CurrentModulePath);
}
else
{
//
// error might be shown by GetLastError()
//
CloseHandle(Handle);
return NULL;
}
}
//
// unable to get handle
//
return NULL;
return PlatformGetCurrentProcessName();
#endif // SCRIPT_ENGINE_USER_MODE
#ifdef SCRIPT_ENGINE_KERNEL_MODE
@ -159,6 +127,7 @@ UINT64
ScriptEnginePseudoRegGetPeb()
{
#ifdef SCRIPT_ENGINE_USER_MODE
# ifdef _WIN32
//
// Hand-rolled structs ( may cause conflict depending on your dev env )
//
@ -269,6 +238,22 @@ ScriptEnginePseudoRegGetPeb()
return (UINT64)PebPtr;
# else // !_WIN32
//
// The PEB (Process Environment Block) is a Windows NT-specific structure
// maintained by the kernel for every user-mode process. It holds loader
// data, heap pointers, the image path, and other process-wide state that
// has no direct equivalent in the Linux process model.
//
// TODO: investigate whether a meaningful substitute exists on Linux
// (e.g. /proc/self/maps, dl_iterate_phdr, or a custom auxv walk)
// and implement it here if HyperDbg user-mode on Linux ever needs $peb.
//
return 0;
# endif // _WIN32
#endif // SCRIPT_ENGINE_USER_MODE
#ifdef SCRIPT_ENGINE_KERNEL_MODE