Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | # Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com> |
fenuks | 110ab1d | 2014-04-11 11:00:33 +0200 | [diff] [blame] | 4 | from __future__ import print_function |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 5 | from capstone import * |
| 6 | from capstone.x86 import * |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 7 | from xprint import to_hex, to_x, to_x_32 |
| 8 | |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 9 | |
fenuks | 110ab1d | 2014-04-11 11:00:33 +0200 | [diff] [blame] | 10 | X86_CODE64 = b"\x55\x48\x8b\x05\xb8\x13\x00\x00" |
| 11 | X86_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" |
| 12 | X86_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" |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 13 | |
| 14 | all_tests = ( |
Nguyen Anh Quynh | 4649071 | 2013-12-06 00:44:44 +0800 | [diff] [blame] | 15 | (CS_ARCH_X86, CS_MODE_16, X86_CODE16, "X86 16bit (Intel syntax)", 0), |
| 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)", 0), |
| 18 | (CS_ARCH_X86, CS_MODE_64, X86_CODE64, "X86 64 (Intel syntax)", 0), |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 19 | ) |
| 20 | |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 21 | |
| 22 | def print_insn_detail(mode, insn): |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 23 | def print_string_hex(comment, str): |
fenuks | 110ab1d | 2014-04-11 11:00:33 +0200 | [diff] [blame] | 24 | print(comment, end=' '), |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 25 | for c in str: |
Nguyen Anh Quynh | e96e34d | 2014-05-22 12:33:29 +0800 | [diff] [blame] | 26 | print("0x%02x " % c, end=''), |
fenuks | 110ab1d | 2014-04-11 11:00:33 +0200 | [diff] [blame] | 27 | print() |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 28 | |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 29 | # print address, mnemonic and operands |
| 30 | print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str)) |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 31 | |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 32 | # "data" instruction generated by SKIPDATA option has no detail |
| 33 | if insn.id == 0: |
| 34 | return |
Nguyen Anh Quynh | 49f8f22 | 2014-04-10 17:40:10 +0800 | [diff] [blame] | 35 | |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 36 | # print instruction prefix |
| 37 | print_string_hex("\tPrefix:", insn.prefix) |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 38 | |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 39 | # print instruction's opcode |
| 40 | print_string_hex("\tOpcode:", insn.opcode) |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 41 | |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 42 | # print operand's size, address size, displacement size & immediate size |
Nguyen Anh Quynh | e792451 | 2014-06-18 12:27:54 +0800 | [diff] [blame] | 43 | print("\taddr_size: %u" % (insn.addr_size)) |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 44 | |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 45 | # print modRM byte |
| 46 | print("\tmodrm: 0x%x" % (insn.modrm)) |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 47 | |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 48 | # print displacement value |
| 49 | print("\tdisp: 0x%s" % to_x_32(insn.disp)) |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 50 | |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 51 | # SIB is not available in 16-bit mode |
| 52 | if (mode & CS_MODE_16 == 0): |
| 53 | # print SIB byte |
| 54 | print("\tsib: 0x%x" % (insn.sib)) |
| 55 | if (insn.sib): |
Nguyen Anh Quynh | 688efe3 | 2014-05-17 11:08:08 +0800 | [diff] [blame] | 56 | if insn.sib_base != 0: |
Nguyen Anh Quynh | cb2c4f9 | 2014-05-17 13:12:29 +0800 | [diff] [blame] | 57 | print("\t\tsib_base: %s" % (insn.reg_name(insn.sib_base))) |
Nguyen Anh Quynh | 688efe3 | 2014-05-17 11:08:08 +0800 | [diff] [blame] | 58 | if insn.sib_index != 0: |
Nguyen Anh Quynh | cb2c4f9 | 2014-05-17 13:12:29 +0800 | [diff] [blame] | 59 | print("\t\tsib_index: %s" % (insn.reg_name(insn.sib_index))) |
Nguyen Anh Quynh | 688efe3 | 2014-05-17 11:08:08 +0800 | [diff] [blame] | 60 | if insn.sib_scale != 0: |
Nguyen Anh Quynh | cb2c4f9 | 2014-05-17 13:12:29 +0800 | [diff] [blame] | 61 | print("\t\tsib_scale: %d" % (insn.sib_scale)) |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 62 | |
Nguyen Anh Quynh | 4c5eabc | 2014-06-24 23:50:41 +0800 | [diff] [blame] | 63 | # SSE CC type |
| 64 | if insn.sse_cc != X86_SSE_CC_INVALID: |
| 65 | print("\tsse_cc: %u" % (insn.sse_cc)) |
| 66 | |
| 67 | # AVX CC type |
| 68 | if insn.avx_cc != X86_AVX_CC_INVALID: |
| 69 | print("\tavx_cc: %u" % (insn.avx_cc)) |
| 70 | |
Nguyen Anh Quynh | 1a66fec | 2014-06-26 12:09:15 +0800 | [diff] [blame^] | 71 | # AVX Suppress All Exception |
| 72 | if insn.avx_sae: |
| 73 | print("\tavx_sae: TRUE") |
| 74 | |
| 75 | # AVX Rounding Mode type |
| 76 | if insn.avx_rm != X86_AVX_RM_INVALID: |
| 77 | print("\tavx_rm: %u" % (insn.avx_rm)) |
| 78 | |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 79 | count = insn.op_count(X86_OP_IMM) |
| 80 | if count > 0: |
| 81 | print("\timm_count: %u" % count) |
| 82 | for i in range(count): |
| 83 | op = insn.op_find(X86_OP_IMM, i + 1) |
| 84 | print("\t\timms[%u]: 0x%s" % (i + 1, to_x(op.imm))) |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 85 | |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 86 | if len(insn.operands) > 0: |
| 87 | print("\top_count: %u" % len(insn.operands)) |
| 88 | c = -1 |
| 89 | for i in insn.operands: |
| 90 | c += 1 |
| 91 | if i.type == X86_OP_REG: |
| 92 | print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg))) |
| 93 | if i.type == X86_OP_IMM: |
| 94 | print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm))) |
| 95 | if i.type == X86_OP_FP: |
| 96 | print("\t\toperands[%u].type: FP = %f" % (c, i.fp)) |
| 97 | if i.type == X86_OP_MEM: |
| 98 | print("\t\toperands[%u].type: MEM" % c) |
Nguyen Anh Quynh | 14ba46b | 2014-06-24 14:32:01 +0800 | [diff] [blame] | 99 | if i.mem.segment != 0: |
| 100 | print("\t\t\toperands[%u].mem.segment: REG = %s" % (c, insn.reg_name(i.mem.segment))) |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 101 | if i.mem.base != 0: |
| 102 | print("\t\t\toperands[%u].mem.base: REG = %s" % (c, insn.reg_name(i.mem.base))) |
| 103 | if i.mem.index != 0: |
| 104 | print("\t\t\toperands[%u].mem.index: REG = %s" % (c, insn.reg_name(i.mem.index))) |
| 105 | if i.mem.scale != 1: |
| 106 | print("\t\t\toperands[%u].mem.scale: %u" % (c, i.mem.scale)) |
| 107 | if i.mem.disp != 0: |
| 108 | print("\t\t\toperands[%u].mem.disp: 0x%s" % (c, to_x(i.mem.disp))) |
Nguyen Anh Quynh | 83800cd | 2014-06-18 14:21:36 +0800 | [diff] [blame] | 109 | |
Nguyen Anh Quynh | 0d71645 | 2014-06-24 22:51:56 +0800 | [diff] [blame] | 110 | # AVX broadcast type |
| 111 | if i.avx_bcast != X86_AVX_BCAST_INVALID: |
| 112 | print("\t\toperands[%u].avx_bcast: %u" % (c, i.avx_bcast)) |
| 113 | |
Nguyen Anh Quynh | 92a3d4c | 2014-06-25 23:10:39 +0800 | [diff] [blame] | 114 | # AVX zero opmask {z} |
Nguyen Anh Quynh | 7de200a | 2014-06-26 11:31:36 +0800 | [diff] [blame] | 115 | if i.avx_zero_opmask: |
| 116 | print("\t\toperands[%u].avx_zero_opmask: TRUE" % (c)) |
Nguyen Anh Quynh | 92a3d4c | 2014-06-25 23:10:39 +0800 | [diff] [blame] | 117 | |
Nguyen Anh Quynh | f1ec526 | 2014-06-25 22:03:18 +0800 | [diff] [blame] | 118 | print("\t\toperands[%u].size: %u" % (c, i.size)) |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 119 | |
| 120 | |
Nguyen Anh Quynh | 1098329 | 2014-05-17 09:51:15 +0800 | [diff] [blame] | 121 | # ## Test class Cs |
| 122 | def test_class(): |
| 123 | |
Nguyen Anh Quynh | 4649071 | 2013-12-06 00:44:44 +0800 | [diff] [blame] | 124 | for (arch, mode, code, comment, syntax) in all_tests: |
danghvu | 1a7c449 | 2013-11-27 22:51:11 -0600 | [diff] [blame] | 125 | print("*" * 16) |
fenuks | 110ab1d | 2014-04-11 11:00:33 +0200 | [diff] [blame] | 126 | print("Platform: %s" % comment) |
danghvu | 1a7c449 | 2013-11-27 22:51:11 -0600 | [diff] [blame] | 127 | print("Code: %s" % to_hex(code)) |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 128 | print("Disasm:") |
danghvu | 1a7c449 | 2013-11-27 22:51:11 -0600 | [diff] [blame] | 129 | |
Nguyen Anh Quynh | f1618bc | 2013-12-06 20:58:04 +0800 | [diff] [blame] | 130 | try: |
| 131 | md = Cs(arch, mode) |
Nguyen Anh Quynh | 428fdcd | 2014-01-07 23:39:40 +0800 | [diff] [blame] | 132 | md.detail = True |
Nguyen Anh Quynh | c618db4 | 2013-12-04 00:05:04 +0800 | [diff] [blame] | 133 | |
Nguyen Anh Quynh | f1618bc | 2013-12-06 20:58:04 +0800 | [diff] [blame] | 134 | if syntax != 0: |
| 135 | md.syntax = syntax |
Nguyen Anh Quynh | daaed13 | 2013-12-03 22:18:28 +0800 | [diff] [blame] | 136 | |
Nguyen Anh Quynh | f1618bc | 2013-12-06 20:58:04 +0800 | [diff] [blame] | 137 | for insn in md.disasm(code, 0x1000): |
| 138 | print_insn_detail(mode, insn) |
danghvu | cdf6b82 | 2014-05-14 02:36:45 -0500 | [diff] [blame] | 139 | print () |
Nguyen Anh Quynh | f1618bc | 2013-12-06 20:58:04 +0800 | [diff] [blame] | 140 | print ("0x%x:\n" % (insn.address + insn.size)) |
| 141 | except CsError as e: |
fenuks | 110ab1d | 2014-04-11 11:00:33 +0200 | [diff] [blame] | 142 | print("ERROR: %s" % e) |
Nguyen Anh Quynh | 26ee41a | 2013-11-27 12:11:31 +0800 | [diff] [blame] | 143 | |
| 144 | |
fenuks | 110ab1d | 2014-04-11 11:00:33 +0200 | [diff] [blame] | 145 | if __name__ == '__main__': |
| 146 | test_class() |