1 /* radare - Apache 2.0 - Copyright 2010-2019 - pancake and
2  Adam Pridgen <dso@rice.edu || adam.pridgen@thecoverofnight.com> */
3 
4 #include <string.h>
5 
6 #include <r_types.h>
7 #include <r_lib.h>
8 #include <r_anal.h>
9 
10 #include "../../../shlr/java/ops.h"
11 #include "../../../shlr/java/code.h"
12 #include "../../../shlr/java/class.h"
13 
14 #define DO_THE_DBG 0
15 #define IFDBG  if(DO_THE_DBG)
16 
17 static ut64 METHOD_START = 0;
18 
19 static void java_update_anal_types (RAnal *anal, RBinJavaObj *bin_obj);
20 
21 static int java_cmd_ext(RAnal *anal, const char* input);
22 
23 static int java_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask);
24 
25 static RBinJavaObj * get_java_bin_obj(RAnal *anal);
26 
get_java_bin_obj(RAnal * anal)27 static RBinJavaObj * get_java_bin_obj(RAnal *anal) {
28 	RBin *b = anal->binb.bin;
29 	RBinPlugin *plugin = b->cur && b->cur->o ? b->cur->o->plugin : NULL;
30 	ut8 is_java = (plugin && strcmp (plugin->name, "java") == 0) ? 1 : 0;
31 	return is_java ? b->cur->o->bin_obj : NULL;
32 }
33 
java_get_method_start(void)34 static ut64 java_get_method_start(void) {
35 	return METHOD_START;
36 }
37 
java_switch_op(RAnal * anal,RAnalOp * op,ut64 addr,const ut8 * data,int len)38 static int java_switch_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) {
39 	ut8 op_byte = data[0];
40 	ut64 offset = addr - java_get_method_start ();
41 	ut8 pos = (offset + 1)%4 ? 1 + 4 - (offset+1)%4 : 1;
42 
43 	if (op_byte == 0xaa) {
44 		// handle a table switch condition
45 		if (pos + 8 + 8 > len) {
46 			return op->size;
47 		}
48 		const int min_val = (ut32)(UINT (data, pos + 4));
49 		const int max_val = (ut32)(UINT (data, pos + 8));
50 
51 		ut32 default_loc = (ut32) (UINT (data, pos)), cur_case = 0;
52 		op->switch_op = r_anal_switch_op_new (addr, min_val, max_val, default_loc);
53 		pos += 12;
54 		if (max_val > min_val && ((max_val - min_val)<(UT16_MAX/4))) {
55 			//caseop = r_anal_switch_op_add_case(op->switch_op, addr+default_loc, -1, addr+offset);
56 			for (cur_case = 0; cur_case <= max_val - min_val; pos += 4, cur_case++) {
57 				//ut32 value = (ut32)(UINT (data, pos));
58 				if (pos + 4 >= len) {
59 					// switch is too big can't read further
60 					break;
61 				}
62 				int offset = (int)(ut32)(R_BIN_JAVA_UINT (data, pos));
63 				r_anal_switch_op_add_case (op->switch_op, addr + pos, cur_case + min_val, addr + offset);
64 			}
65 		} else {
66 			eprintf ("Invalid switch boundaries at 0x%"PFMT64x"\n", addr);
67 		}
68 	}
69 	op->size = pos;
70 	return op->size;
71 }
72 
73 
extract_bin_op(ut64 ranal2_op_type)74 static ut64 extract_bin_op(ut64 ranal2_op_type) {
75 	ut64 bin_op_val = ranal2_op_type & (R_ANAL_JAVA_BIN_OP | 0x80000);
76 	switch (bin_op_val) {
77 	case R_ANAL_JAVA_BINOP_XCHG:return R_ANAL_OP_TYPE_XCHG;
78 	case R_ANAL_JAVA_BINOP_CMP: return R_ANAL_OP_TYPE_CMP;
79 	case R_ANAL_JAVA_BINOP_ADD: return R_ANAL_OP_TYPE_ADD;
80 	case R_ANAL_JAVA_BINOP_SUB: return R_ANAL_OP_TYPE_SUB;
81 	case R_ANAL_JAVA_BINOP_MUL: return R_ANAL_OP_TYPE_MUL;
82 	case R_ANAL_JAVA_BINOP_DIV: return R_ANAL_OP_TYPE_DIV;
83 	case R_ANAL_JAVA_BINOP_SHR: return R_ANAL_OP_TYPE_SHR;
84 	case R_ANAL_JAVA_BINOP_SHL: return R_ANAL_OP_TYPE_SHL;
85 	case R_ANAL_JAVA_BINOP_SAL: return R_ANAL_OP_TYPE_SAL;
86 	case R_ANAL_JAVA_BINOP_SAR: return R_ANAL_OP_TYPE_SAR;
87 	case R_ANAL_JAVA_BINOP_OR : return R_ANAL_OP_TYPE_OR;
88 	case R_ANAL_JAVA_BINOP_AND: return R_ANAL_OP_TYPE_AND;
89 	case R_ANAL_JAVA_BINOP_XOR: return R_ANAL_OP_TYPE_XOR;
90 	case R_ANAL_JAVA_BINOP_NOT: return R_ANAL_OP_TYPE_NOT;
91 	case R_ANAL_JAVA_BINOP_MOD: return R_ANAL_OP_TYPE_MOD;
92 	case R_ANAL_JAVA_BINOP_ROR: return R_ANAL_OP_TYPE_ROR;
93 	case R_ANAL_JAVA_BINOP_ROL: return R_ANAL_OP_TYPE_ROL;
94 	default: break;
95 	}
96 	return R_ANAL_OP_TYPE_UNK;
97 }
98 
99 
100 
101 
extract_unknown_op(ut64 ranal2_op_type)102 ut64 extract_unknown_op(ut64 ranal2_op_type) {
103 	if ((ranal2_op_type & R_ANAL_JAVA_CODEOP_JMP) == R_ANAL_JAVA_CODEOP_JMP) {
104 		return R_ANAL_OP_TYPE_UJMP;
105 	}
106 	if ((ranal2_op_type & R_ANAL_JAVA_CODEOP_CALL) == R_ANAL_JAVA_CODEOP_CALL) {
107 		return R_ANAL_OP_TYPE_UCALL;
108 	}
109 	if ((ranal2_op_type & R_ANAL_JAVA_LDST_OP_PUSH) == R_ANAL_JAVA_LDST_OP_PUSH) {
110 		return R_ANAL_OP_TYPE_UPUSH;
111 	}
112 	return R_ANAL_OP_TYPE_UNK;
113 }
114 
extract_code_op(ut64 ranal2_op_type)115 static ut64 extract_code_op(ut64 ranal2_op_type) {
116 	ut64 conditional = R_ANAL_JAVA_COND_OP & ranal2_op_type ? R_ANAL_OP_TYPE_COND : 0;
117 	ut64 code_op_val = ranal2_op_type & (R_ANAL_JAVA_CODE_OP | 0x1FF);
118 	switch (code_op_val) {
119 	case R_ANAL_JAVA_CODEOP_CALL: return conditional | R_ANAL_OP_TYPE_CALL;
120 	case R_ANAL_JAVA_CODEOP_JMP: return conditional | R_ANAL_OP_TYPE_JMP;
121 	case R_ANAL_JAVA_CODEOP_RET: return conditional | R_ANAL_OP_TYPE_RET;
122 	case R_ANAL_JAVA_CODEOP_LEAVE: return R_ANAL_OP_TYPE_LEAVE;
123 	case R_ANAL_JAVA_CODEOP_SWI: return R_ANAL_OP_TYPE_SWI;
124 	case R_ANAL_JAVA_CODEOP_TRAP: return R_ANAL_OP_TYPE_TRAP;
125 	case R_ANAL_JAVA_CODEOP_SWITCH: return R_ANAL_OP_TYPE_SWITCH;
126 	}
127 	return R_ANAL_OP_TYPE_UNK;
128 }
129 
extract_load_store_op(ut64 ranal2_op_type)130 ut64 extract_load_store_op(ut64 ranal2_op_type) {
131 	if ( (ranal2_op_type & R_ANAL_JAVA_LDST_OP_PUSH) == R_ANAL_JAVA_LDST_OP_PUSH) {
132 		return R_ANAL_OP_TYPE_PUSH;
133 	}
134 	if ( (ranal2_op_type & R_ANAL_JAVA_LDST_OP_POP) == R_ANAL_JAVA_LDST_OP_POP) {
135 		return R_ANAL_OP_TYPE_POP;
136 	}
137 	if ( (ranal2_op_type & R_ANAL_JAVA_LDST_OP_MOV) == R_ANAL_JAVA_LDST_OP_MOV) {
138 		return R_ANAL_OP_TYPE_MOV;
139 	}
140 	if ( (ranal2_op_type & R_ANAL_JAVA_LDST_OP_EFF_ADDR) == R_ANAL_JAVA_LDST_OP_EFF_ADDR) {
141 		return R_ANAL_OP_TYPE_LEA;
142 	}
143 	return R_ANAL_OP_TYPE_UNK;
144 }
145 
map_java_op_to_anal_op_type(ut64 t)146 static ut64 map_java_op_to_anal_op_type (ut64 t) {
147 	ut64 t2 = extract_bin_op(t);
148 	if (t2 != R_ANAL_OP_TYPE_UNK) {
149 		return t2;
150 	}
151 	switch (t) {
152 	case R_ANAL_JAVA_NULL_OP: return R_ANAL_OP_TYPE_NULL;
153 	case R_ANAL_JAVA_NOP: return R_ANAL_OP_TYPE_NOP;
154 	case R_ANAL_JAVA_BINOP_ADD: return R_ANAL_OP_TYPE_ADD;
155 	case R_ANAL_JAVA_BINOP_AND: return R_ANAL_OP_TYPE_AND;
156 	case R_ANAL_JAVA_BINOP_MUL: return R_ANAL_OP_TYPE_MUL;
157 	case R_ANAL_JAVA_BINOP_XOR: return R_ANAL_OP_TYPE_XOR;
158 	case R_ANAL_JAVA_BINOP_XCHG: return R_ANAL_OP_TYPE_MOV;
159 	case R_ANAL_JAVA_OBJOP_NEW: return R_ANAL_OP_TYPE_UCALL;
160 	case R_ANAL_JAVA_OBJOP_SIZE: return R_ANAL_OP_TYPE_UCALL;
161 	case R_ANAL_JAVA_ILL_OP: return R_ANAL_OP_TYPE_ILL;
162 	default:
163 		if (t & R_ANAL_JAVA_UNK_OP) {
164 			return extract_unknown_op (t);
165 		}
166 		if (t & R_ANAL_JAVA_CODE_OP) {
167 			return extract_code_op (t);
168 		}
169 		if (t & R_ANAL_JAVA_REP_OP) {
170 			ut64 ret = map_java_op_to_anal_op_type (t & ~R_ANAL_JAVA_REP_OP);
171 			return R_ANAL_OP_TYPE_REP | ret;
172 		}
173 		if (t & (R_ANAL_JAVA_LOAD_OP | R_ANAL_JAVA_STORE_OP)) {
174 			return extract_load_store_op(t);
175 		}
176 		if (t & R_ANAL_JAVA_BIN_OP) {
177 			return extract_bin_op (t);
178 		}
179 		break;
180 	}
181 	if (R_ANAL_JAVA_OBJOP_CAST & t) {
182 		return R_ANAL_OP_TYPE_MOV;
183 	}
184 	return R_ANAL_OP_TYPE_UNK;
185 }
186 
r_anal_java_is_op_type_eop(ut64 x)187 static int r_anal_java_is_op_type_eop(ut64 x) {
188 	ut8 result = (x & R_ANAL_JAVA_CODE_OP) ? 1 : 0;
189 	return result &&
190 			( (x & R_ANAL_JAVA_CODEOP_LEAVE) == R_ANAL_JAVA_CODEOP_LEAVE ||
191 			 (x & R_ANAL_JAVA_CODEOP_RET) == R_ANAL_JAVA_CODEOP_RET ||
192 			 (x & R_ANAL_JAVA_CODEOP_JMP) == R_ANAL_JAVA_CODEOP_JMP ||
193 			 (x & R_ANAL_JAVA_CODEOP_SWITCH) == R_ANAL_JAVA_CODEOP_SWITCH);
194 }
195 
196 
java_op(RAnal * anal,RAnalOp * op,ut64 addr,const ut8 * data,int len,RAnalOpMask mask)197 static int java_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask) {
198 	/* get opcode size */
199 	if (len < 1) {
200 		op->type = R_ANAL_OP_TYPE_ILL;
201 		return 1;
202 	}
203 	//ut8 op_byte = data[0];
204 	ut8 op_byte = data[0];
205 	int sz = JAVA_OPS[op_byte].size;
206 	if (!op) {
207 		op->type = R_ANAL_OP_TYPE_ILL;
208 		return sz;
209 	}
210 	IFDBG {
211 		//eprintf ("Extracting op from buffer (%d byte(s)) @ 0x%04x\n", len, addr);
212 		//eprintf ("Parsing op: (0x%02x) %s.\n", op_byte, JAVA_OPS[op_byte].name);
213 	}
214 	op->addr = addr;
215 	op->size = sz;
216 	op->id = data[0];
217 	op->type2 = JAVA_OPS[op_byte].op_type;
218 	op->type = map_java_op_to_anal_op_type (op->type2);
219 	// handle lookup and table switch offsets
220 	if (op_byte == 0xaa || op_byte == 0xab) {
221 		java_switch_op (anal, op, addr, data, len);
222 		// IN_SWITCH_OP = 1;
223 	}
224 	/* TODO:
225 	// not sure how to handle the states for IN_SWITCH_OP, SWITCH_OP_CASES,
226 	// and NUM_CASES_SEEN, because these are dependent on whether or not we
227 	// are in a switch, and given the non-reentrant state of opcode analysis
228 	// this can't always be guaranteed.  Below is the pseudo code for handling
229 	// the easy parts though
230 	if (IN_SWITCH_OP) {
231 		NUM_CASES_SEEN++;
232 		if (NUM_CASES_SEEN == SWITCH_OP_CASES) IN_SWITCH_OP=0;
233 		op->addr = addr;
234 		op->size = 4;
235 		op->type2 = 0;
236 		op->type = R_ANAL_OP_TYPE_CASE
237 		op->eob = 0;
238 		return op->sizes;
239 	}
240 	*/
241 
242 	op->eob = r_anal_java_is_op_type_eop (op->type2);
243 	IFDBG {
244 		const char *ot_str = r_anal_optype_to_string (op->type);
245 		eprintf ("op_type2: %s @ 0x%04"PFMT64x" 0x%08"PFMT64x" op_type: (0x%02"PFMT64x") %s.\n",
246 			JAVA_OPS[op_byte].name, addr, (ut64)op->type2, (ut64)op->type,  ot_str);
247 		//eprintf ("op_eob: 0x%02x.\n", op->eob);
248 		//eprintf ("op_byte @ 0: 0x%02x op_byte @ 0x%04x: 0x%02x.\n", data[0], addr, data[addr]);
249 	}
250 
251 	if (len < 4) {
252 		// incomplete analysis here
253 		return 0;
254 	}
255 	if (op->type == R_ANAL_OP_TYPE_POP) {
256 		op->stackop = R_ANAL_STACK_INC;
257 		op->stackptr = 8;
258 	}
259 		op->direction = R_ANAL_OP_DIR_EXEC;
260 	if (op->type == R_ANAL_OP_TYPE_PUSH) {
261 		op->stackop = R_ANAL_STACK_INC;
262 		op->stackptr = -8;
263 	}
264 	if (op->type == R_ANAL_OP_TYPE_CJMP) {
265 		op->jump = addr + (short)(USHORT (data, 1));
266 		op->fail = addr + sz;
267 		IFDBG eprintf ("%s jmpto 0x%04"PFMT64x"  failto 0x%04"PFMT64x".\n",
268 			JAVA_OPS[op_byte].name, op->jump, op->fail);
269 	} else if (op->type  == R_ANAL_OP_TYPE_JMP) {
270 		op->jump = addr + (short)(USHORT (data, 1));
271 		IFDBG eprintf ("%s jmpto 0x%04"PFMT64x".\n", JAVA_OPS[op_byte].name, op->jump);
272 	} else if ( (op->type & R_ANAL_OP_TYPE_CALL) == R_ANAL_OP_TYPE_CALL ) {
273 		op->jump = (int)(short)(USHORT (data, 1));
274 		op->fail = addr + sz;
275 		//IFDBG eprintf ("%s callto 0x%04x  failto 0x%04x.\n", JAVA_OPS[op_byte].name, op->jump, op->fail);
276 	}
277 
278 	//r_java_disasm(addr, data, len, output, outlen);
279 	//IFDBG eprintf ("%s\n", output);
280 	return op->size;
281 }
282 
283 
java_update_anal_types(RAnal * anal,RBinJavaObj * bin_obj)284 static void java_update_anal_types (RAnal *anal, RBinJavaObj *bin_obj) {
285 	Sdb *D = anal->sdb_types;
286 	if (D && bin_obj) {
287 		RListIter *iter;
288 		char *str;
289 		RList * the_list = r_bin_java_extract_all_bin_type_values (bin_obj);
290 		if (the_list) {
291 			r_list_foreach (the_list, iter, str) {
292 				IFDBG eprintf ("Adding type: %s to known types.\n", str);
293 				if (str) {
294 					sdb_set (D, str, "type", 0);
295 				}
296 			}
297 		}
298 		r_list_free (the_list);
299 	}
300 }
301 
java_cmd_ext(RAnal * anal,const char * input)302 static int java_cmd_ext(RAnal *anal, const char* input) {
303 	RBinJavaObj *obj = (RBinJavaObj *) get_java_bin_obj (anal);
304 
305 	if (!obj) {
306 		eprintf ("Execute \"af\" to set the current bin, and this will bind the current bin\n");
307 		return -1;
308 	}
309 	switch (*input) {
310 	case 'c':
311 		// reset bytes counter for case operations
312 		r_java_new_method ();
313 		break;
314 	case 'u':
315 		switch (*(input+1)) {
316 			case 't': {java_update_anal_types (anal, obj); return true;}
317 			default: break;
318 		}
319 		break;
320 	case 's':
321 		switch (*(input+1)) {
322 			//case 'e': return java_resolve_cp_idx_b64 (anal, input+2);
323 			default: break;
324 		}
325 		break;
326 
327 	default: eprintf("Command not supported"); break;
328 	}
329 	return 0;
330 }
331 
332 RAnalPlugin r_anal_plugin_java = {
333 	.name = "java",
334 	.desc = "Java bytecode analysis plugin",
335 	.license = "Apache",
336 	.arch = "java",
337 	.bits = 32,
338 	.op = &java_op,
339 	.cmd_ext = java_cmd_ext,
340 	0
341 };
342 
343 #ifndef R2_PLUGIN_INCORE
344 R_API RLibStruct radare_plugin = {
345 	.type = R_LIB_TYPE_ANAL,
346 	.data = &r_anal_plugin_java,
347 	.version = R2_VERSION
348 };
349 #endif
350