1 /* Capstone Disassembler Engine */
2 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 
7 #include <platform.h>
8 #include <capstone.h>
9 
10 static csh handle;
11 
12 struct platform {
13 	cs_arch arch;
14 	cs_mode mode;
15 	unsigned char *code;
16 	size_t size;
17 	char *comment;
18 	cs_opt_type opt_type;
19 	cs_opt_value opt_value;
20 };
21 
print_string_hex(char * comment,unsigned char * str,size_t len)22 static void print_string_hex(char *comment, unsigned char *str, size_t len)
23 {
24 	unsigned char *c;
25 
26 	printf("%s", comment);
27 	for (c = str; c < str + len; c++) {
28 		printf("0x%02x ", *c & 0xff);
29 	}
30 
31 	printf("\n");
32 }
33 
print_insn_detail(csh ud,cs_mode mode,cs_insn * ins)34 static void print_insn_detail(csh ud, cs_mode mode, cs_insn *ins)
35 {
36 	int count, i;
37 	cs_x86 *x86;
38 
39 	// detail can be NULL on "data" instruction if SKIPDATA option is turned ON
40 	if (ins->detail == NULL)
41 		return;
42 
43 	x86 = &(ins->detail->x86);
44 
45 	print_string_hex("\tPrefix:", x86->prefix, 4);
46 
47 	print_string_hex("\tOpcode:", x86->opcode, 4);
48 
49 	printf("\trex: 0x%x\n", x86->rex);
50 
51 	printf("\taddr_size: %u\n", x86->addr_size);
52 	printf("\tmodrm: 0x%x\n", x86->modrm);
53 	printf("\tdisp: 0x%x\n", x86->disp);
54 
55 	// SIB is not available in 16-bit mode
56 	if ((mode & CS_MODE_16) == 0) {
57 		printf("\tsib: 0x%x\n", x86->sib);
58 		if (x86->sib_base != X86_REG_INVALID)
59 			printf("\t\tsib_base: %s\n", cs_reg_name(handle, x86->sib_base));
60 		if (x86->sib_index != X86_REG_INVALID)
61 			printf("\t\tsib_index: %s\n", cs_reg_name(handle, x86->sib_index));
62 		if (x86->sib_scale != 0)
63 			printf("\t\tsib_scale: %d\n", x86->sib_scale);
64 	}
65 
66 	// SSE code condition
67 	if (x86->sse_cc != X86_SSE_CC_INVALID) {
68 		printf("\tsse_cc: %u\n", x86->sse_cc);
69 	}
70 
71 	// AVX code condition
72 	if (x86->avx_cc != X86_AVX_CC_INVALID) {
73 		printf("\tavx_cc: %u\n", x86->avx_cc);
74 	}
75 
76 	// AVX Suppress All Exception
77 	if (x86->avx_sae) {
78 		printf("\tavx_sae: %u\n", x86->avx_sae);
79 	}
80 
81 	// AVX Rounding Mode
82 	if (x86->avx_rm != X86_AVX_RM_INVALID) {
83 		printf("\tavx_rm: %u\n", x86->avx_rm);
84 	}
85 
86 	count = cs_op_count(ud, ins, X86_OP_IMM);
87 	if (count) {
88 		printf("\timm_count: %u\n", count);
89 		for (i = 1; i < count + 1; i++) {
90 			int index = cs_op_index(ud, ins, X86_OP_IMM, i);
91 			printf("\t\timms[%u]: 0x%" PRIx64 "\n", i, x86->operands[index].imm);
92 		}
93 	}
94 
95 	if (x86->op_count)
96 		printf("\top_count: %u\n", x86->op_count);
97 	for (i = 0; i < x86->op_count; i++) {
98 		cs_x86_op *op = &(x86->operands[i]);
99 
100 		switch((int)op->type) {
101 			case X86_OP_REG:
102 				printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
103 				break;
104 			case X86_OP_IMM:
105 				printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
106 				break;
107 			case X86_OP_MEM:
108 				printf("\t\toperands[%u].type: MEM\n", i);
109 				if (op->mem.segment != X86_REG_INVALID)
110 					printf("\t\t\toperands[%u].mem.segment: REG = %s\n", i, cs_reg_name(handle, op->mem.segment));
111 				if (op->mem.base != X86_REG_INVALID)
112 					printf("\t\t\toperands[%u].mem.base: REG = %s\n", i, cs_reg_name(handle, op->mem.base));
113 				if (op->mem.index != X86_REG_INVALID)
114 					printf("\t\t\toperands[%u].mem.index: REG = %s\n", i, cs_reg_name(handle, op->mem.index));
115 				if (op->mem.scale != 1)
116 					printf("\t\t\toperands[%u].mem.scale: %u\n", i, op->mem.scale);
117 				if (op->mem.disp != 0)
118 					printf("\t\t\toperands[%u].mem.disp: 0x%" PRIx64 "\n", i, op->mem.disp);
119 				break;
120 			default:
121 				break;
122 		}
123 
124 		// AVX broadcast type
125 		if (op->avx_bcast != X86_AVX_BCAST_INVALID)
126 			printf("\t\toperands[%u].avx_bcast: %u\n", i, op->avx_bcast);
127 
128 		// AVX zero opmask {z}
129 		if (op->avx_zero_opmask != false)
130 			printf("\t\toperands[%u].avx_zero_opmask: TRUE\n", i);
131 
132 		printf("\t\toperands[%u].size: %u\n", i, op->size);
133 	}
134 
135 	printf("\n");
136 }
137 
test()138 static void test()
139 {
140 //#define X86_CODE32 "\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x78\x56\x00\x00"
141 //#define X86_CODE32 "\x05\x78\x56\x00\x00"
142 //#define X86_CODE32 "\x01\xd8"
143 //#define X86_CODE32 "\x05\x23\x01\x00\x00"
144 //#define X86_CODE32 "\x8d\x87\x89\x67\x00\x00"
145 //#define X86_CODE32 "\xa1\x13\x48\x6d\x3a\x8b\x81\x23\x01\x00\x00\x8b\x84\x39\x23\x01\x00\x00"
146 //#define X86_CODE32 "\xb4\xc6"	// mov	ah, 0x6c
147 //#define X86_CODE32 "\x77\x04"	// ja +6
148 #define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00"
149 //#define X86_CODE64 "\xe9\x79\xff\xff\xff"	// jmp 0xf7e
150 
151 #define X86_CODE16 "\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"
152 //#define X86_CODE16 "\x67\x00\x18"
153 #define X86_CODE32 "\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"
154 //#define X86_CODE32 "\x0f\xa7\xc0"	// xstorerng
155 //#define X86_CODE32 "\x64\xa1\x18\x00\x00\x00"	// mov eax, dword ptr fs:[18]
156 //#define X86_CODE32 "\x64\xa3\x00\x00\x00\x00"	// mov [fs:0x0], eax
157 //#define X86_CODE32 "\xd1\xe1"	// shl ecx, 1
158 //#define X86_CODE32 "\xd1\xc8"	// ror eax, 1
159 //#define X86_CODE32 "\x83\xC0\x80"	// add	eax, -x80
160 //#define X86_CODE32 "\xe8\x26\xfe\xff\xff"		// call	0xe2b
161 //#define X86_CODE32 "\xcd\x80"		// int 0x80
162 //#define X86_CODE32 "\x24\xb8"		// and    $0xb8,%al
163 //#define X86_CODE32 "\xf0\x01\xd8"   // lock add eax,ebx
164 //#define X86_CODE32 "\xf3\xaa"		// rep stosb
165 
166 	struct platform platforms[] = {
167 		{
168 			CS_ARCH_X86,
169 			CS_MODE_16,
170 			(unsigned char *)X86_CODE16,
171 			sizeof(X86_CODE16) - 1,
172 			"X86 16bit (Intel syntax)"
173 		},
174 		{
175 			CS_ARCH_X86,
176 			CS_MODE_32,
177 			(unsigned char *)X86_CODE32,
178 			sizeof(X86_CODE32) - 1,
179 			"X86 32 (AT&T syntax)",
180 			CS_OPT_SYNTAX,
181 			CS_OPT_SYNTAX_ATT,
182 		},
183 		{
184 			CS_ARCH_X86,
185 			CS_MODE_32,
186 			(unsigned char *)X86_CODE32,
187 			sizeof(X86_CODE32) - 1,
188 			"X86 32 (Intel syntax)"
189 		},
190 		{
191 			CS_ARCH_X86,
192 			CS_MODE_64,
193 			(unsigned char *)X86_CODE64,
194 			sizeof(X86_CODE64) - 1,
195 			"X86 64 (Intel syntax)"
196 		},
197 	};
198 
199 	uint64_t address = 0x1000;
200 	cs_insn *insn;
201 	int i;
202 	size_t count;
203 
204 	for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
205 		cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
206 		if (err) {
207 			printf("Failed on cs_open() with error returned: %u\n", err);
208 			continue;
209 		}
210 
211 		if (platforms[i].opt_type)
212 			cs_option(handle, platforms[i].opt_type, platforms[i].opt_value);
213 
214 		cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
215 
216 		count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
217 		if (count) {
218 			size_t j;
219 
220 			printf("****************\n");
221 			printf("Platform: %s\n", platforms[i].comment);
222 			print_string_hex("Code:", platforms[i].code, platforms[i].size);
223 			printf("Disasm:\n");
224 
225 			for (j = 0; j < count; j++) {
226 				printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
227 				print_insn_detail(handle, platforms[i].mode, &insn[j]);
228 			}
229 			printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
230 
231 			// free memory allocated by cs_disasm()
232 			cs_free(insn, count);
233 		} else {
234 			printf("****************\n");
235 			printf("Platform: %s\n", platforms[i].comment);
236 			print_string_hex("Code:", platforms[i].code, platforms[i].size);
237 			printf("ERROR: Failed to disasm given code!\n");
238 		}
239 
240 		printf("\n");
241 
242 		cs_close(&handle);
243 	}
244 }
245 
main()246 int main()
247 {
248 	test();
249 
250 	return 0;
251 }
252