Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def simulate(self, instructions):
for insn in instructions:
if insn.mnemonic == 'add':
assert insn.operands[1].type == capstone.x86.X86_OP_IMM
self.store(insn.operands[0], ptrutil.pointer_offset(self.settings, self.load(insn.operands[0]), insn.operands[1].imm))
if insn.operands[0].type == capstone.x86.X86_OP_REG and base_register(insn.operands[0].reg) == self.settings.rt.heap_register:
self.heap += [None] * (insn.operands[1].imm // self.settings.rt.word.size)
elif insn.mnemonic == 'mov':
self.store(insn.operands[0], self.load(insn.operands[1]))
elif insn.mnemonic == 'lea':
self.store(insn.operands[0], self.read_memory_operand(insn.operands[1].mem))
def __init__(self) -> None:
import capstone.x86
Operand._x86_op_imm = capstone.x86.X86_OP_IMM
Operand._x86_op_reg = capstone.x86.X86_OP_REG
Operand._x86_op_mem = capstone.x86.X86_OP_MEM
# Index the available x86 registers.
for reg in dir(capstone.x86):
if not reg.startswith("X86_REG_"):
continue
Operand.regs[getattr(capstone.x86, reg)] = reg.split("_")[2].lower()
def reg_write(inst, reg_id):
if len(inst.operands) == 0:
return False
op = inst.operands[0]
return op.type == X86_OP_REG and op.value.reg == reg_id
OP_TYPE_MEM = 3
OP_TYPE_MAP = {
OP_TYPE_REG: 'REG',
OP_TYPE_IMM: 'IMM',
OP_TYPE_MEM: 'MEM',
}
CAPSTONE_OP_TYPE_MAP = {
'X86': {
capstone.x86.X86_OP_REG: OP_TYPE_REG,
capstone.x86.X86_OP_IMM: OP_TYPE_IMM,
capstone.x86.X86_OP_MEM: OP_TYPE_MEM,
},
'AMD64': {
capstone.x86.X86_OP_REG: OP_TYPE_REG,
capstone.x86.X86_OP_IMM: OP_TYPE_IMM,
capstone.x86.X86_OP_MEM: OP_TYPE_MEM,
},
}
CAPSTONE_REG_MAP = {
# will be filled up by fill_reg_map()
'X86': {
},
'AMD64': {
}
}
# Utils
def string_escape(s):
def x86_mov(ctx, i):
size = operand.get_size(ctx, i, 0)
value = None
clear = True
if len(i.operands) == 1:
# source is the accumulator
value = ctx.accumulator
if i.operands[0].type == capstone.x86.X86_OP_REG:
clear = False
else:
value = operand.get(ctx, i, 1, size=size)
if (i.operands[0].type == capstone.x86.X86_OP_REG and
i.operands[1].type == capstone.x86.X86_OP_REG):
clear = False
# Oh x86 how I hate you
if i.operands[1].type == capstone.x86.X86_OP_MEM and operand.get_size(ctx, i, 1) != 32:
clear = False
operand.set(ctx, i, 0, value, clear=clear)
def is_reg(self):
return self.type == cpu.X86_OP_REG
def fuse_inst_with_if(ctx, ast):
if isinstance(ast, Ast_Branch):
types_ast = (Ast_Ifelse, Ast_IfGoto, Ast_AndIf)
for i, n in enumerate(ast.nodes):
if isinstance(n, list):
if ((n[-1].id in FUSE_OPS or (n[-1].id == X86_INS_TEST and
all(op.type == X86_OP_REG for op in n[-1].operands) and
len(set(op.value.reg for op in n[-1].operands)) == 1))
and i+1 < len(ast.nodes)
and isinstance(ast.nodes[i+1], types_ast)):
ast.nodes[i+1].fused_inst = n[-1]
ctx.all_fused_inst.add(n[-1].address)
else: # ast
fuse_inst_with_if(ctx, n)
elif isinstance(ast, Ast_Ifelse):
fuse_inst_with_if(ctx, ast.br_next)
fuse_inst_with_if(ctx, ast.br_next_jump)
elif isinstance(ast, Ast_Loop):
fuse_inst_with_if(ctx, ast.branch)
X86_INS_IMUL, X86_INS_INC, X86_INS_JA, X86_INS_JAE, X86_INS_JE,
X86_INS_JGE, X86_INS_JL, X86_INS_JLE, X86_INS_JG, X86_INS_JBE,
X86_INS_JB, X86_INS_JMP, X86_INS_JCXZ, X86_INS_JECXZ,
X86_INS_JNE, X86_INS_JNO, X86_INS_JNP, X86_INS_JNS, X86_INS_JO,
X86_INS_JP, X86_INS_JRCXZ, X86_INS_JS, X86_INS_MOV, X86_INS_SHL,
X86_INS_SAL, X86_INS_SAR, X86_OP_IMM, X86_OP_MEM, X86_OP_REG,
X86_INS_SHR, X86_INS_SUB, X86_INS_XOR, X86_INS_OR, X86_INS_MOVSX,
X86_REG_RSP, X86_REG_ESP, X86_REG_SP, X86_INS_PUSH, X86_INS_LEAVE,
X86_INS_POPAW, X86_INS_POPAL, X86_INS_POPF, X86_INS_POPFD, X86_INS_POPFQ,
X86_INS_PUSHAW, X86_INS_PUSHAL, X86_INS_PUSHF, X86_INS_PUSHFD,
X86_INS_PUSHFQ, X86_INS_PUSH, X86_INS_POP)
OP_IMM = X86_OP_IMM
OP_MEM = X86_OP_MEM
OP_REG = X86_OP_REG
# Warning: before adding new prolog check in lib.analyzer.has_prolog
PROLOGS = [
[b"\x55\x89\xe5"], # push ebp; mov ebp, esp
[b"\x55\x48\x89\xe5"], # push rbp; mov rbp, rsp
]
PUSHPOP = {
X86_INS_POPAW, X86_INS_POPAL, X86_INS_POPF, X86_INS_POPFD, X86_INS_POPFQ,
X86_INS_PUSHAW, X86_INS_PUSHAL, X86_INS_PUSHF, X86_INS_PUSHFD, X86_INS_PUSHFQ,
X86_INS_PUSH, X86_INS_POP,
}
def is_cmp(i):
if self.dis.binary.arch == "x86":
if insn.id == X86_INS_PUSH and \
insn.operands[0].type == X86_OP_IMM:
imm = insn.operands[0].value.imm
if arg_count == 0:
new_function(imm, "main")
elif arg_count == 1:
new_function(imm, "__libc_csu_init")
elif arg_count == 2:
new_function(imm, "__libc_csu_fini")
arg_count += 1
else: # x64
if insn.id == X86_INS_MOV and \
insn.operands[0].type == X86_OP_REG and \
insn.operands[1].type == X86_OP_IMM:
reg = insn.operands[0].value.reg
imm = insn.operands[1].value.imm
if reg == X86_REG_RDI:
new_function(imm, "main")
elif reg == X86_REG_RCX:
new_function(imm, "__libc_csu_init")
elif reg == X86_REG_R8:
new_function(imm, "__libc_csu_fini")
insn_count -= 1
ad -= 1
# Detect if the written val is the result from a floating point register
if self.instr.mnemonic.startswith('mov'):
src_op = self.instr.operands[1]
if src_op.type == capstone.x86.X86_OP_FP or\
(src_op.type == capstone.x86.X86_OP_REG and src_op.reg in xmm_regs):
if size == 4:
return _dynStruct.float_str
elif size == 8:
return _dynStruct.double_str
else:
return None
elif self.ctx_opcode and self.ctx_instr.mnemonic.startswith('mov'):
dest_ctx_reg = self.ctx_instr.operands[0].reg
src_ctx_op = self.ctx_instr.operands[1]
if self.instr.operands[1].reg == dest_ctx_reg and\
src_ctx_op.type == capstone.x86.X86_OP_REG and src_ctx_op.reg in xmm_regs:
if size == 4:
return _dynStruct.float_str
elif size == 8:
return _dynStruct.double_str
else:
return None
# Next analysis need a ctx_instr
if not self.ctx_opcode:
return None
# detect ptr if ctx = lea and instr = mov with the reg value
# get from lea. If yes it's a ptr
if self.ctx_instr.id == capstone.x86.X86_INS_LEA:
dest_reg = self.ctx_instr.operands[0].reg
if self.instr.mnemonic.startswith('mov') and\