Example #1
0
void* AllocateFunctionStub(void* origin, void* function, int type) {
  static void* g_currentStub = nullptr;

  if (!g_currentStub) {
    ULONG_PTR minAddr;
    ULONG_PTR maxAddr;

    SYSTEM_INFO si;
    GetSystemInfo(&si);
    minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress;
    maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress;

    if ((ULONG_PTR)origin > MAX_MEMORY_RANGE &&
        minAddr < (ULONG_PTR)origin - MAX_MEMORY_RANGE)
      minAddr = (ULONG_PTR)origin - MAX_MEMORY_RANGE;

    if (maxAddr > (ULONG_PTR)origin + MAX_MEMORY_RANGE)
      maxAddr = (ULONG_PTR)origin + MAX_MEMORY_RANGE;

    LPVOID pAlloc = origin;

    while ((ULONG_PTR)pAlloc >= minAddr) {
      pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr,
                                  si.dwAllocationGranularity);
      if (pAlloc == NULL)
        break;

      g_currentStub =
          VirtualAlloc(pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE,
                       PAGE_EXECUTE_READWRITE);
      if (g_currentStub != NULL)
        break;
    }
  }
  if (!g_currentStub)
    return nullptr;

  char* code = (char*)g_currentStub;

  *(uint8_t*)code = 0x48;
  *(uint8_t*)(code + 1) = 0xb8 | type;

  *(uint64_t*)(code + 2) = (uint64_t)function;

  *(uint16_t*)(code + 10) = 0xE0FF | (type << 8);

  *(uint64_t*)(code + 12) = 0xCCCCCCCCCCCCCCCC;

  g_currentStub = (void*)((uint64_t)g_currentStub + 20);

  return code;
}
Example #2
0
//-------------------------------------------------------------------------
static PMEMORY_BLOCK GetMemoryBlock(LPVOID pOrigin)
{
    PMEMORY_BLOCK pBlock;
#ifdef _M_X64
    ULONG_PTR minAddr;
    ULONG_PTR maxAddr;

    SYSTEM_INFO si;
    GetSystemInfo(&si);
    minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress;
    maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress;

    // pOrigin ± 512MB
    if ((ULONG_PTR)pOrigin > MAX_MEMORY_RANGE)
        minAddr = max(minAddr, (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE);

    maxAddr = min(maxAddr, (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE);

    // Make room for MEMORY_BLOCK_SIZE bytes.
    maxAddr -= MEMORY_BLOCK_SIZE - 1;
#endif

    // Look the registered blocks for a reachable one.
    for (pBlock = g_pMemoryBlocks; pBlock != NULL; pBlock = pBlock->pNext)
    {
#ifdef _M_X64
        // Ignore the blocks too far.
        if ((ULONG_PTR)pBlock < minAddr || (ULONG_PTR)pBlock >= maxAddr)
            continue;
#endif
        // The block has at least one unused slot.
        if (pBlock->pFree != NULL)
            return pBlock;
    }

#ifdef _M_X64
    // Alloc a new block above if not found.
    {
        LPVOID pAlloc = pOrigin;
        while ((ULONG_PTR)pAlloc >= minAddr)
        {
            pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, si.dwAllocationGranularity);
            if (pAlloc == NULL)
                break;

            pBlock = (PMEMORY_BLOCK)VirtualAlloc(
                pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            if (pBlock != NULL)
                break;
        }
    }

    // Alloc a new block below if not found.
    if (pBlock == NULL)
    {
        LPVOID pAlloc = pOrigin;
        while ((ULONG_PTR)pAlloc <= maxAddr)
        {
            pAlloc = FindNextFreeRegion(pAlloc, (LPVOID)maxAddr, si.dwAllocationGranularity);
            if (pAlloc == NULL)
                break;

            pBlock = (PMEMORY_BLOCK)VirtualAlloc(
                pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            if (pBlock != NULL)
                break;
        }
    }
#else
    // In x86 mode, a memory block can be placed anywhere.
    pBlock = (PMEMORY_BLOCK)VirtualAlloc(
        NULL, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
#endif

    if (pBlock != NULL)
    {
        // Build a linked list of all the slots.
        PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBlock + 1;
        pBlock->pFree = NULL;
        pBlock->usedCount = 0;
        do
        {
            pSlot->pNext = pBlock->pFree;
            pBlock->pFree = pSlot;
            pSlot++;
        } while ((ULONG_PTR)pSlot - (ULONG_PTR)pBlock <= MEMORY_BLOCK_SIZE - MEMORY_SLOT_SIZE);

        pBlock->pNext = g_pMemoryBlocks;
        g_pMemoryBlocks = pBlock;
    }

    return pBlock;
}