///////////////////////////////////////////////////// // // // GetKernelModeProcessListingZwq() // // // ///////////////////////////////////////////////////// //Description: Queries the cw driver to return a list // of processes using ZwQuerySystemInformation(). // //Returns: a CWPROCESS_RECORD struct ///////////////////////////////////////////////////// internal static CwStructures.PROCESS_LISTING_ZWQ GetKernelModeProcessListingZwq() { //----------------------------- // SEND COMMAND //----------------------------- //build the IOCTL to send to driver uint ioctl = Win32Helper.GetIOCTL(CwConstants.CW_DRIVER_PROCESS_LISTING_ZWQ, Win32Helper.METHOD_OUT_DIRECT); //build our buffers int InBufSize = 0; int OutBufSize = Marshal.SizeOf(typeof(CwStructures.PROCESS_LISTING_ZWQ)); IntPtr lpInBuf = IntPtr.Zero; IntPtr lpOutBuf = Marshal.AllocHGlobal(OutBufSize); int bytesReturned = 0; //send the IOCTL try { bytesReturned = DriverHelper.SendDriverCommand(ioctl, lpInBuf, InBufSize, ref lpOutBuf, OutBufSize); } catch (Exception ex) { throw new Exception("SendDriverCommand() failed: " + ex.Message); } if (bytesReturned == 0) throw new Exception("A 0-length buffer was returned from the driver."); //----------------------------- // PROCESS RESULTS //----------------------------- CwStructures.PROCESS_LISTING_ZWQ processListing = new CwStructures.PROCESS_LISTING_ZWQ(); //try to marshal the ptr try { processListing = (CwStructures.PROCESS_LISTING_ZWQ)Marshal.PtrToStructure(lpOutBuf, typeof(CwStructures.PROCESS_LISTING_ZWQ)); } catch (Exception ex) { throw new Exception("Failed to marshal lpOutBuf pointer to processListing structure: " + ex.Message); } Marshal.FreeHGlobal(lpOutBuf); return processListing; }
///////////////////////////////////////////////////// // // // IsProcessPidInZwqKMList() // // // ///////////////////////////////////////////////////// //Description: Determines whether or not the given pid // exists in the process list obtained from // the ZwQuerySystemInformation() in kernel mode. // //Returns: true if it was found in the list ///////////////////////////////////////////////////// internal static bool IsProcessPidInZwqKMList(uint pid) { CwStructures.PROCESS_LISTING_ZWQ ZwQueryKmList = new CwStructures.PROCESS_LISTING_ZWQ(); try { ZwQueryKmList = HeuristicsUserModeHelper.GetKernelModeProcessListingZwq(); } catch (Exception ex) { AgentScanLog.AppendLine("SCAN: Failed to get process list using ZwQuerySystemInformation() from kernel mode: " + ex.Message); } for (int i = 0; i < ZwQueryKmList.numProcesses; i++) { CwStructures.CW_PROCESS_ENTRY process = ZwQueryKmList.ProcessList[i]; if (pid == process.UniqueProcessId) return true; } return false; }
///////////////////////////////////////////////////// // // // CrossViewAnalysisWithTrustedProcessList() // // // ///////////////////////////////////////////////////// //Description: This cross-view analysis approach uses // a "trusted list" it obtains from PspCidTable // and diffs that across the 3 user mode // methods. // //Returns: an array of CWPROCESS_RECORD structs ///////////////////////////////////////////////////// /*internal static CwStructures.CWPROCESS_RECORD[] CrossViewAnalysisWithTrustedProcessList() { // // // TODO: THIS FUNCTION IS INCOMPLETE! // // // //1. GET TRUSTED PROCESS LIST // //we will get a listing of processes from kernel mode using the PspCidTable uint[] trustedPidList = new uint[256]; try { trustedPidList = HeuristicsUserModeHelper.GetKernelModeProcessListingPspCidTable(); } catch (Exception ex) { AgentHeuristicMatches.UserModeMatches.ProcessListing = new CwStructures.CWPROCESS_RECORD[0]; AgentScanLog.AppendLine("Failed to get trusted process listing using PspCidTable: " + ex.Message); return false; } //build a CWPROCESS_RECORD array for storing hidden processes CwStructures.CWPROCESS_RECORD[] hiddenProcesses = new CwStructures.CWPROCESS_RECORD[trustedPidList.Length]; //take the "trusted" listing and create a process entry for each process //we will shortly enumerate processes from user mode in 3 ways and then fill //the boolean field of each process in this structure for (int i = 0; i < trustedPidList.Length; i++) { hiddenProcesses[i] = new CwStructures.CWPROCESS_RECORD(); hiddenProcesses[i].pid = trustedPidList[i]; hiddenProcesses[i].IsInUserModePsapiList = false; hiddenProcesses[i].IsInUserModeToolhelp32List = false; hiddenProcesses[i].IsInUserModeZwqList = false; } }*/ ///////////////////////////////////////////////////// // // // CrossViewAnalysis() // // // ///////////////////////////////////////////////////// //Description: This cross-view analysis approach creates // four different process listings using // various process enumeration methods and then // diffs all those lists to see if there are // any discrepancies. // //Returns: an array of CWPROCESS_RECORD structs ///////////////////////////////////////////////////// internal static CwStructures.CWPROCESS_RECORD[] CrossViewAnalysis() { //************************************* //Cross-view analysis //************************************* //user mode enumeration methods: // (1)PSAPI // (2)Toolhelp32 // (3)ZwQuerySystemInformation // //kernel mode enumeration methods: // (1)PspCidTable (TODO) // (2)ZwQuerySystemInformation // //************************************* // GET DATA POINTS //************************************* //1. PSAPI Process[] PsapiList = Process.GetProcesses(); // //2. TOOLHELP32 ArrayList Toolhelp32List = HeuristicsUserModeHelper.GetUserModeProcessListingToolHelp32(); //3. ZWQUERYSYSTEMINFORMATION (KERNEL MODE) CwStructures.PROCESS_LISTING_ZWQ ZwQueryKmList = new CwStructures.PROCESS_LISTING_ZWQ(); try { ZwQueryKmList = HeuristicsUserModeHelper.GetKernelModeProcessListingZwq(); } catch (Exception ex) { AgentScanLog.AppendLine("SCAN: Failed to get process list using ZwQuerySystemInformation() from kernel mode: " + ex.Message); } //4. ZWQUERYSYSTEMINFORMATION (USER MODE) Win32Helper.SYSTEM_PROCESS_INFORMATION[] ZwQueryUmList = new Win32Helper.SYSTEM_PROCESS_INFORMATION[0]; try { ZwQueryUmList = Win32Helper.GetActiveProcessList(); } catch (Exception ex) { AgentScanLog.AppendLine("SCAN: Failed to get process list using ZwQuerySystemInformation from user mode: " + ex.Message); } //prepare return structure - initialize our list of processes to the obvious ones //in the psapi library (using .NET's Process class) ArrayList hiddenProcesses = new ArrayList(); foreach (Process p in Process.GetProcesses()) { string pname = ""; try { pname = p.MainModule.ModuleName; } catch (Exception) { } AddPidToList(ref hiddenProcesses, (uint)p.Id, GetPsapiParentProcessId(p.ProcessName), pname, ""); } //************************************* // DIFF EACH LIST AGAINST ALL LISTS //************************************* // //1. PSAPI foreach (Process p in PsapiList) { if (p.Id == 0) continue; string pname = ""; try { pname = p.MainModule.ModuleName; } catch (Exception) { } if (Toolhelp32List != null) if (!HeuristicsUserModeHelper.IsProcessPidInToolhelp32List((uint)p.Id)) AddPidToList(ref hiddenProcesses, (uint)p.Id, GetPsapiParentProcessId(p.ProcessName), pname, "Toolhelp32"); if (ZwQueryKmList.numProcesses > 0) if (!HeuristicsUserModeHelper.IsProcessPidInZwqKMList((uint)p.Id)) AddPidToList(ref hiddenProcesses, (uint)p.Id, GetPsapiParentProcessId(p.ProcessName), pname, "ZwQueryUM"); if (ZwQueryUmList.Length > GetPsapiParentProcessId(p.ProcessName)) if (!HeuristicsUserModeHelper.IsProcessPidInZwqUMList((uint)p.Id)) AddPidToList(ref hiddenProcesses, (uint)p.Id, GetPsapiParentProcessId(p.ProcessName), pname, "ZwQueryKM"); } //2. Toolhelp32 if (Toolhelp32List != null) { foreach (Win32Helper.PROCESSENTRY32 process in (Win32Helper.PROCESSENTRY32[])Toolhelp32List.ToArray(typeof(Win32Helper.PROCESSENTRY32))) { if (process.th32ProcessID == 0) continue; if (PsapiList != null) if (!HeuristicsUserModeHelper.IsProcessPidInPsapiList(process.th32ProcessID)) AddPidToList(ref hiddenProcesses, process.th32ProcessID, process.th32ParentProcessID, process.szExeFile, "Psapi"); if (ZwQueryKmList.numProcesses > 0) if (!HeuristicsUserModeHelper.IsProcessPidInZwqKMList(process.th32ProcessID)) AddPidToList(ref hiddenProcesses, process.th32ProcessID, process.th32ParentProcessID, process.szExeFile, "ZwQueryUM"); if (ZwQueryUmList.Length > 0) if (!HeuristicsUserModeHelper.IsProcessPidInZwqUMList(process.th32ProcessID)) AddPidToList(ref hiddenProcesses, process.th32ProcessID, process.th32ParentProcessID, process.szExeFile, "ZwQueryKM"); } } //3. ZwQuerySystemInformation USER MODE if (ZwQueryUmList != null) { foreach (Win32Helper.SYSTEM_PROCESS_INFORMATION process in ZwQueryUmList) { if (process.UniqueProcessId == 0) continue; if (PsapiList != null) if (!HeuristicsUserModeHelper.IsProcessPidInPsapiList(process.UniqueProcessId)) AddPidToList(ref hiddenProcesses, process.UniqueProcessId, process.InheritedFromUniqueProcessId, process.ImageName.Buffer, "Psapi"); if (Toolhelp32List != null) if (!HeuristicsUserModeHelper.IsProcessPidInToolhelp32List(process.UniqueProcessId)) AddPidToList(ref hiddenProcesses, process.UniqueProcessId, process.InheritedFromUniqueProcessId, process.ImageName.Buffer, "Toolhelp32"); if (ZwQueryKmList.numProcesses > 0) if (!HeuristicsUserModeHelper.IsProcessPidInZwqKMList(process.UniqueProcessId)) AddPidToList(ref hiddenProcesses, process.UniqueProcessId, process.InheritedFromUniqueProcessId, process.ImageName.Buffer, "ZwQueryKM"); } } //4. ZwQuerySystemInformation KERNEL MODE if (ZwQueryKmList.numProcesses > 0) { for(int i=0;i<ZwQueryKmList.numProcesses;i++) { CwStructures.CW_PROCESS_ENTRY process = ZwQueryKmList.ProcessList[i]; if (process.UniqueProcessId == 0) continue; if (PsapiList != null) if (!HeuristicsUserModeHelper.IsProcessPidInPsapiList(process.UniqueProcessId)) AddPidToList(ref hiddenProcesses, process.UniqueProcessId, process.InheritedFromUniqueProcessId, process.ImageName, "Psapi"); if (Toolhelp32List != null) if (!HeuristicsUserModeHelper.IsProcessPidInToolhelp32List(process.UniqueProcessId)) AddPidToList(ref hiddenProcesses, process.UniqueProcessId, process.InheritedFromUniqueProcessId, process.ImageName, "Toolhelp32"); if (ZwQueryUmList != null && ZwQueryUmList.Length > 0) if (!HeuristicsUserModeHelper.IsProcessPidInZwqUMList(process.UniqueProcessId)) AddPidToList(ref hiddenProcesses, process.UniqueProcessId, process.InheritedFromUniqueProcessId, process.ImageName, "ZwQueryUM"); } } return (CwStructures.CWPROCESS_RECORD[])hiddenProcesses.ToArray(typeof(CwStructures.CWPROCESS_RECORD)); }