Skip to content

Instantly share code, notes, and snippets.

@jojonas
Last active February 10, 2022 09:26
Show Gist options
  • Save jojonas/07c3771711fb19aed1f3 to your computer and use it in GitHub Desktop.
Save jojonas/07c3771711fb19aed1f3 to your computer and use it in GitHub Desktop.
WinSCP deobfuscator
import argparse
class Decrypter:
SIMPLE_STRING = "0123456789ABCDEF"
SIMPLE_MAGIC = 0xA3
def __init__(self, password):
self.data = password
def next(self):
a = self.SIMPLE_STRING.index(self.data[0])
b = self.SIMPLE_STRING.index(self.data[1])
result = ~(((a << 4) + b) ^ self.SIMPLE_MAGIC) % 256
self.discard(2)
return result
def discard(self, n=2):
self.data = self.data[n:]
def decrypt(hostname, username, password):
FLAG_SIMPLE = 0xFF
decrypter = Decrypter(password)
flag = decrypter.next()
if flag == FLAG_SIMPLE:
decrypter.discard(2)
length = decrypter.next()
else:
length = flag
offset = decrypter.next()
decrypter.discard(offset*2)
result = "".join([chr(decrypter.next()) for i in range(length)])
key = username + hostname
if flag == FLAG_SIMPLE and result.startswith(key):
return result[len(key):]
return result
def load_from_registry():
import winreg
results = []
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Martin Prikryl\WinSCP 2\Sessions") as key:
count = winreg.QueryInfoKey(key)[0]
for i in range(count):
try:
session = winreg.EnumKey(key, i)
with winreg.OpenKey(key, session) as subkey:
hostname = winreg.QueryValueEx(subkey, "HostName")[0]
username = winreg.QueryValueEx(subkey, "UserName")[0]
obfuscated = winreg.QueryValueEx(subkey, "Password")[0]
password = decrypt(hostname, username, obfuscated)
results.append((hostname, username, password))
except FileNotFoundError:
pass
return results
def print_results(results, title=""):
width = 50
print("="*width)
print(("WinSCP deobfuscation" + title).center(width))
print("="*width)
for hostname, username, password in results:
print(" Host:", hostname)
print(" User:", username)
print(" Password:", password)
print("-"*width)
if __name__=="__main__":
load_from_registry()
parser = argparse.ArgumentParser(description='Deobfuscate WinSCP password, using info either from registry (if no arguments are given) or from the command line.')
parser.add_argument('--hostname', type=str, help='HostName', required=False)
parser.add_argument('--username', type=str, help='UserName', required=False)
parser.add_argument('--hash', type=str, help='Password', required=False)
args = parser.parse_args()
if not (args.hostname or args.username or args.hash):
results = load_from_registry()
print_results(results, title=" from registry")
elif args.hostname and args.username and args.hash:
password = decrypt(args.hostname, args.username, args.hash)
print_results([(args.hostname, args.username, password)], title=" from command line")
else:
parser.error("When using external values, please provide hostname, username and hash.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment