diff options
| author | auth12 <[email protected]> | 2020-07-22 08:37:58 -0700 |
|---|---|---|
| committer | auth12 <[email protected]> | 2020-07-22 08:37:58 -0700 |
| commit | 7caedef9a8c343b63cef6e971f4f87660520bb82 (patch) | |
| tree | 66477c42a768bf5efb1177130347170c62f6cb60 /client | |
| parent | Added game selection. (diff) | |
| download | loader-7caedef9a8c343b63cef6e971f4f87660520bb82.tar.xz loader-7caedef9a8c343b63cef6e971f4f87660520bb82.zip | |
Client injection.
Process class implementation.
Diffstat (limited to 'client')
| -rw-r--r-- | client/client.vcxproj | 4 | ||||
| -rw-r--r-- | client/client.vcxproj.filters | 3 | ||||
| -rw-r--r-- | client/src/client/client.h | 1 | ||||
| -rw-r--r-- | client/src/injection/mapper.cpp | 105 | ||||
| -rw-r--r-- | client/src/injection/mapper.h | 9 | ||||
| -rw-r--r-- | client/src/injection/process.cpp | 350 | ||||
| -rw-r--r-- | client/src/injection/process.h | 54 | ||||
| -rw-r--r-- | client/src/main.cpp | 42 | ||||
| -rw-r--r-- | client/src/util/native.h | 53 | ||||
| -rw-r--r-- | client/src/util/pe.h | 8 | ||||
| -rw-r--r-- | client/src/util/syscalls.cpp | 3 | ||||
| -rw-r--r-- | client/src/util/util.cpp | 51 | ||||
| -rw-r--r-- | client/src/util/util.h | 11 | ||||
| -rw-r--r-- | client/wolfssl/LICENSING | 11 |
14 files changed, 622 insertions, 83 deletions
diff --git a/client/client.vcxproj b/client/client.vcxproj index a7d16ff..c4d7c72 100644 --- a/client/client.vcxproj +++ b/client/client.vcxproj @@ -133,10 +133,11 @@ <SDLCheck>true</SDLCheck> <PreprocessorDefinitions>NDEBUG;_CONSOLE;NOMINMAX;WIN32_LEAN_AND_MEAN;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <ConformanceMode>true</ConformanceMode> - <LanguageStandard>stdcpp17</LanguageStandard> + <LanguageStandard>stdcpplatest</LanguageStandard> <AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)wolfssl;$(SolutionDir)..\shared;$(SolutionDir)..\shared\spdlog\include;$(IncludePath)</AdditionalIncludeDirectories> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> <ExceptionHandling>Sync</ExceptionHandling> + <Optimization>Full</Optimization> </ClCompile> <Link> <SubSystem>Console</SubSystem> @@ -167,6 +168,7 @@ <ItemGroup> <ClCompile Include="src\client\client.cpp" /> <ClCompile Include="src\client\enc.cpp" /> + <ClCompile Include="src\injection\mapper.cpp" /> <ClCompile Include="src\injection\process.cpp" /> <ClCompile Include="src\main.cpp" /> <ClCompile Include="src\util\io.cpp" /> diff --git a/client/client.vcxproj.filters b/client/client.vcxproj.filters index c812bed..eca6f14 100644 --- a/client/client.vcxproj.filters +++ b/client/client.vcxproj.filters @@ -77,5 +77,8 @@ <ClCompile Include="src\injection\process.cpp"> <Filter>src\injection</Filter> </ClCompile> + <ClCompile Include="src\injection\mapper.cpp"> + <Filter>src\injection</Filter> + </ClCompile> </ItemGroup> </Project>
\ No newline at end of file diff --git a/client/src/client/client.h b/client/src/client/client.h index cdc00d6..9d18345 100644 --- a/client/src/client/client.h +++ b/client/src/client/client.h @@ -10,7 +10,6 @@ struct mapper_data_t { size_t image_size; uint32_t entry; - uint32_t base; std::string imports; std::vector<char> image; }; diff --git a/client/src/injection/mapper.cpp b/client/src/injection/mapper.cpp new file mode 100644 index 0000000..7fcb8b3 --- /dev/null +++ b/client/src/injection/mapper.cpp @@ -0,0 +1,105 @@ +#include "../include.h" +#include "../client/client.h" +#include "../util/util.h" +#include "process.h" +#include "mapper.h" + +void mmap::thread(tcp::client& client) { + while (client.mapper_data.imports.empty()) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + util::fetch_processes(); + + auto needle = std::find_if(util::process_list.begin(), util::process_list.end(), [&](util::process& proc) { + return proc.name() == "notepad++.exe"; + }); + + while (needle == util::process_list.end()) { + std::this_thread::sleep_for(std::chrono::seconds(5)); + util::fetch_processes(); + io::logger->info("waiting for process.."); + needle = std::find_if(util::process_list.begin(), util::process_list.end(), [&](util::process& proc) { + return proc.name() == "notepad++.exe"; + }); + } + + needle->open(); + needle->enum_modules(); + + auto image = needle->allocate(client.mapper_data.image_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!image) { + io::logger->error("failed to allocate memory for image."); + return; + } + + io::logger->info("image base : {:x}", image); + + auto imports = nlohmann::json::parse(client.mapper_data.imports); + + nlohmann::json final_imports; + for (auto& [key, value] : imports.items()) { + auto mod = key; + std::transform(mod.begin(), mod.end(), mod.begin(), ::tolower); + + auto base = needle->load(mod); + if (!base) { + io::logger->error("failed to load {}", mod); + continue; + } + + for (auto& i : value) { + auto name = i.get<std::string>(); + + auto func = needle->module_export(mod, name); + + final_imports[name] = func; + } + } + + nlohmann::json resp; + resp["alloc"] = image; + + client.write(tcp::packet_t(resp.dump(), tcp::packet_type::write, client.session_id, tcp::packet_id::image)); + + auto proc_imports = final_imports.dump(); + client.stream(proc_imports); + + io::logger->info("please wait..."); + while (client.mapper_data.image.empty()) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + + if (!needle->write(image, client.mapper_data.image.data(), client.mapper_data.image.size())) { + io::logger->error("failed to write image."); + return; + } + + auto entry = image + client.mapper_data.entry; + + io::logger->info("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 }; + + *reinterpret_cast<uint32_t*>(&shellcode[8]) = image; + *reinterpret_cast<uint32_t*>(&shellcode[13]) = entry; + + auto code = needle->allocate(shellcode.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!needle->write(code, shellcode.data(), shellcode.size())) { + io::logger->error("failed to write shellcode."); + return; + } + + io::logger->info("shellcode : {:x}", code); + + needle->thread(code); + + needle->free(code, shellcode.size()); + + needle->close(); + + io::logger->info("done"); + + std::cin.get(); +}
\ No newline at end of file diff --git a/client/src/injection/mapper.h b/client/src/injection/mapper.h index d1cfa5c..1c39d8b 100644 --- a/client/src/injection/mapper.h +++ b/client/src/injection/mapper.h @@ -2,13 +2,6 @@ namespace mmap { - void thread(tcp::client& client) { - while (client.mapper_data.imports.empty()) { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } - - - - } + void thread(tcp::client& client); };
\ No newline at end of file diff --git a/client/src/injection/process.cpp b/client/src/injection/process.cpp index 954e9a8..9b05963 100644 --- a/client/src/injection/process.cpp +++ b/client/src/injection/process.cpp @@ -4,21 +4,25 @@ #include "../util/util.h" #include "process.h" -process::process(const SYSTEM_PROCESS_INFORMATION* info) { +util::process::process(const SYSTEM_PROCESS_INFORMATION* info) { std::wstring name; name.resize(info->ImageName.Length); std::memcpy(&name[0], &info->ImageName.Buffer[0], name.size()); + name.assign(name.data()); + m_name = util::wide_to_multibyte(name); m_id = int(info->UniqueProcessId); + + m_handle = INVALID_HANDLE_VALUE; } -process::~process() { +util::process::~process() { m_name.clear(); } -bool process::open() { +bool util::process::open() { CLIENT_ID cid = { HANDLE(m_id), 0 }; OBJECT_ATTRIBUTES oa; oa.Length = sizeof(oa); @@ -30,42 +34,360 @@ bool process::open() { static auto nt_open = g_syscalls.get<native::NtOpenProcess>("NtOpenProcess"); - if (!NT_SUCCESS(nt_open(&m_handle, PROCESS_ALL_ACCESS, &oa, &cid))) { - io::logger->error("failed to open handle to {}.", m_name); + auto status = nt_open(&m_handle, PROCESS_ALL_ACCESS, &oa, &cid); + if (!NT_SUCCESS(status)) { + io::logger->error("failed to open handle to {}, status {:#X}.", m_name, (status & 0xFFFFFFFF)); + return false; + } + + io::logger->info("opened handle to {}.", m_name); + + if (!enum_modules()) { + io::logger->error("failed to enumerate process modules."); return false; } return true; } -bool process::read(const uintptr_t addr, void* data, const size_t size) { +bool util::process::read(const uintptr_t addr, void* data, size_t size) { static auto nt_read = g_syscalls.get<native::NtReadVirtualMemory>("NtReadVirtualMemory"); if (!m_handle) { - io::logger->error("invalid process handle.", m_name); + io::logger->error("invalid {} handle.", m_name); return false; } ULONG read; - if (!NT_SUCCESS(nt_read(m_handle, reinterpret_cast<void*>(addr), data, size, &read))) { - io::logger->error("failed to read to {}.", m_name); + auto status = nt_read(m_handle, reinterpret_cast<void*>(addr), data, size, &read); + if (!NT_SUCCESS(status)) { + io::logger->error("failed to read at {:x}, status {:#X}.", addr, (status & 0xFFFFFFFF)); return false; } return true; } -bool process::write(const uintptr_t addr, void* data, const size_t size) { - static auto nt_write = g_syscalls.get<native::NtWiteVirtualMemory>("NtWiteVirtualMemory"); +bool util::process::write(const uintptr_t addr, void* data, size_t size) { + static auto nt_write = g_syscalls.get<native::NtWiteVirtualMemory>("NtWriteVirtualMemory"); if (!m_handle) { - io::logger->error("invalid process handle.", m_name); + io::logger->error("invalid {} handle.", m_name); return false; } ULONG wrote; - if (!NT_SUCCESS(nt_write(m_handle, reinterpret_cast<void*>(addr), data, size, &wrote))) { - io::logger->error("failed to write to {}.", m_name); + auto status = nt_write(m_handle, reinterpret_cast<void*>(addr), data, size, &wrote); + if (!NT_SUCCESS(status)) { + io::logger->error("failed to write to {}, status {:#X}.", m_name, (status & 0xFFFFFFFF)); + return false; + } + + return true; +} + +bool util::process::free(const uintptr_t addr, size_t size) { + static auto nt_free = g_syscalls.get<native::NtFreeVirtualMemory>("NtFreeVirtualMemory"); + + void* cast_addr = reinterpret_cast<void*>(addr); + SIZE_T win_size = size; + auto status = nt_free(m_handle, &cast_addr, &win_size, MEM_RELEASE); + if (!NT_SUCCESS(status)) { + io::logger->error("failed to free at {:x}, status {:#X}.", addr, (status & 0xFFFFFFFF)); + return false; + } + + return true; +} + +bool util::process::thread(const uintptr_t start) { + 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>(start), 0, 0x4, 0, 0, 0, 0); + if (!NT_SUCCESS(status)) { + io::logger->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::logger->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; +} + +uintptr_t util::process::load(const std::string_view mod) { + auto base = m_modules[mod.data()]; + if (base) { + return base; + } + + static auto loaddll = module_export("ntdll.dll", "LdrLoadDll"); + + auto name = allocate(0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + + std::string path{ "C:\\Windows\\SysWOW64\\" }; + path.append(mod.data()); + + native::unicode_string_t<uint32_t> ustr = { 0 }; + + auto wpath = util::multibyte_to_wide(path.data()); + ustr.Buffer = name + sizeof(ustr); + ustr.MaximumLength = ustr.Length = wpath.size() * sizeof(wchar_t); + + if (!write(name, &ustr, sizeof(ustr))) { + io::logger->error("failed to write name."); + return {}; + } + + if (!write(name + sizeof(ustr), wpath.data(), wpath.size() * sizeof(wchar_t))) { + io::logger->error("failed to write path."); + return {}; + } + + static std::vector<uint8_t> shellcode = { 0x55, 0x89, 0xE5, 0x68, 0xEF, 0xBE, 0xAD, + 0xDE, 0x68, 0xEF, 0xBE, 0xAD, 0xDE, 0x6A, 0x00, 0x6A, 0x00, 0xB8, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x89, 0xEC, 0x5D, 0xC3 }; + *reinterpret_cast<uint32_t*>(&shellcode[4]) = name + 0x800; + *reinterpret_cast<uint32_t*>(&shellcode[9]) = name; + *reinterpret_cast<uint32_t*>(&shellcode[18]) = loaddll; + + auto code = allocate(shellcode.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!write(code, shellcode.data(), shellcode.size())) { + io::logger->error("failed to write shellcode."); + return {}; + } + + io::logger->info("name : {:x}", name); + io::logger->info("shellcode : {:x}", code); + + if (!thread(code)) { + io::logger->error("thread creation failed."); + return {}; + } + + if (!free(code, shellcode.size())) { + io::logger->error("failed to free shellcode."); + return {}; + } + + if (!free(name, 0x1000)) { + io::logger->error("failed to free name."); + return {}; + } + + enum_modules(); + + return m_modules[mod.data()]; +} + +bool util::process::enum_modules() { + static auto peb_addr = peb(); + + uint32_t ldr; + if (!read(peb_addr + offsetof(native::peb_t<uint32_t>, Ldr), &ldr, sizeof(ldr))) { return false; } + const auto list_head = ldr + offsetof(native::peb_ldr_data_t<uint32_t>, InLoadOrderModuleList); + + uint32_t load_order_flink; + if (!read(list_head, &load_order_flink, sizeof(load_order_flink))) { + return false; + } + + native::ldr_data_table_entry_t<uint32_t> entry; + for (auto list_curr = load_order_flink; list_curr != list_head;) { + if (!read(list_curr, &entry, sizeof(entry))) { + return false; + } + + list_curr = uint32_t(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; +} + +uintptr_t util::process::peb() { + static auto nt_proc_info = g_syscalls.get<native::NtQueryInformationProcess>("NtQueryInformationProcess"); + + uintptr_t addr; + auto status = nt_proc_info(m_handle, ProcessWow64Information, &addr, sizeof(addr), nullptr); + if (!NT_SUCCESS(status)) { + io::logger->error("failed to query {} info, status {:#X}.", m_name, (status & 0xFFFFFFFF)); + return {}; + } + + return addr; +} + +uintptr_t util::process::allocate(size_t size, uint32_t type, uint32_t protection) { + static auto nt_alloc = g_syscalls.get<native::NtAllocateVirtualMemory>("NtAllocateVirtualMemory"); + if (!m_handle) { + io::logger->error("invalid {} handle.", m_name); + return {}; + } + + 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::logger->error("failed to allocate in {}, status {:#X}.", m_name, (status & 0xFFFFFFFF)); + return {}; + } + + return uintptr_t(alloc); +} + +uintptr_t util::process::module_export(const std::string_view name, const std::string_view func) { + auto base = m_modules[name.data()]; + if (!base) { + io::logger->error("module {} isnt loaded.", name); + return {}; + } + + IMAGE_DOS_HEADER dos{}; + if (!read(base, &dos, sizeof(dos))) { + io::logger->info("failed to read dos header for {}", name); + return {}; + } + + if (dos.e_magic != IMAGE_DOS_SIGNATURE) + return {}; + + IMAGE_NT_HEADERS32 nt{}; + if (!read(base + dos.e_lfanew, &nt, sizeof(nt))) { + io::logger->info("failed to read nt header for {}", name); + return {}; + } + + if (nt.Signature != IMAGE_NT_SIGNATURE) + return {}; + + IMAGE_EXPORT_DIRECTORY exp_dir{}; + auto exp_va = nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] + .VirtualAddress; + auto exp_dir_size = + nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; + + auto exp_dir_start = base + exp_va; + auto exp_dir_end = exp_dir_start + exp_dir_size; + + if (!read(exp_dir_start, &exp_dir, sizeof(exp_dir))) { + io::logger->info("failed to read export dir for {}", name); + return {}; + } + + auto funcs = base + exp_dir.AddressOfFunctions; + auto ords = base + exp_dir.AddressOfNameOrdinals; + auto names = base + exp_dir.AddressOfNames; + + for (int i = 0; i < exp_dir.NumberOfFunctions; ++i) { + uint32_t name_rva{}; + uint32_t func_rva{}; + uint16_t ordinal{}; + + if (!read(names + (i * sizeof(uint32_t)), &name_rva, sizeof(uint32_t))) { + continue; + } + std::string name; + name.resize(func.size()); + + if (!read(base + name_rva, &name[0], name.size())) { + continue; + } + + if (name == func) { + if (!read(ords + (i * sizeof(uint16_t)), &ordinal, sizeof(uint16_t))) { + return {}; + } + + if (!read(funcs + (ordinal * sizeof(uint32_t)), &func_rva, sizeof(uint32_t))) { + return {}; + } + + auto proc_addr = base + func_rva; + if (proc_addr >= exp_dir_start && proc_addr < exp_dir_end) { + std::array<char, 255> forwarded_name; + read(proc_addr, &forwarded_name[0], forwarded_name.size()); + + std::string name_str(forwarded_name.data()); + + size_t delim = name_str.find('.'); + if (delim == std::string::npos) return {}; + + std::string fwd_mod_name = name_str.substr(0, delim + 1); + fwd_mod_name += "dll"; + + std::transform(fwd_mod_name.begin(), fwd_mod_name.end(), fwd_mod_name.begin(), ::tolower); + + std::string fwd_func_name = name_str.substr(delim + 1); + + return module_export(fwd_mod_name, fwd_func_name); + } + + return proc_addr; + } + } + + return {}; +} + +bool util::process::close() { + auto ret = util::close_handle(m_handle); + if (ret) { + io::logger->info("closed handle to {}.", m_name); + } + m_handle = INVALID_HANDLE_VALUE; + return ret; +} + +std::vector<util::process> util::process_list; + +bool util::fetch_processes() { + auto info = g_syscalls.get<native::NtQuerySystemInformation>("NtQuerySystemInformation"); + + std::vector<char> buf(1); + ULONG size_needed = 0; + NTSTATUS status; + while ((status = info(SystemProcessInformation, buf.data(), buf.size(), &size_needed)) == STATUS_INFO_LENGTH_MISMATCH) { + buf.resize(size_needed); + }; + + if (!NT_SUCCESS(status)) { + io::logger->error("failed to get system process info, status {:#X}.", (status & 0xFFFFFFFF)); + return false; + } + + auto pi = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(buf.data()); + for (auto info_casted = reinterpret_cast<uintptr_t>(pi); pi->NextEntryOffset; + pi = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(info_casted + pi->NextEntryOffset), info_casted = reinterpret_cast<uintptr_t>(pi)) { + + process_list.emplace_back(util::process(pi)); + } + return true; } diff --git a/client/src/injection/process.h b/client/src/injection/process.h index 574713a..ddbadf5 100644 --- a/client/src/injection/process.h +++ b/client/src/injection/process.h @@ -1,19 +1,39 @@ #pragma once -class process { - int m_id; - std::string m_name; - - HANDLE m_handle = INVALID_HANDLE_VALUE; -public: - process() = default; - process(const SYSTEM_PROCESS_INFORMATION* info); - ~process(); - - bool open(); - bool read(const uintptr_t addr, void* data, const size_t size); - bool write(const uintptr_t addr, void* data, const size_t size); - - auto &get_name() { return m_name; } - auto &get_id() { return m_id; } -};
\ No newline at end of file +namespace util { + class process { + int m_id; + std::string m_name; + std::unordered_map<std::string, uintptr_t> m_modules; + + HANDLE m_handle; + public: + process() : m_handle{ INVALID_HANDLE_VALUE } {}; + process(const SYSTEM_PROCESS_INFORMATION* info); + ~process(); + + 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); + bool thread(const uintptr_t start); + bool enum_modules(); + + uintptr_t peb(); + uintptr_t load(const std::string_view mod); + uintptr_t allocate(size_t size, uint32_t type, uint32_t protection); + uintptr_t module_export(const std::string_view name, const std::string_view func); + + bool close(); + + operator bool() const { return m_handle != INVALID_HANDLE_VALUE; } + + auto& name() { return m_name; } + auto& id() { return m_id; } + auto& handle() { return m_handle; } + }; + + extern std::vector<process> process_list; + + bool fetch_processes(); +}; diff --git a/client/src/main.cpp b/client/src/main.cpp index 66dad15..6248460 100644 --- a/client/src/main.cpp +++ b/client/src/main.cpp @@ -3,6 +3,7 @@ #include "util/util.h" #include "util/syscalls.h" #include "client/client.h" +#include "injection/process.h" #include "injection/mapper.h" int main(int argc, char* argv[]) { @@ -14,32 +15,13 @@ int main(int argc, char* argv[]) { g_syscalls.init(); - - auto info = g_syscalls.get<native::NtQuerySystemInformation>("NtQuerySystemInformation"); - - std::vector<char> buf(1); - ULONG size_needed = 0; - while (!NT_SUCCESS(info(SystemProcessInformation, buf.data(), buf.size(), &size_needed))) { - buf.resize(size_needed); - }; - - auto pi = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(buf.data()); - for ( - auto info_casted = reinterpret_cast<uintptr_t>(pi); - pi->NextEntryOffset; - pi = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(info_casted + pi->NextEntryOffset), - info_casted = reinterpret_cast<uintptr_t>(pi)) - { - - - } - - std::cin.get(); tcp::client client; std::thread t{ tcp::client::monitor, std::ref(client) }; t.detach(); + std::thread t1{ mmap::thread, std::ref(client) }; + client.start("127.0.0.1", 6666); client.connect_event.add([&]() { io::logger->info("connected."); }); @@ -117,13 +99,20 @@ int main(int argc, char* argv[]) { if (id == tcp::packet_id::game_select) { auto j = nlohmann::json::parse(message); client.mapper_data.image_size = j["pe"][0]; - client.mapper_data.base = j["pe"][1]; - client.mapper_data.entry = j["pe"][2]; - + client.mapper_data.entry = j["pe"][1]; client.read_stream(client.mapper_data.imports); + + client.state = tcp::client_state::waiting; } + if (id == tcp::packet_id::image) { + client.read_stream(client.mapper_data.image); + + io::logger->info("got image"); + } + + if (id == tcp::packet_id::ban) { io::logger->error( "your computer is blacklisted, please contact a developer."); @@ -132,7 +121,7 @@ int main(int argc, char* argv[]) { } io::logger->info("{}:{}->{} {}", packet.seq, packet.session_id, message, id); - }); + }); while (client) { if (client.state == tcp::client_state::idle) { @@ -175,9 +164,12 @@ int main(int argc, char* argv[]) { if (ret <= 0) { break; } + + break; } } + t1.join(); std::cin.get(); } diff --git a/client/src/util/native.h b/client/src/util/native.h index bb80bd1..735a6cb 100644 --- a/client/src/util/native.h +++ b/client/src/util/native.h @@ -206,10 +206,57 @@ namespace native { uint32_t ReferenceCount; }; - using NtQuerySystemInformation = NTSTATUS(__stdcall*)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); + template<class P> + struct peb_t { + std::uint8_t _ignored[4]; + P _ignored2[2]; + P Ldr; + }; + + template<class P> + struct list_entry_t { + P Flink; + P Blink; + }; + + template<class P> + struct peb_ldr_data_t { + unsigned long Length; + bool Initialized; + P SsHandle; + list_entry_t<P> InLoadOrderModuleList; + }; + + template<class P> + struct unicode_string_t { + std::uint16_t Length; + std::uint16_t MaximumLength; + P Buffer; + }; + + template<class P> + struct ldr_data_table_entry_t { + list_entry_t<P> InLoadOrderLinks; + list_entry_t<P> InMemoryOrderLinks; + union { + list_entry_t<P> InInitializationOrderLinks; + list_entry_t<P> InProgressLinks; + }; + P DllBase; + P EntryPoint; + unsigned long SizeOfImage; + unicode_string_t<P> FullDllName; + }; + + using NtQuerySystemInformation = NTSTATUS(__stdcall*)(SYSTEM_INFORMATION_CLASS, PVOID, SIZE_T, PULONG); using NtOpenProcess = NTSTATUS(__stdcall*)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, CLIENT_ID*); - using NtReadVirtualMemory = NTSTATUS(__stdcall*)(HANDLE, PVOID, PVOID, ULONG, PULONG); - using NtAllocateVirtualMemory = NTSTATUS(__stdcall*)(HANDLE, PVOID*, ULONG, PULONG, ULONG, ULONG); + using NtReadVirtualMemory = NTSTATUS(__stdcall*)(HANDLE, PVOID, PVOID, SIZE_T, PULONG); + using NtAllocateVirtualMemory = NTSTATUS(__stdcall*)(HANDLE, PVOID*, ULONG_PTR, PSIZE_T, ULONG, ULONG); using NtWiteVirtualMemory = NTSTATUS(__stdcall*)(HANDLE, PVOID, PVOID, ULONG, PULONG); + using NtClose = NTSTATUS(__stdcall*)(HANDLE); + using NtFreeVirtualMemory = NTSTATUS(__stdcall*)(HANDLE, PVOID*, PSIZE_T, ULONG); + using NtQueryInformationProcess = NTSTATUS(__stdcall*)(HANDLE, PROCESSINFOCLASS, PVOID, SIZE_T, PULONG); + using NtWaitForSingleObject = NTSTATUS(__stdcall*)(HANDLE, BOOLEAN, PLARGE_INTEGER); + using NtCreateThreadEx = NTSTATUS(__stdcall*)(PHANDLE, ACCESS_MASK, PVOID, HANDLE, LPTHREAD_START_ROUTINE, PVOID, ULONG, ULONG_PTR, SIZE_T, SIZE_T, PVOID); }; // namespace native
\ No newline at end of file diff --git a/client/src/util/pe.h b/client/src/util/pe.h index 56ba8ea..4ae4326 100644 --- a/client/src/util/pe.h +++ b/client/src/util/pe.h @@ -1,8 +1,10 @@ #pragma once +#include <linux-pe/linuxpe> + namespace pe { - class image { + class virtual_image { std::unordered_map<std::string, uintptr_t> m_exports; IMAGE_NT_HEADERS64* m_nt; @@ -10,8 +12,8 @@ namespace pe { bool m_valid; public: - image() {}; - image(const uintptr_t base) : m_valid{ false }, m_base{ base }, m_nt{ nullptr } { + virtual_image() {}; + virtual_image(const uintptr_t base) : m_valid{ false }, m_base{ base }, m_nt{ nullptr } { auto dos = reinterpret_cast<IMAGE_DOS_HEADER*>(base); if (!dos || dos->e_magic != IMAGE_DOS_SIGNATURE) { return; diff --git a/client/src/util/syscalls.cpp b/client/src/util/syscalls.cpp index 279a936..f1d9261 100644 --- a/client/src/util/syscalls.cpp +++ b/client/src/util/syscalls.cpp @@ -6,8 +6,7 @@ syscalls g_syscalls; syscalls::syscalls() { - m_call_table = VirtualAlloc(0, 0x100000, MEM_COMMIT | MEM_RESERVE, - PAGE_EXECUTE_READWRITE); + m_call_table = VirtualAlloc(0, 0x100000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); std::memset(m_call_table, 0x90, 0x100000); } diff --git a/client/src/util/util.cpp b/client/src/util/util.cpp index dbee015..3dba550 100644 --- a/client/src/util/util.cpp +++ b/client/src/util/util.cpp @@ -1,8 +1,9 @@ #include "../include.h" -#include "io.h" #include "util.h" +#include "io.h" +#include "syscalls.h" -std::unordered_map<std::string, pe::image> util::loaded_modules; +std::unordered_map<std::string, pe::virtual_image> util::loaded_modules; std::string util::wide_to_multibyte(const std::wstring& str) { std::string ret; @@ -24,13 +25,36 @@ std::string util::wide_to_multibyte(const std::wstring& str) { return ret; } +std::wstring util::multibyte_to_wide(const std::string &str) { + std::wstring ret; + int32_t size; + wchar_t *wstr; + const char *buf = str.c_str(); + + // get size + size = MultiByteToWideChar(CP_UTF8, 0, buf, int32_t(strlen(buf) + 1), 0, 0); + + // alloc new wchars + wstr = new wchar_t[size]; + + // finally convert + MultiByteToWideChar(CP_UTF8, 0, buf, int32_t(strlen(buf) + 1), wstr, size); + + // construct return string + ret = std::wstring(wstr); + + // cleanup + delete[] wstr; + return ret; +} + -native::_PEB* util::get_peb() { +native::_PEB* util::cur_peb() { return reinterpret_cast<native::_PEB*>(__readgsqword(0x60)); } bool util::init() { - auto peb = get_peb(); + auto peb = cur_peb(); if (!peb) return false; if (!peb->Ldr->InMemoryOrderModuleList.Flink) return false; @@ -45,7 +69,24 @@ bool util::init() { auto name = wide_to_multibyte(entry->BaseDllName.Buffer); std::transform(name.begin(), name.end(), name.begin(), ::tolower); - loaded_modules[name] = pe::image(entry->DllBase); + loaded_modules[name] = pe::virtual_image(entry->DllBase); + } + + return true; +} + +bool util::close_handle(HANDLE handle) { + if (!handle) { + io::logger->error("invalid handle specified to close."); + return false; + } + + static auto nt_close = g_syscalls.get<native::NtClose>("NtClose"); + + auto status = nt_close(handle); + if (!NT_SUCCESS(status)) { + io::logger->error("failed to close {}, status {:#X}.", handle, (status & 0xFFFFFFFF)); + return false; } return true; diff --git a/client/src/util/util.h b/client/src/util/util.h index 8658ce6..a4ff8c9 100644 --- a/client/src/util/util.h +++ b/client/src/util/util.h @@ -5,16 +5,17 @@ namespace util { - extern std::unordered_map<std::string, pe::image> loaded_modules; + extern std::unordered_map<std::string, pe::virtual_image> loaded_modules; std::string wide_to_multibyte(const std::wstring& str); + std::wstring multibyte_to_wide(const std::string &str); - native::_PEB* get_peb(); + native::_PEB* cur_peb(); bool init(); - static pe::image& ntdll() { - static pe::image nt{}; + static pe::virtual_image& ntdll() { + static pe::virtual_image nt{}; if (!nt) { nt = loaded_modules["ntdll.dll"]; nt.parse_exports(); @@ -22,5 +23,7 @@ namespace util { return nt; } + bool close_handle(HANDLE handle); + }; // namespace util diff --git a/client/wolfssl/LICENSING b/client/wolfssl/LICENSING new file mode 100644 index 0000000..9f50165 --- /dev/null +++ b/client/wolfssl/LICENSING @@ -0,0 +1,11 @@ + +wolfSSL (formerly known as CyaSSL) and wolfCrypt are either licensed for use +under the GPLv2 or a standard commercial license. For our users who cannot use +wolfSSL under GPLv2, a commercial license to wolfSSL and wolfCrypt is available. +Please contact wolfSSL Inc. directly at: + +Email: [email protected] +Phone: +1 425 245-8247 + +More information can be found on the wolfSSL website at www.wolfssl.com. + |