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 authored and oleavr committed May 13, 2024
1 parent ab28e33 commit 298bed5
Showing 1 changed file with 25 additions and 10 deletions.
35 changes: 25 additions & 10 deletions src/windows/frida-helper-backend-glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,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 page_size, alloc_size;
DWORD old_protect;

gum_init ();

Expand Down Expand Up @@ -347,7 +348,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 +359,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 +404,24 @@ 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);
page_size = gum_query_page_size ();
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 +434,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 +452,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 298bed5

Please sign in to comment.