/// <summary>Enumerate all sections and modules of the remote process.</summary> /// <remarks><![CDATA[ /// Protocoll: /// -> EnumerateRemoteSectionsAndModulesRequest /// <- EnumerateRemoteSectionResponse [*] /// <- EnumerateRemoteModuleResponse [*] /// <- StatusResponse /// /// Both callback messages can arrive in random order and count. The enumeration is finished if the StatusResponse was received. /// ]]></remarks> /// <param name="process">The process.</param> /// <param name="callbackSection">The callback which gets called for every section.</param> /// <param name="callbackModule">The callback which gets called for every module.</param> public void EnumerateRemoteSectionsAndModules(IntPtr process, EnumerateRemoteSectionCallback callbackSection, EnumerateRemoteModuleCallback callbackModule) { if (callbackSection == null && callbackModule == null) { return; } lock (sync) { var mapping = GetProcessMappingById(process); if (mapping != null) { try { mapping.Client.Send(new EnumerateRemoteSectionsAndModulesRequest(mapping.RemoteId)); while (true) { var message = mapping.Client.Receive(); if (message is StatusResponse) { break; } if (message is EnumerateRemoteSectionResponse callbackSectionMessage) { var data = new EnumerateRemoteSectionData { BaseAddress = callbackSectionMessage.BaseAddress, Size = callbackSectionMessage.Size, Type = callbackSectionMessage.Type, Category = callbackSectionMessage.Category, Protection = callbackSectionMessage.Protection, Name = callbackSectionMessage.Name, ModulePath = callbackSectionMessage.ModulePath }; callbackSection?.Invoke(ref data); } else if (message is EnumerateRemoteModuleResponse callbackModuleMessage) { var data = new EnumerateRemoteModuleData { BaseAddress = callbackModuleMessage.BaseAddress, Size = callbackModuleMessage.Size, Path = callbackModuleMessage.Path }; callbackModule?.Invoke(ref data); } } } catch (Exception ex) { LogErrorAndRemoveClient(process, ex); } } } }
public bool GetProcessModules(int ProcessId, ref EnumerateRemoteModuleCallback Callback) { if (!IsLoaded()) { return(false); } KERNEL_PROCESS_PEB_INFO Request = new KERNEL_PROCESS_PEB_INFO(); Request.ProcessId = ProcessId; int BufferSize = Marshal.SizeOf(Request); IntPtr Buffer = Marshal.AllocHGlobal(BufferSize); Marshal.StructureToPtr(Request, Buffer, false); bool Result = DeviceIoControl(Handle, IO_PROCESS_PEB_INFO, Buffer, BufferSize, Buffer, BufferSize, out _, IntPtr.Zero); KERNEL_PROCESS_PEB_INFO Response = (KERNEL_PROCESS_PEB_INFO)Marshal.PtrToStructure(Buffer, typeof(KERNEL_PROCESS_PEB_INFO)); if (Result) { IntPtr PebAddress = Response.PebAddress; if (Response.IsWow64) { OutputDebugString("Getting 32bit process PEB " + PebAddress.ToString("X")); var Peb32 = ReadMemory <PEB32>(ProcessId, PebAddress); if (Peb32.Ldr == 0) { OutputDebugString("Process LDR is not initialised"); return(false); } var Ldr = ReadMemory <PEB_LDR_DATA32>(ProcessId, new IntPtr(Peb32.Ldr)); IntPtr Head = new IntPtr(Ldr.InLoadOrderModuleList.Flink); IntPtr Next = Head; do { var Entry = ReadMemory <LDR_DATA_TABLE_ENTRY32>(ProcessId, Next); Next = new IntPtr(Entry.InLoadOrderLinks.Flink); if (Entry.SizeOfImage == 0 || Entry.DllBase == 0) { continue; } var FullDllName = ReadUnicodeString(ProcessId, new IntPtr(Entry.FullDllName.Buffer), Entry.FullDllName.Length); var BaseDllName = ReadUnicodeString(ProcessId, new IntPtr(Entry.BaseDllName.Buffer), Entry.BaseDllName.Length); var Data = new EnumerateRemoteModuleData(); Data.BaseAddress = new IntPtr(Entry.DllBase); Data.Path = FullDllName; Data.Size = new IntPtr(Entry.SizeOfImage); OutputDebugString( BaseDllName + ", Address: " + Entry.DllBase.ToString("X") + ", Size: " + Entry.SizeOfImage.ToString("X")); Callback.Invoke(ref Data); } while (Next != Head); } else { OutputDebugString("Getting 64bit process PEB " + PebAddress.ToString("X")); var Peb = ReadMemory <PEB>(ProcessId, PebAddress); if (Peb.Ldr == IntPtr.Zero) { OutputDebugString("Process LDR is not initialised"); return(false); } OutputDebugString("Process LDR at: " + Peb.Ldr.ToString("X")); var Ldr = ReadMemory <PEB_LDR_DATA>(ProcessId, Peb.Ldr); IntPtr Head = Ldr.InLoadOrderModuleList.Flink; IntPtr Next = Head; do { var Entry = ReadMemory <LDR_DATA_TABLE_ENTRY>(ProcessId, Next); Next = Entry.InLoadOrderLinks.Flink; if (Entry.SizeOfImage == 0 || Entry.DllBase == IntPtr.Zero) { continue; } var FullDllName = ReadUnicodeString(ProcessId, Entry.FullDllName.Buffer, Entry.FullDllName.Length); var BaseDllName = ReadUnicodeString(ProcessId, Entry.BaseDllName.Buffer, Entry.BaseDllName.Length); var Data = new EnumerateRemoteModuleData(); Data.BaseAddress = Entry.DllBase; Data.Path = FullDllName; Data.Size = new IntPtr(Entry.SizeOfImage); OutputDebugString( BaseDllName + ", Address: " + Entry.DllBase.ToString("X") + ", Size: " + Entry.SizeOfImage.ToString("X")); Callback.Invoke(ref Data); } while (Next != Head); } } Marshal.FreeHGlobal(Buffer); return(Result); }