#ifndef REPORT_H #define REPORT_H #include #include "threadpool.h" #include "pipe.h" #include #include "common.h" #define REPORT_BUFFER_SIZE 8192 #define SEND_BUFFER_SIZE 8192 #define MAX_SIGNATURE_SIZE 256 #define MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT 20 #define REPORT_CODE_PROCESS_MODULE_VERIFICATION 10 #define REPORT_CODE_START_ADDRESS_VERIFICATION 20 #define REPORT_PAGE_PROTECTION_VERIFICATION 30 #define REPORT_PATTERN_SCAN_FAILURE 40 #define REPORT_NMI_CALLBACK_FAILURE 50 #define REPORT_MODULE_VALIDATION_FAILURE 60 #define REPORT_ILLEGAL_HANDLE_OPERATION 70 #define REPORT_INVALID_PROCESS_ALLOCATION 80 #define REPORT_HIDDEN_SYSTEM_THREAD 90 #define REPORT_ILLEGAL_ATTACH_PROCESS 100 #define REPORT_APC_STACKWALK 110 #define REPORT_DPC_STACKWALK 120 #define TEST_STEAM_64_ID 123456789; enum REPORT_CODES { USERMODE_MODULE = 10, START_ADDRESS = 20, PAGE_PROTECTION = 30, PATTERN_SCAN = 40, NMI_CALLBACK = 50, SYSTEM_MODULE = 60, HANDLE_OPERATION = 70 }; #define CLIENT_REQUEST_MODULE_INTEGRITY_CHECK 10 #define CLIENT_SEND_SYSTEM_INFORMATION 10 #define MAX_CLIENT_SEND_PACKET_SIZE 60000 enum SERVER_SEND_CODES { MODULE_INTEGRITY_CHECK = 10 }; namespace global { class Client { std::shared_ptr thread_pool; std::shared_ptr pipe; std::mutex mutex; byte report_buffer[REPORT_BUFFER_SIZE]; public: Client(std::shared_ptr ThreadPool, LPTSTR PipeName); void UpdateSystemInformation(global::headers::SYSTEM_INFORMATION* SystemInformation); /* lock buffer, attach header, copy report, send to service then clear buffer */ template void ReportViolation(T* Report) { #if NO_SERVER return; #else mutex.lock(); global::headers::PIPE_PACKET_HEADER header = {0}; header.message_type = MESSAGE_TYPE_CLIENT_REPORT; header.steam64_id = TEST_STEAM_64_ID; memcpy(&this->report_buffer, &header, sizeof(global::headers::PIPE_PACKET_HEADER)); memcpy(PVOID((UINT64)this->report_buffer + sizeof(global::headers::PIPE_PACKET_HEADER)), Report, sizeof(T)); this->pipe->WriteToPipe(this->report_buffer, sizeof(T) + sizeof(global::headers::PIPE_PACKET_HEADER)); RtlZeroMemory(this->report_buffer, REPORT_BUFFER_SIZE); mutex.unlock(); #endif } void ServerReceive(PVOID Buffer, SIZE_T Size); void ServerSend(PVOID Buffer, SIZE_T Size, INT RequestId); }; namespace report_structures { struct PROCESS_MODULES_INTEGRITY_CHECK_FAILURE { INT report_code; UINT64 module_base_address; UINT64 module_size; CHAR module_name[256]; }; struct PROCESS_THREAD_START_FAILURE { INT report_code; LONG thread_id; UINT64 start_address; }; struct PAGE_PROTECTION_FAILURE { INT report_code; UINT64 page_base_address; LONG allocation_protection; LONG allocation_state; LONG allocation_type; }; struct PATTERN_SCAN_FAILURE { INT report_code; INT signature_id; UINT64 address; }; struct NMI_CALLBACK_FAILURE { INT report_code; INT were_nmis_disabled; UINT64 kthread_address; UINT64 invalid_rip; }; struct MODULE_VALIDATION_FAILURE_HEADER { INT module_count; }; struct MODULE_VALIDATION_FAILURE { INT report_code; INT report_type; UINT64 driver_base_address; UINT64 driver_size; CHAR driver_name[128]; }; struct REPORT_QUEUE_HEADER { INT count; }; struct OPEN_HANDLE_FAILURE_REPORT { INT report_code; INT is_kernel_handle; LONG process_id; LONG thread_id; LONG desired_access; CHAR process_name[64]; }; struct INVALID_PROCESS_ALLOCATION_REPORT { INT report_code; CHAR process[4096]; }; /* * No point copying data from the start address here * since people can easily change it. */ struct HIDDEN_SYSTEM_THREAD_REPORT { INT report_code; INT found_in_kthreadlist; INT found_in_pspcidtable; UINT64 thread_address; LONG thread_id; CHAR thread[4096]; }; struct ATTACH_PROCESS_REPORT { INT report_code; UINT32 thread_id; UINT64 thread_address; }; struct SYSTEM_INFORMATION_REQUEST_RESPONSE { INT RequestId; INT CanUserProceed; INT reason; }; struct APC_STACKWALK_REPORT { INT report_code; UINT64 kthread_address; UINT64 invalid_rip; CHAR driver[4096]; }; struct DPC_STACKWALK_REPORT { UINT32 report_code; UINT64 kthread_address; UINT64 invalid_rip; CHAR driver[4096]; }; } } #endif