diff options
| author | auth12 <[email protected]> | 2020-07-28 07:34:55 -0700 |
|---|---|---|
| committer | auth12 <[email protected]> | 2020-07-28 07:34:55 -0700 |
| commit | 733272ed4960324a20606fba1b7810412c06bac7 (patch) | |
| tree | e7f33f10eae3a212fcdd2250910a7d7d88d67069 /client/src | |
| parent | Removed linuxpe dependency on windows client. (diff) | |
| download | loader-733272ed4960324a20606fba1b7810412c06bac7.tar.xz loader-733272ed4960324a20606fba1b7810412c06bac7.zip | |
Process class redesign.
Diffstat (limited to 'client/src')
| -rw-r--r-- | client/src/injection/mapper.cpp | 19 | ||||
| -rw-r--r-- | client/src/injection/pe.h | 75 | ||||
| -rw-r--r-- | client/src/injection/process.cpp | 222 | ||||
| -rw-r--r-- | client/src/injection/process.h | 224 | ||||
| -rw-r--r-- | client/src/main.cpp | 3 | ||||
| -rw-r--r-- | client/src/util/apiset.h | 4 | ||||
| -rw-r--r-- | client/src/util/native.h | 225 |
7 files changed, 328 insertions, 444 deletions
diff --git a/client/src/injection/mapper.cpp b/client/src/injection/mapper.cpp index 3857948..1951ab2 100644 --- a/client/src/injection/mapper.cpp +++ b/client/src/injection/mapper.cpp @@ -13,7 +13,7 @@ void mmap::thread(tcp::client& client) { util::fetch_system_data(dat); auto needle = std::find_if(dat.processes.begin(), dat.processes.end(), [&](util::process_data_t& dat) { - return dat.name == client.selected_game.process_name; + return dat.name == "sublime_text.exe"; }); if (needle == dat.processes.end()) { @@ -21,7 +21,7 @@ void mmap::thread(tcp::client& client) { return; } - util::process32 proc(*needle); + util::process<uint64_t> proc(*needle); if (!proc.open()) { return; @@ -77,11 +77,18 @@ void mmap::thread(tcp::client& client) { io::log("entry : {:x}", entry); - static std::vector<uint8_t> shellcode = { 0x55, 0x89, 0xE5, 0x6A, 0x00, 0x6A, 0x01, 0x68, 0xEF, 0xBE, - 0xAD, 0xDE, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0xFF, 0xD0, 0x89, 0xEC, 0x5D, 0xC3 }; + /*static std::vector<uint8_t> shellcode = { 0x55, 0x89, 0xE5, 0x6A, 0x00, 0x6A, 0x01, 0x68, 0xEF, 0xBE, + 0xAD, 0xDE, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0xFF, 0xD0, 0x89, 0xEC, 0x5D, 0xC3 };*/ - *reinterpret_cast<uint32_t*>(&shellcode[8]) = image; - *reinterpret_cast<uint32_t*>(&shellcode[13]) = entry; + static std::vector<uint8_t> shellcode = { 0x48, 0x83, 0xEC, 0x28, 0x48, 0xB9, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0xC7, 0xC2,0x01, 0x00, 0x00, 0x00, 0x4D, 0x31, 0xC0, + 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xD0, 0x48, 0x83, 0xC4, 0x28, 0xC3 }; + + /**reinterpret_cast<uint32_t*>(&shellcode[8]) = image; + *reinterpret_cast<uint32_t*>(&shellcode[13]) = entry;*/ + + *reinterpret_cast<uint64_t*>(&shellcode[6]) = image; + *reinterpret_cast<uint64_t*>(&shellcode[26]) = entry; auto code = proc.allocate(shellcode.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!proc.write(code, shellcode.data(), shellcode.size())) { diff --git a/client/src/injection/pe.h b/client/src/injection/pe.h index 9978170..f246108 100644 --- a/client/src/injection/pe.h +++ b/client/src/injection/pe.h @@ -3,7 +3,6 @@ #include "../util/native.h" namespace pe { - class virtual_image { std::unordered_map<std::string, uintptr_t> m_exports; @@ -11,7 +10,7 @@ namespace pe { uintptr_t m_base; public: virtual_image() : m_nt{ nullptr }, m_base{ 0 } {}; - virtual_image(const std::string_view mod) { + virtual_image(const std::string_view mod) : m_base{0}, m_nt{nullptr} { auto peb = util::peb(); if (!peb) return; @@ -77,67 +76,6 @@ namespace pe { uint32_t va; }; -#pragma pack(push, 4) - struct reloc_entry_t { - uint16_t offset : 12; - uint16_t type : 4; - }; - - struct reloc_block_t { - uint32_t base_rva; - uint32_t size_block; - reloc_entry_t entries[ 1 ]; // Variable length array - - - inline reloc_block_t* get_next() { return ( reloc_block_t* ) ( ( char* ) this + this->size_block ); } - inline uint32_t num_entries() { return ( reloc_entry_t* ) get_next() - &entries[ 0 ]; } - }; - - struct image_named_import_t - { - uint16_t hint; - char name[ 1 ]; - }; - -#pragma pack(push, 8) - struct image_thunk_data_x64_t - { - union - { - uint64_t forwarder_string; - uint64_t function; - uint64_t address; // -> image_named_import_t - struct - { - uint64_t ordinal : 16; - uint64_t _reserved0 : 47; - uint64_t is_ordinal : 1; - }; - }; - }; -#pragma pack(pop) - - struct image_thunk_data_x86_t - { - union - { - uint32_t forwarder_string; - uint32_t function; - uint32_t address; // -> image_named_import_t - struct - { - uint32_t ordinal : 16; - uint32_t _reserved0 : 15; - uint32_t is_ordinal : 1; - }; - }; - }; -#pragma pack(pop) - - template<bool x64, - typename base_type = typename std::conditional<x64, image_thunk_data_x64_t, image_thunk_data_x86_t>::type> - struct image_thunk_data_t : base_type {}; - template <bool x64 = false> class image { std::vector<char> m_buffer; @@ -147,7 +85,7 @@ namespace pe { native::nt_headers_t<x64>* m_nt; IMAGE_DOS_HEADER* m_dos; - std::vector<std::pair<uint32_t, reloc_entry_t>> m_relocs; + std::vector<std::pair<uint32_t, native::reloc_entry_t>> m_relocs; public: image() = default; @@ -196,7 +134,7 @@ namespace pe { if (!reloc_dir.Size) return; const auto ptr = rva_to_ptr(reloc_dir.VirtualAddress); - auto block = reinterpret_cast<reloc_block_t*>(ptr); + auto block = reinterpret_cast<native::reloc_block_t*>(ptr); while (block->base_rva) { for (size_t i = 0; i < block->num_entries(); ++i) { @@ -218,11 +156,11 @@ namespace pe { for (uint32_t i = 0; i < table->Name; i = table->Name, ++table) { auto mod_name = std::string(reinterpret_cast<char*>(rva_to_ptr(table->Name))); - auto thunk = reinterpret_cast<image_thunk_data_t<x64>*>(rva_to_ptr(table->OriginalFirstThunk)); + auto thunk = reinterpret_cast<native::image_thunk_data_t<x64>*>(rva_to_ptr(table->OriginalFirstThunk)); auto step = x64 ? sizeof(uint64_t) : sizeof(uint32_t); for (uint32_t index = 0; thunk->address; index += step, ++thunk) { - auto named_import = reinterpret_cast<image_named_import_t*>(rva_to_ptr(thunk->address)); + auto named_import = reinterpret_cast<native::image_named_import_t*>(rva_to_ptr(thunk->address)); if (!thunk->is_ordinal) { import_t data; @@ -248,8 +186,7 @@ namespace pe { } void relocate(std::vector<char>& image, uintptr_t base) { - const auto delta = - base - m_nt->OptionalHeader.ImageBase; + const auto delta = base - m_nt->OptionalHeader.ImageBase; if (delta > 0) { for (auto& [base_rva, entry] : m_relocs) { if (x64) { diff --git a/client/src/injection/process.cpp b/client/src/injection/process.cpp index 23a7e2f..38a676b 100644 --- a/client/src/injection/process.cpp +++ b/client/src/injection/process.cpp @@ -2,9 +2,200 @@ #include "../util/io.h" #include "../util/util.h" #include "../util/apiset.h" +#include "../util/syscalls.h" #include "process.h" -uintptr_t util::process32::module_export(const uintptr_t base, const std::string_view func) { +bool util::base_process::open() { + CLIENT_ID cid = { HANDLE(m_id), 0 }; + OBJECT_ATTRIBUTES oa; + oa.Length = sizeof(oa); + oa.Attributes = 0; + oa.RootDirectory = 0; + oa.SecurityDescriptor = 0; + oa.ObjectName = 0; + oa.SecurityQualityOfService = 0; + + static auto nt_open = g_syscalls.get<native::NtOpenProcess>("NtOpenProcess"); + + auto status = nt_open(&m_handle, PROCESS_ALL_ACCESS, &oa, &cid); + if (!NT_SUCCESS(status)) { + io::log_error("failed to open handle to {}, status {:#X}.", m_name, (status & 0xFFFFFFFF)); + return false; + } + + io::log("opened handle to {}.", m_name); + + return true; +} + +bool util::base_process::read(const uintptr_t addr, void* data, size_t size) { + static auto nt_read = g_syscalls.get<native::NtReadVirtualMemory>("NtReadVirtualMemory"); + + ULONG read; + auto status = nt_read(m_handle, reinterpret_cast<void*>(addr), data, size, &read); + if (!NT_SUCCESS(status)) { + io::log_error("failed to read at {:x}, status {:#X}.", addr, (status & 0xFFFFFFFF)); + return false; + } + + return true; +} + +bool util::base_process::write(const uintptr_t addr, void* data, size_t size) { + static auto nt_write = g_syscalls.get<native::NtWiteVirtualMemory>("NtWriteVirtualMemory"); + + ULONG wrote; + auto status = nt_write(m_handle, reinterpret_cast<void*>(addr), data, size, &wrote); + if (!NT_SUCCESS(status)) { + io::log_error("failed to write to {}, status {:#X}.", m_name, (status & 0xFFFFFFFF)); + return false; + } + + return true; +} + +bool util::base_process::free(const uintptr_t addr, size_t size, uint32_t type /*= MEM_RELEASE*/) { + static auto nt_free = g_syscalls.get<native::NtFreeVirtualMemory>("NtFreeVirtualMemory"); + + SIZE_T win_size = size; + void* addr_cast = reinterpret_cast<void*>(addr); + auto status = nt_free(m_handle, &addr_cast, &win_size, MEM_RELEASE); + if (!NT_SUCCESS(status)) { + io::log_error("failed to free at {:x}, status {:#X}.", addr, (status & 0xFFFFFFFF)); + return false; + } + + return true; +} + +bool util::base_process::info(PROCESSINFOCLASS proc_info, void* data, size_t size) { + static auto nt_proc_info = g_syscalls.get<native::NtQueryInformationProcess>("NtQueryInformationProcess"); + auto status = nt_proc_info(m_handle, proc_info, data, size, nullptr); + if (!NT_SUCCESS(status)) { + io::log_error("failed to query {} info, status {:#X}.", m_name, (status & 0xFFFFFFFF)); + return false; + } + + return true; +} + +bool util::base_process::thread(const uintptr_t func) { + static auto nt_create = g_syscalls.get<native::NtCreateThreadEx>("NtCreateThreadEx"); + static auto nt_wait = g_syscalls.get<native::NtWaitForSingleObject>("NtWaitForSingleObject"); + + HANDLE out; + auto status = nt_create(&out, THREAD_ALL_ACCESS, nullptr, m_handle, reinterpret_cast<LPTHREAD_START_ROUTINE>(func), 0, 0x4, 0, 0, 0, 0); + if (!NT_SUCCESS(status)) { + io::log_error("failed to create thread in {}, status {:#X}.", m_name, (status & 0xFFFFFFFF)); + return false; + } + + status = nt_wait(out, false, nullptr); + if (!NT_SUCCESS(status)) { + io::log_error("failed to wait for handle {}, status {:#X}.", out, (status & 0xFFFFFFFF)); + + util::close_handle(out); + return false; + } + + if (!util::close_handle(out)) { + return false; + } + + return true; +} + +bool util::base_process::close() { + auto ret = util::close_handle(m_handle); + if (ret) { + io::log("closed handle to {}.", m_name); + } + m_handle = INVALID_HANDLE_VALUE; + return ret; +} + +uintptr_t util::base_process::allocate(size_t size, uint32_t type, uint32_t protection) { + static auto nt_alloc = g_syscalls.get<native::NtAllocateVirtualMemory>("NtAllocateVirtualMemory"); + + void* alloc = nullptr; + SIZE_T win_size = size; + auto status = nt_alloc(m_handle, &alloc, 0, &win_size, type, protection); + if (!NT_SUCCESS(status)) { + io::log_error("failed to allocate in {}, status {:#X}.", m_name, (status & 0xFFFFFFFF)); + return {}; + } + + return uintptr_t(alloc); +} + +template<typename T> +bool util::process<T>::enum_modules() { + m_modules.clear(); + + static auto peb_addr = peb(); + + T ldr; + if (!read(peb_addr + offsetof(native::peb_t<T>, Ldr), &ldr, sizeof(ldr))) { + return false; + } + + const auto list_head = ldr + offsetof(native::peb_ldr_data_t<T>, InLoadOrderModuleList); + + T load_order_flink; + if (!read(list_head, &load_order_flink, sizeof(load_order_flink))) { + return false; + } + + native::ldr_data_table_entry_t<T> entry; + for (auto list_curr = load_order_flink; list_curr != list_head;) { + if (!read(list_curr, &entry, sizeof(entry))) { + return false; + } + + list_curr = entry.InLoadOrderLinks.Flink; + + std::vector<wchar_t> name_vec(entry.FullDllName.Length); + + if (!read(entry.FullDllName.Buffer, &name_vec[0], name_vec.size())) { + continue; + } + + auto name = util::wide_to_multibyte(name_vec.data()); + auto pos = name.rfind('\\'); + if (pos != std::string::npos) { + name = name.substr(pos + 1); + std::transform(name.begin(), name.end(), name.begin(), ::tolower); + + m_modules[name] = entry.DllBase; + } + } + + return true; +} + +template<typename T> +uintptr_t util::process<T>::peb() { + constexpr bool is64 = sizeof(T) == sizeof(uint64_t); + if (is64) { + native::PROCESS_EXTENDED_BASIC_INFORMATION proc_info; + proc_info.Size = sizeof(proc_info); + if (!info(ProcessBasicInformation, &proc_info, sizeof(proc_info))) { + return {}; + } + + return uintptr_t(proc_info.BasicInfo.PebBaseAddress); + } + + uintptr_t addr; + if (!info(ProcessWow64Information, &addr, sizeof(addr))) { + return {}; + } + + return addr; +} + +template<typename T> +uintptr_t util::process<T>::module_export(const uintptr_t base, const std::string_view func) { if (!base) { return {}; } @@ -18,7 +209,8 @@ uintptr_t util::process32::module_export(const uintptr_t base, const std::string if (dos.e_magic != IMAGE_DOS_SIGNATURE) return {}; - native::nt_headers_t<false> nt{}; + constexpr bool is64 = sizeof(T) == sizeof(uint64_t); + native::nt_headers_t<is64> nt{}; if (!read(base + dos.e_lfanew, &nt, sizeof(nt))) { io::log_error("failed to read nt header for {}", m_name); return {}; @@ -96,9 +288,12 @@ uintptr_t util::process32::module_export(const uintptr_t base, const std::string return {}; } -uintptr_t util::process32::map(const std::string_view module_name) { - std::string mod{module_name}; - g_apiset(mod); +template<typename T> +uintptr_t util::process<T>::map(const std::string_view module_name) { + std::string mod{ module_name }; + if (g_apiset(mod)) { + io::log("resolved {} -> {}", module_name, mod); + } auto base = m_modules[mod]; if (base) { @@ -107,7 +302,8 @@ uintptr_t util::process32::map(const std::string_view module_name) { io::log("mapping {}", module_name); - std::string path{"C:\\Windows\\SysWOW64\\"}; + constexpr bool is64 = sizeof(T) == sizeof(uint64_t); + std::string path{ is64 ? "C:\\Windows\\System32\\" : "C:\\Windows\\SysWOW64\\" }; path.append(mod); std::vector<char> local_image; @@ -115,7 +311,7 @@ uintptr_t util::process32::map(const std::string_view module_name) { return {}; } - pe::image img(local_image); + pe::image<is64> img(local_image); if (!img) { io::log_error("failed to init image."); @@ -132,11 +328,11 @@ uintptr_t util::process32::map(const std::string_view module_name) { img.relocate(remote_image, base); - for (auto &[mod, funcs] : img.imports()) { - for (auto &func : funcs) { + for (auto& [mod, funcs] : img.imports()) { + for (auto& func : funcs) { auto addr = module_export(map(mod), func.name); //io::log("{}:{}->{:x}", mod, func.name, addr); - *reinterpret_cast<uint32_t *>(&remote_image[func.rva]) = addr; + *reinterpret_cast<T*>(&remote_image[func.rva]) = addr; } } @@ -152,6 +348,10 @@ uintptr_t util::process32::map(const std::string_view module_name) { return base; } +// explicit template instantiation +template class util::process<uint64_t>; +template class util::process<uint32_t>; + bool util::fetch_system_data(system_data_t& out) { static auto info = g_syscalls.get<native::NtQuerySystemInformation>("NtQuerySystemInformation"); @@ -180,7 +380,7 @@ bool util::fetch_system_data(system_data_t& out) { for (auto i = 0; i < pi->NumberOfThreads; ++i) { auto dat = ti[i]; - threads.emplace_back(thread_data_t{int(dat.ClientId.UniqueProcess), uintptr_t(dat.ClientId.UniqueThread), dat.ThreadState}); + threads.emplace_back(thread_data_t{ int(dat.ClientId.UniqueProcess), uintptr_t(dat.ClientId.UniqueThread), dat.ThreadState }); } pi = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(uintptr_t(pi) + pi->NextEntryOffset); diff --git a/client/src/injection/process.h b/client/src/injection/process.h index f397a8a..e5d3f18 100644 --- a/client/src/injection/process.h +++ b/client/src/injection/process.h @@ -1,210 +1,28 @@ #pragma once -#include "../util/syscalls.h" namespace util { - template<typename T = uint32_t> class base_process { protected: HANDLE m_handle; int m_id; std::string m_name; - - std::unordered_map<std::string, uintptr_t> m_modules; public: - base_process() = default; + base_process() : m_handle{ INVALID_HANDLE_VALUE }, m_name{}, m_id{} {} ~base_process() = default; - bool open() { - CLIENT_ID cid = { HANDLE(m_id), 0 }; - OBJECT_ATTRIBUTES oa; - oa.Length = sizeof(oa); - oa.Attributes = 0; - oa.RootDirectory = 0; - oa.SecurityDescriptor = 0; - oa.ObjectName = 0; - oa.SecurityQualityOfService = 0; - - static auto nt_open = g_syscalls.get<native::NtOpenProcess>("NtOpenProcess"); - - auto status = nt_open(&m_handle, PROCESS_ALL_ACCESS, &oa, &cid); - if (!NT_SUCCESS(status)) { - io::log_error("failed to open handle to {}, status {:#X}.", m_name, (status & 0xFFFFFFFF)); - return false; - } - - io::log("opened handle to {}.", m_name); - - return true; - } - - bool read(const uintptr_t addr, void* data, size_t size) { - static auto nt_read = g_syscalls.get<native::NtReadVirtualMemory>("NtReadVirtualMemory"); - - ULONG read; - auto status = nt_read(m_handle, reinterpret_cast<void*>(addr), data, size, &read); - if (!NT_SUCCESS(status)) { - io::log_error("failed to read at {:x}, status {:#X}.", addr, (status & 0xFFFFFFFF)); - return false; - } - - return true; - } - - bool write(const uintptr_t addr, void* data, size_t size) { - static auto nt_write = g_syscalls.get<native::NtWiteVirtualMemory>("NtWriteVirtualMemory"); - - ULONG wrote; - auto status = nt_write(m_handle, reinterpret_cast<void*>(addr), data, size, &wrote); - if (!NT_SUCCESS(status)) { - io::log_error("failed to write to {}, status {:#X}.", m_name, (status & 0xFFFFFFFF)); - return false; - } - - return true; - } - - bool free(const uintptr_t addr, size_t size, uint32_t type = MEM_RELEASE) { - static auto nt_free = g_syscalls.get<native::NtFreeVirtualMemory>("NtFreeVirtualMemory"); - - SIZE_T win_size = size; - void *addr_cast = reinterpret_cast<void*>(addr); - auto status = nt_free(m_handle, &addr_cast, &win_size, MEM_RELEASE); - if (!NT_SUCCESS(status)) { - io::log_error("failed to free at {:x}, status {:#X}.", addr, (status & 0xFFFFFFFF)); - return false; - } - - return true; - } - - bool info(PROCESSINFOCLASS proc_info, void* data, size_t size) { - static auto nt_proc_info = g_syscalls.get<native::NtQueryInformationProcess>("NtQueryInformationProcess"); - auto status = nt_proc_info(m_handle, proc_info, data, size, nullptr); - if (!NT_SUCCESS(status)) { - io::log_error("failed to query {} info, status {:#X}.", m_name, (status & 0xFFFFFFFF)); - return false; - } - - return true; - } - - bool thread(const uintptr_t func) { - static auto nt_create = g_syscalls.get<native::NtCreateThreadEx>("NtCreateThreadEx"); - static auto nt_wait = g_syscalls.get<native::NtWaitForSingleObject>("NtWaitForSingleObject"); - - HANDLE out; - auto status = nt_create(&out, THREAD_ALL_ACCESS, nullptr, m_handle, reinterpret_cast<LPTHREAD_START_ROUTINE>(func), 0, 0x4, 0, 0, 0, 0); - if (!NT_SUCCESS(status)) { - io::log_error("failed to create thread in {}, status {:#X}.", m_name, (status & 0xFFFFFFFF)); - return false; - } - - status = nt_wait(out, false, nullptr); - if (!NT_SUCCESS(status)) { - io::log_error("failed to wait for handle {}, status {:#X}.", out, (status & 0xFFFFFFFF)); - - util::close_handle(out); - return false; - } - - if (!util::close_handle(out)) { - return false; - } - - return true; - } - - bool enum_modules() { - m_modules.clear(); - - static auto peb_addr = peb(); - - T ldr; - if (!read(peb_addr + offsetof(native::peb_t<T>, Ldr), &ldr, sizeof(ldr))) { - return false; - } - - const auto list_head = ldr + offsetof(native::peb_ldr_data_t<T>, InLoadOrderModuleList); - - T load_order_flink; - if (!read(list_head, &load_order_flink, sizeof(load_order_flink))) { - return false; - } - - native::ldr_data_table_entry_t<T> entry; - for (auto list_curr = load_order_flink; list_curr != list_head;) { - if (!read(list_curr, &entry, sizeof(entry))) { - return false; - } - - list_curr = entry.InLoadOrderLinks.Flink; - - std::vector<wchar_t> name_vec(entry.FullDllName.Length); - - if (!read(entry.FullDllName.Buffer, &name_vec[0], name_vec.size())) { - continue; - } - - auto name = util::wide_to_multibyte(name_vec.data()); - auto pos = name.rfind('\\'); - if (pos != std::string::npos) { - name = name.substr(pos + 1); - std::transform(name.begin(), name.end(), name.begin(), ::tolower); - - m_modules[name] = entry.DllBase; - } - } - - return true; - } + bool open(); + bool read(const uintptr_t addr, void* data, size_t size); + bool write(const uintptr_t addr, void* data, size_t size); + bool free(const uintptr_t addr, size_t size, uint32_t type = MEM_RELEASE); + bool info(PROCESSINFOCLASS proc_info, void* data, size_t size); + bool thread(const uintptr_t func); + bool close(); - bool close() { - auto ret = util::close_handle(m_handle); - if (ret) { - io::log("closed handle to {}.", m_name); - } - m_handle = INVALID_HANDLE_VALUE; - return ret; - } - - uintptr_t peb() { - bool is64 = sizeof(T) == sizeof(uint64_t); - if (is64) { - native::PROCESS_EXTENDED_BASIC_INFORMATION proc_info; - proc_info.Size = sizeof(proc_info); - if (!info(ProcessBasicInformation, &proc_info, sizeof(proc_info))) { - return {}; - } - - return uintptr_t(proc_info.BasicInfo.PebBaseAddress); - } - - uintptr_t addr; - if (!info(ProcessWow64Information, &addr, sizeof(addr))) { - return {}; - } - - return addr; - } - - uintptr_t allocate(size_t size, uint32_t type, uint32_t protection) { - static auto nt_alloc = g_syscalls.get<native::NtAllocateVirtualMemory>("NtAllocateVirtualMemory"); - - void* alloc = nullptr; - SIZE_T win_size = size; - auto status = nt_alloc(m_handle, &alloc, 0, &win_size, type, protection); - if (!NT_SUCCESS(status)) { - io::log_error("failed to allocate in {}, status {:#X}.", m_name, (status & 0xFFFFFFFF)); - return {}; - } + uintptr_t allocate(size_t size, uint32_t type, uint32_t protection); - return uintptr_t(alloc); - } - - auto &modules() { return m_modules; } - auto &handle() { return m_handle; } - auto &name() { return m_name; } - auto &id() { return m_id; } + auto& handle() { return m_handle; } + auto& name() { return m_name; } + auto& id() { return m_id; } }; struct process_data_t { @@ -223,27 +41,29 @@ namespace util { std::vector<thread_data_t> threads; }; - class process32 : public base_process<uint32_t> { + template<typename T> + class process : public base_process { + std::unordered_map<std::string, uintptr_t> m_modules; public: - process32(const process_data_t &data) { + process(const process_data_t& data) { m_name = data.name; m_id = data.id; } + ~process() = default; + + bool enum_modules(); + uintptr_t peb(); uintptr_t module_export(const uintptr_t base, const std::string_view func); uintptr_t map(const std::string_view module_name); }; - class process64 : public base_process<uint64_t> { - - }; - struct handle_info_t { uint32_t access; uintptr_t handle; uint32_t obj_type; }; - bool fetch_system_data(system_data_t &out); - bool fetch_process_handles(const int pid, std::vector<handle_info_t> &out); + bool fetch_system_data(system_data_t& out); + bool fetch_process_handles(const int pid, std::vector<handle_info_t>& out); }; diff --git a/client/src/main.cpp b/client/src/main.cpp index 4a11061..83b96fe 100644 --- a/client/src/main.cpp +++ b/client/src/main.cpp @@ -182,4 +182,7 @@ int main(int argc, char* argv[]) { } t1.join(); + + std::cin.get(); + std::cin.get(); } diff --git a/client/src/util/apiset.h b/client/src/util/apiset.h index 440dcc0..a13f3bb 100644 --- a/client/src/util/apiset.h +++ b/client/src/util/apiset.h @@ -5,14 +5,16 @@ class apiset { public: apiset(); - void operator()(std::string &mod) { + bool operator()(std::string &mod) { auto it = std::find_if(m_apimap.begin(), m_apimap.end(), [&](const std::pair<std::string, std::string>& pair) { return mod.find(pair.first) != std::string::npos; }); if (it != m_apimap.end()) { mod = it->second; + return true; } + return false; } auto &map() { return m_apimap; } diff --git a/client/src/util/native.h b/client/src/util/native.h index 44b8ab6..9c8cef7 100644 --- a/client/src/util/native.h +++ b/client/src/util/native.h @@ -25,153 +25,28 @@ namespace native { char *Buffer; }; - struct CURDIR { - UNICODE_STRING DosPath; - uintptr_t Handle; - }; - - struct RTL_DRIVE_LETTER_CURDIR { - uint16_t Flags; - uint16_t Length; - uint32_t TimeStamp; - STRING DosPath; - }; - - struct RTL_USER_PROCESS_PARAMETERS { - uint32_t MaximumLength; - uint32_t Length; - uint32_t Flags; - uint32_t DebugFlags; - uintptr_t ConsoleHandle; - uint32_t ConsoleFlags; - uintptr_t StandardInput; - uintptr_t StandardOutput; - uintptr_t StandardError; - CURDIR CurrentDirectory; - UNICODE_STRING DllPath; - UNICODE_STRING ImagePathName; - UNICODE_STRING CommandLine; - uintptr_t Environment; - uint32_t StartingX; - uint32_t StartingY; - uint32_t CountX; - uint32_t CountY; - uint32_t CountCharsX; - uint32_t CountCharsY; - uint32_t FillAttribute; - uint32_t WindowFlags; - uint32_t ShowWindowFlags; - UNICODE_STRING WindowTitle; - UNICODE_STRING DesktopInfo; - UNICODE_STRING ShellInfo; - UNICODE_STRING RuntimeData; - RTL_DRIVE_LETTER_CURDIR CurrentDirectores[ 32 ]; - uintptr_t EnvironmentSize; - uintptr_t EnvironmentVersion; - uintptr_t PackageDependencyData; - uint32_t ProcessGroupId; - uint32_t LoaderThreads; - }; - - struct RTL_BALANCED_NODE { - RTL_BALANCED_NODE *Children[ 2 ]; - RTL_BALANCED_NODE *Left; - RTL_BALANCED_NODE *Right; - uintptr_t ParentValue; - }; - struct _PEB { uint8_t InheritedAddressSpace; uint8_t ReadImageFileExecOptions; uint8_t BeingDebugged; uint8_t BitField; - //uchar Padding0[ 4 ]; uintptr_t Mutant; uintptr_t ImageBaseAddress; PEB_LDR_DATA *Ldr; - RTL_USER_PROCESS_PARAMETERS *ProcessParameters; + uintptr_t ProcessParameters; uintptr_t SubSystemData; uintptr_t ProcessHeap; - RTL_CRITICAL_SECTION *FastPebLock; + uintptr_t FastPebLock; uintptr_t AtlThunkSListPtr; uintptr_t IFEOKey; - uint32_t CrossProcessFlags; - uint8_t Padding1[ 4 ]; - uintptr_t KernelCallbackTable; - uintptr_t UserSharedInfoPtr; - uint32_t SystemReserved[ 1 ]; + uintptr_t CrossProcessFlags; + union { + uintptr_t KernelCallbackTable; + uintptr_t UserSharedInfoPtr; + }; + uint32_t SystemReserved; uint32_t AtlThunkSListPtr32; uintptr_t ApiSetMap; - uint32_t TlsExpansionCounter; - uint8_t Padding2[ 4 ]; - uintptr_t TlsBitmap; - uint32_t TlsBitmapBits[ 2 ]; - uintptr_t ReadOnlySharedMemoryBase; - uintptr_t SparePvoid0; - uintptr_t ReadOnlyStaticServerData; - uintptr_t AnsiCodePageData; - uintptr_t OemCodePageData; - uintptr_t UnicodeCaseTableData; - uint32_t NumberOfProcessors; - uint32_t NtGlobalFlag; - LARGE_INTEGER CriticalSectionTimeout; - uintptr_t HeapSegmentReserve; - uintptr_t HeapSegmentCommit; - uintptr_t HeapDeCommitTotalFreeThreshold; - uintptr_t HeapDeCommitFreeBlockThreshold; - uint32_t NumberOfHeaps; - uint32_t MaximumNumberOfHeaps; - uintptr_t ProcessHeaps; - uintptr_t GdiSharedHandleTable; - uintptr_t ProcessStarterHelper; - uint32_t GdiDCAttributeList; - uint8_t Padding3[ 4 ]; - RTL_CRITICAL_SECTION *LoaderLock; - uint32_t OSMajorVersion; - uint32_t OSMinorVersion; - uint16_t OSBuildNumber; - uint16_t OSCSDVersion; - uint32_t OSPlatformId; - uint32_t ImageSubsystem; - uint32_t ImageSubsystemMajorVersion; - uint32_t ImageSubsystemMinorVersion; - uint8_t Padding4[ 4 ]; - uintptr_t ActiveProcessAffinityMask; -#ifdef _WIN32 - uint32_t GdiHandleBuffer[ 34 ]; -#else - uint32_t GdiHandleBuffer[ 60 ]; -#endif - uintptr_t PostProcessInitRoutine; - uintptr_t TlsExpansionBitmap; - uint32_t TlsExpansionBitmapBits[ 32 ]; - uint32_t SessionId; - uint8_t Padding5[ 4 ]; - ULARGE_INTEGER AppCompatFlags; - ULARGE_INTEGER AppCompatFlagsUser; - uintptr_t pShimData; - uintptr_t AppCompatInfo; - UNICODE_STRING CSDVersion; - uintptr_t ActivationContextData; - uintptr_t ProcessAssemblyStorageMap; - uintptr_t SystemDefaultActivationContextData; - uintptr_t SystemAssemblyStorageMap; - uintptr_t MinimumStackCommit; - uintptr_t FlsCallback; - LIST_ENTRY FlsListHead; - uintptr_t FlsBitmap; - uint32_t FlsBitmapBits[ 4 ]; - uint32_t FlsHighIndex; - uintptr_t WerRegistrationData; - uintptr_t WerShipAssertPtr; - uintptr_t pUnused; - uintptr_t pImageHeaderHash; - uint32_t TracingFlags; - uint8_t Padding6[ 4 ]; - uint64_t CsrServerReadOnlySharedMemoryBase; - uintptr_t TppWorkerpListLock; - LIST_ENTRY TppWorkerpList; - uintptr_t WaitOnAddressHashTable[ 128 ]; }; struct LDR_DATA_TABLE_ENTRY { @@ -183,30 +58,8 @@ namespace native { uint32_t SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; - uint8_t FlagGroup[ 4 ]; - uint32_t Flags; - uint16_t ObsoleteLoadCount; - uint16_t TlsIndex; - LIST_ENTRY HashLinks; - uint32_t TimeDateStamp; - uintptr_t EntryPointActivationContext; - uintptr_t Lock; - uintptr_t DdagNode; - LIST_ENTRY NodeModuleLink; - uintptr_t LoadContext; - uintptr_t ParentDllBase; - uintptr_t SwitchBackContext; - RTL_BALANCED_NODE BaseAddressIndexNode; - RTL_BALANCED_NODE MappingInfoIndexNode; - uintptr_t OriginalBase; - LARGE_INTEGER LoadTime; - uint32_t BaseNameHashValue; - uint32_t LoadReason; - uint32_t ImplicitPathOptions; - uint32_t ReferenceCount; }; - template<bool x64, typename base_type = typename std::conditional<x64, IMAGE_NT_HEADERS64, IMAGE_NT_HEADERS32>::type> struct nt_headers_t : base_type {}; @@ -252,6 +105,68 @@ namespace native { unicode_string_t<P> FullDllName; }; + +#pragma pack(push, 4) + struct reloc_entry_t { + uint16_t offset : 12; + uint16_t type : 4; + }; + + struct reloc_block_t { + uint32_t base_rva; + uint32_t size_block; + reloc_entry_t entries[ 1 ]; // Variable length array + + + inline reloc_block_t* get_next() { return ( reloc_block_t* ) ( ( char* ) this + this->size_block ); } + inline uint32_t num_entries() { return ( reloc_entry_t* ) get_next() - &entries[ 0 ]; } + }; + + struct image_named_import_t + { + uint16_t hint; + char name[ 1 ]; + }; + +#pragma pack(push, 8) + struct image_thunk_data_x64_t + { + union + { + uint64_t forwarder_string; + uint64_t function; + uint64_t address; // -> image_named_import_t + struct + { + uint64_t ordinal : 16; + uint64_t _reserved0 : 47; + uint64_t is_ordinal : 1; + }; + }; + }; +#pragma pack(pop) + + struct image_thunk_data_x86_t + { + union + { + uint32_t forwarder_string; + uint32_t function; + uint32_t address; // -> image_named_import_t + struct + { + uint32_t ordinal : 16; + uint32_t _reserved0 : 15; + uint32_t is_ordinal : 1; + }; + }; + }; +#pragma pack(pop) + + template<bool x64, + typename base_type = typename std::conditional<x64, image_thunk_data_x64_t, image_thunk_data_x86_t>::type> + struct image_thunk_data_t : base_type {}; + typedef struct _PROCESS_EXTENDED_BASIC_INFORMATION { SIZE_T Size; // set to sizeof structure on input |