mirror of
https://github.com/bats3c/DarkLoadLibrary
synced 2026-06-06 15:14:33 +00:00
Merge pull request #6 from physics-sp/add-syscalls
add NtAllocateVirtualMemory and NtProtectVirtualMemory syscalls
This commit is contained in:
@@ -56,6 +56,7 @@
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
@@ -152,14 +153,20 @@
|
||||
<ClCompile Include="src\ldrutils.c" />
|
||||
<ClCompile Include="src\main.c" />
|
||||
<ClCompile Include="src\pebutils.c" />
|
||||
<ClCompile Include="src\syscalls.c" />
|
||||
<MASM Include="src\syscallsstubs.asm">
|
||||
<FileType>Document</FileType>
|
||||
</MASM>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\darkloadlibrary.h" />
|
||||
<ClInclude Include="include\ldrutils.h" />
|
||||
<ClInclude Include="include\pebstructs.h" />
|
||||
<ClInclude Include="include\pebutils.h" />
|
||||
<ClInclude Include="include\syscalls.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -27,6 +27,9 @@
|
||||
<ClCompile Include="src\main.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\syscalls.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\darkloadlibrary.h">
|
||||
@@ -41,5 +44,13 @@
|
||||
<ClInclude Include="include\pebutils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\syscalls.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="src\syscallsstubs.asm">
|
||||
<Filter>Source Files</Filter>
|
||||
</MASM>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
// Code below is adapted from @modexpblog. Read linked article for more details.
|
||||
// https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams
|
||||
|
||||
#ifndef SW2_HEADER_H_
|
||||
#define SW2_HEADER_H_
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#define SW2_SEED 0x63191199
|
||||
#define SW2_ROL8(v) (v << 8 | v >> 24)
|
||||
#define SW2_ROR8(v) (v >> 8 | v << 24)
|
||||
#define SW2_ROX8(v) ((SW2_SEED % 2) ? SW2_ROL8(v) : SW2_ROR8(v))
|
||||
#define SW2_MAX_ENTRIES 500
|
||||
#define SW2_RVA2VA(Type, DllBase, Rva) (Type)((ULONG_PTR) DllBase + Rva)
|
||||
|
||||
// Typedefs are prefixed to avoid pollution.
|
||||
|
||||
typedef struct _SW2_SYSCALL_ENTRY
|
||||
{
|
||||
DWORD Hash;
|
||||
DWORD Address;
|
||||
} SW2_SYSCALL_ENTRY, *PSW2_SYSCALL_ENTRY;
|
||||
|
||||
typedef struct _SW2_SYSCALL_LIST
|
||||
{
|
||||
DWORD Count;
|
||||
SW2_SYSCALL_ENTRY Entries[SW2_MAX_ENTRIES];
|
||||
} SW2_SYSCALL_LIST, *PSW2_SYSCALL_LIST;
|
||||
|
||||
typedef struct _SW2_PEB_LDR_DATA {
|
||||
BYTE Reserved1[8];
|
||||
PVOID Reserved2[3];
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
} SW2_PEB_LDR_DATA, *PSW2_PEB_LDR_DATA;
|
||||
|
||||
typedef struct _SW2_LDR_DATA_TABLE_ENTRY {
|
||||
PVOID Reserved1[2];
|
||||
LIST_ENTRY InMemoryOrderLinks;
|
||||
PVOID Reserved2[2];
|
||||
PVOID DllBase;
|
||||
} SW2_LDR_DATA_TABLE_ENTRY, *PSW2_LDR_DATA_TABLE_ENTRY;
|
||||
|
||||
typedef struct _SW2_PEB {
|
||||
BYTE Reserved1[2];
|
||||
BYTE BeingDebugged;
|
||||
BYTE Reserved2[1];
|
||||
PVOID Reserved3[2];
|
||||
PSW2_PEB_LDR_DATA Ldr;
|
||||
} SW2_PEB, *PSW2_PEB;
|
||||
|
||||
DWORD SW2_HashSyscall(PCSTR FunctionName);
|
||||
BOOL SW2_PopulateSyscallList();
|
||||
EXTERN_C DWORD SW2_GetSyscallNumber(DWORD FunctionHash);
|
||||
|
||||
EXTERN_C NTSTATUS NtProtectVirtualMemory(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN OUT PVOID * BaseAddress,
|
||||
IN OUT PSIZE_T RegionSize,
|
||||
IN ULONG NewProtect,
|
||||
OUT PULONG OldProtect);
|
||||
|
||||
EXTERN_C NTSTATUS NtAllocateVirtualMemory(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN OUT PVOID * BaseAddress,
|
||||
IN ULONG ZeroBits,
|
||||
IN OUT PSIZE_T RegionSize,
|
||||
IN ULONG AllocationType,
|
||||
IN ULONG Protect);
|
||||
|
||||
#endif
|
||||
+101
-54
@@ -1,4 +1,7 @@
|
||||
#include "ldrutils.h"
|
||||
#if _M_X64
|
||||
#include "syscalls.h"
|
||||
#endif
|
||||
|
||||
BOOL IsValidPE(
|
||||
PBYTE pbData
|
||||
@@ -7,8 +10,8 @@ BOOL IsValidPE(
|
||||
PIMAGE_NT_HEADERS pNtHeaders;
|
||||
|
||||
pNtHeaders = RVA(
|
||||
PIMAGE_NT_HEADERS,
|
||||
pbData,
|
||||
PIMAGE_NT_HEADERS,
|
||||
pbData,
|
||||
((PIMAGE_DOS_HEADER)pbData)->e_lfanew
|
||||
);
|
||||
|
||||
@@ -30,12 +33,41 @@ BOOL MapSections(
|
||||
PIMAGE_SECTION_HEADER pSectionHeader;
|
||||
|
||||
pNtHeaders = RVA(
|
||||
PIMAGE_NT_HEADERS,
|
||||
pdModule->pbDllData,
|
||||
PIMAGE_NT_HEADERS,
|
||||
pdModule->pbDllData,
|
||||
((PIMAGE_DOS_HEADER)pdModule->pbDllData)->e_lfanew
|
||||
);
|
||||
|
||||
// try get prefered address
|
||||
#if _M_X64
|
||||
pdModule->ModuleBase = pNtHeaders->OptionalHeader.ImageBase;
|
||||
SIZE_T RegionSize = pNtHeaders->OptionalHeader.SizeOfImage;
|
||||
NTSTATUS status = NtAllocateVirtualMemory(
|
||||
(HANDLE)-1,
|
||||
&pdModule->ModuleBase,
|
||||
0,
|
||||
&RegionSize,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_READWRITE
|
||||
);
|
||||
if (!NT_SUCCESS(status) || pdModule->ModuleBase != pNtHeaders->OptionalHeader.ImageBase)
|
||||
{
|
||||
pdModule->ModuleBase = NULL;
|
||||
RegionSize = pNtHeaders->OptionalHeader.SizeOfImage;
|
||||
status = NtAllocateVirtualMemory(
|
||||
(HANDLE)-1,
|
||||
&pdModule->ModuleBase,
|
||||
0,
|
||||
&RegionSize,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_READWRITE
|
||||
);
|
||||
}
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
pdModule->ModuleBase = (ULONG_PTR)VirtualAlloc(
|
||||
(LPVOID)(pNtHeaders->OptionalHeader.ImageBase),
|
||||
(SIZE_T)pNtHeaders->OptionalHeader.SizeOfImage,
|
||||
@@ -57,7 +89,7 @@ BOOL MapSections(
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
// copy across the headers
|
||||
for (INT i = 0; i < pNtHeaders->OptionalHeader.SizeOfHeaders; i++)
|
||||
{
|
||||
@@ -82,8 +114,8 @@ BOOL MapSections(
|
||||
if ((pdModule->ModuleBase - pNtHeaders->OptionalHeader.ImageBase) && pDataDir)
|
||||
{
|
||||
pRelocation = RVA(
|
||||
PIMAGE_BASE_RELOCATION,
|
||||
pdModule->ModuleBase,
|
||||
PIMAGE_BASE_RELOCATION,
|
||||
pdModule->ModuleBase,
|
||||
pDataDir->VirtualAddress
|
||||
);
|
||||
|
||||
@@ -137,8 +169,8 @@ BOOL ResolveImports(
|
||||
LDRGETPROCADDRESS pLdrGetProcAddress = NULL;
|
||||
|
||||
pNtHeaders = RVA(
|
||||
PIMAGE_NT_HEADERS,
|
||||
pdModule->pbDllData,
|
||||
PIMAGE_NT_HEADERS,
|
||||
pdModule->pbDllData,
|
||||
((PIMAGE_DOS_HEADER)pdModule->pbDllData)->e_lfanew
|
||||
);
|
||||
|
||||
@@ -158,8 +190,8 @@ BOOL ResolveImports(
|
||||
if (pDataDir->Size)
|
||||
{
|
||||
pImportDesc = RVA(
|
||||
PIMAGE_IMPORT_DESCRIPTOR,
|
||||
pdModule->ModuleBase,
|
||||
PIMAGE_IMPORT_DESCRIPTOR,
|
||||
pdModule->ModuleBase,
|
||||
pDataDir->VirtualAddress
|
||||
);
|
||||
|
||||
@@ -172,7 +204,7 @@ BOOL ResolveImports(
|
||||
|
||||
pImportDesc = RVA(
|
||||
PIMAGE_IMPORT_DESCRIPTOR,
|
||||
pdModule->ModuleBase,
|
||||
pdModule->ModuleBase,
|
||||
pDataDir->VirtualAddress
|
||||
);
|
||||
|
||||
@@ -185,14 +217,14 @@ BOOL ResolveImports(
|
||||
);
|
||||
|
||||
pFirstThunk = RVA(
|
||||
PIMAGE_THUNK_DATA,
|
||||
pdModule->ModuleBase,
|
||||
PIMAGE_THUNK_DATA,
|
||||
pdModule->ModuleBase,
|
||||
pImportDesc->FirstThunk
|
||||
);
|
||||
|
||||
|
||||
pOrigFirstThunk = RVA(
|
||||
PIMAGE_THUNK_DATA,
|
||||
pdModule->ModuleBase,
|
||||
PIMAGE_THUNK_DATA,
|
||||
pdModule->ModuleBase,
|
||||
pImportDesc->OriginalFirstThunk
|
||||
);
|
||||
|
||||
@@ -201,30 +233,30 @@ BOOL ResolveImports(
|
||||
if (IMAGE_SNAP_BY_ORDINAL(pOrigFirstThunk->u1.Ordinal))
|
||||
{
|
||||
pLdrGetProcAddress(
|
||||
hLibrary,
|
||||
NULL,
|
||||
(WORD)pOrigFirstThunk->u1.Ordinal,
|
||||
(PVOID *)&(pFirstThunk->u1.Function)
|
||||
hLibrary,
|
||||
NULL,
|
||||
(WORD)pOrigFirstThunk->u1.Ordinal,
|
||||
(PVOID*)&(pFirstThunk->u1.Function)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
pImportByName = RVA(
|
||||
PIMAGE_IMPORT_BY_NAME,
|
||||
pdModule->ModuleBase,
|
||||
PIMAGE_IMPORT_BY_NAME,
|
||||
pdModule->ModuleBase,
|
||||
pOrigFirstThunk->u1.AddressOfData
|
||||
);
|
||||
|
||||
|
||||
FILL_STRING(
|
||||
aString,
|
||||
aString,
|
||||
pImportByName->Name
|
||||
);
|
||||
|
||||
pLdrGetProcAddress(
|
||||
hLibrary,
|
||||
&aString,
|
||||
0,
|
||||
(PVOID *)&(pFirstThunk->u1.Function)
|
||||
hLibrary,
|
||||
&aString,
|
||||
0,
|
||||
(PVOID*)&(pFirstThunk->u1.Function)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -237,8 +269,8 @@ BOOL ResolveImports(
|
||||
if (pDataDir->Size)
|
||||
{
|
||||
pDelayDesc = RVA(
|
||||
PIMAGE_DELAYLOAD_DESCRIPTOR,
|
||||
pdModule->ModuleBase,
|
||||
PIMAGE_DELAYLOAD_DESCRIPTOR,
|
||||
pdModule->ModuleBase,
|
||||
pDataDir->VirtualAddress
|
||||
);
|
||||
|
||||
@@ -249,14 +281,14 @@ BOOL ResolveImports(
|
||||
HMODULE hLibrary = LoadLibraryA((LPSTR)(pdModule->ModuleBase + pDelayDesc->DllNameRVA));
|
||||
|
||||
pFirstThunk = RVA(
|
||||
PIMAGE_THUNK_DATA,
|
||||
pdModule->ModuleBase,
|
||||
PIMAGE_THUNK_DATA,
|
||||
pdModule->ModuleBase,
|
||||
pDelayDesc->ImportAddressTableRVA
|
||||
);
|
||||
|
||||
|
||||
pOrigFirstThunk = RVA(
|
||||
PIMAGE_THUNK_DATA,
|
||||
pdModule->ModuleBase,
|
||||
PIMAGE_THUNK_DATA,
|
||||
pdModule->ModuleBase,
|
||||
pDelayDesc->ImportNameTableRVA
|
||||
);
|
||||
|
||||
@@ -265,30 +297,30 @@ BOOL ResolveImports(
|
||||
if (IMAGE_SNAP_BY_ORDINAL(pOrigFirstThunk->u1.Ordinal))
|
||||
{
|
||||
pLdrGetProcAddress(
|
||||
hLibrary,
|
||||
NULL,
|
||||
(WORD)pOrigFirstThunk->u1.Ordinal,
|
||||
(PVOID *)&(pFirstThunk->u1.Function)
|
||||
hLibrary,
|
||||
NULL,
|
||||
(WORD)pOrigFirstThunk->u1.Ordinal,
|
||||
(PVOID*)&(pFirstThunk->u1.Function)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
pImportByName = RVA(
|
||||
PIMAGE_IMPORT_BY_NAME,
|
||||
pdModule->ModuleBase,
|
||||
PIMAGE_IMPORT_BY_NAME,
|
||||
pdModule->ModuleBase,
|
||||
pOrigFirstThunk->u1.AddressOfData
|
||||
);
|
||||
|
||||
|
||||
FILL_STRING(
|
||||
aString,
|
||||
aString,
|
||||
pImportByName->Name
|
||||
);
|
||||
|
||||
pLdrGetProcAddress(
|
||||
hLibrary,
|
||||
&aString,
|
||||
0,
|
||||
(PVOID *)&(pFirstThunk->u1.Function)
|
||||
hLibrary,
|
||||
&aString,
|
||||
0,
|
||||
(PVOID*)&(pFirstThunk->u1.Function)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -313,8 +345,8 @@ BOOL BeginExecution(
|
||||
DLLMAIN DllMain = NULL;
|
||||
|
||||
pNtHeaders = RVA(
|
||||
PIMAGE_NT_HEADERS,
|
||||
pdModule->pbDllData,
|
||||
PIMAGE_NT_HEADERS,
|
||||
pdModule->pbDllData,
|
||||
((PIMAGE_DOS_HEADER)pdModule->pbDllData)->e_lfanew
|
||||
);
|
||||
|
||||
@@ -342,13 +374,28 @@ BOOL BeginExecution(
|
||||
{
|
||||
dwProtect |= PAGE_NOCACHE;
|
||||
}
|
||||
|
||||
#if _M_X64
|
||||
PVOID BaseAddress = pdModule->ModuleBase + pSectionHeader->VirtualAddress;
|
||||
SIZE_T RegionSize = pSectionHeader->SizeOfRawData;
|
||||
NTSTATUS status = NtProtectVirtualMemory(
|
||||
(HANDLE)-1,
|
||||
&BaseAddress,
|
||||
&RegionSize,
|
||||
dwProtect,
|
||||
&dwProtect
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
VirtualProtect(
|
||||
(LPVOID)(pdModule->ModuleBase + pSectionHeader->VirtualAddress),
|
||||
pSectionHeader->SizeOfRawData,
|
||||
dwProtect,
|
||||
&dwProtect
|
||||
);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,12 +408,12 @@ BOOL BeginExecution(
|
||||
if (pDataDir->Size)
|
||||
{
|
||||
pTlsDir = RVA(
|
||||
PIMAGE_TLS_DIRECTORY,
|
||||
pdModule->ModuleBase,
|
||||
PIMAGE_TLS_DIRECTORY,
|
||||
pdModule->ModuleBase,
|
||||
pDataDir->VirtualAddress
|
||||
);
|
||||
|
||||
ppCallback = (PIMAGE_TLS_CALLBACK *)(pTlsDir->AddressOfCallBacks);
|
||||
ppCallback = (PIMAGE_TLS_CALLBACK*)(pTlsDir->AddressOfCallBacks);
|
||||
|
||||
for (; *ppCallback; ppCallback++)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "syscalls.h"
|
||||
|
||||
// Code below is adapted from @modexpblog. Read linked article for more details.
|
||||
// https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams
|
||||
|
||||
SW2_SYSCALL_LIST SW2_SyscallList;
|
||||
|
||||
DWORD SW2_HashSyscall(PCSTR FunctionName)
|
||||
{
|
||||
DWORD i = 0;
|
||||
DWORD Hash = SW2_SEED;
|
||||
|
||||
while (FunctionName[i])
|
||||
{
|
||||
WORD PartialName = *(WORD*)((ULONG64)FunctionName + i++);
|
||||
Hash ^= PartialName + SW2_ROR8(Hash);
|
||||
}
|
||||
|
||||
return Hash;
|
||||
}
|
||||
|
||||
BOOL SW2_PopulateSyscallList()
|
||||
{
|
||||
// Return early if the list is already populated.
|
||||
if (SW2_SyscallList.Count) return TRUE;
|
||||
|
||||
PSW2_PEB Peb = (PSW2_PEB)__readgsqword(0x60);
|
||||
PSW2_PEB_LDR_DATA Ldr = Peb->Ldr;
|
||||
PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
|
||||
PVOID DllBase = NULL;
|
||||
|
||||
// Get the DllBase address of NTDLL.dll. NTDLL is not guaranteed to be the second
|
||||
// in the list, so it's safer to loop through the full list and find it.
|
||||
PSW2_LDR_DATA_TABLE_ENTRY LdrEntry;
|
||||
for (LdrEntry = (PSW2_LDR_DATA_TABLE_ENTRY)Ldr->Reserved2[1]; LdrEntry->DllBase != NULL; LdrEntry = (PSW2_LDR_DATA_TABLE_ENTRY)LdrEntry->Reserved1[0])
|
||||
{
|
||||
DllBase = LdrEntry->DllBase;
|
||||
PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)DllBase;
|
||||
PIMAGE_NT_HEADERS NtHeaders = SW2_RVA2VA(PIMAGE_NT_HEADERS, DllBase, DosHeader->e_lfanew);
|
||||
PIMAGE_DATA_DIRECTORY DataDirectory = (PIMAGE_DATA_DIRECTORY)NtHeaders->OptionalHeader.DataDirectory;
|
||||
DWORD VirtualAddress = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
if (VirtualAddress == 0) continue;
|
||||
|
||||
ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)SW2_RVA2VA(ULONG_PTR, DllBase, VirtualAddress);
|
||||
|
||||
// If this is NTDLL.dll, exit loop.
|
||||
PCHAR DllName = SW2_RVA2VA(PCHAR, DllBase, ExportDirectory->Name);
|
||||
|
||||
if ((*(ULONG*)DllName | 0x20202020) != 'ldtn') continue;
|
||||
if ((*(ULONG*)(DllName + 4) | 0x20202020) == 'ld.l') break;
|
||||
}
|
||||
|
||||
if (!ExportDirectory) return FALSE;
|
||||
|
||||
DWORD NumberOfNames = ExportDirectory->NumberOfNames;
|
||||
PDWORD Functions = SW2_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfFunctions);
|
||||
PDWORD Names = SW2_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfNames);
|
||||
PWORD Ordinals = SW2_RVA2VA(PWORD, DllBase, ExportDirectory->AddressOfNameOrdinals);
|
||||
|
||||
// Populate SW2_SyscallList with unsorted Zw* entries.
|
||||
DWORD i = 0;
|
||||
PSW2_SYSCALL_ENTRY Entries = SW2_SyscallList.Entries;
|
||||
do
|
||||
{
|
||||
PCHAR FunctionName = SW2_RVA2VA(PCHAR, DllBase, Names[NumberOfNames - 1]);
|
||||
|
||||
// Is this a system call?
|
||||
if (*(USHORT*)FunctionName == 'wZ')
|
||||
{
|
||||
Entries[i].Hash = SW2_HashSyscall(FunctionName);
|
||||
Entries[i].Address = Functions[Ordinals[NumberOfNames - 1]];
|
||||
|
||||
i++;
|
||||
if (i == SW2_MAX_ENTRIES) break;
|
||||
}
|
||||
} while (--NumberOfNames);
|
||||
|
||||
// Save total number of system calls found.
|
||||
SW2_SyscallList.Count = i;
|
||||
|
||||
// Sort the list by address in ascending order.
|
||||
for (DWORD i = 0; i < SW2_SyscallList.Count - 1; i++)
|
||||
{
|
||||
for (DWORD j = 0; j < SW2_SyscallList.Count - i - 1; j++)
|
||||
{
|
||||
if (Entries[j].Address > Entries[j + 1].Address)
|
||||
{
|
||||
// Swap entries.
|
||||
SW2_SYSCALL_ENTRY TempEntry;
|
||||
|
||||
TempEntry.Hash = Entries[j].Hash;
|
||||
TempEntry.Address = Entries[j].Address;
|
||||
|
||||
Entries[j].Hash = Entries[j + 1].Hash;
|
||||
Entries[j].Address = Entries[j + 1].Address;
|
||||
|
||||
Entries[j + 1].Hash = TempEntry.Hash;
|
||||
Entries[j + 1].Address = TempEntry.Address;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EXTERN_C DWORD SW2_GetSyscallNumber(DWORD FunctionHash)
|
||||
{
|
||||
// Ensure SW2_SyscallList is populated.
|
||||
if (!SW2_PopulateSyscallList()) return -1;
|
||||
|
||||
for (DWORD i = 0; i < SW2_SyscallList.Count; i++)
|
||||
{
|
||||
if (FunctionHash == SW2_SyscallList.Entries[i].Hash)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
.code
|
||||
|
||||
EXTERN SW2_GetSyscallNumber: PROC
|
||||
|
||||
NtProtectVirtualMemory PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0079D1B09h ; Load function hash into ECX.
|
||||
call SW2_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp +8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtProtectVirtualMemory ENDP
|
||||
|
||||
NtAllocateVirtualMemory PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 00B9D010Fh ; Load function hash into ECX.
|
||||
call SW2_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp +8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtAllocateVirtualMemory ENDP
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user