1 /* radare2 - LGPL - Copyright 2009-2019 - pancake */
2 
3 #include "r_core.h"
4 
r_core_setup_debugger(RCore * r,const char * debugbackend,bool attach)5 R_API int r_core_setup_debugger (RCore *r, const char *debugbackend, bool attach) {
6 	int pid, *p = NULL;
7 	bool is_gdb = !strcmp (debugbackend, "gdb");
8 	RIODesc * fd = r->io->desc;
9 	const char *prompt = NULL;
10 
11 	p = fd ? fd->data : NULL;
12 	r_config_set_i (r->config, "cfg.debug", 1);
13 	if (!p) {
14 		eprintf ("Invalid debug io\n");
15 		return false;
16 	}
17 
18 	r_config_set (r->config, "io.ff", "true");
19 	r_core_cmdf (r, "dL %s", debugbackend);
20 	if (!is_gdb) {
21 		pid = r_io_desc_get_pid (fd);
22 		r_core_cmdf (r, "dp=%d", pid);
23 		if (attach) {
24 			r_core_cmdf (r, "dpa %d", pid);
25 		}
26 	}
27 	//this makes to attach twice showing warnings in the output
28 	//we get "resource busy" so it seems isn't an issue
29 	r_core_cmd (r, ".dr*", 0);
30 	/* honor dbg.bep */
31 	{
32 		const char *bep = r_config_get (r->config, "dbg.bep");
33 		if (bep) {
34 			if (!strcmp (bep, "loader")) {
35 				/* do nothing here */
36 			} else if (!strcmp (bep, "entry")) {
37 				r_core_cmd (r, "dcu entry0", 0);
38 			} else {
39 				r_core_cmdf (r, "dcu %s", bep);
40 			}
41 		}
42 	}
43 	r_core_cmd (r, "sr PC", 0);
44 
45 	/* set the prompt if it's not been set already by the callbacks */
46 	prompt = r_config_get (r->config, "cmd.prompt");
47 	if (prompt && !strcmp (prompt, "")) {
48 		if (r_config_get_i (r->config, "dbg.status")) {
49 			r_config_set (r->config, "cmd.prompt", ".dr*;drd;sr PC;pi 1;s-");
50 		} else {
51 			r_config_set (r->config, "cmd.prompt", ".dr*");
52 		}
53 	}
54 	r_config_set (r->config, "cmd.vprompt", ".dr*");
55 	r_config_set (r->config, "cmd.gprompt", ".dr*");
56 	return true;
57 }
58 
r_core_seek_base(RCore * core,const char * hex)59 R_API int r_core_seek_base (RCore *core, const char *hex) {
60 	ut64 addr = r_num_tail (core->num, core->offset, hex);
61 	return r_core_seek (core, addr, true);
62 }
63 
r_core_dump(RCore * core,const char * file,ut64 addr,ut64 size,int append)64 R_API bool r_core_dump(RCore *core, const char *file, ut64 addr, ut64 size, int append) {
65 	ut64 i;
66 	ut8 *buf;
67 	int bs = core->blocksize;
68 	FILE *fd;
69 	if (append) {
70 		fd = r_sandbox_fopen (file, "ab");
71 	} else {
72 		r_sys_truncate (file, 0);
73 		fd = r_sandbox_fopen (file, "wb");
74 	}
75 	if (!fd) {
76 		eprintf ("Cannot open '%s' for writing\n", file);
77 		return false;
78 	}
79 	/* some io backends seems to be buggy in those cases */
80 	if (bs > 4096) {
81 		bs = 4096;
82 	}
83 	buf = malloc (bs);
84 	if (!buf) {
85 		eprintf ("Cannot alloc %d byte(s)\n", bs);
86 		fclose (fd);
87 		return false;
88 	}
89 	r_cons_break_push (NULL, NULL);
90 	for (i = 0; i < size; i += bs) {
91 		if (r_cons_is_breaked ()) {
92 			break;
93 		}
94 		if ((i + bs) > size) {
95 			bs = size - i;
96 		}
97 		r_io_read_at (core->io, addr + i, buf, bs);
98 		if (fwrite (buf, bs, 1, fd) < 1) {
99 			eprintf ("write error\n");
100 			break;
101 		}
102 	}
103 	r_cons_break_pop ();
104 	fclose (fd);
105 	free (buf);
106 	return true;
107 }
108 
__endian_swap(ut8 * buf,ut32 blocksize,ut8 len)109 static bool __endian_swap(ut8 *buf, ut32 blocksize, ut8 len) {
110 	ut32 i;
111 	ut16 v16;
112 	ut32 v32;
113 	ut64 v64;
114 	if (len != 8 && len != 4 && len != 2 && len != 1) {
115 		eprintf ("Invalid word size. Use 1, 2, 4 or 8\n");
116 		return false;
117 	}
118 	if (len == 1) {
119 		return true;
120 	}
121 	for (i = 0; i < blocksize; i += len) {
122 		switch (len) {
123 		case 8:
124 			v64 = r_read_at_be64 (buf, i);
125 			r_write_at_le64 (buf, v64, i);
126 			break;
127 		case 4:
128 			v32 = r_read_at_be32 (buf, i);
129 			r_write_at_le32 (buf, v32, i);
130 			break;
131 		case 2:
132 			v16 = r_read_at_be16 (buf, i);
133 			r_write_at_le16 (buf, v16, i);
134 			break;
135 		}
136 	}
137 	return true;
138 }
139 
r_core_transform_op(RCore * core,const char * arg,char op)140 R_API ut8* r_core_transform_op(RCore *core, const char *arg, char op) {
141 	int i, j;
142 	ut64 len;
143 	char *str = NULL;
144 	ut8 *buf;
145 
146 	buf = (ut8 *)malloc (core->blocksize);
147 	if (!buf) {
148 		return NULL;
149 	}
150 	memcpy (buf, core->block, core->blocksize);
151 
152 	if (op!='e') {
153 		// fill key buffer either from arg or from clipboard
154 		if (arg) {  // parse arg for key
155 			// r_hex_str2bin() is guaranteed to output maximum half the
156 			// input size, or 1 byte if there is just a single nibble.
157 			str = (char *)malloc (strlen (arg) / 2 + 1);
158 			if (!str) {
159 				goto beach;
160 			}
161 			len = r_hex_str2bin (arg, (ut8 *)str);
162 			// Output is invalid if there was just a single nibble,
163 			// but in that case, len is negative (-1).
164 			if (len <= 0) {
165 				eprintf ("Invalid hexpair string\n");
166 				goto beach;
167 			}
168 		} else {  // use clipboard as key
169 			const ut8 *tmp = r_buf_data (core->yank_buf, &len);
170 			str = r_mem_dup (tmp, len);
171 			if (!str) {
172 				goto beach;
173 			}
174 		}
175 	} else {
176 		len = 0;
177 	}
178 
179 	// execute the operand
180 	if (op=='e') {
181 		int wordsize = 1;
182 		char *os, *p, *s = strdup (arg);
183 		int n = 0, from = 0, to = UT8_MAX, dif = 0, step = 1;
184 		os = s;
185 		p = strchr (s, ' ');
186 		if (p) {
187 			*p = 0;
188 			from = r_num_math (core->num, s);
189 			s = p + 1;
190 		}
191 		p = strchr (s, ' ');
192 		if (p) {
193 			*p = 0;
194 			to = r_num_math (core->num, s);
195 			s = p + 1;
196 		}
197 		p = strchr (s, ' ');
198 		if (p) {
199 			*p = 0;
200 			step = r_num_math (core->num, s);
201 			s = p + 1;
202 			wordsize = r_num_math (core->num, s);
203 		} else {
204 			step = r_num_math (core->num, s);
205 		}
206 		free (os);
207 		eprintf ("from %d to %d step %d size %d\n", from, to, step, wordsize);
208 		dif = (to <= from)? UT8_MAX: to - from + 1;
209 		if (wordsize == 1) {
210 			from %= (UT8_MAX + 1);
211 		}
212 		if (dif < 1) {
213 			dif = UT8_MAX + 1;
214 		}
215 		if (step < 1) {
216 			step = 1;
217 		}
218 		if (wordsize < 1) {
219 			wordsize = 1;
220 		}
221 		if (wordsize == 1) {
222 			for (i = n = 0; i < core->blocksize; i++, n += step) {
223 				buf[i] = (ut8)(n % dif) + from;
224 			}
225 		} else if (wordsize == 2) {
226 			ut16 num16 = from;
227 			for (i = 0; i < core->blocksize; i += wordsize, num16 += step) {
228 				r_write_le16 (buf + i, num16);
229 			}
230 		} else if (wordsize == 4) {
231 			ut32 num32 = from;
232 			for (i = 0; i < core->blocksize; i += wordsize, num32 += step) {
233 				r_write_le32 (buf + i, num32);
234 			}
235 		} else if (wordsize == 8) {
236 			ut64 num64 = from;
237 			for (i = 0; i < core->blocksize; i += wordsize, num64 += step) {
238 				r_write_le64 (buf + i, num64);
239 			}
240 		} else {
241 			eprintf ("Invalid word size. Use 1, 2, 4 or 8\n");
242 		}
243 	} else if (op == '2' || op == '4' || op == '8') { // "wo2" "wo4" "wo8"
244 		int inc = op - '0';
245 		ut8 tmp;
246 		for (i = 0; (i + inc) <= core->blocksize; i += inc) {
247 			if (inc == 2) {
248 				tmp = buf[i];
249 				buf[i] = buf[i+1];
250 				buf[i+1] = tmp;
251 			} else if (inc == 4) {
252 				tmp = buf[i];
253 				buf[i] = buf[i+3];
254 				buf[i+3] = tmp;
255 				tmp = buf[i+1];
256 				buf[i+1] = buf[i+2];
257 				buf[i+2] = tmp;
258 			} else if (inc == 8) {
259 				tmp = buf[i];
260 				buf[i] = buf[i+7];
261 				buf[i+7] = tmp;
262 
263 				tmp = buf[i+1];
264 				buf[i+1] = buf[i+6];
265 				buf[i+6] = tmp;
266 
267 				tmp = buf[i+2];
268 				buf[i+2] = buf[i+5];
269 				buf[i+5] = tmp;
270 
271 				tmp = buf[i+3];
272 				buf[i+3] = buf[i+4];
273 				buf[i+4] = tmp;
274 			} else {
275 				eprintf ("Invalid inc, use 2, 4 or 8.\n");
276 				break;
277 			}
278 		}
279 	} else {
280 		bool be = r_config_get_i (core->config, "cfg.bigendian");
281 		if (!be) {
282 			if (!__endian_swap ((ut8*)str, len, len)) {
283 				goto beach;
284 			}
285 		}
286 		for (i = j = 0; i < core->blocksize; i++) {
287 			switch (op) {
288 			case 'x': buf[i] ^= str[j]; break;
289 			case 'a': buf[i] += str[j]; break;
290 			case 's': buf[i] -= str[j]; break;
291 			case 'm': buf[i] *= str[j]; break;
292 			case 'w': buf[i] = str[j]; break;
293 			case 'd': buf[i] = (str[j])? (buf[i] / str[j]): 0; break;
294 			case 'r': buf[i] >>= str[j]; break;
295 			case 'l': buf[i] <<= str[j]; break;
296 			case 'o': buf[i] |= str[j]; break;
297 			case 'A': buf[i] &= str[j]; break;
298 			}
299 			j++;
300 			if (j >= len) {
301 				j = 0; /* cyclic key */
302 			}
303 		}
304 	}
305 
306 	free (str);
307 	return buf;
308 beach:
309 	free (str);
310 	free (buf);
311 	return NULL;
312 }
313 
r_core_write_op(RCore * core,const char * arg,char op)314 R_API int r_core_write_op(RCore *core, const char *arg, char op) {
315 	ut8 *buf = r_core_transform_op(core, arg, op);
316 	if (!buf) {
317 		return false;
318 	}
319 	int ret = r_core_write_at (core, core->offset, buf, core->blocksize);
320 	free (buf);
321 	return ret;
322 }
323 
324 // Get address-specific bits and arch at a certain address.
325 // If there are no specific infos (i.e. asm.bits and asm.arch should apply), the bits and arch will be 0 or NULL respectively!
r_core_arch_bits_at(RCore * core,ut64 addr,R_OUT R_NULLABLE int * bits,R_OUT R_BORROW R_NULLABLE const char ** arch)326 R_API void r_core_arch_bits_at(RCore *core, ut64 addr, R_OUT R_NULLABLE int *bits, R_OUT R_BORROW R_NULLABLE const char **arch) {
327 	int bitsval = 0;
328 	const char *archval = NULL;
329 	RBinObject *o = r_bin_cur_object (core->bin);
330 	RBinSection *s = o ? r_bin_get_section_at (o, addr, core->io->va) : NULL;
331 	if (s) {
332 		if (!core->fixedarch) {
333 			archval = s->arch;
334 		}
335 		if (!core->fixedbits && s->bits) {
336 			// only enforce if there's one bits set
337 			switch (s->bits) {
338 			case R_SYS_BITS_16:
339 			case R_SYS_BITS_32:
340 			case R_SYS_BITS_64:
341 				bitsval = s->bits * 8;
342 				break;
343 			}
344 		}
345 	}
346 	//if we found bits related with anal hints pick it up
347 	if (bits && !bitsval && !core->fixedbits) {
348 		bitsval = r_anal_hint_bits_at (core->anal, addr, NULL);
349 	}
350 	if (arch && !archval && !core->fixedarch) {
351 		archval = r_anal_hint_arch_at (core->anal, addr, NULL);
352 	}
353 	if (bits && bitsval) {
354 		*bits = bitsval;
355 	}
356 	if (arch && archval) {
357 		*arch = archval;
358 	}
359 }
360 
r_core_seek_arch_bits(RCore * core,ut64 addr)361 R_API void r_core_seek_arch_bits(RCore *core, ut64 addr) {
362 	int bits = 0;
363 	const char *arch = NULL;
364 	r_core_arch_bits_at (core, addr, &bits, &arch);
365 	if (bits) {
366 		r_config_set_i (core->config, "asm.bits", bits);
367 	}
368 	if (arch) {
369 		r_config_set (core->config, "asm.arch", arch);
370 	}
371 }
372 
r_core_seek(RCore * core,ut64 addr,bool rb)373 R_API bool r_core_seek(RCore *core, ut64 addr, bool rb) {
374 	core->offset = r_io_seek (core->io, addr, R_IO_SEEK_SET);
375 	if (rb) {
376 		r_core_block_read (core);
377 	}
378 	if (core->binat) {
379 		RBinFile *bf = r_bin_file_at (core->bin, core->offset);
380 		if (bf) {
381 			core->bin->cur = bf;
382 			r_bin_select_bfid (core->bin, bf->id);
383 			// XXX r_core_cmdf (core, "obb %d", bf->id);
384 		} else {
385 			core->bin->cur = NULL;
386 		}
387 	}
388 	return core->offset == addr;
389 }
390 
r_core_seek_delta(RCore * core,st64 addr)391 R_API int r_core_seek_delta(RCore *core, st64 addr) {
392 	ut64 tmp = core->offset;
393 	if (addr == 0) {
394 		return true;
395 	}
396 	if (addr > 0LL) {
397 		/* TODO: check end of file */
398 		addr += tmp;
399 	} else {
400 		/* check < 0 */
401 		if (-addr > tmp) {
402 			addr = 0;
403 		} else {
404 			addr += tmp;
405 		}
406 	}
407 	core->offset = addr;
408 	return r_core_seek (core, addr, true);
409 }
410 
411 // TODO: kill this wrapper
r_core_write_at(RCore * core,ut64 addr,const ut8 * buf,int size)412 R_API bool r_core_write_at(RCore *core, ut64 addr, const ut8 *buf, int size) {
413 	r_return_val_if_fail (core && buf && addr != UT64_MAX, false);
414 	if (size < 1) {
415 		return false;
416 	}
417 	bool ret = r_io_write_at (core->io, addr, buf, size);
418 	if (addr >= core->offset && addr <= core->offset + core->blocksize - 1) {
419 		r_core_block_read (core);
420 	}
421 	return ret;
422 }
423 
r_core_extend_at(RCore * core,ut64 addr,int size)424 R_API bool r_core_extend_at(RCore *core, ut64 addr, int size) {
425 	if (!core->io || !core->io->desc || size < 1) {
426 		return false;
427 	}
428 	int io_va = r_config_get_i (core->config, "io.va");
429 	if (io_va) {
430 		RIOMap *map = r_io_map_get (core->io, core->offset);
431 		if (map) {
432 			addr = addr - r_io_map_begin (map) + map->delta;
433 		}
434 		r_config_set_i (core->config, "io.va", false);
435 	}
436 	int ret = r_io_extend_at (core->io, addr, size);
437 	if (addr >= core->offset && addr <= core->offset+core->blocksize) {
438 		r_core_block_read (core);
439 	}
440 	r_config_set_i (core->config, "io.va", io_va);
441 	return ret;
442 }
443 
r_core_shift_block(RCore * core,ut64 addr,ut64 b_size,st64 dist)444 R_API int r_core_shift_block(RCore *core, ut64 addr, ut64 b_size, st64 dist) {
445 	// bstart - block start, fstart file start
446 	ut64 fend = 0, fstart = 0, bstart = 0, file_sz = 0;
447 	ut8 * shift_buf = NULL;
448 	int res = false;
449 
450 	if (!core->io || !core->io->desc) {
451 		return false;
452 	}
453 
454 	if (b_size == 0 || b_size == (ut64) -1) {
455 		r_io_use_fd (core->io, core->io->desc->fd);
456 		file_sz = r_io_size (core->io);
457 		if (file_sz == UT64_MAX) {
458 			file_sz = 0;
459 		}
460 #if 0
461 		bstart = r_io_seek (core->io, addr, R_IO_SEEK_SET);
462 		fend = r_io_seek (core->io, 0, R_IO_SEEK_END);
463 		if (fend < 1) {
464 			fend = 0;
465 		}
466 #else
467 		bstart = 0;
468 		fend = file_sz;
469 #endif
470 		fstart = file_sz - fend;
471 		b_size = fend > bstart ? fend - bstart: 0;
472 	}
473 
474 	if ((st64)b_size < 1) {
475 		return false;
476 	}
477 	shift_buf = calloc (b_size, 1);
478 	if (!shift_buf) {
479 		eprintf ("Cannot allocated %d byte(s)\n", (int)b_size);
480 		return false;
481 	}
482 
483 	// cases
484 	// addr + b_size + dist > file_end
485 	//if ( (addr+b_size) + dist > file_end ) {
486 	//	res = false;
487 	//}
488 	// addr + b_size + dist < file_start (should work since dist is signed)
489 	//else if ( (addr+b_size) + dist < 0 ) {
490 	//	res = false;
491 	//}
492 	// addr + dist < file_start
493 	if (addr + dist < fstart) {
494 		res = false;
495 	// addr + dist > file_end
496 	} else if ( (addr) + dist > fend) {
497 		res = false;
498 	} else {
499 		r_io_read_at (core->io, addr, shift_buf, b_size);
500 		r_io_write_at (core->io, addr + dist, shift_buf, b_size);
501 		res = true;
502 	}
503 	r_core_seek (core, addr, true);
504 	free (shift_buf);
505 	return res;
506 }
507 
r_core_block_read(RCore * core)508 R_API int r_core_block_read(RCore *core) {
509 	if (core && core->block) {
510 		return r_io_read_at (core->io, core->offset, core->block, core->blocksize);
511 	}
512 	return -1;
513 }
514