winmr-api/Services/Scanners/ModuleScanner.cs
2025-07-04 00:04:51 +03:00

104 lines
4.0 KiB
C#

/* 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<ProcessModuleInfo>
{
override public ScanTarget Target { get => ScanTarget.Modules; }
internal int PID { get; private set; }
override async internal Task<bool> ScanAsync(Dictionary<long, ProcessModuleInfo> data)
{
var success = await Task.Run<bool?>(() =>
{
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<ProcessModuleInfo> container, int pid)
: base(scanner, container)
{
PID = pid;
}
}
}