|
|
|
@ -5,25 +5,65 @@
|
|
|
|
|
#include "hmdm_ctx.h"
|
|
|
|
|
#include "linker/linker.hpp"
|
|
|
|
|
|
|
|
|
|
using extern_symbols_t = std::vector<std::pair<std::string, lnk::map_symbols_t>>;
|
|
|
|
|
using objs_buffer_t = std::vector<lnk::obj_buffer_t>;
|
|
|
|
|
|
|
|
|
|
auto get_mapping_info(int argc, char** argv) -> std::pair<objs_buffer_t, extern_symbols_t>
|
|
|
|
|
{
|
|
|
|
|
auto maps_offset = 0u;
|
|
|
|
|
std::vector<lnk::obj_buffer_t> image_objs;
|
|
|
|
|
std::vector<std::pair<std::string, lnk::map_symbols_t>> extern_symbols;
|
|
|
|
|
|
|
|
|
|
for (auto idx = 2; idx < argc; ++idx)
|
|
|
|
|
{
|
|
|
|
|
if (!strcmp(argv[idx], "--maps"))
|
|
|
|
|
{
|
|
|
|
|
maps_offset = idx + 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!lnk::get_objs(argv[idx], image_objs))
|
|
|
|
|
{
|
|
|
|
|
std::printf("> failed to parse lib...\n");
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (maps_offset)
|
|
|
|
|
{
|
|
|
|
|
for (auto idx = maps_offset; idx <= argc - 1; ++idx)
|
|
|
|
|
{
|
|
|
|
|
extern_symbols.push_back
|
|
|
|
|
({
|
|
|
|
|
std::filesystem::path(argv[idx]).stem().string(),
|
|
|
|
|
lnk::get_map_symbols(argv[idx])
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return { image_objs, extern_symbols };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char** argv)
|
|
|
|
|
{
|
|
|
|
|
if (argc < 2)
|
|
|
|
|
if (argc < 3 || strcmp(argv[1], "--libs"))
|
|
|
|
|
{
|
|
|
|
|
std::printf("> please provide a folder of objs to be linked...\n");
|
|
|
|
|
std::printf("[!] invalid usage... please use one of the following:\n");
|
|
|
|
|
std::printf(" > theo.exe --libs one.lib two.lib three.lib\n");
|
|
|
|
|
std::printf(" > theo.exe --libs one.lib --maps ntoskrnl.exe.map win32kbase.sys.map\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// read each .obj file from directory into std::vector...
|
|
|
|
|
std::vector<lnk::obj_buffer_t> image_objs;
|
|
|
|
|
if (!lnk::get_objs(argv[1], image_objs))
|
|
|
|
|
auto [image_objs, extern_symbols] = get_mapping_info(argc, argv);
|
|
|
|
|
std::printf("[+] number of objs = %d\n", image_objs.size());
|
|
|
|
|
|
|
|
|
|
if (!image_objs.size())
|
|
|
|
|
{
|
|
|
|
|
std::printf("> failed to parse lib...\n");
|
|
|
|
|
std::printf("[!] failed to parse .lib...\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::printf("> number of objs = %d\n", image_objs.size());
|
|
|
|
|
const auto [drv_handle, drv_key, drv_status] = vdm::load_drv();
|
|
|
|
|
|
|
|
|
|
if (drv_status != STATUS_SUCCESS || drv_handle == INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
std::printf("> failed to load driver... reason -> 0x%x\n", drv_status);
|
|
|
|
@ -37,7 +77,7 @@ int main(int argc, char** argv)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
vdm::msrexec_ctx msrexec(_write_msr);
|
|
|
|
|
theo::kalloc_t _kalloc = [&](std::size_t size) -> void*
|
|
|
|
|
theo::malloc_t _kalloc = [&](std::size_t size) -> void*
|
|
|
|
|
{
|
|
|
|
|
void* alloc_base;
|
|
|
|
|
msrexec.exec
|
|
|
|
@ -57,7 +97,7 @@ int main(int argc, char** argv)
|
|
|
|
|
return alloc_base;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
theo::kmemcpy_t _kmemcpy =
|
|
|
|
|
theo::memcpy_t _kmemcpy =
|
|
|
|
|
[&](void* dest, const void* src, std::size_t size) -> void*
|
|
|
|
|
{
|
|
|
|
|
void* result = nullptr;
|
|
|
|
@ -76,9 +116,87 @@ int main(int argc, char** argv)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
theo::resolve_symbol_t resolve_symbol =
|
|
|
|
|
[&](const char* symbol_name) -> std::uintptr_t
|
|
|
|
|
[&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t
|
|
|
|
|
{
|
|
|
|
|
return utils::kmodule::get_export("ntoskrnl.exe", symbol_name);
|
|
|
|
|
std::uintptr_t result = 0u;
|
|
|
|
|
for (auto& [drv_name, drv_symbols] : extern_symbols)
|
|
|
|
|
{
|
|
|
|
|
// each kernel module... find a driver with a matching map file name...
|
|
|
|
|
// I.E ntoskrnl.exe.map == ntoskrnl.exe...
|
|
|
|
|
utils::kmodule::each_module
|
|
|
|
|
(
|
|
|
|
|
[&, &drv_name = drv_name, &drv_symbols = drv_symbols]
|
|
|
|
|
(PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
|
|
|
|
|
{
|
|
|
|
|
const auto _drv_name =
|
|
|
|
|
reinterpret_cast<const char*>(
|
|
|
|
|
drv_info->OffsetToFileName + drv_info->FullPathName);
|
|
|
|
|
|
|
|
|
|
// if this is the driver, load it, loop over its sections
|
|
|
|
|
// calc the absolute virtual address of the symbol...
|
|
|
|
|
if (!strcmp(_drv_name, drv_name.c_str()))
|
|
|
|
|
{
|
|
|
|
|
const auto drv_load_addr =
|
|
|
|
|
reinterpret_cast<std::uintptr_t>(
|
|
|
|
|
LoadLibraryExA(drv_path, NULL, DONT_RESOLVE_DLL_REFERENCES));
|
|
|
|
|
|
|
|
|
|
std::uint32_t section_count = 1u;
|
|
|
|
|
utils::pe::each_section
|
|
|
|
|
(
|
|
|
|
|
[&, &drv_symbols = drv_symbols]
|
|
|
|
|
(PIMAGE_SECTION_HEADER section_header, std::uintptr_t img_base) -> bool
|
|
|
|
|
{
|
|
|
|
|
if (section_count == drv_symbols[symbol_name].first)
|
|
|
|
|
{
|
|
|
|
|
result = reinterpret_cast<std::uintptr_t>(drv_info->ImageBase) +
|
|
|
|
|
section_header->VirtualAddress + drv_symbols[symbol_name].second;
|
|
|
|
|
|
|
|
|
|
// we found the symbol...
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++section_count;
|
|
|
|
|
// keep going over sections...
|
|
|
|
|
return true;
|
|
|
|
|
}, drv_load_addr
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// keep looping over modules until we resolve the symbol...
|
|
|
|
|
return !result;
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if the symbol was not resolved in any of the map files then try
|
|
|
|
|
// to see if its an export from any other drivers...
|
|
|
|
|
if (!result)
|
|
|
|
|
{
|
|
|
|
|
utils::kmodule::each_module
|
|
|
|
|
(
|
|
|
|
|
[&](PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
|
|
|
|
|
{
|
|
|
|
|
const auto drv_name =
|
|
|
|
|
reinterpret_cast<const char*>(
|
|
|
|
|
drv_info->OffsetToFileName + drv_info->FullPathName);
|
|
|
|
|
|
|
|
|
|
__try
|
|
|
|
|
{
|
|
|
|
|
const auto temp_result =
|
|
|
|
|
utils::kmodule::get_export(drv_name, symbol_name);
|
|
|
|
|
|
|
|
|
|
if (!temp_result)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// false if we found the symbol...
|
|
|
|
|
return (!(result = temp_result));
|
|
|
|
|
}
|
|
|
|
|
__except (EXCEPTION_EXECUTE_HANDLER) { return true; }
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
theo::hmm_ctx drv_mapper({ _kalloc, _kmemcpy, resolve_symbol });
|
|
|
|
|