frida / frida-gum

Cross-platform instrumentation and introspection library written in C
https://frida.re
Other
753 stars 245 forks source link

[Stalker]Unable to allocate code slab near 0x7c4f333000 with max_distance=2138779647 #793

Open DiamondHunters opened 6 months ago

DiamondHunters commented 6 months ago

When I tried to perform tracing by stalker like itrace, I got this error.

It works fine on a single function, but when I use it to trace a heavily obfuscated algorithm, the exception occurs.

The issue seems to be that the stalker is unable to allocate memory within a ±2GB address space.

However, my code would only cause the rewritten code size to expand by several times.

I checked the maps file, and many libraries were mapped near that address, which might be the reason why the stalker was unable to allocate space.

Is there a way to control the code generation location of the stalker to make it start at a less crowded memory position?

map:

maps.txt

DiamondHunters commented 6 months ago

I think the root cause of the issue lies in the ctx address selected by mmap. When the system allocates in a crowded address space, this significantly reduces the likelihood of successfully allocating near the ctx address.

near_address at: https://github.com/frida/frida-gum/blob/ffda5fc03b7e9fd2414e395c72ea011aa4fe27f6/gum/backend-arm64/gumstalker-arm64.c#L2318

ctx at: https://github.com/frida/frida-gum/blob/ffda5fc03b7e9fd2414e395c72ea011aa4fe27f6/gum/backend-arm64/gumstalker-arm64.c#L2155

A possible solution is requesting a large block of memory to ensure ample free address space, then unmap that area and use its address to request memory. This approach might introduce some race condition issues. A more comprehensive solution is to mmap a large block of memory and then allocate new memory within it using remap / fixed mmap, involving considerable modifications. Let me give it a try.

DiamondHunters commented 6 months ago

This is a modification I tested that is available but not complete.

gum_exec_ctx_new (GumStalker * stalker,
                  GumThreadId thread_id,
                  GumStalkerTransformer * transformer,
                  GumEventSink * sink)
{
  GumExecCtx * ctx;
  guint8 * base;
  GumCodeSlab * code_slab;
  GumSlowSlab * slow_slab;
  GumDataSlab * data_slab;
  base = gum_memory_allocate (NULL, INT32_MAX, stalker->page_size, GUM_PAGE_RW);
  g_warning("Alloc big memory at base %p:",base);
  gum_memory_free(base,INT32_MAX);
  base = gum_memory_allocate (base + INT32_MAX / 2, stalker->ctx_size, stalker->page_size,
      stalker->is_rwx_supported ? GUM_PAGE_RWX : GUM_PAGE_RW);
  g_warning("target base: %p, real base %p:",base + INT32_MAX / 2,base);
  ctx = (GumExecCtx *) base;

It can temporarily solve the problem, but I think that parts of the memory allocation mechanism should be refactored.