Last active
May 3, 2021 00:09
-
-
Save zwade/d2f4eb452b7f873462cefedc7ae6b802 to your computer and use it in GitHub Desktop.
Tiamat Disassembler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import Dict, List, Optional | |
from capstone import * | |
import sys | |
from capstone.ppc_const import PPC_INS_XVABSSP | |
sparc_little = Cs(CS_ARCH_SPARC, CS_MODE_V9 | CS_MODE_BIG_ENDIAN) | |
sparc_big = Cs(CS_ARCH_SPARC, CS_MODE_V9 | CS_MODE_BIG_ENDIAN) | |
riscv_little = Cs(CS_ARCH_RISCV, CS_MODE_RISCV32) | |
riscv_big = Cs(CS_ARCH_RISCV, CS_MODE_RISCV32) | |
arm_little = Cs(CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_LITTLE_ENDIAN) | |
arm_big = Cs(CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_BIG_ENDIAN) | |
mips_little = Cs(CS_ARCH_MIPS, CS_MODE_MIPS32 | CS_MODE_LITTLE_ENDIAN) | |
mips_big = Cs(CS_ARCH_MIPS, CS_MODE_MIPS32 | CS_MODE_BIG_ENDIAN) | |
all_arch = [ | |
sparc_little, | |
sparc_big, | |
riscv_little, | |
riscv_big, | |
arm_little, | |
arm_big, | |
mips_little, | |
mips_big, | |
] | |
for arch in all_arch: | |
arch.detail = True | |
class A: | |
red = "\x1b[38;5;1m" | |
green = "\x1b[38;5;2m" | |
yellow = "\x1b[38;5;3m" | |
blue = "\x1b[38;5;4m" | |
gray = "\x1b[38;5;8m" | |
clear = "\x1b[0m" | |
def get_arch_by_tmap(i: int): | |
return all_arch[i] | |
def get_name_by_tmap(i: int): | |
return [ | |
"sparc (little)", | |
"sparc (big) ", | |
"riscv (little)", | |
"riscv (big) ", | |
"arm (little)", | |
"arm (big) ", | |
"mips (little)", | |
"mips (big) ", | |
][i] | |
tmap_arch = open("./tmap_arch.bin", "rb").read() | |
def get_tmap(pc: int): | |
offset = int((pc - 0x100d0) >> 2) | |
return tmap_arch[offset] | |
def get_arch(pc: int): | |
return get_arch_by_tmap(get_tmap(pc)) | |
def byteswap(i32: bytes): | |
a, b, c, d = i32 | |
return bytes([d, c, b, a]) | |
program = open("./liccheck.bin", "rb").read()[208:] | |
def format_program(a: int, b: bytes): | |
return (b * int(a / 4) + b) | |
def print_instruction(pc: int, instruction: Optional[CsInsn], refs_to: List[int], refs_from: List[int]): | |
tmap = get_tmap(pc) | |
ref_from_str = "" | |
if len(refs_from) > 0: | |
fmt_refs = [f"{ref:4x}" for ref in refs_from] | |
ref_from_str = f" {A.green}(xrefs from: {', '.join(fmt_refs)}){A.clear}" | |
ref_to_str = "" | |
if len(refs_to) > 0: | |
fmt_refs = [f"{ref:4x}" for ref in refs_to] | |
ref_to_str = f" {A.red}(xrefs to: {', '.join(fmt_refs)}){A.clear}" | |
if len(refs_from) > 0: | |
sys.stdout.write(f"\n{A.gray}{'-'*100}{A.clear}\n") | |
sys.stdout.write(f"{A.gray}{pc:8x}{A.yellow} {get_name_by_tmap(tmap)} {A.clear}") | |
if instruction is None: | |
sys.stdout.write(f"{A.red}Failed\n") | |
return | |
sys.stdout.write(f"{A.blue}{instruction.mnemonic:8s} {A.clear}{instruction.op_str:20s}{A.clear}{ref_to_str}{ref_from_str}\n") | |
if instruction.mnemonic == "ret" or len(refs_to) > 0: | |
sys.stdout.write(f"{A.gray}{'-'*100}{A.clear}\n\n") | |
def parse_instruction(pc: int, xrefs_to: Dict[int, List[int]], xrefs_from: Dict[int, List[int]]): | |
arch = get_arch(pc) | |
tmap = get_tmap(pc) | |
code = program[(pc - 0x100d0):(pc - 0x100d0 + 4)] | |
if (tmap & 14 == 2 and tmap & 1) or (tmap & 14 == 0 and not (tmap & 1)): | |
code = byteswap(code) | |
try: | |
instruction = next(arch.disasm(format_program(pc, code), pc, 1)) | |
refs: List[int] = [] | |
if (instruction.mnemonic in ("b",)): | |
refs.append(instruction.operands[0].value.imm) | |
if (instruction.mnemonic in ("jal", "j")): | |
refs.append(instruction.operands[0].value.imm + pc) | |
if (instruction.mnemonic in ("beqz",)): | |
refs.append(instruction.operands[1].value.imm + pc) | |
if (instruction.mnemonic in ("beq", "bge", "bne")): | |
refs.append(instruction.operands[2].value.imm + pc) | |
xrefs_from[pc] = refs | |
for ref in refs: | |
xrefs_to[ref] = (xrefs_to.get(ref, [])) + [pc] | |
return instruction | |
except Exception as e: | |
return None | |
back_refs: Dict[int, List[int]] = {} | |
fwd_refs: Dict[int, List[int]] = {} | |
insts: List[Optional[CsInsn]] = [] | |
addr = 0x100d0 | |
while addr <= 0x110dc: | |
insts.append(parse_instruction(addr, fwd_refs, back_refs)) | |
addr += 4 | |
for i, inst in enumerate(insts): | |
pc = 0x100d0 + i * 4 | |
print_instruction(pc, inst, back_refs.get(pc, []), fwd_refs.get(pc, [])) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment