Universal smart card reader unlocking kit for Windows Remote Desktop sessions
PatchRDP restores visibility of physical smart card readers inside Windows Remote Desktop (RDP) sessions by bypassing the Windows session isolation behavior implemented in winscard.dll.
It is designed for environments where smart card readers are physically connected to the host machine but must be used from an RDP session.
PatchRDP is:
- configurable through
config.ini - reversible through
uninstall.ps1 - compatible with both x86 and x64 target processes
- resilient to Windows Updates through dynamic Microsoft PDB symbol resolution
- non-invasive: no Windows system DLL is modified on disk
Windows treats an RDP session as a remote session.
When an application accesses the Windows PC/SC subsystem through winscard.dll, Windows may attempt to redirect smart card access through the RDP channel instead of exposing smart card readers physically connected to the host machine.
In environments where the reader is connected directly to the host computer rather than to the RDP client, this behavior can cause:
- no smart card reader detected
- no certificate visible
- failed authentication
- failed electronic signature operations
- PKCS#11 middleware unable to enumerate tokens
- business applications blocked waiting for a reader
This affects:
- Windows 10 / 11
- Windows Server with RDS
- standard Remote Desktop sessions
- multi-session environments
- shared workstations
- remote-access desktops
- business applications relying on the Windows smart card stack
PatchRDP can be useful for applications relying on:
- Windows PC/SC
winscard.dll- smart card readers
- PKCS#11 middleware
- Cryptolib / CPS middleware
- electronic signature platforms
- healthcare business applications
- authentication certificates
- smart card based workflows
PatchRDP dynamically patches the internal WinSCard function:
winscard!RedirectionContextIsLocal
The goal is to force WinSCard to treat the current context as local.
The in-memory patch is:
mov al,1
retMachine code:
B0 01 C3
This patch is applied only in memory.
PatchRDP does not modify winscard.dll on disk.
PatchRDP v2 uses the memory hook method as the primary mechanism.
It also keeps an optional version.dll proxy mode for advanced or legacy scenarios.
PatchRDP combines three mechanisms:
- WinSCard memory hook through
cdb.exe - Smart card redirection policy adjustment
- Optional
version.dllproxy mode
This is the primary and recommended method.
Two scheduled tasks are created:
HookCPS_Target_x86
HookCPS_Target_x64
Both tasks launch the same script:
hook_cps_target.ps1
but under different PowerShell architectures.
The x86 task launches:
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe
It reads target processes from:
[HookProcesses32]Example:
[HookProcesses32]
Proc1=AxiMessageV3The x64 task launches:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
It reads target processes from:
[HookProcesses64]Example:
[HookProcesses64]
Proc1=cpgesw64
Proc2=msedgeFor each configured process, hook_cps_target.ps1:
- detects the target process
- waits until
winscard.dllis loaded - launches
cdb.exe - loads WinSCard symbols
- resolves
WinSCard!RedirectionContextIsLocal - applies the patch
B0 01 C3 - detaches without terminating the process
- caches the patched PID to avoid duplicate patching
The patch command executed by cdb.exe is:
.reload /f WinSCard.dll;
eb WinSCard!RedirectionContextIsLocal B0 01 C3;
qd
PatchRDP configures the following registry value:
HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services
fEnableSmartCard = 0This disables Windows smart card redirection behavior.
The objective is to prevent Windows from trying to redirect smart card access through the RDP client and instead allow applications to access locally connected readers.
PatchRDP keeps support for a legacy / advanced compatibility mode based on a proxy version.dll.
This mode is disabled by default.
Enable it in config.ini:
DeployDllProxy=trueWhen enabled, PatchRDP deploys the following files next to configured executables:
version.dll
dbghelp.dll
symsrv.dll
srcsrv.dll
This mode can be useful for:
- legacy applications
- diagnostics
- compatibility testing
- cases where direct memory patching is not desired
Recommended default:
DeployDllProxy=falsePatchRDP does not rely on hardcoded offsets.
The address of RedirectionContextIsLocal is resolved dynamically through Microsoft PDB symbols.
The symbol path used is:
srv*<KitRoot>\Symbols*https://msdl.microsoft.com/download/symbols
At runtime:
- WinSCard symbols are loaded
- the matching PDB is downloaded if needed
- the symbol address is resolved
- the patch is applied to the resolved address
This makes PatchRDP resilient to:
- Windows cumulative updates
- WinSCard recompilation
- address layout changes
- ASLR differences
The PDB cache is stored in:
<KitRoot>\Symbols\
PatchRDP does not redistribute Microsoft Debugging Tools binaries.
The following files are required for PatchRDP to work, but must be obtained separately by the administrator from a properly licensed Microsoft Windows SDK / Debugging Tools installation:
cdb.exe
dbgeng.dll
dbghelp.dll
symsrv.dll
srcsrv.dll
msdia140.dll
These files are Microsoft components and are subject to Microsoft's licensing terms.
They are not included in the PatchRDP repository.
Before running install.ps1, copy the required Microsoft Debugging Tools files into the PatchRDP package folder.
Required files:
cdb.exe
dbgeng.dll
dbghelp.dll
symsrv.dll
srcsrv.dll
msdia140.dll
PatchRDP expects these files to be present next to:
install.ps1
uninstall.ps1
hook_cps_target.ps1
config.ini
Install Debugging Tools for Windows from the Microsoft Windows SDK.
During Windows SDK installation, select only:
Debugging Tools for Windows
Microsoft Windows SDK download page:
https://developer.microsoft.com/windows/downloads/windows-sdk/
After installation, the files are typically located under a folder similar to:
C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\
Depending on the installed SDK version, the exact path may vary.
Copy the required files into the PatchRDP source folder before running the installer.
The PatchRDP repository should contain only PatchRDP-owned files, for example:
install.ps1
uninstall.ps1
hook_cps_target.ps1
config.ini
README.md
version.dll
Microsoft Debugging Tools binaries must be supplied separately by the administrator.
Before running install.ps1, the local package folder should look like:
PatchRDP\
│
├─ install.ps1
├─ uninstall.ps1
├─ hook_cps_target.ps1
├─ config.ini
├─ README.md
│
├─ version.dll optional / advanced mode
│
├─ cdb.exe supplied by administrator
├─ dbgeng.dll supplied by administrator
├─ dbghelp.dll supplied by administrator
├─ symsrv.dll supplied by administrator
├─ srcsrv.dll supplied by administrator
└─ msdia140.dll supplied by administrator
If DeployDllProxy=false, version.dll is not required for the primary memory hook mode.
All customization is done through:
config.ini
No script modification is required.
[General]
KitName=PatchRDP
KitRoot=C:\!KIT\PatchRDP
[Options]
DeployHook=true
DeployDllProxy=false
[HookProcesses32]
Proc1=AxiMessageV3
[HookProcesses64]
Proc1=cpgesw64
Proc2=msedge[General]
KitName=PatchRDP
KitRoot=C:\!KIT\PatchRDPDisplay name used by the installer and uninstaller.
Runtime installation directory.
Example:
C:\!KIT\PatchRDP
[Options]
DeployHook=true
DeployDllProxy=falseEnables the memory hook system.
Recommended:
DeployHook=trueEnables optional version.dll proxy deployment.
Recommended:
DeployDllProxy=falseEnable only for advanced compatibility mode:
DeployDllProxy=trueProcesses monitored by the x86 hook service.
[HookProcesses32]
Proc1=AxiMessageV3Do not include .exe.
Correct:
Proc1=AxiMessageV3Incorrect:
Proc1=AxiMessageV3.exeProcesses monitored by the x64 hook service.
[HookProcesses64]
Proc1=cpgesw64
Proc2=msedgeDo not include .exe.
These sections are only used when:
DeployDllProxy=trueExample:
[SearchPaths]
Path1=C:\Program Files\Application
Path2=C:\Program Files (x86)\Application
[Executables]
Exe1=Application.exeThe installer searches recursively for the configured executables and deploys the proxy files next to them.
Used by uninstall.ps1 to close applications before removing files.
Example:
[ProcessesToClose]
Proc1=firefox.exe
Proc2=CCM.exe
Proc3=Axi5.exeUse the full process image name including .exe.
- Download or clone the PatchRDP repository
- Install Microsoft Debugging Tools for Windows
- Copy the required Microsoft files into the PatchRDP folder
- Edit
config.ini - Run:
.\install.ps1Administrator elevation is automatic.
Optional proxy DLL deployment if:
DeployDllProxy=trueConfigure:
fEnableSmartCard = 0Deploy runtime components into:
KitRoot
Example:
C:\!KIT\PatchRDP
Create and start scheduled tasks:
HookCPS_Target_x86
HookCPS_Target_x64
Disconnect and reconnect the RDP session.
This ensures:
- policy refresh
- task execution
- process monitoring startup
Get-ScheduledTask HookCPS_Target_x86
Get-ScheduledTask HookCPS_Target_x64Get-Content C:\!KIT\PatchRDP\hook_cps_x86.log -Tail 20Get-Content C:\!KIT\PatchRDP\hook_cps_x64.log -Tail 20Demarrage service hook CPS
Process cibles : ...
Patch OK sur ...
Get-ChildItem C:\!KIT\PatchRDP\Symbols -Recurse -Filter "*.pdb"C:\!KIT\PatchRDP\
│
├─ config.ini
├─ uninstall.ps1
├─ hook_cps_target.ps1
│
├─ cdb.exe
├─ dbgeng.dll
├─ dbghelp.dll
├─ symsrv.dll
├─ srcsrv.dll
├─ msdia140.dll
│
├─ hook_cps_x86.log
├─ hook_cps_x64.log
│
└─ Symbols\
Optional advanced DLL proxy mode:
<Application Folder>\
│
├─ version.dll
├─ dbghelp.dll
├─ symsrv.dll
└─ srcsrv.dll
| File | Purpose |
|---|---|
hook_cps_x86.log |
x86 memory hook service |
hook_cps_x64.log |
x64 memory hook service |
version_debug.log |
optional version.dll proxy mode |
Logs rotate automatically when they exceed:
5 MB
Run:
.\uninstall.ps1Administrator elevation is automatic.
The uninstaller will:
- remove scheduled tasks
- stop running hook scripts
- close configured applications
- remove the smart card policy value
- unregister
msdia140.dll - remove optional proxy DLLs if enabled
- delete the runtime directory
Removed tasks:
HookCPS_Target
HookCPS_Target_x86
HookCPS_Target_x64
PatchRDP:
- does not modify Windows system files on disk
- does not patch
winscard.dllon disk - does not capture PIN codes
- does not capture certificates
- does not intercept cryptographic data
- does not modify smart card contents
- only changes smart card reader visibility inside configured target processes
All changes are reversible through:
.\uninstall.ps1PatchRDP requires access to Microsoft public symbols during the first run for a given WinSCard build.
If the machine has no Internet access, the required PDB files must be pre-populated in:
<KitRoot>\Symbols\
PatchRDP also depends on the continued availability of the internal symbol:
RedirectionContextIsLocal
If Microsoft removes or renames this internal function, the patch target may need to be re-evaluated.
- Windows Internals
- WinDbg / CDB
- PC/SC
- WinSCard
- Smart Card redirection
- PKCS#11
- Cryptolib
- Microsoft public symbols
- dynamic PDB resolution
- PowerShell automation
- scheduled tasks
- RDP / Terminal Services
- optional DLL proxy loading
PatchRDP does not include Microsoft Debugging Tools binaries.
Users are responsible for obtaining required Microsoft components from a properly licensed installation of the Windows SDK / Debugging Tools for Windows.
Microsoft components remain subject to Microsoft's own license terms.
Add your project license here.
Example:
MIT
Apache-2.0
Proprietary
Internal use only
PatchRDP changes smart card reader visibility behavior inside selected target processes.
Use only in environments where you are authorized to administer the machine and modify process memory.
Test thoroughly before production deployment.
PatchRDP v2.0
Universal smart card reader visibility restoration for Windows Remote Desktop environments.