-
Notifications
You must be signed in to change notification settings - Fork 3
/
util.hpp
147 lines (124 loc) · 4.88 KB
/
util.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#pragma once
#include <memory>
#include <Windows.h>
#include <string>
namespace util
{
using smart_handle = std::unique_ptr<void, decltype(&CloseHandle)>;
// https://stackoverflow.com/posts/54491532
template <typename TChar, typename TStringGetterFunc>
std::basic_string<TChar> get_string_from_windows_api(TStringGetterFunc string_getter, int initial_size = 0)
{
if (initial_size <= 0)
{
initial_size = MAX_PATH;
}
std::basic_string<TChar> result(initial_size, 0);
for (;;) // kinda ugly ngl
{
auto length = string_getter(result.data(), result.length());
if (length == 0)
{
return std::basic_string<TChar>();
}
if (length < result.length() - 1)
{
result.resize(length);
result.shrink_to_fit();
return result;
}
result.resize(result.length() * 2);
}
}
}
namespace image
{
inline PIMAGE_EXPORT_DIRECTORY get_export_directory(const std::uint64_t base)
{
const auto dos = reinterpret_cast<PIMAGE_DOS_HEADER>(base);
const auto nt_sig = reinterpret_cast<DWORD*>(base + dos->e_lfanew);
if (*nt_sig != IMAGE_NT_SIGNATURE) { // Corrupted image
return nullptr;
}
auto coff_header = reinterpret_cast<PIMAGE_FILE_HEADER>(nt_sig + 1);
if (coff_header->Machine == IMAGE_FILE_MACHINE_AMD64) {
auto oh64 = reinterpret_cast<PIMAGE_OPTIONAL_HEADER64>(coff_header + 1);
if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh64->NumberOfRvaAndSizes) {
return nullptr;
}
const auto rva = oh64->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
return reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(base + rva);
}
else if (coff_header->Machine == IMAGE_FILE_MACHINE_I386) {
auto oh32 = reinterpret_cast<PIMAGE_OPTIONAL_HEADER32>(coff_header + 1);
if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh32->NumberOfRvaAndSizes) {
return nullptr;
}
const auto rva = oh32->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
return reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(base + rva);
}
return nullptr;
}
inline std::uint32_t get_import_descriptor_va(uint64_t base)
{
const auto dos = reinterpret_cast<PIMAGE_DOS_HEADER>(base);
const auto nt_sig = reinterpret_cast<DWORD*>(base + dos->e_lfanew);
if (*nt_sig != IMAGE_NT_SIGNATURE) { // Corrupted image
return 0;
}
auto coff_header = reinterpret_cast<PIMAGE_FILE_HEADER>(nt_sig + 1);
if (coff_header->Machine == IMAGE_FILE_MACHINE_AMD64) {
auto oh64 = reinterpret_cast<PIMAGE_OPTIONAL_HEADER64>(coff_header + 1);
if (IMAGE_DIRECTORY_ENTRY_IMPORT >= oh64->NumberOfRvaAndSizes) {
return 0;
}
return oh64->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
}
else if (coff_header->Machine == IMAGE_FILE_MACHINE_I386) {
auto oh32 = reinterpret_cast<PIMAGE_OPTIONAL_HEADER32>(coff_header + 1);
if (IMAGE_DIRECTORY_ENTRY_IMPORT >= oh32->NumberOfRvaAndSizes) {
return 0;
}
return oh32->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
}
return 0;
}
// Returns the .text section for most dlls
inline uint64_t get_text_section(const uint64_t base)
{
const auto dos = reinterpret_cast<PIMAGE_DOS_HEADER>(base);
const auto nt_headers = reinterpret_cast<PIMAGE_NT_HEADERS>(base + dos->e_lfanew);
if (nt_headers->Signature != IMAGE_NT_SIGNATURE) { // Corrupted image
return 0;
}
PIMAGE_FILE_HEADER coffFileHeader = &nt_headers->FileHeader;
WORD sizeOfOptionalheader = coffFileHeader->SizeOfOptionalHeader;
PIMAGE_OPTIONAL_HEADER optional_header = reinterpret_cast<PIMAGE_OPTIONAL_HEADER>((PBYTE)nt_headers + 0x18);
PIMAGE_SECTION_HEADER section_headers = reinterpret_cast<PIMAGE_SECTION_HEADER>((PBYTE)optional_header + sizeOfOptionalheader);
for (int i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i)
{
// We could maybe rewrite it and scan for entry point instead of hardcodign the section name
if (strcmp((char*)section_headers[i].Name, ".text") == 0)
return section_headers[i].VirtualAddress + base;
}
return 0;
}
inline size_t get_text_section_size(const uint64_t base)
{
const auto dos = reinterpret_cast<PIMAGE_DOS_HEADER>(base);
const auto nt_headers = reinterpret_cast<PIMAGE_NT_HEADERS>(base + dos->e_lfanew);
if (nt_headers->Signature != IMAGE_NT_SIGNATURE) { // Corrupted image
return 0;
}
const PIMAGE_FILE_HEADER coff_file_header = &nt_headers->FileHeader;
const WORD size_of_optional_header = coff_file_header->SizeOfOptionalHeader;
const auto optional_header = reinterpret_cast<PIMAGE_OPTIONAL_HEADER>((PBYTE)nt_headers + 0x18);
const auto section_headers = reinterpret_cast<PIMAGE_SECTION_HEADER>((PBYTE)optional_header + size_of_optional_header);
for (int i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i)
{
if (strcmp((char*)section_headers[i].Name, ".text") == 0)
return section_headers[i].Misc.VirtualSize;
}
return 0;
}
}