diff options
| author | auth12 <[email protected]> | 2020-07-24 10:56:14 -0700 |
|---|---|---|
| committer | auth12 <[email protected]> | 2020-07-24 10:56:14 -0700 |
| commit | e487ffe1671ba807528d4039ef66f8f8f7eeb853 (patch) | |
| tree | c65cc4dd529f8e37f9cca81d38c749dece13a574 /client/src | |
| parent | Injection and server changes. (diff) | |
| download | loader-e487ffe1671ba807528d4039ef66f8f8f7eeb853.tar.xz loader-e487ffe1671ba807528d4039ef66f8f8f7eeb853.zip | |
Injection process changes and server improvements.
Diffstat (limited to 'client/src')
| -rw-r--r-- | client/src/client/client.h | 6 | ||||
| -rw-r--r-- | client/src/client/packet.h | 105 | ||||
| -rw-r--r-- | client/src/injection/mapper.cpp | 46 | ||||
| -rw-r--r-- | client/src/injection/pe.h (renamed from client/src/util/pe.h) | 4 | ||||
| -rw-r--r-- | client/src/injection/process.cpp | 99 | ||||
| -rw-r--r-- | client/src/injection/process.h | 9 | ||||
| -rw-r--r-- | client/src/main.cpp | 5 | ||||
| -rw-r--r-- | client/src/util/io.cpp | 22 | ||||
| -rw-r--r-- | client/src/util/io.h | 1 | ||||
| -rw-r--r-- | client/src/util/syscalls.cpp | 2 | ||||
| -rw-r--r-- | client/src/util/util.cpp | 28 | ||||
| -rw-r--r-- | client/src/util/util.h | 7 |
12 files changed, 209 insertions, 125 deletions
diff --git a/client/src/client/client.h b/client/src/client/client.h index b76ac9f..4e6af90 100644 --- a/client/src/client/client.h +++ b/client/src/client/client.h @@ -8,8 +8,8 @@ #include "packet.h" struct mapper_data_t { - size_t image_size; - uint32_t entry; + size_t image_size = 0; + uint32_t entry = 0; std::string imports; std::vector<char> image; }; @@ -56,7 +56,7 @@ namespace tcp { event<packet_t&> receive_event; event<> connect_event; - client() : m_socket{ -1 }, m_active{ false }, state{ client_state::idle } {} + client() : m_socket{ -1 }, m_active{ false }, state{ client_state::idle }, m_server_ssl{ nullptr } {} void start(const std::string_view server_ip, const uint16_t port); diff --git a/client/src/client/packet.h b/client/src/client/packet.h index fccd1a5..b8d9ecf 100644 --- a/client/src/client/packet.h +++ b/client/src/client/packet.h @@ -4,67 +4,68 @@ #include <json.hpp> namespace tcp { -constexpr size_t session_id_len = 10; -constexpr size_t message_len = 512; + constexpr size_t session_id_len = 10; + constexpr size_t message_len = 512; -enum packet_type { write = 0, read }; + enum packet_type { write = 0, read }; -enum packet_id { - message = 0, - hwid, - session, - login_req, - login_resp, - process_list, - ban, - game_select, - image -}; + enum packet_id { + message = 0, + hwid, + session, + login_req, + login_resp, + process_list, + ban, + game_select, + image + }; -struct packet_t { - std::string message; - std::string session_id; - int id; - int seq; + struct packet_t { + std::string message; + std::string session_id; + int id; + int seq; - packet_t() {} - packet_t(const std::string_view msg, const packet_type &type, - std::string_view session = "", - const packet_id &action = packet_id::message) { - if (type == read) { - ++seq; + packet_t() {} + packet_t(const std::string_view msg, const packet_type type, + std::string_view session = "", + const packet_id action = packet_id::message) { + if (type == read) { + ++seq; - message = msg; - enc::decrypt_message(message); + message = msg; + enc::decrypt_message(message); - auto json = nlohmann::json::parse(message); + auto json = nlohmann::json::parse(message); - id = json["id"]; - message = json["message"]; - session_id = json["session_id"]; - } else { - nlohmann::json json; - json["id"] = action; - json["session_id"] = session; - json["message"] = msg.data(); + id = json["id"]; + message = json["message"]; + session_id = json["session_id"]; + } + else { + nlohmann::json json; + json["id"] = action; + json["session_id"] = session; + json["message"] = msg.data(); - message = json.dump(); - session_id = session; - id = action; + message = json.dump(); + session_id = session; + id = action; - enc::encrypt_message(message); - } - } + enc::encrypt_message(message); + } + } - ~packet_t() { - message.clear(); - session_id.clear(); - id = -1; - } + ~packet_t() { + message.clear(); + session_id.clear(); + id = -1; + } - operator bool() const { - return !message.empty() && !session_id.empty() && id != -1; - } - auto &operator()() { return message; } -}; + operator bool() const { + return !message.empty() && !session_id.empty() && id != -1; + } + auto& operator()() { return message; } + }; }; // namespace tcp diff --git a/client/src/injection/mapper.cpp b/client/src/injection/mapper.cpp index 570155e..68f0f6e 100644 --- a/client/src/injection/mapper.cpp +++ b/client/src/injection/mapper.cpp @@ -9,23 +9,24 @@ void mmap::thread(tcp::client& client) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } - util::fetch_processes(); + std::vector<util::process> process_list; + util::fetch_processes(process_list); - auto needle = std::find_if(util::process_list.begin(), util::process_list.end(), [&](util::process& proc) { - return strcmp(proc.name().c_str(), "notepad++.exe") == 0; + auto needle = std::find_if(process_list.begin(), 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)); + while (needle == process_list.end()) { + std::this_thread::sleep_for(std::chrono::seconds(2)); - util::fetch_processes(); - - io::logger->info("size {}", util::process_list.size()); + util::fetch_processes(process_list); + + io::logger->info("size {}", process_list.size()); io::logger->info("waiting for process.."); - needle = std::find_if(util::process_list.begin(), util::process_list.end(), [&](util::process& proc) { - return strcmp(proc.name().c_str(), "notepad++.exe") == 0; + needle = std::find_if(process_list.begin(), process_list.end(), [&](util::process& proc) { + return proc.name() == "notepad++.exe"; }); } @@ -44,27 +45,25 @@ void mmap::thread(tcp::client& client) { return; } + client.mapper_data.image_size = 0; + 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); + auto base = needle->load(key); if (!base) { - io::logger->error("failed to load {}", mod); + io::logger->error("failed to load {}", key); continue; } for (auto& i : value) { auto name = i.get<std::string>(); - auto func = needle->module_export(mod, name); - - final_imports[name] = func; + final_imports[name] = needle->module_export(base, name); } } @@ -76,6 +75,11 @@ void mmap::thread(tcp::client& client) { auto proc_imports = final_imports.dump(); client.stream(proc_imports); + proc_imports.clear(); + final_imports.clear(); + imports.clear(); + client.mapper_data.imports.clear(); + io::logger->info("please wait..."); while (client.mapper_data.image.empty()) { std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -86,6 +90,8 @@ void mmap::thread(tcp::client& client) { return; } + client.mapper_data.image.clear(); + auto entry = image + client.mapper_data.entry; io::logger->info("entry : {:x}", entry); @@ -96,6 +102,12 @@ void mmap::thread(tcp::client& client) { *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<uint64_t*>(&shellcode[6]) = image; + *reinterpret_cast<uint32_t*>(&shellcode[26]) = 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."); diff --git a/client/src/util/pe.h b/client/src/injection/pe.h index 4ae4326..b5f9faa 100644 --- a/client/src/util/pe.h +++ b/client/src/injection/pe.h @@ -1,7 +1,5 @@ #pragma once -#include <linux-pe/linuxpe> - namespace pe { class virtual_image { @@ -12,7 +10,7 @@ namespace pe { bool m_valid; public: - virtual_image() {}; + virtual_image() : m_nt{ nullptr }, m_valid{ false }, m_base{ 0 } {}; 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) { diff --git a/client/src/injection/process.cpp b/client/src/injection/process.cpp index 6552d3c..06e5ea8 100644 --- a/client/src/injection/process.cpp +++ b/client/src/injection/process.cpp @@ -35,6 +35,7 @@ bool util::process::open() { io::logger->info("opened handle to {}.", m_name); + return true; } @@ -81,14 +82,14 @@ bool util::process::free(const uintptr_t addr, size_t size) { 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)); @@ -110,7 +111,7 @@ uintptr_t util::process::load(const std::string_view mod) { return base; } - static auto loaddll = module_export("ntdll.dll", "LdrLoadDll"); + static auto loaddll = module_export(m_modules["ntdll.dll"], "LdrLoadDll"); auto name = allocate(0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); @@ -169,7 +170,62 @@ uintptr_t util::process::load(const std::string_view mod) { return m_modules[mod.data()]; } +uintptr_t util::process::map(const std::string_view mod) { + auto base = m_modules[mod.data()]; + if (base) { + return base; + } + + std::string path{ "C:\\Windows\\SysWOW64\\" }; + path.append(mod.data()); + + std::vector<char> buf; + if (!io::read_file(path, buf)) { + return {}; + } + + std::vector<char> final_image; + + auto dos = reinterpret_cast<IMAGE_DOS_HEADER*>(buf.data()); + auto nt = reinterpret_cast<IMAGE_NT_HEADERS32*>(buf.data() + dos->e_lfanew); + + + final_image.resize(nt->OptionalHeader.SizeOfImage); + + // headers + std::memcpy(&final_image[0], &buf[0], nt->OptionalHeader.SizeOfHeaders); + + // copy image + auto secs = IMAGE_FIRST_SECTION(nt); + for (int i = 0; i < nt->FileHeader.NumberOfSections; i++) { + auto sec = secs[i]; + std::memcpy(&final_image[sec.VirtualAddress], &buf[sec.PointerToRawData], sec.SizeOfRawData); + } + + auto image = allocate(final_image.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!image) { + io::logger->error("failed to alloc buffer for {}.", path); + return {}; + } + + io::logger->info("{:x}->{}", image, mod); + + // fix relocations + + + if (!write(image, final_image.data(), final_image.size())) { + io::logger->error("failed to write final image."); + return {}; + } + + m_modules[mod.data()] = image; + + return image; +} + bool util::process::enum_modules() { + m_modules.clear(); + static auto peb_addr = peb(); uint32_t ldr; @@ -238,16 +294,15 @@ uintptr_t util::process::allocate(size_t size, uint32_t type, uint32_t protectio 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()]; +uintptr_t util::process::module_export(const uintptr_t base, const std::string_view func) { if (!base) { - io::logger->error("module {} isnt loaded.", name); + io::logger->error("module {} isnt loaded.", m_name); return {}; } IMAGE_DOS_HEADER dos{}; if (!read(base, &dos, sizeof(dos))) { - io::logger->info("failed to read dos header for {}", name); + io::logger->info("failed to read dos header for {}", m_name); return {}; } @@ -256,7 +311,7 @@ uintptr_t util::process::module_export(const std::string_view name, const std::s IMAGE_NT_HEADERS32 nt{}; if (!read(base + dos.e_lfanew, &nt, sizeof(nt))) { - io::logger->info("failed to read nt header for {}", name); + io::logger->info("failed to read nt header for {}", m_name); return {}; } @@ -273,7 +328,7 @@ uintptr_t util::process::module_export(const std::string_view name, const std::s 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); + io::logger->info("failed to read export dir for {}", m_name); return {}; } @@ -322,7 +377,7 @@ uintptr_t util::process::module_export(const std::string_view name, const std::s std::string fwd_func_name = name_str.substr(delim + 1); - return module_export(fwd_mod_name, fwd_func_name); + return module_export(load(fwd_mod_name), fwd_func_name); } return proc_addr; @@ -341,14 +396,11 @@ bool util::process::close() { return ret; } -std::vector<util::process> util::process_list; - -bool util::fetch_processes() { - process_list.clear(); - +bool util::fetch_processes(std::vector<process> &out) { static auto info = g_syscalls.get<native::NtQuerySystemInformation>("NtQuerySystemInformation"); - std::vector<char> buf(1); + std::vector<uint8_t> buf(1); + ULONG size_needed = 0; NTSTATUS status; while ((status = info(SystemProcessInformation, buf.data(), buf.size(), &size_needed)) == STATUS_INFO_LENGTH_MISMATCH) { @@ -360,12 +412,19 @@ bool util::fetch_processes() { return false; } + out.clear(); 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)); + while (pi->NextEntryOffset) { + out.emplace_back(util::process(pi)); + pi = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(uintptr_t(pi) + pi->NextEntryOffset); } + /*std::set_difference(new_list.begin(), new_list.end(), process_list.begin(), process_list.end(), std::inserter(diff, diff.begin()), [&](util::process &l, util::process &r) { + return l.id() != r.id(); + }); + + for (auto& p : diff) { + io::logger->info("{} is new", p.name()); + }*/ return true; } diff --git a/client/src/injection/process.h b/client/src/injection/process.h index ddbadf5..8e2c4f1 100644 --- a/client/src/injection/process.h +++ b/client/src/injection/process.h @@ -8,7 +8,7 @@ namespace util { HANDLE m_handle; public: - process() : m_handle{ INVALID_HANDLE_VALUE } {}; + process() : m_handle{ INVALID_HANDLE_VALUE }, m_id{ -1 } {}; process(const SYSTEM_PROCESS_INFORMATION* info); ~process(); @@ -21,8 +21,9 @@ namespace util { uintptr_t peb(); uintptr_t load(const std::string_view mod); + uintptr_t map(const std::string_view path); 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); + uintptr_t module_export(const uintptr_t base, const std::string_view func); bool close(); @@ -33,7 +34,5 @@ namespace util { auto& handle() { return m_handle; } }; - extern std::vector<process> process_list; - - bool fetch_processes(); + bool fetch_processes(std::vector<process> &out); }; diff --git a/client/src/main.cpp b/client/src/main.cpp index 0b6580c..441118a 100644 --- a/client/src/main.cpp +++ b/client/src/main.cpp @@ -42,13 +42,15 @@ int main(int argc, char* argv[]) { if (version != message) { io::logger->error("please update your client."); client.shutdown(); + + return; } int ret = client.write(tcp::packet_t("hwid", tcp::packet_type::write, client.session_id, tcp::packet_id::hwid)); if (ret <= 0) { - io::logger->error("internal error."); + io::logger->error("failed to send hwid."); client.shutdown(); return; } @@ -174,5 +176,4 @@ int main(int argc, char* argv[]) { while (client.state != tcp::client_state::injected) { std::this_thread::sleep_for(std::chrono::seconds(1)); } - } diff --git a/client/src/util/io.cpp b/client/src/util/io.cpp index 019ec3f..f6048ba 100644 --- a/client/src/util/io.cpp +++ b/client/src/util/io.cpp @@ -10,3 +10,25 @@ void io::init() { logger = std::make_shared<spdlog::logger>("client", sink); } + +bool io::read_file(const std::string_view name, std::vector<char>& out) { + std::ifstream file(name.data(), std::ios::binary); + if (!file.good()) { + io::logger->error("{} isnt valid.", name); + return false; + } + + file.unsetf(std::ios::skipws); + + file.seekg(0, std::ios::end); + const size_t size = file.tellg(); + file.seekg(0, std::ios::beg); + + out.resize(size); + + file.read(&out[0], size); + + file.close(); + + return true; +} diff --git a/client/src/util/io.h b/client/src/util/io.h index a69940e..0678e9f 100644 --- a/client/src/util/io.h +++ b/client/src/util/io.h @@ -8,4 +8,5 @@ namespace io { extern std::shared_ptr<spdlog::logger> logger; void init(); + bool read_file(const std::string_view name, std::vector<char>& out); }; // namespace io diff --git a/client/src/util/syscalls.cpp b/client/src/util/syscalls.cpp index f1d9261..d7d4254 100644 --- a/client/src/util/syscalls.cpp +++ b/client/src/util/syscalls.cpp @@ -35,7 +35,7 @@ void syscalls::init() { } } - io::logger->info("{:x}", uintptr_t(m_call_table)); + io::logger->info("call table : {:x}", uintptr_t(m_call_table)); for (auto& syscall : m_indexes) { auto idx = syscall.second.first; diff --git a/client/src/util/util.cpp b/client/src/util/util.cpp index 3dba550..b79f6cd 100644 --- a/client/src/util/util.cpp +++ b/client/src/util/util.cpp @@ -7,45 +7,37 @@ std::unordered_map<std::string, pe::virtual_image> util::loaded_modules; std::string util::wide_to_multibyte(const std::wstring& str) { std::string ret; - int32_t str_len; + size_t str_len; // check if not empty str if (str.empty()) return{}; // count size - str_len = WideCharToMultiByte(CP_UTF8, 0, &str[0], (int32_t)str.size(), 0, 0, 0, 0); + str_len = WideCharToMultiByte(CP_UTF8, 0, &str[0], str.size(), 0, 0, 0, 0); // setup return value ret = std::string(str_len, 0); // final conversion - WideCharToMultiByte(CP_UTF8, 0, &str[0], (int32_t)str.size(), &ret[0], str_len, 0, 0); + WideCharToMultiByte(CP_UTF8, 0, &str[0], str.size(), &ret[0], str_len, 0, 0); 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(); +std::wstring util::multibyte_to_wide(const std::string& str) { + size_t size; + std::wstring out; // get size - size = MultiByteToWideChar(CP_UTF8, 0, buf, int32_t(strlen(buf) + 1), 0, 0); + size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.size() + 1, 0, 0); - // alloc new wchars - wstr = new wchar_t[size]; + out.resize(size); // finally convert - MultiByteToWideChar(CP_UTF8, 0, buf, int32_t(strlen(buf) + 1), wstr, size); + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.size() + 1, &out[0], size); - // construct return string - ret = std::wstring(wstr); - - // cleanup - delete[] wstr; - return ret; + return out; } diff --git a/client/src/util/util.h b/client/src/util/util.h index a4ff8c9..8734bd9 100644 --- a/client/src/util/util.h +++ b/client/src/util/util.h @@ -1,14 +1,14 @@ #pragma once #include "native.h" -#include "pe.h" +#include "../injection/pe.h" namespace util { 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); + std::wstring multibyte_to_wide(const std::string& str); native::_PEB* cur_peb(); @@ -25,5 +25,4 @@ namespace util { bool close_handle(HANDLE handle); -}; // namespace util - +}; // namespace util
\ No newline at end of file |