mirror of
https://github.com/ricardojoserf/trickdump
synced 2026-06-08 17:10:13 +00:00
183 lines
7.1 KiB
Python
183 lines
7.1 KiB
Python
import os
|
|
import sys
|
|
import json
|
|
import zipfile
|
|
import argparse
|
|
|
|
|
|
def get_args():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('-l', '--lock_json', required=False, default='lock.json', action='store', help='File path for lock.json')
|
|
parser.add_argument('-s', '--shock_json', required=False, default='shock.json', action='store', help='File path for shock.json')
|
|
parser.add_argument('-b', '--barrel_json', required=False, default='barrel.json', action='store', help='File path for barrel.json')
|
|
parser.add_argument('-z', '--barrel_zip', required=False, default='barrel.zip', action='store', help='Zip file containing the regions memory dumps')
|
|
parser.add_argument('-zp', '--barrel_zip_pwd', required=False, default='', action='store', help='Zip file containing the regions memory dumps')
|
|
parser.add_argument('-o', '--output_file', required=False, default='oogie.dmp', action='store', help='Dump file name')
|
|
my_args = parser.parse_args()
|
|
return my_args
|
|
|
|
|
|
def read_binary_file(file_path):
|
|
with open(file_path, 'rb') as file:
|
|
byte_array = file.read()
|
|
return byte_array
|
|
|
|
|
|
def get_dump_bytearr(lock_json, shock_json, barrel_json, zip_file, zip_file_pwd):
|
|
# Calculations
|
|
number_modules = str(len(shock_json))
|
|
modulelist_size = 4
|
|
modulelist_size += 108*int(number_modules)
|
|
for module in shock_json:
|
|
module_fullpath_len = len(module.get("field1"))
|
|
modulelist_size += (module_fullpath_len*2 + 8)
|
|
|
|
mem64list_offset = modulelist_size + 0x7c
|
|
mem64list_size = 16 + 16*len(barrel_json)
|
|
offset_memory_regions = mem64list_offset + mem64list_size
|
|
|
|
print("[+] Total number of modules: \t" + number_modules)
|
|
print("[+] ModuleListStream size: \t" + str(modulelist_size))
|
|
print("[+] Mem64List offset: \t\t" + str(mem64list_offset))
|
|
print("[+] Mem64List size: \t\t" + str(mem64list_size))
|
|
|
|
# Header
|
|
header = b'\x4d\x44\x4d\x50' # Signature
|
|
header += b'\x93\xa7' # Version
|
|
header += b'\x00\x00' # ImplementationVersion
|
|
header += b'\x03\x00\x00\x00' # NumberOfStreams
|
|
header += b'\x20\x00\x00\x00' # StreamDirectoryRva
|
|
header += b'\x00'*(32 - len(header)) # Other fields
|
|
|
|
# Stream Directory
|
|
stream_directory = b'\x04\x00\x00\x00' # Type 4 = ModuleListStream
|
|
stream_directory += modulelist_size.to_bytes(4, 'little') # Size
|
|
stream_directory += b'\x7c\x00\x00\x00' # Address
|
|
|
|
stream_directory += b'\x07\x00\x00\x00' # Type 7 = SystemInfoStream
|
|
stream_directory += b'\x38\x00\x00\x00' # Size = 56 (constant)
|
|
stream_directory += b'\x44\x00\x00\x00' # Address = 0x44 (constant)
|
|
|
|
stream_directory += b'\x09\x00\x00\x00' # Type 9 = Memory64ListStream
|
|
stream_directory += mem64list_size.to_bytes(4, 'little') # # Size
|
|
stream_directory += mem64list_offset.to_bytes(4, 'little') # Address
|
|
|
|
# SystemInfoStream
|
|
processor_architecture = 9
|
|
majorversion = int(lock_json.get("field0"))
|
|
minorversion = int(lock_json.get("field1"))
|
|
build_number = int(lock_json.get("field2"))
|
|
systeminfo_stream = processor_architecture.to_bytes(2, 'little') # Processor architecture
|
|
systeminfo_stream += b'\x00'*6
|
|
systeminfo_stream += majorversion.to_bytes(4, 'little') # Major version
|
|
systeminfo_stream += minorversion.to_bytes(4, 'little') # Minor version
|
|
systeminfo_stream += build_number.to_bytes(4, 'little') # Build number
|
|
systeminfo_stream += b'\x00'*(56-len(systeminfo_stream))
|
|
|
|
# ModuleListStream
|
|
modulelist_stream = int(number_modules).to_bytes(4, 'little') # NumberOfModules
|
|
pointer_index = 0x7c
|
|
pointer_index += len(modulelist_stream) # 4
|
|
pointer_index += 108*int(number_modules)
|
|
|
|
for module in shock_json:
|
|
modulelist_stream += int(module.get("field2"),16).to_bytes(8, 'little') # Module Address
|
|
modulelist_stream += int(module.get("field3")).to_bytes(8, 'little') # Module Size
|
|
modulelist_stream += b'\x00'*4
|
|
modulelist_stream += pointer_index.to_bytes(8, 'little') # Pointer to unicode string
|
|
full_path = module.get("field1")
|
|
pointer_index += len(full_path)*2 + 8
|
|
modulelist_stream += b'\x00'*(108-(8+8+4+8))
|
|
|
|
for module in shock_json:
|
|
full_path = module.get("field1")
|
|
unicode_bytearr = bytearray(full_path.encode('utf-16-le'))
|
|
modulelist_stream += (len(full_path)*2).to_bytes(4, 'little') # Unicode length
|
|
modulelist_stream += unicode_bytearr # Unicode string
|
|
modulelist_stream += 4*b'\x00' # Empty character + padding
|
|
|
|
# Memory64List
|
|
memory64list_stream = len(barrel_json).to_bytes(8, 'little') # NumberOfEntries
|
|
memory64list_stream += offset_memory_regions.to_bytes(8, 'little') # MemoryRegionsBaseAddress
|
|
for mem64 in barrel_json:
|
|
memory64list_stream += int(mem64.get("field1"),16).to_bytes(8, 'little') # Mem64 Address
|
|
memory64list_stream += int(mem64.get("field2")).to_bytes(8, 'little') # Mem64 Size
|
|
|
|
# Add memory regions from zip file
|
|
memory_bytearr = b''
|
|
|
|
if zip_file_pwd == "":
|
|
with zipfile.ZipFile(zip_file, 'r') as zip_file_handle:
|
|
for file_info in zip_file_handle.infolist():
|
|
with zip_file_handle.open(file_info.filename) as file:
|
|
file_bytes = file.read()
|
|
memory_bytearr += file_bytes
|
|
else:
|
|
import pyzipper
|
|
with pyzipper.AESZipFile(zip_file, 'r') as zip_file_handle:
|
|
zip_file_handle.pwd = zip_file_pwd.encode('utf-8')
|
|
for file_info in zip_file_handle.infolist():
|
|
with zip_file_handle.open(file_info.filename) as file:
|
|
file_bytes = file.read()
|
|
memory_bytearr += file_bytes
|
|
|
|
dump_file = header + stream_directory + systeminfo_stream + modulelist_stream + memory64list_stream + memory_bytearr
|
|
return dump_file
|
|
|
|
|
|
def create_file(output_file, dump_file):
|
|
with open(output_file, "wb") as binary_file:
|
|
binary_file.write(dump_file)
|
|
|
|
|
|
def show_banner():
|
|
print(" _______ _ _ _____ ")
|
|
print(" |__ __| (_) | | | __ \\ ")
|
|
print(" | |_ __ _ ___| | _| | | |_ _ _ __ ___ _ __ ")
|
|
print(" | | '__| |/ __| |/ / | | | | | | '_ ` _ \\| '_ \\ ")
|
|
print(" | | | | | (__| <| |__| | |_| | | | | | | |_) |")
|
|
print(" |_|_| |_|\\___|_|\\_\\_____/ \\__,_|_| |_| |_| .__/ ")
|
|
print(" | | ")
|
|
print(" by @ricardojoserf |_| ")
|
|
print("")
|
|
|
|
|
|
def main():
|
|
args = get_args()
|
|
lock_file = args.lock_json
|
|
shock_file = args.shock_json
|
|
barrel_file = args.barrel_json
|
|
zip_file = args.barrel_zip
|
|
zip_file_pwd = args.barrel_zip_pwd
|
|
output_file = args.output_file
|
|
|
|
show_banner()
|
|
|
|
# Generate JSON object from file
|
|
if os.path.exists(lock_file):
|
|
lock_json = json.loads(open(lock_file).read().splitlines()[0])[0]
|
|
else:
|
|
print("[-] File " + lock_file + " not found")
|
|
sys.exit(0)
|
|
if os.path.exists(shock_file):
|
|
shock_json = json.loads(open(shock_file).read().splitlines()[0])
|
|
shock_json = [obj for obj in shock_json if obj.get('field0') != ""]
|
|
else:
|
|
print("[-] File " + shock_file + " not found")
|
|
sys.exit(0)
|
|
if os.path.exists(barrel_file):
|
|
barrel_json = json.loads(open(barrel_file).read().splitlines()[0])
|
|
else:
|
|
print("[-] File " + barrel_file + " not found")
|
|
sys.exit(0)
|
|
if not os.path.exists(zip_file):
|
|
print("[-] File or Directory " + memory_files + " not found")
|
|
sys.exit(0)
|
|
|
|
dump_file = get_dump_bytearr(lock_json, shock_json, barrel_json, zip_file, zip_file_pwd)
|
|
create_file(output_file, dump_file)
|
|
print("[+] Dump file " + output_file + " created ")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |