parent
b7db7c9c86
commit
09d0342da6
Binary file not shown.
@ -0,0 +1,52 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include "xtils.hpp"
|
||||
|
||||
int __cdecl main(int argc, const char** argv)
|
||||
{
|
||||
auto utils = xtils::um_t::get_instance();
|
||||
const auto explorer_pid =
|
||||
utils->get_pid(L"explorer.exe");
|
||||
|
||||
const auto explorer_module_base =
|
||||
utils->get_process_base(utils->get_handle(explorer_pid).get());
|
||||
|
||||
std::printf("> explorer pid = 0x%x, module base = 0x%p\n",
|
||||
explorer_pid, explorer_module_base);
|
||||
|
||||
std::map<std::wstring, std::uintptr_t> modules;
|
||||
if (!utils->get_modules(explorer_pid, modules))
|
||||
{
|
||||
std::printf("[!] failed to get modules...\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::printf("> user32.dll base = 0x%p\n",
|
||||
modules[L"user32.dll"]);
|
||||
|
||||
const auto [notepad_handle, notepad_pid, notepad_base] =
|
||||
utils->start_exec("C:\\Windows\\System32\\notepad.exe");
|
||||
|
||||
std::printf("> notepad handle = 0x%x, notepad pid = 0x%x, notepad_base = 0x%p\n",
|
||||
notepad_handle, notepad_pid, notepad_base);
|
||||
|
||||
const auto module_base = utils->load_lib(notepad_handle,
|
||||
(std::filesystem::current_path()
|
||||
.string() + "\\hello-world-x64.dll").c_str());
|
||||
|
||||
std::printf("> module base = 0x%p\n", module_base);
|
||||
auto km_utils = xtils::km_t::get_instance();
|
||||
|
||||
km_utils->each_module(
|
||||
[](PRTL_PROCESS_MODULE_INFORMATION kmodule_info, const char* module_name) -> bool
|
||||
{
|
||||
std::printf("> module name = %s, module base = 0x%p\n",
|
||||
module_name, kmodule_info->ImageBase);
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
std::printf("> ntoskrnl base = 0x%p\n", km_utils->get_base("ntoskrnl.exe"));
|
||||
}
|
@ -0,0 +1,523 @@
|
||||
#pragma once
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#pragma comment(lib, "ntdll.lib")
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <psapi.h>
|
||||
#include <winternl.h>
|
||||
#include <ntstatus.h>
|
||||
|
||||
#define LOG_SIG "[xtils]"
|
||||
#define LOG(...) \
|
||||
{ \
|
||||
char buff[256]; \
|
||||
snprintf(buff, sizeof buff, LOG_SIG ## __VA_ARGS__); \
|
||||
OutputDebugStringA(buff); \
|
||||
}
|
||||
|
||||
#define NT_HEADER(x) reinterpret_cast<PIMAGE_NT_HEADERS>( uint64_t(x) + reinterpret_cast<PIMAGE_DOS_HEADER>(x)->e_lfanew )
|
||||
|
||||
typedef struct _RTL_PROCESS_MODULE_INFORMATION
|
||||
{
|
||||
HANDLE Section;
|
||||
PVOID MappedBase;
|
||||
PVOID ImageBase;
|
||||
ULONG ImageSize;
|
||||
ULONG Flags;
|
||||
USHORT LoadOrderIndex;
|
||||
USHORT InitOrderIndex;
|
||||
USHORT LoadCount;
|
||||
USHORT OffsetToFileName;
|
||||
UCHAR FullPathName[256];
|
||||
} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;
|
||||
|
||||
typedef struct _RTL_PROCESS_MODULES
|
||||
{
|
||||
ULONG NumberOfModules;
|
||||
RTL_PROCESS_MODULE_INFORMATION Modules[1];
|
||||
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;
|
||||
|
||||
|
||||
namespace xtils
|
||||
{
|
||||
using uq_handle = std::unique_ptr<void, decltype(&CloseHandle)>;
|
||||
|
||||
class um_t
|
||||
{
|
||||
using module_callback_t = std::function<bool(std::wstring, std::uintptr_t)>;
|
||||
using module_map_t = std::map<std::wstring, std::uintptr_t>;
|
||||
|
||||
public:
|
||||
static auto get_instance() -> um_t* { static um_t obj; return &obj; }
|
||||
|
||||
auto get_modules(std::uint32_t pid, module_map_t& module_map) -> bool
|
||||
{
|
||||
uq_handle snapshot = { CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid), &CloseHandle };
|
||||
|
||||
if (snapshot.get() == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
MODULEENTRY32 module_info = { sizeof MODULEENTRY32 };
|
||||
Module32First(snapshot.get(), &module_info);
|
||||
|
||||
// lowercase the module name...
|
||||
std::for_each(module_info.szModule,
|
||||
module_info.szModule + wcslen(module_info.szModule) * 2,
|
||||
[](wchar_t& c) { c = ::towlower(c); });
|
||||
|
||||
module_map[module_info.szModule] = reinterpret_cast<std::uintptr_t>(module_info.modBaseAddr);
|
||||
|
||||
for (Module32First(snapshot.get(), &module_info); Module32Next(snapshot.get(), &module_info);)
|
||||
{
|
||||
// lowercase the module name...
|
||||
std::for_each(module_info.szModule,
|
||||
module_info.szModule + wcslen(module_info.szModule) * 2,
|
||||
[](wchar_t& c) { c = ::towlower(c); });
|
||||
|
||||
module_map[module_info.szModule] =
|
||||
reinterpret_cast<std::uintptr_t>(module_info.modBaseAddr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void each_module(std::uint32_t pid, module_callback_t callback)
|
||||
{
|
||||
module_map_t module_map;
|
||||
if (!get_modules(pid, module_map))
|
||||
return;
|
||||
|
||||
for (auto& [module_name, module_base] : module_map)
|
||||
if (!callback(module_name, module_base))
|
||||
break;
|
||||
}
|
||||
|
||||
// https://github.com/PierreCiholas/GetBaseAddress/blob/master/main.cpp#L7
|
||||
auto get_process_base(HANDLE proc_handle)->std::uintptr_t
|
||||
{
|
||||
HMODULE lph_modules[1024];
|
||||
DWORD needed = 0u;
|
||||
|
||||
if (!EnumProcessModules(proc_handle, lph_modules, sizeof(lph_modules), &needed))
|
||||
return {};
|
||||
|
||||
TCHAR mod_name[MAX_PATH];
|
||||
if (!GetModuleFileNameEx(proc_handle, lph_modules[0], mod_name, sizeof(mod_name) / sizeof(TCHAR)))
|
||||
return {};
|
||||
|
||||
return reinterpret_cast<std::uintptr_t>(lph_modules[0]);
|
||||
}
|
||||
|
||||
auto get_pid(const wchar_t* proc_name) -> std::uint32_t
|
||||
{
|
||||
uq_handle snapshot = { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL), &CloseHandle };
|
||||
|
||||
if (snapshot.get() == INVALID_HANDLE_VALUE)
|
||||
return {};
|
||||
|
||||
PROCESSENTRY32W process_entry{ sizeof(PROCESSENTRY32W) };
|
||||
Process32FirstW(snapshot.get(), &process_entry);
|
||||
if (!std::wcscmp(proc_name, process_entry.szExeFile))
|
||||
return process_entry.th32ProcessID;
|
||||
|
||||
for (Process32FirstW(snapshot.get(), &process_entry); Process32NextW(snapshot.get(), &process_entry); )
|
||||
if (!std::wcscmp(proc_name, process_entry.szExeFile))
|
||||
return process_entry.th32ProcessID;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
auto get_handle(const wchar_t* proc_name, DWORD access = PROCESS_ALL_ACCESS) -> uq_handle
|
||||
{
|
||||
std::uint32_t pid = 0u;
|
||||
if (!(pid = get_pid(proc_name)))
|
||||
return { NULL, &CloseHandle };
|
||||
|
||||
return { OpenProcess(access, FALSE, pid), &CloseHandle };
|
||||
}
|
||||
|
||||
auto get_handle(std::uint32_t pid, DWORD access = PROCESS_ALL_ACCESS)->uq_handle
|
||||
{
|
||||
if (!pid) return { NULL, &CloseHandle };
|
||||
return { OpenProcess(access, FALSE, pid), &CloseHandle };
|
||||
}
|
||||
|
||||
auto load_lib(HANDLE proc_handle, const char* dll_path) -> std::uintptr_t
|
||||
{
|
||||
const auto dll_path_page =
|
||||
VirtualAllocEx(
|
||||
proc_handle,
|
||||
nullptr,
|
||||
0x1000,
|
||||
MEM_COMMIT | MEM_RESERVE,
|
||||
PAGE_READWRITE
|
||||
);
|
||||
|
||||
if (!dll_path_page)
|
||||
return {};
|
||||
|
||||
SIZE_T handled_bytes;
|
||||
if (!WriteProcessMemory(proc_handle, dll_path_page,
|
||||
dll_path, strlen(dll_path), &handled_bytes))
|
||||
return {};
|
||||
|
||||
// +6 for string address
|
||||
// +16 for LoadLibrary address...
|
||||
unsigned char jmp_code[] =
|
||||
{
|
||||
0x48, 0x83, 0xEC, 0x28, // sub rsp, 0x28
|
||||
0x48, 0xB9, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // mov rcx, &dllpath
|
||||
0x48, 0xB8, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // mov rax, &LoadLibraryA
|
||||
0xFF, 0xD0, // call rax
|
||||
0x48, 0x83, 0xC4, 0x28, // add rsp, 0x28
|
||||
0x48, 0x89, 0x05, 0x01, 0x00, 0x00, 0x00, // mov [rip+1], rax
|
||||
0xC3 // ret
|
||||
};
|
||||
|
||||
*reinterpret_cast<std::uintptr_t*>(&jmp_code[6]) =
|
||||
reinterpret_cast<std::uintptr_t>(dll_path_page);
|
||||
|
||||
*reinterpret_cast<std::uintptr_t*>(&jmp_code[16]) =
|
||||
reinterpret_cast<std::uintptr_t>(&LoadLibraryA);
|
||||
|
||||
const auto jmp_code_page =
|
||||
VirtualAllocEx(
|
||||
proc_handle,
|
||||
nullptr,
|
||||
0x1000,
|
||||
MEM_COMMIT | MEM_RESERVE,
|
||||
PAGE_EXECUTE_READWRITE
|
||||
);
|
||||
|
||||
if (!jmp_code_page)
|
||||
return {};
|
||||
|
||||
if (!WriteProcessMemory(proc_handle,
|
||||
jmp_code_page, jmp_code, sizeof jmp_code, &handled_bytes))
|
||||
return {};
|
||||
|
||||
DWORD tid = 0u;
|
||||
auto thandle = CreateRemoteThread(proc_handle, nullptr,
|
||||
NULL, (LPTHREAD_START_ROUTINE)jmp_code_page, nullptr, NULL, &tid);
|
||||
|
||||
if (thandle == INVALID_HANDLE_VALUE)
|
||||
return {};
|
||||
|
||||
WaitForSingleObject(thandle, INFINITE);
|
||||
|
||||
// read the base address out of the shellcode...
|
||||
std::uintptr_t module_base = 0u;
|
||||
if (!ReadProcessMemory(proc_handle, reinterpret_cast<void*>(
|
||||
reinterpret_cast<std::uintptr_t>(jmp_code_page) + sizeof jmp_code),
|
||||
&module_base, sizeof module_base, &handled_bytes))
|
||||
return {};
|
||||
|
||||
return module_base;
|
||||
}
|
||||
|
||||
auto start_exec(const char* image_path, char* cmdline = nullptr,
|
||||
bool suspend = false) -> std::tuple<HANDLE, std::uint32_t, std::uintptr_t>
|
||||
{
|
||||
STARTUPINFOA info = { sizeof info };
|
||||
PROCESS_INFORMATION proc_info;
|
||||
|
||||
if (!CreateProcessA(image_path, cmdline, nullptr,
|
||||
nullptr, false,
|
||||
suspend ? CREATE_SUSPENDED | CREATE_NEW_CONSOLE : CREATE_NEW_CONSOLE,
|
||||
nullptr, nullptr, &info, &proc_info
|
||||
))
|
||||
return { {}, {}, {} };
|
||||
|
||||
Sleep(1); // sleep just for a tiny amount of time so that get_process_base works...
|
||||
return { proc_info.hProcess, proc_info.dwProcessId, get_process_base(proc_info.hProcess) };
|
||||
}
|
||||
|
||||
std::uintptr_t scan(std::uintptr_t base, std::uint32_t size, const char* pattern, const char* mask)
|
||||
{
|
||||
static const auto check_mask =
|
||||
[&](const char* base, const char* pattern, const char* mask) -> bool
|
||||
{
|
||||
for (; *mask; ++base, ++pattern, ++mask)
|
||||
if (*mask == 'x' && *base != *pattern)
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
size -= strlen(mask);
|
||||
for (auto i = 0; i <= size; ++i)
|
||||
{
|
||||
void* addr = (void*)&(((char*)base)[i]);
|
||||
if (check_mask((char*)addr, pattern, mask))
|
||||
return reinterpret_cast<std::uintptr_t>(addr);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
explicit um_t() {}
|
||||
};
|
||||
|
||||
class km_t
|
||||
{
|
||||
using kmodule_callback_t = std::function<bool(PRTL_PROCESS_MODULE_INFORMATION, const char*)>;
|
||||
public:
|
||||
static auto get_instance() -> km_t* { static km_t obj; return &obj; };
|
||||
auto get_base(const char* drv_name)->std::uintptr_t
|
||||
{
|
||||
void* buffer = nullptr;
|
||||
DWORD buffer_size = NULL;
|
||||
|
||||
auto status = NtQuerySystemInformation(
|
||||
static_cast<SYSTEM_INFORMATION_CLASS>(0xB),
|
||||
buffer, buffer_size, &buffer_size);
|
||||
|
||||
while (status == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
VirtualFree(buffer, NULL, MEM_RELEASE);
|
||||
buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
status = NtQuerySystemInformation(
|
||||
static_cast<SYSTEM_INFORMATION_CLASS>(0xB),
|
||||
buffer, buffer_size, &buffer_size);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
VirtualFree(buffer, NULL, MEM_RELEASE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const auto modules = static_cast<PRTL_PROCESS_MODULES>(buffer);
|
||||
for (auto idx = 0u; idx < modules->NumberOfModules; ++idx)
|
||||
{
|
||||
const auto current_module_name =
|
||||
std::string(reinterpret_cast<char*>(
|
||||
modules->Modules[idx].FullPathName) +
|
||||
modules->Modules[idx].OffsetToFileName);
|
||||
|
||||
if (!_stricmp(current_module_name.c_str(), drv_name))
|
||||
{
|
||||
const auto result =
|
||||
reinterpret_cast<std::uint64_t>(
|
||||
modules->Modules[idx].ImageBase);
|
||||
|
||||
VirtualFree(buffer, NULL, MEM_RELEASE);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
VirtualFree(buffer, NULL, MEM_RELEASE);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
void each_module(kmodule_callback_t callback)
|
||||
{
|
||||
void* buffer = nullptr;
|
||||
DWORD buffer_size = NULL;
|
||||
|
||||
auto status = NtQuerySystemInformation(
|
||||
static_cast<SYSTEM_INFORMATION_CLASS>(0xB),
|
||||
buffer, buffer_size, &buffer_size);
|
||||
|
||||
while (status == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
VirtualFree(buffer, NULL, MEM_RELEASE);
|
||||
buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
status = NtQuerySystemInformation(
|
||||
static_cast<SYSTEM_INFORMATION_CLASS>(0xB),
|
||||
buffer, buffer_size, &buffer_size);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
VirtualFree(buffer, NULL, MEM_RELEASE);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto modules = static_cast<PRTL_PROCESS_MODULES>(buffer);
|
||||
for (auto idx = 0u; idx < modules->NumberOfModules; ++idx)
|
||||
{
|
||||
auto full_path = std::string(
|
||||
reinterpret_cast<char*>(
|
||||
modules->Modules[idx].FullPathName));
|
||||
|
||||
if (full_path.find("\\SystemRoot\\") != std::string::npos)
|
||||
full_path.replace(full_path.find("\\SystemRoot\\"),
|
||||
sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\"));
|
||||
|
||||
else if (full_path.find("\\??\\") != std::string::npos)
|
||||
full_path.replace(full_path.find("\\??\\"),
|
||||
sizeof("\\??\\") - 1, "");
|
||||
|
||||
if (!callback(&modules->Modules[idx], full_path.c_str()))
|
||||
{
|
||||
VirtualFree(buffer, NULL, MEM_RELEASE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
VirtualFree(buffer, NULL, MEM_RELEASE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
auto get_export(const char* drv_name, const char* export_name)->std::uintptr_t
|
||||
{
|
||||
void* buffer = nullptr;
|
||||
DWORD buffer_size = NULL;
|
||||
|
||||
NTSTATUS status = NtQuerySystemInformation(
|
||||
static_cast<SYSTEM_INFORMATION_CLASS>(0xB),
|
||||
buffer,
|
||||
buffer_size,
|
||||
&buffer_size
|
||||
);
|
||||
|
||||
while (status == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
VirtualFree(buffer, 0, MEM_RELEASE);
|
||||
buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
status = NtQuerySystemInformation(
|
||||
static_cast<SYSTEM_INFORMATION_CLASS>(0xB),
|
||||
buffer,
|
||||
buffer_size,
|
||||
&buffer_size
|
||||
);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
VirtualFree(buffer, 0, MEM_RELEASE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const auto modules = static_cast<PRTL_PROCESS_MODULES>(buffer);
|
||||
for (auto idx = 0u; idx < modules->NumberOfModules; ++idx)
|
||||
{
|
||||
// find module and then load library it
|
||||
const std::string current_module_name =
|
||||
std::string(reinterpret_cast<char*>(
|
||||
modules->Modules[idx].FullPathName) +
|
||||
modules->Modules[idx].OffsetToFileName
|
||||
);
|
||||
|
||||
if (!_stricmp(current_module_name.c_str(), drv_name))
|
||||
{
|
||||
auto full_path = std::string(
|
||||
reinterpret_cast<char*>(
|
||||
modules->Modules[idx].FullPathName));
|
||||
|
||||
full_path.replace(full_path.find("\\SystemRoot\\"),
|
||||
sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\"));
|
||||
|
||||
const auto module_base =
|
||||
LoadLibraryExA(
|
||||
full_path.c_str(),
|
||||
NULL,
|
||||
DONT_RESOLVE_DLL_REFERENCES
|
||||
);
|
||||
|
||||
const auto image_base =
|
||||
reinterpret_cast<std::uintptr_t>(
|
||||
modules->Modules[idx].ImageBase);
|
||||
|
||||
// free the RTL_PROCESS_MODULES buffer...
|
||||
VirtualFree(buffer, NULL, MEM_RELEASE);
|
||||
|
||||
const auto rva =
|
||||
reinterpret_cast<std::uintptr_t>(
|
||||
GetProcAddress(module_base, export_name)) -
|
||||
reinterpret_cast<std::uintptr_t>(module_base);
|
||||
|
||||
return image_base + rva;
|
||||
}
|
||||
}
|
||||
|
||||
VirtualFree(buffer, NULL, MEM_RELEASE);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
private:
|
||||
explicit km_t() {}
|
||||
};
|
||||
|
||||
class pe_t
|
||||
{
|
||||
using section_callback_t = std::function<bool(PIMAGE_SECTION_HEADER, std::uintptr_t)>;
|
||||
public:
|
||||
static auto get_instance() -> pe_t* { static pe_t obj; return &obj; }
|
||||
|
||||
// returns an std::vector containing all of the bytes of the section
|
||||
// and also the RVA from the image base to the beginning of the section...
|
||||
auto get_section(std::uintptr_t module_base,
|
||||
const char* section_name) -> std::pair<std::vector<std::uint8_t>, std::uint32_t>
|
||||
{
|
||||
const auto nt_headers = reinterpret_cast<PIMAGE_NT_HEADERS>(
|
||||
reinterpret_cast<PIMAGE_DOS_HEADER>(module_base)->e_lfanew + module_base);
|
||||
|
||||
const auto section_header =
|
||||
reinterpret_cast<PIMAGE_SECTION_HEADER>(
|
||||
reinterpret_cast<std::uintptr_t>(nt_headers) + sizeof(DWORD)
|
||||
+ sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader);
|
||||
|
||||
for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx)
|
||||
{
|
||||
const auto _section_name =
|
||||
reinterpret_cast<char*>(
|
||||
section_header[idx].Name);
|
||||
|
||||
// sometimes section names are not null terminated...
|
||||
if (!strncmp(_section_name, section_name, strlen(section_name) - 1))
|
||||
{
|
||||
const auto section_base =
|
||||
reinterpret_cast<std::uint8_t*>(
|
||||
module_base + section_header[idx].VirtualAddress);
|
||||
|
||||
const auto section_end =
|
||||
reinterpret_cast<std::uint8_t*>(
|
||||
section_base + section_header[idx].Misc.VirtualSize);
|
||||
|
||||
std::vector<std::uint8_t> section_bin(section_base, section_end);
|
||||
return { section_bin, section_header[idx].VirtualAddress };
|
||||
}
|
||||
}
|
||||
|
||||
return { {}, {} };
|
||||
}
|
||||
|
||||
void each_section(section_callback_t callback, std::uintptr_t module_base)
|
||||
{
|
||||
if (!module_base)
|
||||
return;
|
||||
|
||||
const auto nt_headers = reinterpret_cast<PIMAGE_NT_HEADERS>(
|
||||
reinterpret_cast<PIMAGE_DOS_HEADER>(module_base)->e_lfanew + module_base);
|
||||
|
||||
const auto section_header =
|
||||
reinterpret_cast<PIMAGE_SECTION_HEADER>(
|
||||
reinterpret_cast<std::uintptr_t>(nt_headers) + sizeof(DWORD)
|
||||
+ sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader);
|
||||
|
||||
for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx)
|
||||
{
|
||||
const auto _section_name =
|
||||
reinterpret_cast<char*>(
|
||||
section_header[idx].Name);
|
||||
|
||||
// keep looping until the callback returns false...
|
||||
if (!callback(§ion_header[idx], module_base))
|
||||
return;
|
||||
}
|
||||
}
|
||||
private:
|
||||
explicit pe_t() {};
|
||||
};
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{47343e59-10b7-4f29-b7a0-561b106f7d0b}</ProjectGuid>
|
||||
<RootNamespace>xtils</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<Optimization>Disabled</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="xtils.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="xtils.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
Loading…
Reference in new issue