/* This software is licensed by the MIT License, see LICENSE file */ /* Copyright © 2024-2025 Gregory Lirent */ using System.Diagnostics; using WebmrAPI.Exceptions; using WebmrAPI.Models; using WebmrAPI.Utils; namespace WebmrAPI.Services.Scanners { public class ModuleScanner : AbstractScanner { override public ScanTarget Target { get => ScanTarget.Modules; } internal int PID { get; private set; } override async internal Task ScanAsync(Dictionary data) { var success = await Task.Run(() => { try { using (var process = Process.GetProcessById(PID)) { foreach (ProcessModule module in process.Modules) { long addr = module.BaseAddress.ToInt64(); data.Add(addr, new ProcessModuleInfo { MemoryAddress = addr, ModuleName = module.ModuleName, FileName = module.FileName, MemorySize = (ulong)module.ModuleMemorySize, EntrypointRawAddress = module.EntryPointAddress.ToInt64() }); } return true; } } catch (System.ComponentModel.Win32Exception ex) when (ex.NativeErrorCode == 5) { Provider.Logger.LogWarning($"Access denied to Process.Modules for PID {PID}. Attempting P/Invoke. Error: {ex.Message}"); if (Provider.ProcessReadAccess) return null; } catch (InvalidOperationException ex) { Provider.Logger.LogWarning($"Process with PID {PID} might have exited before module scanning. Error: {ex.Message}"); } catch (Exception ex) { Provider.Logger.LogError(ex, $"An unexpected error occurred while getting modules for PID {PID} using managed API."); } return false; }); if (success != null) return success == true ? true : false; return await Task.Run(() => { try { using (var process = new WindowsProcess(PID, true)) { process.ForeachLoadedModule(info => { long addr = info.BaseAddress.ToInt64(); data.Add(addr, new ProcessModuleInfo { ModuleName = info.Name.ToString(), MemoryAddress = addr, FileName = info.FileName.ToString(), MemorySize = info.MemorySize, EntrypointRawAddress = info.EntryPointAddress.ToInt64() }); }); return true; } } catch (GettingModuleInfoException ex) { Provider.Logger.LogDebug(ex.Message); } catch (ProcessMonitorException ex) { Provider.Logger.LogError(ex.Message); } catch (Exception ex) { Provider.Logger.LogError(ex, $"An error occurred while getting modules for PID {PID} using P/Invoke."); } return false; }); } public ModuleScanner(IScanProvider scanner, LazyConcurrentContainer container, int pid) : base(scanner, container) { PID = pid; } } }