using Serilog; using server.Database.Entity; using server.Database.Entity.Report; using server.Database.Entity.Report.Types; using server.Database.Model; using server.Types.ClientReport; using System; using System.Collections.Generic; using System.Drawing.Printing; using System.Linq; using System.Text; using System.Threading.Tasks; using static server.Message.MessageHandler; namespace server.Message { public class ClientReport : IClientMessage { private readonly ILogger _logger; private byte[] _buffer; private int _bufferSize; private PACKET_HEADER _packetHeader; private CLIENT_REPORT_PACKET_HEADER _clientReportPacketHeader; private CLIENT_REPORT_PACKET_RESPONSE _responsePacket; private enum CLIENT_SEND_REPORT_ID { PROCESS_MODULE_VERIFICATION = 10, START_ADDRESS_VERIFICATION = 20, PAGE_PROTECTION_VERIFICATION = 30, PATTERN_SCAN_FAILURE = 40, NMI_CALLBACK_FAILURE = 50, MODULE_VALIDATION_FAILURE = 60, ILLEGAL_HANDLE_OPERATION = 70, INVALID_PROCESS_ALLOCATION = 80, HIDDEN_SYSTEM_THREAD = 90, ILLEGAL_ATTACH_PROCESS = 100 } private struct CLIENT_REPORT_PACKET_HEADER { public int reportCode; } private struct CLIENT_REPORT_PACKET_RESPONSE { public int success; } public ClientReport(ILogger logger, ref byte[] buffer, int bufferSize, PACKET_HEADER packetHeader) { this._logger = logger; this._buffer = buffer; this._bufferSize = bufferSize; this._packetHeader = packetHeader; this._responsePacket = new CLIENT_REPORT_PACKET_RESPONSE(); this.GetPacketHeader(); } unsafe public void GetPacketHeader() { this._clientReportPacketHeader = Helper.BytesToStructure(_buffer, sizeof(PACKET_HEADER)); } public byte[] GetResponsePacket() { return Helper.StructureToBytes(ref this._responsePacket); } private void SetResponsePacketData(int success) { this._responsePacket.success = success; } public bool HandleMessage() { if (this._clientReportPacketHeader.reportCode == 0) { _logger.Error("Failed to get the report packet code"); return false; } switch (this._clientReportPacketHeader.reportCode) { case (int)CLIENT_SEND_REPORT_ID.PROCESS_MODULE_VERIFICATION: _logger.Information("REPORT CODE: MODULE_VERIFICATION"); break; case (int)CLIENT_SEND_REPORT_ID.START_ADDRESS_VERIFICATION: _logger.Information("REPORT CODE: START_ADDRESS_VERIFICATION"); HandleReportStartAddressVerification(); break; case (int)CLIENT_SEND_REPORT_ID.PAGE_PROTECTION_VERIFICATION: _logger.Information("REPORT CODE: PAGE_PROTECTION_VERIFICATION"); HandleReportPageProtection(); break; case (int)CLIENT_SEND_REPORT_ID.PATTERN_SCAN_FAILURE: _logger.Information("REPORT_PATTERN_SCAN_FAILURE"); HandleReportPatternScan(); break; case (int)CLIENT_SEND_REPORT_ID.NMI_CALLBACK_FAILURE: _logger.Information("REPORT_NMI_CALLBACK_FAILURE"); HandleReportNmiCallback(); break; case (int)CLIENT_SEND_REPORT_ID.MODULE_VALIDATION_FAILURE: _logger.Information("REPORT_MODULE_VALIDATION_FAILURE"); HandleReportSystemModuleValidation(); break; case (int)CLIENT_SEND_REPORT_ID.ILLEGAL_HANDLE_OPERATION: HandleReportIllegalHandleOperation(); break; case (int)CLIENT_SEND_REPORT_ID.INVALID_PROCESS_ALLOCATION: _logger.Information("REPORT_INVALID_PROCESS_ALLOCATION"); HandleInvalidProcessAllocation(); break; case (int)CLIENT_SEND_REPORT_ID.HIDDEN_SYSTEM_THREAD: _logger.Information("REPORT_HIDDEN_SYSTEM_THREAD"); HandleReportHiddenSystemThread(); break; case (int)CLIENT_SEND_REPORT_ID.ILLEGAL_ATTACH_PROCESS: _logger.Information("REPORT_ILLEGAL_ATTACH_PROCESS"); HandleReportAttachProcess(); break; default: _logger.Information("Report code not handled yet"); break; } SetResponsePacketData(1); return true; } unsafe public void HandleReportIllegalHandleOperation() { OPEN_HANDLE_FAILURE report = Helper.BytesToStructure(_buffer, sizeof(PACKET_HEADER)); _logger.Information("ProcessName: {0}, ProcessID: {1:x}, ThreadId: {2:x}, DesiredAccess{3:x}", report.ProcessName, report.ProcessId, report.ThreadId, report.DesiredAccess); using (var context = new ModelContext()) { /* * This doesn't seem to be the most optimal way to do this, but it works.. * Maybe look into it further at somepoint.. */ UserEntity user = new UserEntity(context); var newReport = new ReportEntity(context) { User = user.GetUserBySteamId(this._packetHeader.steam64_id), ReportCode = (int)CLIENT_SEND_REPORT_ID.ILLEGAL_HANDLE_OPERATION }; newReport.InsertReport(); var reportTypeIllegalHandleOperation = new ReportTypeIllegalHandleOperationEntity(context) { Report = newReport, IsKernelHandle = report.IsKernelHandle, ProcessId = report.ProcessId, ThreadId = report.ThreadId, DesiredAccess = report.DesiredAccess, ProcessName = report.ProcessName }; reportTypeIllegalHandleOperation.InsertReport(); context.SaveChanges(); } } unsafe public void HandleReportStartAddressVerification() { PROCESS_THREAD_START_FAILURE report = Helper.BytesToStructure(_buffer, sizeof(PACKET_HEADER)); _logger.Information("ThreadId: {0}, ThreadStartAddress: {1:x}", report.ThreadId, report.StartAddress); using (var context = new ModelContext()) { UserEntity user = new UserEntity(context); var newReport = new ReportEntity(context) { User = user.GetUserBySteamId(this._packetHeader.steam64_id), ReportCode = (int)CLIENT_SEND_REPORT_ID.START_ADDRESS_VERIFICATION }; newReport.InsertReport(); var reportTypeStartAddress = new StartAddressEntity(context) { Report = newReport, ThreadId = report.ThreadId, ThreadStartAddress = report.StartAddress }; reportTypeStartAddress.InsertReport(); context.SaveChanges(); } } unsafe public void HandleReportPageProtection() { PAGE_PROTECTION_FAILURE report = Helper.BytesToStructure(_buffer, sizeof(PACKET_HEADER)); _logger.Information("Page base address: {0:x}, allocation protection: {1:x}, allocation state: {2:x}, allocationtype: {3:x}", report.PageBaseAddress, report.AllocationProtection, report.AllocationState, report.AllocationType); using (var context = new ModelContext()) { UserEntity user = new UserEntity(context); var newReport = new ReportEntity(context) { User = user.GetUserBySteamId(this._packetHeader.steam64_id), ReportCode = (int)CLIENT_SEND_REPORT_ID.PAGE_PROTECTION_VERIFICATION }; newReport.InsertReport(); var reportTypePageProtection = new PageProtectionEntity(context) { Report = newReport, PageBaseAddress = report.PageBaseAddress, AllocationProtection = report.AllocationProtection, AllocationState = report.AllocationState, AllocationType = report.AllocationType }; reportTypePageProtection.InsertReport(); context.SaveChanges(); } } unsafe public void HandleReportPatternScan() { PATTERN_SCAN_FAILURE report = Helper.BytesToStructure(_buffer, sizeof(PACKET_HEADER)); _logger.Information("signature id: {0}, address: {1:x}", report.SignatureId, report.Address); using (var context = new ModelContext()) { UserEntity user = new UserEntity(context); var newReport = new ReportEntity(context) { User = user.GetUserBySteamId(this._packetHeader.steam64_id), ReportCode = (int)CLIENT_SEND_REPORT_ID.PATTERN_SCAN_FAILURE }; newReport.InsertReport(); var reportTypePatternScan = new PatternScanEntity(context) { Report = newReport, SignatureId = report.SignatureId, Address = report.Address }; reportTypePatternScan.InsertReport(); context.SaveChanges(); } } unsafe public void HandleReportNmiCallback() { NMI_CALLBACK_FAILURE report = Helper.BytesToStructure(_buffer, sizeof(PACKET_HEADER)); _logger.Information("were nmis disabled: {0}, kthread: {1:x}, invalid rip: {2:x}", report.WereNmisDisabled, report.KThreadAddress, report.InvalidRip); using (var context = new ModelContext()) { UserEntity user = new UserEntity(context); var newReport = new ReportEntity(context) { User = user.GetUserBySteamId(this._packetHeader.steam64_id), ReportCode = (int)CLIENT_SEND_REPORT_ID.NMI_CALLBACK_FAILURE }; newReport.InsertReport(); var reportTypeNmiCallback = new NmiCallbackEntity(context) { Report = newReport, WereNmisDisabled = report.WereNmisDisabled, KThreadAddress = report.KThreadAddress, InvalidRip = report.InvalidRip }; reportTypeNmiCallback.InsertReport(); context.SaveChanges(); } } unsafe public void HandleReportSystemModuleValidation() { MODULE_VALIDATION_FAILURE report = Helper.BytesToStructure(_buffer, sizeof(PACKET_HEADER)); _logger.Information("report type: {0}, driver base: {1:x}, size: {2}, module name: {3}", report.ReportType, report.DriverBaseAddress, report.DriverSize, report.ModuleName); using (var context = new ModelContext()) { UserEntity user = new UserEntity(context); var newReport = new ReportEntity(context) { User = user.GetUserBySteamId(this._packetHeader.steam64_id), ReportCode = (int)CLIENT_SEND_REPORT_ID.MODULE_VALIDATION_FAILURE }; newReport.InsertReport(); var reportTypeSystemModuleValidation = new SystemModuleValidationEntity(context) { Report = newReport, ReportType = report.ReportType, DriverBaseAddress = report.DriverBaseAddress, DriverSize = report.DriverSize, ModuleName = report.ModuleName }; reportTypeSystemModuleValidation.InsertReport(); context.SaveChanges(); } } unsafe public void HandleReportHiddenSystemThread() { HIDDEN_SYSTEM_THREAD_FAILURE report = Helper.BytesToStructure(_buffer, sizeof(PACKET_HEADER)); _logger.Information("found in kthread list: {0}, found in pspcidtable: {1}, thread address: {2:x}, thread id: {3:x}", report.FoundInKThreadList, report.FoundInPspCidTable, report.ThreadAddress, report.ThreadId); using (var context = new ModelContext()) { UserEntity user = new UserEntity(context); var newReport = new ReportEntity(context) { User = user.GetUserBySteamId(this._packetHeader.steam64_id), ReportCode = (int)CLIENT_SEND_REPORT_ID.HIDDEN_SYSTEM_THREAD }; newReport.InsertReport(); var reportTypeHiddenSystemThread = new HiddenSystemThreadEntity(context) { Report = newReport, FoundInKThreadList = report.FoundInKThreadList, FoundInPspCidTable = report.FoundInPspCidTable, ThreadAddress = report.ThreadAddress, ThreadId = report.ThreadId }; reportTypeHiddenSystemThread.InsertReport(); context.SaveChanges(); } } unsafe public void HandleReportAttachProcess() { ATTACH_PROCESS_FAILURE report = Helper.BytesToStructure(_buffer, sizeof(PACKET_HEADER)); _logger.Information("thread id: {0:x}, thread address: {1:x}", report.ThreadId, report.ThreadAddress); using (var context = new ModelContext()) { UserEntity user = new UserEntity(context); var newReport = new ReportEntity(context) { User = user.GetUserBySteamId(this._packetHeader.steam64_id), ReportCode = (int)CLIENT_SEND_REPORT_ID.ILLEGAL_ATTACH_PROCESS }; newReport.InsertReport(); var reportTypeAttachProcess = new AttachProcessEntity(context) { Report = newReport, ThreadId = report.ThreadId, ThreadAddress = report.ThreadAddress, }; reportTypeAttachProcess.InsertReport(); context.SaveChanges(); } } unsafe public void HandleInvalidProcessAllocation() { INVALID_PROCESS_ALLOCATION_FAILURE report = Helper.BytesToStructure(_buffer, sizeof(PACKET_HEADER)); _logger.Information("received invalid process allocation structure"); using (var context = new ModelContext()) { UserEntity user = new UserEntity(context); var newReport = new ReportEntity(context) { User = user.GetUserBySteamId(this._packetHeader.steam64_id), ReportCode = (int)CLIENT_SEND_REPORT_ID.INVALID_PROCESS_ALLOCATION }; newReport.InsertReport(); var reportTypeInvalidProcessAllocation = new InvalidProcessAllocationEntity(context) { Report = newReport, ProcessStructure = report.ProcessStructure }; reportTypeInvalidProcessAllocation.InsertReport(); context.SaveChanges(); } } } }