spotless
, we will find some functions that take spotless
as a string argument and one of those functions is CredIsMarshaledCredentialW
as shown below: ADVAPI32!CredIsMarshaledCredentialW
and print out its first and only argument (stored in RCX register per x64 calling convention), we will see DESKTOP-NU8QCIB\spotless
printed out:ws01
(our hostname) as a string argument. Although RdpThief hooks SSPICLI!SspiPrepareForCredRead
(hostname supplied as a second argument), another function that could be considered for hooking is CredReadW
(hostname a the first argument) as seen below:CredReadW
and attempt to RDP to our host ws01
, we get a hit:SSPICLI!SspiPrepareForCredRead
and once it's hit, print out the second argument supplied to the function, which is stored in the RDX register:CryptProtectMemory
. CryptUnprotectMemory
:CryptProtectMemory
calls manually in API Monitor showed no plaintext password either, although there were multiple calls to the function and I would see the password already encrypted:CryptProtectMemory
in WinDBG and print out a unicode string (this should be the plaintext password passed to the function for encryption) starting 4 bytes into the address (first 4 bytes indicate the size of the encrypted data) pointed by the RCX register:CryptProtectMemory
function call (in API Monitor) and also mentioned the 4 byte offset into RCX that holds the size of the encrypted blob - below shows that - first 4 bytes found at RCX (during the CryptProtectMemory
break) are 0x20 or 32 in decimal:ws01
- we see the credentials getting intercepted and written to a file: CredReadW
for intercepting the hostname was possible, so I made some quick changes to the RdpThief's project to test it. _SspiPrepareForCredRead
signature and hooked CreadReadW
with a new function called HookedCredReadW
which will pop a message box each time CredReadW
is called and print its first argument as the message box text. lpServer
variable which is later written to the file creds.txt together with the username and password.HookedCredReadW
and unregister the old hook _SspiPrepareForCredRead
:CredReadW
can be used to intercept the the hostname: