コード例 #1
0
void
gum_module_enumerate_ranges (const gchar * module_name,
                             GumPageProtection prot,
                             GumFoundRangeFunc func,
                             gpointer user_data)
{
  HANDLE this_process = GetCurrentProcess ();
  HMODULE module;
  MODULEINFO mi;
  guint8 * cur_base_address, * end_address;

  module = get_module_handle_utf8 (module_name);
  if (module == NULL)
    return;

  if (!GetModuleInformation (this_process, module, &mi, sizeof (mi)))
    return;

  cur_base_address = (guint8 *) mi.lpBaseOfDll;
  end_address = (guint8 *) mi.lpBaseOfDll + mi.SizeOfImage;

  do
  {
    MEMORY_BASIC_INFORMATION mbi;
    SIZE_T ret;

    ret = VirtualQuery (cur_base_address, &mbi, sizeof (mbi));
    g_assert (ret != 0);

    if (mbi.Protect != 0)
    {
      GumPageProtection cur_prot;

      cur_prot = gum_page_protection_from_windows (mbi.Protect);

      if ((cur_prot & prot) == prot)
      {
        GumMemoryRange range;
        GumRangeDetails details;

        range.base_address = GUM_ADDRESS (cur_base_address);
        range.size = mbi.RegionSize;

        details.range = ⦥
        details.prot = cur_prot;
        details.file = NULL; /* TODO */

        if (!func (&details, user_data))
          return;
      }
    }

    cur_base_address += mbi.RegionSize;
  }
  while (cur_base_address < end_address);
}
コード例 #2
0
static gboolean
gum_memory_get_protection (GumAddress address,
                           gsize len,
                           GumPageProtection * prot)
{
  gboolean success = FALSE;
  MEMORY_BASIC_INFORMATION mbi;

  if (prot == NULL)
  {
    GumPageProtection ignored_prot;

    return gum_memory_get_protection (address, len, &ignored_prot);
  }

  *prot = GUM_PAGE_NO_ACCESS;

  if (len > 1)
  {
    GumAddress page_size, start_page, end_page, cur_page;

    page_size = gum_query_page_size ();

    start_page = address & ~(page_size - 1);
    end_page = (address + len - 1) & ~(page_size - 1);

    success = gum_memory_get_protection (start_page, 1, prot);

    for (cur_page = start_page + page_size;
        cur_page != end_page + page_size;
        cur_page += page_size)
    {
      GumPageProtection cur_prot;

      if (gum_memory_get_protection (cur_page, 1, &cur_prot))
      {
        success = TRUE;
        *prot &= cur_prot;
      }
      else
      {
        *prot = GUM_PAGE_NO_ACCESS;
        break;
      }
    }

    return success;
  }

  success = VirtualQuery (GSIZE_TO_POINTER (address), &mbi, sizeof (mbi)) != 0;
  if (success)
    *prot = gum_page_protection_from_windows (mbi.Protect);

  return success;
}
コード例 #3
0
void
gum_process_enumerate_ranges (GumPageProtection prot,
                              GumFoundRangeFunc func,
                              gpointer user_data)
{
  guint8 * cur_base_address;

  cur_base_address = NULL;

  while (TRUE)
  {
    MEMORY_BASIC_INFORMATION mbi;
    SIZE_T ret;

    ret = VirtualQuery (cur_base_address, &mbi, sizeof (mbi));
    if (ret == 0)
      break;

    if (mbi.Protect != 0 && (mbi.Protect & PAGE_GUARD) == 0)
    {
      GumPageProtection cur_prot;

      cur_prot = gum_page_protection_from_windows (mbi.Protect);

      if ((cur_prot & prot) == prot)
      {
        GumMemoryRange range;
        GumRangeDetails details;

        range.base_address = GUM_ADDRESS (cur_base_address);
        range.size = mbi.RegionSize;

        details.range = &range;
        details.prot = cur_prot;
        details.file = NULL; /* TODO */

        if (!func (&details, user_data))
          return;
      }
    }

    cur_base_address += mbi.RegionSize;
  }
}
コード例 #4
0
static gboolean
gum_memory_access_monitor_on_exception (GumExceptionDetails * details,
                                        gpointer user_data)
{
  GumMemoryAccessMonitor * self = GUM_MEMORY_ACCESS_MONITOR_CAST (user_data);
  const GumMemoryAccessMonitorPrivate * priv = self->priv;
  GumMemoryAccessDetails d;
  guint i;

  d.operation = details->memory.operation;
  d.from = details->address;
  d.address = details->memory.address;

  for (i = 0; i != priv->num_pages; i++)
  {
    const GumPageDetails * page = &priv->pages_details[i];
    const GumMemoryRange * r = &priv->ranges[page->range_index];
    guint operation_mask;
    guint operations_reported;
    guint pages_remaining;

    if ((page->address <= d.address) && 
        ((guint8 *) page->address + priv->page_size > (guint8*) d.address))
    {
      /* make sure that we don't misinterpret access violation / page guard */
      if (page->is_guarded)
      {
        if (details->type != GUM_EXCEPTION_GUARD_PAGE)
          return FALSE;
      }
      else if (details->type == GUM_EXCEPTION_ACCESS_VIOLATION)
      {
        GumPageProtection gum_original_protection = 
            gum_page_protection_from_windows (page->original_protection);
        switch (d.operation)
        {
        case GUM_MEMOP_READ:
          if ((gum_original_protection & GUM_PAGE_READ) == 0)
            return FALSE;
          break;
        case GUM_MEMOP_WRITE:
          if ((gum_original_protection & GUM_PAGE_WRITE) == 0)
            return FALSE;
          break;
        case GUM_MEMOP_EXECUTE:
          if ((gum_original_protection & GUM_PAGE_EXECUTE) == 0)
            return FALSE;
          break;
        default:
          g_assert_not_reached();
        }
      }
      else 
        return FALSE;

      /* restore the original protection if needed */
      if (priv->auto_reset && !page->is_guarded)
      {
        DWORD old_prot;
        /* may be called multiple times in case of simultaneous access
         * but it should not be a problem */
        VirtualProtect (
            (guint8 *) d.address - (((guintptr) d.address) % priv->page_size),
            priv->page_size, page->original_protection, &old_prot);
      }

      /* if an operation was already reported, don't report it. */
      operation_mask = 1 << d.operation;
      operations_reported = g_atomic_int_or (&page->completed, operation_mask);
      if ((operations_reported != 0) && priv->auto_reset)
        return FALSE;

      pages_remaining;
      if (!operations_reported)
        pages_remaining = g_atomic_int_add (&priv->pages_remaining, -1) - 1;
      else
        pages_remaining = g_atomic_int_get (&priv->pages_remaining);
      d.pages_completed = priv->pages_total - pages_remaining;

      d.range_index = page->range_index;
      d.page_index = (guint8 *) d.address - (guint8 *) r->base_address;
      d.page_index = d.page_index / priv->page_size;
      d.pages_total = priv->pages_total;

      priv->notify_func (self, &d, priv->notify_data);

      return TRUE;
    }
  }

  return FALSE;
}