180 lines
6.1 KiB
Python
180 lines
6.1 KiB
Python
import subprocess
|
|
import os
|
|
import re
|
|
|
|
#from engine.FileLib import *
|
|
#from engine.SystemLib import *
|
|
|
|
def chntpw(*args):
|
|
chntpw_path = subprocess.check_output(['which', 'drbl-chntpw']).decode().strip()
|
|
if not chntpw_path:
|
|
chntpw_path = subprocess.check_output(['which', 'chntpw']).decode().strip()
|
|
subprocess.run([chntpw_path, '-e'] + list(args), timeout=5)
|
|
|
|
def ogAddRegistryKey(path_mountpoint, str_hive, str_key):
|
|
# Variables locales.
|
|
FILE = ogGetHivePath(path_mountpoint, str_hive)
|
|
if not FILE:
|
|
return
|
|
|
|
# Añadir nueva clave.
|
|
chntpw(FILE, 'cd', str_key.rsplit('\\', 1)[0])
|
|
chntpw(FILE, 'nk', str_key.rsplit('\\', 1)[-1])
|
|
chntpw(FILE, 'q')
|
|
chntpw(FILE, 'y')
|
|
|
|
def ogAddRegistryValue(path_mountpoint, str_hive, str_key, str_valuename, str_valuetype=''):
|
|
# Variables locales.
|
|
FILE = ogGetHivePath(path_mountpoint, str_hive)
|
|
if not FILE:
|
|
return
|
|
|
|
# Determine the value type.
|
|
if str_valuetype.upper() == 'STRING' or str_valuetype == '':
|
|
TYPE = 1
|
|
elif str_valuetype.upper() == 'BINARY':
|
|
TYPE = 3
|
|
elif str_valuetype.upper() == 'DWORD':
|
|
TYPE = 4
|
|
else:
|
|
ogRaiseError(OG_ERR_OUTOFLIMIT, str_valuetype)
|
|
return
|
|
|
|
# Add the registry value.
|
|
chntpw(FILE, 'cd', str_key.rsplit('\\', 1)[0])
|
|
chntpw(FILE, 'nv', str_valuename.rsplit('\\', 1)[-1], TYPE)
|
|
chntpw(FILE, 'q')
|
|
chntpw(FILE, 'y')
|
|
|
|
def ogDeleteRegistryKey(path_mountpoint, str_hive, str_key):
|
|
# Variables locales.
|
|
FILE = ogGetHivePath(path_mountpoint, str_hive)
|
|
if not FILE:
|
|
return
|
|
|
|
# Delete the registry key.
|
|
subprocess.run(['chntpw', FILE], input=f"cd {str_key.rsplit('\\', 1)[0]}\ndk {str_key.rsplit('\\', 1)[-1]}\nq\ny\n".encode(), timeout=5)
|
|
|
|
def ogDeleteRegistryValue(path_mountpoint, str_hive, str_valuename):
|
|
# Variables locales.
|
|
FILE = ogGetHivePath(path_mountpoint, str_hive)
|
|
if not FILE:
|
|
return
|
|
|
|
# Delete the registry value.
|
|
chntpw(FILE, 'cd', str_valuename.rsplit('\\', 1)[0])
|
|
chntpw(FILE, 'dv', str_valuename.rsplit('\\', 1)[-1])
|
|
chntpw(FILE, 'q')
|
|
chntpw(FILE, 'y')
|
|
|
|
def ogGetHivePath(path_mountpoint, str_hive):
|
|
# Variables locales.
|
|
FILE = None
|
|
|
|
# Camino del fichero de registro de usuario o de sistema (de menor a mayor prioridad).
|
|
FILE = ogGetPath(f"/{path_mountpoint}/Windows/System32/config/{str_hive}")
|
|
if not FILE:
|
|
FILE = ogGetPath(f"/{path_mountpoint}/Users/{str_hive}/NTUSER.DAT")
|
|
if not FILE:
|
|
FILE = ogGetPath(f"/{path_mountpoint}/winnt/system32/config/{str_hive}")
|
|
if not FILE:
|
|
FILE = ogGetPath(f"/{path_mountpoint}/Documents and Settings/{str_hive}/NTUSER.DAT")
|
|
if FILE and os.path.isfile(FILE):
|
|
return FILE
|
|
else:
|
|
ogRaiseError(OG_ERR_NOTFOUND, f"{path_mountpoint} {str_hive}")
|
|
return None
|
|
|
|
def ogGetRegistryValue(path_mountpoint, str_hive, str_valuename):
|
|
# Variables locales.
|
|
FILE = ogGetHivePath(path_mountpoint, str_hive)
|
|
if not FILE:
|
|
return
|
|
|
|
# Devolver el dato del valor de registro.
|
|
chntpw_cmd = f'''
|
|
chntpw "{FILE}" << EOT 2> /dev/null | awk '/> Value/ {{
|
|
if (index($0, "REG_BINARY") > 0) {{
|
|
data=""
|
|
}} else {{
|
|
getline
|
|
data=$0
|
|
}}
|
|
}}
|
|
/^:[0-9A-F]+ / {{
|
|
data=data""substr($0, 9, 48)
|
|
}}
|
|
END {{
|
|
print data
|
|
}}'
|
|
cd {str_valuename.rsplit('\\', 1)[0]}
|
|
cat {str_valuename.rsplit('\\', 1)[-1]}
|
|
q
|
|
EOT
|
|
'''
|
|
subprocess.run(chntpw_cmd, shell=True, timeout=5)
|
|
|
|
def ogListRegistryKeys(path_mountpoint, str_hive, str_key):
|
|
# Variables locales.
|
|
FILE = ogGetHivePath(path_mountpoint, str_hive)
|
|
if not FILE:
|
|
return
|
|
|
|
# Devolver la lista de claves de registro.
|
|
chntpw_cmd = f'''
|
|
chntpw "{FILE}" << EOT 2> /dev/null | awk 'BEGIN {{FS="[<>]"}} $1~/^ $/ {{print $2}}'
|
|
ls {str_key}
|
|
q
|
|
EOT
|
|
'''
|
|
subprocess.run(chntpw_cmd, shell=True, timeout=5)
|
|
|
|
def ogListRegistryValues(path_mountpoint, str_hive, str_key):
|
|
# Variables locales.
|
|
FILE = ogGetHivePath(path_mountpoint, str_hive)
|
|
if not FILE:
|
|
return
|
|
|
|
# Devolver la lista de valores de registro.
|
|
chntpw_cmd = f'''
|
|
chntpw "{FILE}" << EOT 2> /dev/null | awk 'BEGIN {{FS="[<>]"}} $1~/REG_/ {{print $2}}'
|
|
ls {str_key}
|
|
q
|
|
EOT
|
|
'''
|
|
subprocess.run(chntpw_cmd, shell=True, timeout=5)
|
|
|
|
def ogSetRegistryValue(path_mountpoint, str_hive, str_valuename, str_data):
|
|
# Variables locales.
|
|
FILE = ogGetHivePath(path_mountpoint, str_hive)
|
|
if not FILE:
|
|
return
|
|
|
|
# Fichero temporal para componer la entrada al comando "chntpw".
|
|
tmpfile = "/tmp/chntpw$$"
|
|
try:
|
|
# Comprobar tipo de datos del valor del registro.
|
|
with open(tmpfile, 'w') as f:
|
|
f.write(f"ls {str_valuename.rsplit('\\', 1)[0]}\nq\n")
|
|
output = subprocess.check_output(['chntpw', FILE], input=open(tmpfile, 'rb'), stderr=subprocess.DEVNULL).decode()
|
|
if f"BINARY.*<{str_valuename.rsplit('\\', 1)[-1]}>" in output:
|
|
# Procesar tipo binario (incluir nº de bytes y líneas de 16 parejas hexadecimales).
|
|
if not re.match(r'^([0-9A-F]{2} )*$', str_data):
|
|
ogRaiseError(OG_ERR_FORMAT, f'"{str_data}"')
|
|
return
|
|
n = len(str_data) + 1
|
|
with open(tmpfile, 'w') as f:
|
|
f.write(f"cd {str_valuename.rsplit('\\', 1)[0]}\ned {str_valuename.rsplit('\\', 1)[-1]}\n{int(n/3)}\n")
|
|
for i in range(0, n, 48):
|
|
f.write(f":{i//3:05x} {str_data[i:i+48]}\n")
|
|
f.write("s\nq\ny\n")
|
|
else:
|
|
# Cambiar el dato del valor de registro para cadenas y bytes.
|
|
with open(tmpfile, 'w') as f:
|
|
f.write(f"cd {str_valuename.rsplit('\\', 1)[0]}\ned {str_valuename.rsplit('\\', 1)[-1]}\n{str_data}\nq\ny\n")
|
|
|
|
# Aplicar cambios.
|
|
subprocess.run(['chntpw', FILE], input=open(tmpfile, 'rb'), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
finally:
|
|
os.remove(tmpfile)
|