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