我想在进程的特定模块内分配一个内存,而不是一般的进程。以下Windows
C++
代码可以在给定进程ID的情况下在进程内部分配内存:
#include "pch.h"
#include <windows.h>
#include <winternl.h>
#include <processthreadsapi.h>
#include <iostream>
#include <conio.h>
#pragma comment(lib, "ntdll.lib")
typedef NTSTATUS (NTAPI *nt_alloc_virtual_memory_func)(HANDLE process_handle, PVOID* base_address, ULONG_PTR zero_bits,
PSIZE_T region_size, ULONG allocation_type, ULONG protect);
typedef NTSTATUS (NTAPI *nt_free_virtual_memory_func)(HANDLE process_handle, PVOID* base_address, PSIZE_T region_size,
ULONG free_type);
void enable_allocating_executable_memory()
{
PROCESS_MITIGATION_DYNAMIC_CODE_POLICY mp;
ZeroMemory(&mp, sizeof mp);
mp.ProhibitDynamicCode = FALSE;
SetProcessMitigationPolicy(ProcessDynamicCodePolicy, &mp, sizeof mp);
}
long allocate_memory(char** arguments, const HANDLE process_handle, PVOID process_memory, SIZE_T& allocation_size)
{
const auto memory_size = arguments[3];
allocation_size = strtoul(memory_size, nullptr, 10);
const auto nt_allocate_virtual_memory = reinterpret_cast<nt_alloc_virtual_memory_func>(GetProcAddress(
GetModuleHandle(L"ntdll.dll"), "NtAllocateVirtualMemory"));
const auto allocation_status = nt_allocate_virtual_memory(process_handle, &process_memory, 0, &allocation_size,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (NT_SUCCESS(allocation_status))
{
std::cout << std::hex << process_memory << std::endl;
}
return allocation_status;
}
int free_memory(const int argument_count, char** arguments,
const HANDLE process_handle, SIZE_T& mem_size)
{
const auto address_string = arguments[3];
const auto process_address = strtoull(address_string, nullptr, 16);
auto process_memory_address = reinterpret_cast<PVOID>(process_address);
if (argument_count < 4)
{
return EXIT_FAILURE;
}
const auto memory_size = arguments[4];
mem_size = strtoul(memory_size, nullptr, 10);
const auto nt_free_virtual_memory = reinterpret_cast<nt_free_virtual_memory_func>(GetProcAddress(
GetModuleHandle(L"ntdll.dll"), "NtFreeVirtualMemory"));
const auto status = nt_free_virtual_memory(process_handle, &process_memory_address, &mem_size, MEM_RELEASE);
return status;
}
int main(const int argument_count, char* arguments[])
{
if (argument_count < 4)
{
return EXIT_FAILURE;
}
const auto process_id_string = arguments[1];
const auto process_id = strtoul(process_id_string, nullptr, 10);
enable_allocating_executable_memory();
const auto process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id);
if (process_handle == nullptr)
{
std::cout << "Cannot open process with process id " << process_id << std::endl;
exit(EXIT_FAILURE);
}
const PVOID process_memory = nullptr;
SIZE_T mem_size;
const auto command = arguments[2];
if (strcmp(command, "--allocate") == 0)
{
allocate_memory(arguments, process_handle, process_memory, mem_size);
}
else if (strcmp(command, "--free") == 0)
{
return free_memory(argument_count, arguments, process_handle, mem_size);
}
return EXIT_SUCCESS;
}
NtAllocateVirtualMemory
似乎不接受模块的参数。还有什么可以使用的?
其背后的原因是,在分配了一些内存之后,我不想让jmp
从一个模块转到另一个模块,而是希望将其尽可能地保留在本地。这也使jmp
指令在内存上更短。
答案 0 :(得分:1)
我想在特定模块内分配一些内存
您无法执行此操作,在映射模块时会分配其内存。您无法在模块内部分配内存,该模块位于分配的页面内,而在其他位置则没有。任何分配的页面都将在模块之外。
或者,如果您要使用已分配但未使用的内存,则称为代码洞穴。它通常是模块内部的内存区域,其中填充有零。因此,您可以通过在模块内找到一定长度的冗余零来扫描代码洞穴,然后可以写入该内存。
这经常执行,如果页面上设置了执行位,这将非常有用,因为您不必更改任何可能有风险的权限。
在使用“分散映射”的注入器中也经常这样做,在这种情况下,注入器仅使用这些代码洞穴来注入代码。