[7260bdc2] | 1 | import subprocess |
---|
| 2 | import os |
---|
| 3 | import re |
---|
| 4 | |
---|
| 5 | from engine.FileLib import * |
---|
| 6 | from engine.SystemLib import * |
---|
| 7 | |
---|
| 8 | def chntpw(*args): |
---|
| 9 | chntpw_path = subprocess.check_output(['which', 'drbl-chntpw']).decode().strip() |
---|
| 10 | if not chntpw_path: |
---|
| 11 | chntpw_path = subprocess.check_output(['which', 'chntpw']).decode().strip() |
---|
| 12 | subprocess.run([chntpw_path, '-e'] + list(args), timeout=5) |
---|
| 13 | |
---|
| 14 | def ogAddRegistryKey(path_mountpoint, str_hive, str_key): |
---|
| 15 | # Variables locales. |
---|
| 16 | FILE = ogGetHivePath(path_mountpoint, str_hive) |
---|
| 17 | if not FILE: |
---|
| 18 | return |
---|
| 19 | |
---|
| 20 | # Añadir nueva clave. |
---|
| 21 | chntpw(FILE, 'cd', str_key.rsplit('\\', 1)[0]) |
---|
| 22 | chntpw(FILE, 'nk', str_key.rsplit('\\', 1)[-1]) |
---|
| 23 | chntpw(FILE, 'q') |
---|
| 24 | chntpw(FILE, 'y') |
---|
| 25 | |
---|
| 26 | def ogAddRegistryValue(path_mountpoint, str_hive, str_key, str_valuename, str_valuetype=''): |
---|
| 27 | # Variables locales. |
---|
| 28 | FILE = ogGetHivePath(path_mountpoint, str_hive) |
---|
| 29 | if not FILE: |
---|
| 30 | return |
---|
| 31 | |
---|
| 32 | # Determine the value type. |
---|
| 33 | if str_valuetype.upper() == 'STRING' or str_valuetype == '': |
---|
| 34 | TYPE = 1 |
---|
| 35 | elif str_valuetype.upper() == 'BINARY': |
---|
| 36 | TYPE = 3 |
---|
| 37 | elif str_valuetype.upper() == 'DWORD': |
---|
| 38 | TYPE = 4 |
---|
| 39 | else: |
---|
| 40 | ogRaiseError(OG_ERR_OUTOFLIMIT, str_valuetype) |
---|
| 41 | return |
---|
| 42 | |
---|
| 43 | # Add the registry value. |
---|
| 44 | chntpw(FILE, 'cd', str_key.rsplit('\\', 1)[0]) |
---|
| 45 | chntpw(FILE, 'nv', str_valuename.rsplit('\\', 1)[-1], TYPE) |
---|
| 46 | chntpw(FILE, 'q') |
---|
| 47 | chntpw(FILE, 'y') |
---|
| 48 | |
---|
| 49 | def ogDeleteRegistryKey(path_mountpoint, str_hive, str_key): |
---|
| 50 | # Variables locales. |
---|
| 51 | FILE = ogGetHivePath(path_mountpoint, str_hive) |
---|
| 52 | if not FILE: |
---|
| 53 | return |
---|
| 54 | |
---|
| 55 | # Delete the registry key. |
---|
| 56 | subprocess.run(['chntpw', FILE], input=f"cd {str_key.rsplit('\\', 1)[0]}\ndk {str_key.rsplit('\\', 1)[-1]}\nq\ny\n".encode(), timeout=5) |
---|
| 57 | |
---|
| 58 | def ogDeleteRegistryValue(path_mountpoint, str_hive, str_valuename): |
---|
| 59 | # Variables locales. |
---|
| 60 | FILE = ogGetHivePath(path_mountpoint, str_hive) |
---|
| 61 | if not FILE: |
---|
| 62 | return |
---|
| 63 | |
---|
| 64 | # Delete the registry value. |
---|
| 65 | chntpw(FILE, 'cd', str_valuename.rsplit('\\', 1)[0]) |
---|
| 66 | chntpw(FILE, 'dv', str_valuename.rsplit('\\', 1)[-1]) |
---|
| 67 | chntpw(FILE, 'q') |
---|
| 68 | chntpw(FILE, 'y') |
---|
| 69 | |
---|
| 70 | def ogGetHivePath(path_mountpoint, str_hive): |
---|
| 71 | # Variables locales. |
---|
| 72 | FILE = None |
---|
| 73 | |
---|
| 74 | # Camino del fichero de registro de usuario o de sistema (de menor a mayor prioridad). |
---|
| 75 | FILE = ogGetPath(f"/{path_mountpoint}/Windows/System32/config/{str_hive}") |
---|
| 76 | if not FILE: |
---|
| 77 | FILE = ogGetPath(f"/{path_mountpoint}/Users/{str_hive}/NTUSER.DAT") |
---|
| 78 | if not FILE: |
---|
| 79 | FILE = ogGetPath(f"/{path_mountpoint}/winnt/system32/config/{str_hive}") |
---|
| 80 | if not FILE: |
---|
| 81 | FILE = ogGetPath(f"/{path_mountpoint}/Documents and Settings/{str_hive}/NTUSER.DAT") |
---|
| 82 | if FILE and os.path.isfile(FILE): |
---|
| 83 | return FILE |
---|
| 84 | else: |
---|
| 85 | ogRaiseError(OG_ERR_NOTFOUND, f"{path_mountpoint} {str_hive}") |
---|
| 86 | return None |
---|
| 87 | |
---|
| 88 | def ogGetRegistryValue(path_mountpoint, str_hive, str_valuename): |
---|
| 89 | # Variables locales. |
---|
| 90 | FILE = ogGetHivePath(path_mountpoint, str_hive) |
---|
| 91 | if not FILE: |
---|
| 92 | return |
---|
| 93 | |
---|
| 94 | # Devolver el dato del valor de registro. |
---|
| 95 | chntpw_cmd = f''' |
---|
| 96 | chntpw "{FILE}" << EOT 2> /dev/null | awk '/> Value/ {{ |
---|
| 97 | if (index($0, "REG_BINARY") > 0) {{ |
---|
| 98 | data="" |
---|
| 99 | }} else {{ |
---|
| 100 | getline |
---|
| 101 | data=$0 |
---|
| 102 | }} |
---|
| 103 | }} |
---|
| 104 | /^:[0-9A-F]+ / {{ |
---|
| 105 | data=data""substr($0, 9, 48) |
---|
| 106 | }} |
---|
| 107 | END {{ |
---|
| 108 | print data |
---|
| 109 | }}' |
---|
| 110 | cd {str_valuename.rsplit('\\', 1)[0]} |
---|
| 111 | cat {str_valuename.rsplit('\\', 1)[-1]} |
---|
| 112 | q |
---|
| 113 | EOT |
---|
| 114 | ''' |
---|
| 115 | subprocess.run(chntpw_cmd, shell=True, timeout=5) |
---|
| 116 | |
---|
| 117 | def ogListRegistryKeys(path_mountpoint, str_hive, str_key): |
---|
| 118 | # Variables locales. |
---|
| 119 | FILE = ogGetHivePath(path_mountpoint, str_hive) |
---|
| 120 | if not FILE: |
---|
| 121 | return |
---|
| 122 | |
---|
| 123 | # Devolver la lista de claves de registro. |
---|
| 124 | chntpw_cmd = f''' |
---|
| 125 | chntpw "{FILE}" << EOT 2> /dev/null | awk 'BEGIN {{FS="[<>]"}} $1~/^ $/ {{print $2}}' |
---|
| 126 | ls {str_key} |
---|
| 127 | q |
---|
| 128 | EOT |
---|
| 129 | ''' |
---|
| 130 | subprocess.run(chntpw_cmd, shell=True, timeout=5) |
---|
| 131 | |
---|
| 132 | def ogListRegistryValues(path_mountpoint, str_hive, str_key): |
---|
| 133 | # Variables locales. |
---|
| 134 | FILE = ogGetHivePath(path_mountpoint, str_hive) |
---|
| 135 | if not FILE: |
---|
| 136 | return |
---|
| 137 | |
---|
| 138 | # Devolver la lista de valores de registro. |
---|
| 139 | chntpw_cmd = f''' |
---|
| 140 | chntpw "{FILE}" << EOT 2> /dev/null | awk 'BEGIN {{FS="[<>]"}} $1~/REG_/ {{print $2}}' |
---|
| 141 | ls {str_key} |
---|
| 142 | q |
---|
| 143 | EOT |
---|
| 144 | ''' |
---|
| 145 | subprocess.run(chntpw_cmd, shell=True, timeout=5) |
---|
| 146 | |
---|
| 147 | def ogSetRegistryValue(path_mountpoint, str_hive, str_valuename, str_data): |
---|
| 148 | # Variables locales. |
---|
| 149 | FILE = ogGetHivePath(path_mountpoint, str_hive) |
---|
| 150 | if not FILE: |
---|
| 151 | return |
---|
| 152 | |
---|
| 153 | # Fichero temporal para componer la entrada al comando "chntpw". |
---|
| 154 | tmpfile = "/tmp/chntpw$$" |
---|
| 155 | try: |
---|
| 156 | # Comprobar tipo de datos del valor del registro. |
---|
| 157 | with open(tmpfile, 'w') as f: |
---|
| 158 | f.write(f"ls {str_valuename.rsplit('\\', 1)[0]}\nq\n") |
---|
| 159 | output = subprocess.check_output(['chntpw', FILE], input=open(tmpfile, 'rb'), stderr=subprocess.DEVNULL).decode() |
---|
| 160 | if f"BINARY.*<{str_valuename.rsplit('\\', 1)[-1]}>" in output: |
---|
| 161 | # Procesar tipo binario (incluir nº de bytes y líneas de 16 parejas hexadecimales). |
---|
| 162 | if not re.match(r'^([0-9A-F]{2} )*$', str_data): |
---|
| 163 | ogRaiseError(OG_ERR_FORMAT, f'"{str_data}"') |
---|
| 164 | return |
---|
| 165 | n = len(str_data) + 1 |
---|
| 166 | with open(tmpfile, 'w') as f: |
---|
| 167 | f.write(f"cd {str_valuename.rsplit('\\', 1)[0]}\ned {str_valuename.rsplit('\\', 1)[-1]}\n{int(n/3)}\n") |
---|
| 168 | for i in range(0, n, 48): |
---|
| 169 | f.write(f":{i//3:05x} {str_data[i:i+48]}\n") |
---|
| 170 | f.write("s\nq\ny\n") |
---|
| 171 | else: |
---|
| 172 | # Cambiar el dato del valor de registro para cadenas y bytes. |
---|
| 173 | with open(tmpfile, 'w') as f: |
---|
| 174 | f.write(f"cd {str_valuename.rsplit('\\', 1)[0]}\ned {str_valuename.rsplit('\\', 1)[-1]}\n{str_data}\nq\ny\n") |
---|
| 175 | |
---|
| 176 | # Aplicar cambios. |
---|
| 177 | subprocess.run(['chntpw', FILE], input=open(tmpfile, 'rb'), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) |
---|
| 178 | finally: |
---|
| 179 | os.remove(tmpfile) |
---|