/// <summary>Reports a single module and section for the loaded file.</summary>
        /// <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)
        {
            lock (sync)
            {
                var info = GetMappedFileById(process);
                if (info != null)
                {
                    var module = new EnumerateRemoteModuleData
                    {
                        BaseAddress = IntPtr.Zero,
                        Path        = info.Path,
                        Size        = (IntPtr)info.Size
                    };
                    callbackModule(ref module);

                    var section = new EnumerateRemoteSectionData
                    {
                        BaseAddress = IntPtr.Zero,
                        Size        = (IntPtr)info.Size,
                        Type        = SectionType.Image,
                        Category    = SectionCategory.Unknown,
                        ModulePath  = info.Path,
                        Name        = string.Empty,
                        Protection  = SectionProtection.Read
                    };
                    callbackSection(ref section);
                }
            }
        }
        /// <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);
                    }
                }
            }
        }
Esempio n. 3
0
        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);
        }