def gen_nop(): """Return a NOP instruction. """ empty_reg = ReilEmptyOperand() return ReilBuilder.build(ReilMnemonic.NOP, empty_reg, empty_reg, empty_reg)
def gen_undef(): """Return an UNDEF instruction. """ empty_reg = ReilEmptyOperand() return ReilBuilder.build(ReilMnemonic.UNDEF, empty_reg, empty_reg, empty_reg)
def _classify_load_memory(self, regs_init, regs_fini, mem_fini, written_regs, read_regs): """Classify load-memory gadgets. """ matches = [] regs_init_inv = self._invert_dictionary(regs_init) # Check for "dst_reg <- mem[src_reg + offset]" pattern. for dst_reg, dst_val in regs_fini.items(): # Make sure the *dst* register was written. if dst_reg not in written_regs: continue dst_size = self._arch_regs_size[dst_reg] # Look for memory addresses that contain *dst_val*. for src_addr in mem_fini.read_inverse(dst_val, dst_size // 8): # Look for registers whose values are used as memory # addresses. for src_reg, src_val in regs_init.items(): # Make sure the *src* register was read. if src_reg not in read_regs: continue # Check restrictions. if self._arch_regs_size[src_reg] != self._address_size: continue offset = (src_addr - src_val) & (2**self._address_size - 1) src_reg_ir = ReilRegisterOperand(src_reg, self._arch_regs_size[src_reg]) src_off_ir = ReilImmediateOperand(offset, self._arch_regs_size[src_reg]) dst_reg_ir = ReilRegisterOperand(dst_reg, self._arch_regs_size[dst_reg]) matches.append({ "src": [src_reg_ir, src_off_ir], "dst": [dst_reg_ir] }) # Check for "dst_reg <- mem[offset]" pattern. for dst_reg, dst_val in regs_fini.items(): # Make sure the *dst* register was written. if dst_reg not in written_regs: continue dst_size = self._arch_regs_size[dst_reg] for src_addr in mem_fini.read_inverse(dst_val, dst_size // 8): src_reg_ir = ReilEmptyOperand() src_off_ir = ReilImmediateOperand(src_addr, self._address_size) dst_reg_ir = ReilRegisterOperand(dst_reg, self._arch_regs_size[dst_reg]) matches.append({ "src": [src_reg_ir, src_off_ir], "dst": [dst_reg_ir] }) return matches
def gen_sext(src, dst): """Return a SEXT instruction. """ assert src.size <= dst.size empty_reg = ReilEmptyOperand() return ReilBuilder.build(ReilMnemonic.SEXT, src, empty_reg, dst)
def _classify_store_memory(self, regs_init, regs_fini, mem_fini, written_regs, read_regs): """Classify store-memory gadgets. """ matches = [] regs_init_inv = self._invert_dictionary(regs_init) # Check for "mem[dst_reg + offset] <- src_reg" pattern. for src_reg, src_val in regs_init.items(): # Make sure the *src* register was read. if src_reg not in read_regs: continue src_size = self._arch_regs_size[src_reg] for addr in mem_fini.read_inverse(src_val, src_size // 8): for dst_reg, dst_val in regs_init.items(): # Make sure the *dst* register was written. if dst_reg not in read_regs: continue # Check restrictions. if self._arch_regs_size[dst_reg] != self._address_size: continue offset = (addr - dst_val) & (2**self._address_size - 1) src_reg_ir = ReilRegisterOperand(src_reg, self._arch_regs_size[src_reg]) dst_reg_ir = ReilRegisterOperand(dst_reg, self._arch_regs_size[dst_reg]) dst_off_ir = ReilImmediateOperand(offset, self._arch_regs_size[dst_reg]) matches.append({ "src": [src_reg_ir], "dst": [dst_reg_ir, dst_off_ir] }) # Check for "mem[offset] <- src_reg" pattern. for src_reg, src_val in regs_init.items(): # Make sure the *src* register was read. if src_reg not in read_regs: continue src_size = self._arch_regs_size[src_reg] for addr in mem_fini.read_inverse(src_val, src_size // 8): offset = addr & (2**self._address_size - 1) src_reg_ir = ReilRegisterOperand(src_reg, self._arch_regs_size[src_reg]) dst_reg_ir = ReilEmptyOperand() dst_off_ir = ReilImmediateOperand(offset, self._address_size) matches.append({ "src": [src_reg_ir], "dst": [dst_reg_ir, dst_off_ir] }) return matches
def parse_operand(string, location, tokens): """Parse instruction operand. """ sizes = { "dqword": 128, "pointer": 72, "qword": 64, "pointer": 40, "dword": 32, "word": 16, "byte": 8, "bit": 1, } if "immediate" in tokens: imm_str = "".join(tokens["immediate"]) base = 16 if imm_str.startswith("0x") or imm_str.startswith( "-0x") else 10 imm = int(imm_str, base) oprnd = ReilImmediateOperand(imm) if "register" in tokens: if tokens["register"] in ["e", "empty"]: oprnd = ReilEmptyOperand() oprnd.size = 0 else: name = tokens["register"] oprnd = ReilRegisterOperand(name) if "size" in tokens: oprnd.size = int(sizes[tokens["size"]]) return [oprnd]
def _classify_arithmetic_store(self, regs_init, regs_fini, mem_fini, written_regs, read_regs): """Classify arithmetic-store gadgets. """ matchings = [] # Check for "m[dst_reg + offset] <- m[dst_reg + offset] OP src_reg" pattern. for op_name, op_fn in self._binary_ops.items(): for size in [8, 16, 32, 64]: for addr in mem_fini.get_addresses(): success_read_curr, val_curr = mem_fini.try_read( addr, size / 8) success_read_prev, val_prev = mem_fini.try_read_prev( addr, size / 8) if success_read_curr and success_read_prev: for src_reg, src_val in regs_init.items(): # Make sure the *src* register was read. if not src_reg in read_regs: continue # Check restrictions. if self._arch_regs_size[src_reg] != size: continue if val_curr == op_fn(src_val, val_prev) & (2**size - 1): # find dst + offset for dst_reg, dst_val in regs_init.items(): # Make sure the *dst* register was written. if not dst_reg in read_regs: continue # Check restrictions. if self._arch_regs_size[ dst_reg] != self._address_size: continue offset = (addr - dst_val) & ( 2**self._address_size - 1) src_reg_ir = ReilRegisterOperand( src_reg, self._arch_regs_size[src_reg]) dst_reg_ir = ReilRegisterOperand( dst_reg, self._arch_regs_size[dst_reg]) dst_off_ir = ReilImmediateOperand( offset, self._address_size) matchings.append({ "src" : [dst_reg_ir, dst_off_ir, \ src_reg_ir], "dst" : [dst_reg_ir, dst_off_ir], "op" : op_name }) # Check for "m[offset] <- m[offset] OP src_reg" pattern. for op_name, op_fn in self._binary_ops.items(): for size in [8, 16, 32, 64]: for addr in mem_fini.get_addresses(): success_read_curr, val_curr = mem_fini.try_read( addr, size / 8) success_read_prev, val_prev = mem_fini.try_read_prev( addr, size / 8) if success_read_curr and success_read_prev: for src_reg, src_val in regs_init.items(): # Make sure the *src* register was read. if not src_reg in read_regs: continue # Check restrictions. if self._arch_regs_size[src_reg] != size: continue if val_curr == op_fn(src_val, val_prev) & (2**size - 1): src_reg_ir = ReilRegisterOperand( src_reg, self._arch_regs_size[src_reg]) dst_reg_ir = ReilEmptyOperand() dst_off_ir = ReilImmediateOperand( addr, self._address_size) matchings.append({ "src": [dst_reg_ir, dst_off_ir, src_reg_ir], "dst": [dst_reg_ir, dst_off_ir], "op": op_name }) return matchings
def _classify_arithmetic_load(self, regs_init, regs_fini, mem_fini, written_regs, read_regs): """Classify arithmetic-load gadgets. """ matchings = [] # Check for "dst_reg <- dst_reg OP mem[src_reg + offset]" pattern. for op_name, op_fn in self._binary_ops.items(): for dst_reg, dst_val in regs_fini.items(): # Make sure the *dst* register was read and written. if dst_reg not in written_regs or dst_reg not in read_regs: continue dst_size = self._arch_regs_size[dst_reg] for addr in mem_fini.get_addresses(): success, val = mem_fini.try_read(addr, dst_size / 8) if success and dst_val == op_fn(regs_init[dst_reg], val) & (2**dst_size - 1): for src_reg, src_val in regs_init.items(): # Make sure the *src* register was read. if not src_reg in read_regs: continue # Check restrictions. if self._arch_regs_size[ src_reg] != self._address_size: continue offset = (addr - src_val) & (2**self._address_size - 1) src_reg_ir = ReilRegisterOperand( src_reg, self._arch_regs_size[src_reg]) src_off_ir = ReilImmediateOperand( offset, self._address_size) dst_reg_ir = ReilRegisterOperand( dst_reg, self._arch_regs_size[dst_reg]) matchings.append({ "src": [dst_reg_ir, src_reg_ir, src_off_ir], "dst": [dst_reg_ir], "op": op_name }) # Check for "dst_reg <- dst_reg OP mem[offset]" pattern. for op_name, op_fn in self._binary_ops.items(): for dst_reg, dst_val in regs_fini.items(): # Make sure the *dst* register was read and written. if dst_reg not in written_regs or dst_reg not in read_regs: continue dst_size = self._arch_regs_size[dst_reg] for addr in mem_fini.get_addresses(): success, val = mem_fini.try_read(addr, dst_size / 8) if success and dst_val == op_fn(regs_init[dst_reg], val) & (2**dst_size - 1): src_reg_ir = ReilEmptyOperand() src_off_ir = ReilImmediateOperand( addr, self._address_size) dst_reg_ir = ReilRegisterOperand( dst_reg, self._arch_regs_size[dst_reg]) matchings.append({ "src": [dst_reg_ir, src_reg_ir, src_off_ir], "dst": [dst_reg_ir], "op": op_name }) return matchings
def gen_jcc(src, dst): """Return a JCC instruction. """ return ReilBuilder.build(ReilMnemonic.JCC, src, ReilEmptyOperand(), dst)
def gen_bisz(src, dst): """Return a BISZ instruction. """ return ReilBuilder.build(ReilMnemonic.BISZ, src, ReilEmptyOperand(), dst)
def gen_str(src, dst): """Return a STR instruction. """ return ReilBuilder.build(ReilMnemonic.STR, src, ReilEmptyOperand(), dst)
def gen_ldm(src, dst): """Return a LDM instruction. """ return ReilBuilder.build(ReilMnemonic.LDM, src, ReilEmptyOperand(), dst)
def gen_unkn(self): """Return an UNKN instruction. """ empty_reg = ReilEmptyOperand() return self.build(ReilMnemonic.UNKN, empty_reg, empty_reg, empty_reg)
def gen_stm(self, src, dst): """Return a STM instruction. """ return self.build(ReilMnemonic.STM, src, ReilEmptyOperand(), dst)