""" Disassemble the actual BCrypt crypto operations at 0x18015ba45+ and map all indirect calls to IAT entries. """ import struct from capstone import Cs, CS_ARCH_X86, CS_MODE_64 DLL_PATH = r"c:\Users\MattyMroz\Desktop\PROJECTS\ONEOCR\ocr_data\oneocr.dll" IMAGE_BASE = 0x180000000 TEXT_VA = 0x1000 TEXT_FILE_OFFSET = 0x400 def rva_to_file(rva): return rva - TEXT_VA + TEXT_FILE_OFFSET def file_to_rva(foff): return foff - TEXT_FILE_OFFSET + TEXT_VA with open(DLL_PATH, "rb") as f: dll_data = f.read() md = Cs(CS_ARCH_X86, CS_MODE_64) md.detail = False def disasm_region(name, file_start, file_end): rva_start = file_to_rva(file_start) va_start = IMAGE_BASE + rva_start code = dll_data[file_start:file_end] print(f"\n{'='*100}") print(f"{name}") print(f"File: 0x{file_start:08x}-0x{file_end:08x}, RVA: 0x{rva_start:08x}") print(f"{'='*100}") for insn in md.disasm(code, va_start): foff = rva_to_file(insn.address - IMAGE_BASE) line = f" {insn.address - IMAGE_BASE:08x} ({foff:08x}): {insn.bytes.hex():<40s} {insn.mnemonic:<14s} {insn.op_str}" # Annotate indirect calls if insn.mnemonic == 'call' and insn.bytes[0] == 0xFF and insn.bytes[1] == 0x15: disp = struct.unpack_from(' IAT@0x{target_rva:08x}") # Also disassemble the function at 0x18015abd0 (called to process data when r14b=true) # RVA 0x0015abd0, file 0x00159fd0 disasm_region( "Function at 0x18015abd0 (called on data when r14b=true)", 0x00159fd0, 0x0015a0c0 )