ogclone-engine/client/lib/engine/bin/RegistryLib.py

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)