parent
f48a879e31
commit
cfd41dd6f5
5 changed files with 242 additions and 0 deletions
@ -0,0 +1,65 @@ |
||||
from libcpp cimport bool |
||||
from libc.stdint cimport uint8_t, uint64_t, uint16_t |
||||
|
||||
cdef extern from "<capstone/capstone.h>": |
||||
|
||||
ctypedef size_t csh |
||||
|
||||
ctypedef enum cs_mode: |
||||
pass |
||||
|
||||
ctypedef enum cs_arch: |
||||
pass |
||||
|
||||
ctypedef struct cs_detail: |
||||
pass |
||||
|
||||
ctypedef struct cs_insn: |
||||
unsigned int id |
||||
uint64_t address |
||||
uint16_t size |
||||
uint8_t bytes[16] |
||||
char mnemonic[32] |
||||
char op_str[96] |
||||
cs_detail *detail |
||||
|
||||
ctypedef enum cs_err: |
||||
pass |
||||
|
||||
ctypedef enum cs_opt_type: |
||||
pass |
||||
|
||||
unsigned int cs_version(int *major, int *minor) |
||||
|
||||
bool cs_support(int arch) |
||||
|
||||
cs_err cs_open(cs_arch arch, cs_mode mode, csh *handle) |
||||
|
||||
cs_err cs_close(csh handle) |
||||
|
||||
cs_err cs_errno(csh handle) |
||||
|
||||
size_t cs_disasm_ex(csh handle, |
||||
const uint8_t *code, size_t code_size, |
||||
uint64_t address, |
||||
size_t count, |
||||
cs_insn **insn) |
||||
|
||||
cs_err cs_option(csh handle, cs_opt_type type, size_t value) |
||||
|
||||
void cs_free(cs_insn *insn, size_t count) |
||||
|
||||
const char *cs_reg_name(csh handle, unsigned int reg_id) |
||||
|
||||
const char *cs_insn_name(csh handle, unsigned int insn_id) |
||||
|
||||
bool cs_insn_group(csh handle, cs_insn *insn, unsigned int group_id) |
||||
|
||||
bool cs_reg_read(csh handle, cs_insn *insn, unsigned int reg_id) |
||||
|
||||
bool cs_reg_write(csh handle, cs_insn *insn, unsigned int reg_id) |
||||
|
||||
int cs_op_count(csh handle, cs_insn *insn, unsigned int op_type) |
||||
|
||||
int cs_op_index(csh handle, cs_insn *insn, unsigned int op_type, |
||||
unsigned int position) |
@ -0,0 +1,167 @@ |
||||
cimport ccapstone as cc |
||||
import ctypes |
||||
from capstone import * |
||||
import capstone |
||||
from capstone import arm, x86, mips, ppc, arm64 |
||||
|
||||
class CsDetail: |
||||
|
||||
def __init__(self, arch, raw_detail = None): |
||||
if not raw_detail: |
||||
return |
||||
detail = ctypes.cast(raw_detail, ctypes.POINTER(capstone._cs_detail)).contents |
||||
|
||||
self.regs_read = detail.regs_read |
||||
self.regs_write = detail.regs_write |
||||
self.groups = detail.groups |
||||
|
||||
if arch == capstone.CS_ARCH_ARM: |
||||
(self.cc, self.update_flags, self.writeback, self.operands) = \ |
||||
arm.get_arch_info(detail.arch.arm) |
||||
elif arch == capstone.CS_ARCH_ARM64: |
||||
(self.cc, self.update_flags, self.writeback, self.operands) = \ |
||||
arm64.get_arch_info(detail.arch.arm64) |
||||
elif arch == capstone.CS_ARCH_X86: |
||||
(self.prefix, self.segment, self.opcode, self.op_size, self.addr_size, \ |
||||
self.disp_size, self.imm_size, self.modrm, self.sib, self.disp, \ |
||||
self.sib_index, self.sib_scale, self.sib_base, self.operands) = x86.get_arch_info(detail.arch.x86) |
||||
elif arch == capstone.CS_ARCH_MIPS: |
||||
self.operands = mips.get_arch_info(detail.arch.mips) |
||||
elif arch == capstone.CS_ARCH_PPC: |
||||
(self.bc, self.bh, self.update_cr0, self.operands) = \ |
||||
ppc.get_arch_info(detail.arch.ppc) |
||||
|
||||
cdef class CCsInsn(object): |
||||
|
||||
cdef cc.cs_insn _raw |
||||
cdef cc.csh _csh |
||||
cdef object _detail |
||||
|
||||
def __cinit__(self, _detail): |
||||
self._detail = _detail |
||||
|
||||
def __getattr__(self, name): |
||||
_detail = self._detail |
||||
return getattr(_detail, name) |
||||
|
||||
@property |
||||
def operands(self): |
||||
return self._detail.operands |
||||
|
||||
@property |
||||
def id(self): |
||||
return self._raw.id |
||||
|
||||
@property |
||||
def address(self): |
||||
return self._raw.address |
||||
|
||||
@property |
||||
def size(self): |
||||
return self._raw.size |
||||
|
||||
@property |
||||
def bytes(self): |
||||
return bytearray(self._raw.bytes)[:self._raw.size] |
||||
|
||||
@property |
||||
def mnemonic(self): |
||||
return self._raw.mnemonic |
||||
|
||||
@property |
||||
def op_str(self): |
||||
return self._raw.op_str |
||||
|
||||
@property |
||||
def regs_read(self): |
||||
if self._detail: |
||||
detail = self._detail |
||||
return detail.regs_read[:detail.regs_read_count] |
||||
|
||||
raise CsError(CS_ERR_DETAIL) |
||||
|
||||
@property |
||||
def regs_write(self): |
||||
if self._detail: |
||||
detail = self._detail |
||||
return detail.regs_write[:detail.regs_write_count] |
||||
|
||||
raise CsError(CS_ERR_DETAIL) |
||||
|
||||
@property |
||||
def groups(self): |
||||
if self._detail: |
||||
detail = self._detail |
||||
return detail.groups[:detail.groups_count] |
||||
|
||||
raise CsError(CS_ERR_DETAIL) |
||||
|
||||
# get the last error code |
||||
def errno(self): |
||||
return cc.cs_errno(self._csh) |
||||
|
||||
# get the register name, given the register ID |
||||
def reg_name(self, reg_id): |
||||
return cc.cs_reg_name(self._csh, reg_id) |
||||
|
||||
# get the instruction string |
||||
def insn_name(self): |
||||
return cc.cs_insn_name(self._csh, self.id) |
||||
|
||||
# verify if this insn belong to group with id as @group_id |
||||
def group(self, group_id): |
||||
return group_id in self._detail.groups |
||||
|
||||
# verify if this instruction implicitly read register @reg_id |
||||
def reg_read(self, reg_id): |
||||
return reg_id in self._detail.regs_read |
||||
|
||||
# verify if this instruction implicitly modified register @reg_id |
||||
def reg_write(self, reg_id): |
||||
return reg_id in self._detail.regs_write |
||||
|
||||
# return number of operands having same operand type @op_type |
||||
def op_count(self, op_type): |
||||
c = 0 |
||||
for op in self._detail.operands: |
||||
if op.type == op_type: |
||||
c += 1 |
||||
return c |
||||
|
||||
# get the operand at position @position of all operands having the same type @op_type |
||||
def op_find(self, op_type, position): |
||||
c = 0 |
||||
for op in self._detail.operands: |
||||
if op.type == op_type: |
||||
c += 1 |
||||
if c == position: |
||||
return op |
||||
|
||||
cdef class CCs: |
||||
|
||||
cdef cc.csh csh |
||||
cdef object _cs |
||||
|
||||
def __cinit__(self, _cs): |
||||
self.csh = <cc.csh> _cs.csh.value |
||||
self._cs = _cs |
||||
|
||||
def getcsh(self): |
||||
return ctypes.c_size_t(<size_t>self.csh) |
||||
|
||||
def disasm(self, code, addr, count=0): |
||||
cdef cc.cs_insn *allinsn |
||||
cdef res = cc.cs_disasm_ex(self.csh, code, len(code), addr, count, &allinsn) |
||||
detail = self._cs.detail |
||||
arch = self._cs.arch |
||||
|
||||
for i from 0 <= i < res: |
||||
if detail: |
||||
dummy = CCsInsn(CsDetail(arch, <size_t>allinsn[i].detail)) |
||||
else: |
||||
dummy = CCsInsn(None) |
||||
dummy._raw = allinsn[i] |
||||
dummy._csh = self.csh |
||||
yield dummy |
||||
|
||||
|
Loading…
Reference in new issue