Skip to content

Commit

Permalink
windows: Use RW/RX permissions for injection
Browse files Browse the repository at this point in the history
* Use a dedicated memory page for the injected code.

* Use RW permissions when writing the injected code and data.

* Switch the code page to RX permissions after writing.

This makes Frida injection compatible with more software. In particular,
Mozilla Firefox rejects thread startup if the start address is RWX.
  • Loading branch information
yjugl committed Apr 4, 2024
1 parent fe9dafe commit 7e9046c
Showing 1 changed file with 26 additions and 10 deletions.
36 changes: 26 additions & 10 deletions src/windows/frida-helper-backend-glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <tlhelp32.h>
#include <strsafe.h>

#define PAGE_SIZE 0x1000

#define CHECK_OS_RESULT(n1, cmp, n2, op) \
if (!((n1) cmp (n2))) \
{ \
Expand Down Expand Up @@ -305,10 +307,11 @@ frida_remote_worker_context_init (FridaRemoteWorkerContext * rwc, FridaInjection
gpointer code;
guint code_size;
GumX86Writer cw;
const gsize data_alignment = 4;
const gchar * loadlibrary_failed = "loadlibrary_failed";
const gchar * skip_unload = "skip_unload";
const gchar * return_result = "return_result";
SIZE_T alloc_size;
DWORD old_protect;

gum_init ();

Expand Down Expand Up @@ -347,7 +350,7 @@ frida_remote_worker_context_init (FridaRemoteWorkerContext * rwc, FridaInjection
GUM_ARG_REGISTER, GUM_X86_XSI,
GUM_ARG_REGISTER, GUM_X86_XDX);

/* xax (xbx->entrypoint_data, &stay_resident, NULL) */
/* xax (xbx->entrypoint_data, &xbx->stay_resident, NULL) */
gum_x86_writer_put_lea_reg_reg_offset (&cw, GUM_X86_XCX,
GUM_X86_XBX, G_STRUCT_OFFSET (FridaRemoteWorkerContext, entrypoint_data));
gum_x86_writer_put_lea_reg_reg_offset (&cw, GUM_X86_XDX,
Expand All @@ -358,7 +361,7 @@ frida_remote_worker_context_init (FridaRemoteWorkerContext * rwc, FridaInjection
GUM_ARG_REGISTER, GUM_X86_XDX,
GUM_ARG_ADDRESS, GUM_ADDRESS (0));

/* if (!stay_resident) { */
/* if (!xbx->stay_resident) { */
gum_x86_writer_put_mov_reg_reg_offset_ptr (&cw, GUM_X86_EAX,
GUM_X86_XBX, G_STRUCT_OFFSET (FridaRemoteWorkerContext, stay_resident));
gum_x86_writer_put_test_reg_reg (&cw, GUM_X86_EAX, GUM_X86_EAX);
Expand Down Expand Up @@ -403,19 +406,23 @@ frida_remote_worker_context_init (FridaRemoteWorkerContext * rwc, FridaInjection
StringCbCopyA (rwc->entrypoint_name, sizeof (rwc->entrypoint_name), details->entrypoint_name);
StringCbCopyA (rwc->entrypoint_data, sizeof (rwc->entrypoint_data), details->entrypoint_data);

rwc->entrypoint = VirtualAllocEx (details->process_handle, NULL,
code_size + data_alignment + sizeof (FridaRemoteWorkerContext), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
g_assert (code_size <= PAGE_SIZE);

alloc_size = PAGE_SIZE + sizeof (FridaRemoteWorkerContext);
rwc->entrypoint = VirtualAllocEx (details->process_handle, NULL, alloc_size, MEM_COMMIT, PAGE_READWRITE);
if (rwc->entrypoint == NULL)
goto virtual_alloc_failed;
goto virtual_alloc_ex_failed;

if (!WriteProcessMemory (details->process_handle, rwc->entrypoint, code, code_size, NULL))
goto write_process_memory_failed;

rwc->argument = GSIZE_TO_POINTER (
(GPOINTER_TO_SIZE (rwc->entrypoint) + code_size + data_alignment - 1) & ~(data_alignment - 1));
rwc->argument = GSIZE_TO_POINTER (GPOINTER_TO_SIZE (rwc->entrypoint) + PAGE_SIZE);
if (!WriteProcessMemory (details->process_handle, rwc->argument, rwc, sizeof (FridaRemoteWorkerContext), NULL))
goto write_process_memory_failed;

if (!VirtualProtectEx(details->process_handle, rwc->entrypoint, PAGE_SIZE, PAGE_EXECUTE_READ, &old_protect))
goto virtual_protect_ex_failed;

gum_free_pages (code);
return TRUE;

Expand All @@ -428,12 +435,12 @@ frida_remote_worker_context_init (FridaRemoteWorkerContext * rwc, FridaInjection
"Unexpected error while resolving kernel32 functions");
goto error_common;
}
virtual_alloc_failed:
virtual_alloc_ex_failed:
{
g_set_error (error,
FRIDA_ERROR,
FRIDA_ERROR_NOT_SUPPORTED,
"Unexpected error allocating memory in target process (VirtualAlloc returned 0x%08lx)",
"Unexpected error allocating memory in target process (VirtualAllocEx returned 0x%08lx)",
GetLastError ());
goto error_common;
}
Expand All @@ -446,6 +453,15 @@ frida_remote_worker_context_init (FridaRemoteWorkerContext * rwc, FridaInjection
GetLastError ());
goto error_common;
}
virtual_protect_ex_failed:
{
g_set_error (error,
FRIDA_ERROR,
FRIDA_ERROR_NOT_SUPPORTED,
"Unexpected error changing memory permission in target process (VirtualProtectEx returned 0x%08lx)",
GetLastError ());
goto error_common;
}
error_common:
{
frida_remote_worker_context_destroy (rwc, details);
Expand Down

0 comments on commit 7e9046c

Please sign in to comment.