1#!/usr/bin/env python 2 3# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com> 4from __future__ import print_function 5from capstone import * 6from capstone.x86 import * 7from xprint import to_hex, to_x, to_x_32 8 9 10X86_CODE64 = b"\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff" 11X86_CODE16 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x23\x01\x00\x00\x36\x8b\x84\x91\x23\x01\x00\x00\x41\x8d\x84\x39\x89\x67\x00\x00\x8d\x87\x89\x67\x00\x00\xb4\xc6\x66\xe9\xb8\x00\x00\x00\x67\xff\xa0\x23\x01\x00\x00\x66\xe8\xcb\x00\x00\x00\x74\xfc" 12X86_CODE32 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x23\x01\x00\x00\x36\x8b\x84\x91\x23\x01\x00\x00\x41\x8d\x84\x39\x89\x67\x00\x00\x8d\x87\x89\x67\x00\x00\xb4\xc6\xe9\xea\xbe\xad\xde\xff\xa0\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff" 13 14all_tests = ( 15 (CS_ARCH_X86, CS_MODE_16, X86_CODE16, "X86 16bit (Intel syntax)", None), 16 (CS_ARCH_X86, CS_MODE_32, X86_CODE32, "X86 32 (AT&T syntax)", CS_OPT_SYNTAX_ATT), 17 (CS_ARCH_X86, CS_MODE_32, X86_CODE32, "X86 32 (Intel syntax)", None), 18 (CS_ARCH_X86, CS_MODE_64, X86_CODE64, "X86 64 (Intel syntax)", None), 19 ) 20 21 22def get_eflag_name(eflag): 23 if eflag == X86_EFLAGS_UNDEFINED_OF: 24 return "UNDEF_OF" 25 elif eflag == X86_EFLAGS_UNDEFINED_SF: 26 return "UNDEF_SF" 27 elif eflag == X86_EFLAGS_UNDEFINED_ZF: 28 return "UNDEF_ZF" 29 elif eflag == X86_EFLAGS_MODIFY_AF: 30 return "MOD_AF" 31 elif eflag == X86_EFLAGS_UNDEFINED_PF: 32 return "UNDEF_PF" 33 elif eflag == X86_EFLAGS_MODIFY_CF: 34 return "MOD_CF" 35 elif eflag == X86_EFLAGS_MODIFY_SF: 36 return "MOD_SF" 37 elif eflag == X86_EFLAGS_MODIFY_ZF: 38 return "MOD_ZF" 39 elif eflag == X86_EFLAGS_UNDEFINED_AF: 40 return "UNDEF_AF" 41 elif eflag == X86_EFLAGS_MODIFY_PF: 42 return "MOD_PF" 43 elif eflag == X86_EFLAGS_UNDEFINED_CF: 44 return "UNDEF_CF" 45 elif eflag == X86_EFLAGS_MODIFY_OF: 46 return "MOD_OF" 47 elif eflag == X86_EFLAGS_RESET_OF: 48 return "RESET_OF" 49 elif eflag == X86_EFLAGS_RESET_CF: 50 return "RESET_CF" 51 elif eflag == X86_EFLAGS_RESET_DF: 52 return "RESET_DF" 53 elif eflag == X86_EFLAGS_RESET_IF: 54 return "RESET_IF" 55 elif eflag == X86_EFLAGS_TEST_OF: 56 return "TEST_OF" 57 elif eflag == X86_EFLAGS_TEST_SF: 58 return "TEST_SF" 59 elif eflag == X86_EFLAGS_TEST_ZF: 60 return "TEST_ZF" 61 elif eflag == X86_EFLAGS_TEST_PF: 62 return "TEST_PF" 63 elif eflag == X86_EFLAGS_TEST_CF: 64 return "TEST_CF" 65 elif eflag == X86_EFLAGS_RESET_SF: 66 return "RESET_SF" 67 elif eflag == X86_EFLAGS_RESET_AF: 68 return "RESET_AF" 69 elif eflag == X86_EFLAGS_RESET_TF: 70 return "RESET_TF" 71 elif eflag == X86_EFLAGS_RESET_NT: 72 return "RESET_NT" 73 elif eflag == X86_EFLAGS_PRIOR_OF: 74 return "PRIOR_OF" 75 elif eflag == X86_EFLAGS_PRIOR_SF: 76 return "PRIOR_SF" 77 elif eflag == X86_EFLAGS_PRIOR_ZF: 78 return "PRIOR_ZF" 79 elif eflag == X86_EFLAGS_PRIOR_AF: 80 return "PRIOR_AF" 81 elif eflag == X86_EFLAGS_PRIOR_PF: 82 return "PRIOR_PF" 83 elif eflag == X86_EFLAGS_PRIOR_CF: 84 return "PRIOR_CF" 85 elif eflag == X86_EFLAGS_PRIOR_TF: 86 return "PRIOR_TF" 87 elif eflag == X86_EFLAGS_PRIOR_IF: 88 return "PRIOR_IF" 89 elif eflag == X86_EFLAGS_PRIOR_DF: 90 return "PRIOR_DF" 91 elif eflag == X86_EFLAGS_TEST_NT: 92 return "TEST_NT" 93 elif eflag == X86_EFLAGS_TEST_DF: 94 return "TEST_DF" 95 elif eflag == X86_EFLAGS_RESET_PF: 96 return "RESET_PF" 97 elif eflag == X86_EFLAGS_PRIOR_NT: 98 return "PRIOR_NT" 99 elif eflag == X86_EFLAGS_MODIFY_TF: 100 return "MOD_TF" 101 elif eflag == X86_EFLAGS_MODIFY_IF: 102 return "MOD_IF" 103 elif eflag == X86_EFLAGS_MODIFY_DF: 104 return "MOD_DF" 105 elif eflag == X86_EFLAGS_MODIFY_NT: 106 return "MOD_NT" 107 elif eflag == X86_EFLAGS_MODIFY_RF: 108 return "MOD_RF" 109 elif eflag == X86_EFLAGS_SET_CF: 110 return "SET_CF" 111 elif eflag == X86_EFLAGS_SET_DF: 112 return "SET_DF" 113 elif eflag == X86_EFLAGS_SET_IF: 114 return "SET_IF" 115 else: 116 return None 117 118 119def print_insn_detail(mode, insn): 120 def print_string_hex(comment, str): 121 print(comment, end=' '), 122 for c in str: 123 print("0x%02x " % c, end=''), 124 print() 125 126 # print address, mnemonic and operands 127 print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str)) 128 129 # "data" instruction generated by SKIPDATA option has no detail 130 if insn.id == 0: 131 return 132 133 # print instruction prefix 134 print_string_hex("\tPrefix:", insn.prefix) 135 136 # print instruction's opcode 137 print_string_hex("\tOpcode:", insn.opcode) 138 139 # print operand's REX prefix (non-zero value is relavant for x86_64 instructions) 140 print("\trex: 0x%x" % (insn.rex)) 141 142 # print operand's address size 143 print("\taddr_size: %u" % (insn.addr_size)) 144 145 # print modRM byte 146 print("\tmodrm: 0x%x" % (insn.modrm)) 147 148 # print modRM offset 149 if insn.modrm_offset != 0: 150 print("\tmodrm_offset: 0x%x" % (insn.modrm_offset)) 151 152 # print displacement value 153 print("\tdisp: 0x%s" % to_x_32(insn.disp)) 154 155 # print displacement offset (offset into instruction bytes) 156 if insn.disp_offset != 0: 157 print("\tdisp_offset: 0x%x" % (insn.disp_offset)) 158 159 # print displacement size 160 if insn.disp_size != 0: 161 print("\tdisp_size: 0x%x" % (insn.disp_size)) 162 163 # SIB is not available in 16-bit mode 164 if (mode & CS_MODE_16 == 0): 165 # print SIB byte 166 print("\tsib: 0x%x" % (insn.sib)) 167 if (insn.sib): 168 if insn.sib_base != 0: 169 print("\t\tsib_base: %s" % (insn.reg_name(insn.sib_base))) 170 if insn.sib_index != 0: 171 print("\t\tsib_index: %s" % (insn.reg_name(insn.sib_index))) 172 if insn.sib_scale != 0: 173 print("\t\tsib_scale: %d" % (insn.sib_scale)) 174 175 # XOP CC type 176 if insn.xop_cc != X86_XOP_CC_INVALID: 177 print("\txop_cc: %u" % (insn.xop_cc)) 178 179 # SSE CC type 180 if insn.sse_cc != X86_SSE_CC_INVALID: 181 print("\tsse_cc: %u" % (insn.sse_cc)) 182 183 # AVX CC type 184 if insn.avx_cc != X86_AVX_CC_INVALID: 185 print("\tavx_cc: %u" % (insn.avx_cc)) 186 187 # AVX Suppress All Exception 188 if insn.avx_sae: 189 print("\tavx_sae: TRUE") 190 191 # AVX Rounding Mode type 192 if insn.avx_rm != X86_AVX_RM_INVALID: 193 print("\tavx_rm: %u" % (insn.avx_rm)) 194 195 count = insn.op_count(X86_OP_IMM) 196 if count > 0: 197 print("\timm_count: %u" % count) 198 for i in range(count): 199 op = insn.op_find(X86_OP_IMM, i + 1) 200 print("\t\timms[%u]: 0x%s" % (i + 1, to_x(op.imm))) 201 if insn.imm_offset != 0: 202 print("\timm_offset: 0x%x" % (insn.imm_offset)) 203 if insn.imm_size != 0: 204 print("\timm_size: 0x%x" % (insn.imm_size)) 205 206 if len(insn.operands) > 0: 207 print("\top_count: %u" % len(insn.operands)) 208 c = -1 209 for i in insn.operands: 210 c += 1 211 if i.type == X86_OP_REG: 212 print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg))) 213 if i.type == X86_OP_IMM: 214 print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm))) 215 if i.type == X86_OP_MEM: 216 print("\t\toperands[%u].type: MEM" % c) 217 if i.mem.segment != 0: 218 print("\t\t\toperands[%u].mem.segment: REG = %s" % (c, insn.reg_name(i.mem.segment))) 219 if i.mem.base != 0: 220 print("\t\t\toperands[%u].mem.base: REG = %s" % (c, insn.reg_name(i.mem.base))) 221 if i.mem.index != 0: 222 print("\t\t\toperands[%u].mem.index: REG = %s" % (c, insn.reg_name(i.mem.index))) 223 if i.mem.scale != 1: 224 print("\t\t\toperands[%u].mem.scale: %u" % (c, i.mem.scale)) 225 if i.mem.disp != 0: 226 print("\t\t\toperands[%u].mem.disp: 0x%s" % (c, to_x(i.mem.disp))) 227 228 # AVX broadcast type 229 if i.avx_bcast != X86_AVX_BCAST_INVALID: 230 print("\t\toperands[%u].avx_bcast: %u" % (c, i.avx_bcast)) 231 232 # AVX zero opmask {z} 233 if i.avx_zero_opmask: 234 print("\t\toperands[%u].avx_zero_opmask: TRUE" % (c)) 235 236 print("\t\toperands[%u].size: %u" % (c, i.size)) 237 238 if i.access == CS_AC_READ: 239 print("\t\toperands[%u].access: READ\n" % (c)) 240 elif i.access == CS_AC_WRITE: 241 print("\t\toperands[%u].access: WRITE\n" % (c)) 242 elif i.access == CS_AC_READ | CS_AC_WRITE: 243 print("\t\toperands[%u].access: READ | WRITE\n" % (c)) 244 245 (regs_read, regs_write) = insn.regs_access() 246 247 if len(regs_read) > 0: 248 print("\tRegisters read:", end="") 249 for r in regs_read: 250 print(" %s" %(insn.reg_name(r)), end="") 251 print("") 252 253 if len(regs_write) > 0: 254 print("\tRegisters modified:", end="") 255 for r in regs_write: 256 print(" %s" %(insn.reg_name(r)), end="") 257 print("") 258 259 if insn.eflags: 260 updated_flags = [] 261 for i in range(0,46): 262 if insn.eflags & (1 << i): 263 updated_flags.append(get_eflag_name(1 << i)) 264 print("\tEFLAGS: %s" % (','.join(p for p in updated_flags))) 265 266 267# ## Test class Cs 268def test_class(): 269 270 for (arch, mode, code, comment, syntax) in all_tests: 271 print("*" * 16) 272 print("Platform: %s" % comment) 273 print("Code: %s" % to_hex(code)) 274 print("Disasm:") 275 276 try: 277 md = Cs(arch, mode) 278 md.detail = True 279 280 if syntax is not None: 281 md.syntax = syntax 282 283 for insn in md.disasm(code, 0x1000): 284 print_insn_detail(mode, insn) 285 print () 286 print ("0x%x:\n" % (insn.address + insn.size)) 287 except CsError as e: 288 print("ERROR: %s" % e) 289 290 291if __name__ == '__main__': 292 test_class() 293