1 /* radare - LGPL - Copyright 2009-2019 - pancake & dso */
2 
3 #include "r_core.h"
4 #include "r_util.h"
5 #include "r_io.h"
6 
7 /*
8  * perform_mapped_file_yank will map in a file and yank from offset the number of len bytes from
9  * filename.  if the len is -1, the all the bytes are mapped into the yank buffer.
10  */
11 static int perform_mapped_file_yank(RCore *core, ut64 offset, ut64 len, const char *filename);
12 static ut32 find_next_char(const char *input, char b);
13 static ut32 consume_chars(const char *input, char b);
14 
find_next_char(const char * input,char b)15 static ut32 find_next_char(const char *input, char b) {
16 	ut32 i = 0;
17 	if (!input) {
18 		return i;
19 	}
20 	for (; *input != b; i++, input++) {
21 		/* nothing */
22 	}
23 	return i;
24 }
25 
consume_chars(const char * input,char b)26 static ut32 consume_chars(const char *input, char b) {
27 	ut32 i = 0;
28 	if (!input) {
29 		return i;
30 	}
31 	for (; *input == b; i++, input++) {
32 		/* nothing */
33 	}
34 	return i;
35 }
36 
perform_mapped_file_yank(RCore * core,ut64 offset,ut64 len,const char * filename)37 static int perform_mapped_file_yank(RCore *core, ut64 offset, ut64 len, const char *filename) {
38 	// grab the current file descriptor, so we can reset core and io state
39 	// after our io op is done
40 	RIODesc *yankdesc = NULL;
41 	ut64 fd = core->io->desc ? core->io->desc->fd: -1, yank_file_sz = 0,
42 	     loadaddr = 0, addr = offset;
43 	int res = false;
44 
45 	if (filename && *filename) {
46 		ut64 load_align = r_config_get_i (core->config, "file.loadalign");
47 		RIOMap *map = NULL;
48 		yankdesc = r_io_open_nomap (core->io, filename, R_PERM_R, 0644);
49 		// map the file in for IO operations.
50 		if (yankdesc && load_align) {
51 			yank_file_sz = r_io_size (core->io);
52 			ut64 addr = r_io_map_next_available (core->io, 0, yank_file_sz, load_align);
53         		map = r_io_map_new (core->io, yankdesc->fd, R_PERM_R, 0, addr, yank_file_sz);
54 			loadaddr = map? r_io_map_begin (map): -1;
55 			if (yankdesc && map && loadaddr != -1) {
56 				// ***NOTE*** this is important, we need to
57 				// address the file at its physical address!
58 				addr += loadaddr;
59 			} else if (yankdesc) {
60 				eprintf ("Unable to map the opened file: %s", filename);
61 				r_io_desc_close (yankdesc);
62 				yankdesc = NULL;
63 			} else {
64 				eprintf ("Unable to open the file: %s", filename);
65 			}
66 		}
67 	}
68 
69 	// if len is -1 then we yank in everything
70 	if (len == -1) {
71 		len = yank_file_sz;
72 	}
73 
74 	// this wont happen if the file failed to open or the file failed to
75 	// map into the IO layer
76 	if (yankdesc) {
77 		ut64 res = r_io_seek (core->io, addr, R_IO_SEEK_SET);
78 		ut64 actual_len = len <= yank_file_sz? len: 0;
79 		ut8 *buf = NULL;
80 		if (actual_len > 0 && res == addr) {
81 			buf = malloc (actual_len);
82 			if (!r_io_read_at (core->io, addr, buf, actual_len)) {
83 				actual_len = 0;
84 			}
85 			r_core_yank_set (core, R_CORE_FOREIGN_ADDR, buf, len);
86 			res = true;
87 		} else if (res != addr) {
88 			eprintf (
89 				"ERROR: Unable to yank data from file: (loadaddr (0x%"
90 				PFMT64x ") (addr (0x%"
91 				PFMT64x ") > file_sz (0x%"PFMT64x ")\n", res, addr,
92 				yank_file_sz );
93 		} else if (actual_len == 0) {
94 			eprintf (
95 				"ERROR: Unable to yank from file: addr+len (0x%"
96 				PFMT64x ") > file_sz (0x%"PFMT64x ")\n", addr + len,
97 				yank_file_sz );
98 		}
99 		r_io_desc_close (yankdesc);
100 		free (buf);
101 	}
102 	if (fd != -1) {
103 		r_io_use_fd (core->io, fd);
104 		core->switch_file_view = 1;
105 		r_core_block_read (core);
106 	}
107 	return res;
108 }
109 
r_core_yank_set(RCore * core,ut64 addr,const ut8 * buf,ut32 len)110 R_API int r_core_yank_set(RCore *core, ut64 addr, const ut8 *buf, ut32 len) {
111 	// free (core->yank_buf);
112 	if (buf && len) {
113 		// FIXME: direct access to base should be avoided (use _sparse
114 		// when you need buffer that starts at given addr)
115 		r_buf_set_bytes (core->yank_buf, buf, len);
116 		core->yank_addr = addr;
117 		return true;
118 	}
119 	return false;
120 }
121 
122 // Call set and then null terminate the bytes.
r_core_yank_set_str(RCore * core,ut64 addr,const char * str,ut32 len)123 R_API int r_core_yank_set_str(RCore *core, ut64 addr, const char *str, ut32 len) {
124 	// free (core->yank_buf);
125 	int res = r_core_yank_set (core, addr, (ut8 *)str, len);
126 	if (res == true) {
127 		ut8 zero = 0;
128 		r_buf_write_at (core->yank_buf, len - 1, &zero, sizeof (zero));
129 	}
130 	return res;
131 }
132 
r_core_yank(struct r_core_t * core,ut64 addr,int len)133 R_API int r_core_yank(struct r_core_t *core, ut64 addr, int len) {
134 	ut64 curseek = core->offset;
135 	ut8 *buf = NULL;
136 	if (len < 0) {
137 		eprintf ("r_core_yank: cannot yank negative bytes\n");
138 		return false;
139 	}
140 	if (len == 0) {
141 		len = core->blocksize;
142 	}
143 	buf = malloc (len);
144 	if (!buf) {
145 		return false;
146 	}
147 	if (addr != core->offset) {
148 		r_core_seek (core, addr, true);
149 	}
150 	r_io_read_at (core->io, addr, buf, len);
151 	r_core_yank_set (core, addr, buf, len);
152 	if (curseek != addr) {
153 		r_core_seek (core, curseek, true);
154 	}
155 	free (buf);
156 	return true;
157 }
158 
159 /* Copy a zero terminated string to the clipboard. Clamp to maxlen or blocksize. */
r_core_yank_string(RCore * core,ut64 addr,int maxlen)160 R_API int r_core_yank_string(RCore *core, ut64 addr, int maxlen) {
161 	ut64 curseek = core->offset;
162 	ut8 *buf = NULL;
163 	if (maxlen < 0) {
164 		eprintf ("r_core_yank_string: cannot yank negative bytes\n");
165 		return false;
166 	}
167 	if (addr != core->offset) {
168 		r_core_seek (core, addr, true);
169 	}
170 	/* Ensure space and safe termination for largest possible string allowed */
171 	buf = calloc (1, core->blocksize + 1);
172 	if (!buf) {
173 		return false;
174 	}
175 	buf[core->blocksize] = 0;
176 	r_io_read_at (core->io, addr, buf, core->blocksize);
177 	if (maxlen == 0) {
178 		// Don't use strnlen, see: http://sourceforge.net/p/mingw/bugs/1912/
179 		maxlen = r_str_nlen ((const char *) buf, core->blocksize);
180 	} else if (maxlen > core->blocksize) {
181 		maxlen = core->blocksize;
182 	}
183 	r_core_yank_set (core, addr, buf, maxlen);
184 	if (curseek != addr) {
185 		r_core_seek (core, curseek, true);
186 	}
187 	free (buf);
188 	return true;
189 }
190 
r_core_yank_paste(RCore * core,ut64 addr,int len)191 R_API int r_core_yank_paste(RCore *core, ut64 addr, int len) {
192 	if (len < 0) {
193 		return false;
194 	}
195 	if (len == 0 || len >= r_buf_size (core->yank_buf)) {
196 		len = r_buf_size (core->yank_buf);
197 	}
198 	ut8 *buf = R_NEWS (ut8, len);
199 	if (!buf) {
200 		return false;
201 	}
202 	r_buf_read_at (core->yank_buf, 0, buf, len);
203 	if (!r_core_write_at (core, addr, buf, len)) {
204 		return false;
205 	}
206 	return true;
207 }
208 
r_core_yank_to(RCore * core,const char * _arg)209 R_API int r_core_yank_to(RCore *core, const char *_arg) {
210 	ut64 len = 0;
211 	ut64 pos = -1;
212 	char *str, *arg;
213 	int res = false;
214 
215 	while (*_arg == ' ') {
216 		_arg++;
217 	}
218 	arg = strdup (_arg);
219 	str = strchr (arg, ' ');
220 	if (str) {
221 		str[0] = '\0';
222 		len = r_num_math (core->num, arg);
223 		pos = r_num_math (core->num, str + 1);
224 		str[0] = ' ';
225 	}
226 	if (!str || pos == -1 || len == 0) {
227 		eprintf ("Usage: yt [len] [dst-addr]\n");
228 		free (arg);
229 		return res;
230 	}
231 	if (r_core_yank (core, core->offset, len) == true) {
232 		res = r_core_yank_paste (core, pos, len);
233 	}
234 	free (arg);
235 	return res;
236 }
237 
r_core_yank_dump(RCore * core,ut64 pos,int format)238 R_API bool r_core_yank_dump(RCore *core, ut64 pos, int format) {
239 	bool res = false;
240 	int i = 0;
241 	int ybl = r_buf_size (core->yank_buf);
242 	if (ybl > 0) {
243 		if (pos < ybl) {
244 			switch (format) {
245 			case 'q':
246 				for (i = pos; i < r_buf_size (core->yank_buf); i++) {
247 					r_cons_printf ("%02x", r_buf_read8_at (core->yank_buf, i));
248 				}
249 				r_cons_newline ();
250 				break;
251 			case 'j': {
252 				PJ *pj = r_core_pj_new (core);
253 				if (!pj) {
254 					break;
255 				}
256 				pj_o (pj);
257 				pj_kn (pj, "addr", core->yank_addr);
258 				RStrBuf *buf = r_strbuf_new ("");
259 				for (i = pos; i < r_buf_size (core->yank_buf); i++) {
260 					r_strbuf_appendf (buf, "%02x", r_buf_read8_at (core->yank_buf, i));
261 				}
262 				pj_ks (pj, "bytes", r_strbuf_get (buf));
263 				r_strbuf_free (buf);
264 				pj_end (pj);
265 				r_cons_println (pj_string (pj));
266 				pj_free (pj);
267 				break;
268 			}
269 			case '*':
270 				//r_cons_printf ("yfx ");
271 				r_cons_printf ("wx ");
272 				for (i = pos; i < r_buf_size (core->yank_buf); i++) {
273 					r_cons_printf ("%02x", r_buf_read8_at (core->yank_buf, i));
274 				}
275 				//r_cons_printf (" @ 0x%08"PFMT64x, core->yank_addr);
276 				r_cons_newline ();
277 				break;
278 			default:
279 				r_cons_printf ("0x%08" PFMT64x " %" PFMT64d " ",
280 						core->yank_addr + pos,
281 						r_buf_size (core->yank_buf) - pos);
282 				for (i = pos; i < r_buf_size (core->yank_buf); i++) {
283 					r_cons_printf ("%02x", r_buf_read8_at (core->yank_buf, i));
284 				}
285 				r_cons_newline ();
286 			}
287 			res = true;
288 		} else {
289 			eprintf ("Position exceeds buffer length.\n");
290 		}
291 	} else {
292 		if (format == 'j') {
293 			r_cons_printf ("{}\n");
294 		} else {
295 			eprintf ("No buffer yanked already\n");
296 		}
297 	}
298 	return res;
299 }
300 
r_core_yank_hexdump(RCore * core,ut64 pos)301 R_API int r_core_yank_hexdump(RCore *core, ut64 pos) {
302 	int res = false;
303 	int ybl = r_buf_size (core->yank_buf);
304 	if (ybl > 0) {
305 		if (pos < ybl) {
306 			ut8 *buf = R_NEWS (ut8, ybl - pos);
307 			if (!buf) {
308 				return false;
309 			}
310 			r_buf_read_at (core->yank_buf, pos, buf, ybl - pos);
311 			r_print_hexdump (core->print, pos,
312 				buf, ybl - pos, 16, 1, 1);
313 			res = true;
314 		} else {
315 			eprintf ("Position exceeds buffer length.\n");
316 		}
317 	} else {
318 		eprintf ("No buffer yanked already\n");
319 	}
320 	return res;
321 }
322 
r_core_yank_cat(RCore * core,ut64 pos)323 R_API int r_core_yank_cat(RCore *core, ut64 pos) {
324 	int ybl = r_buf_size (core->yank_buf);
325 	if (ybl > 0) {
326 		if (pos < ybl) {
327 			ut64 sz = ybl - pos;
328 			char *buf = R_NEWS (char, sz);
329 			if (!buf) {
330 				return false;
331 			}
332 			r_buf_read_at (core->yank_buf, pos, (ut8 *)buf, sz);
333 			r_cons_memcat (buf, sz);
334 			r_cons_newline ();
335 			return true;
336 		}
337 		eprintf ("Position exceeds buffer length.\n");
338 	} else {
339 		r_cons_newline ();
340 	}
341 	return false;
342 }
343 
r_core_yank_cat_string(RCore * core,ut64 pos)344 R_API int r_core_yank_cat_string(RCore *core, ut64 pos) {
345 	int ybl = r_buf_size (core->yank_buf);
346 	if (ybl > 0) {
347 		if (pos < ybl) {
348 			ut64 sz = ybl - pos;
349 			char *buf = R_NEWS (char, sz);
350 			if (!buf) {
351 				return false;
352 			}
353 			r_buf_read_at (core->yank_buf, pos, (ut8 *)buf, sz);
354 			int len = r_str_nlen (buf, sz);
355 			r_cons_memcat (buf, len);
356 			r_cons_newline ();
357 			return true;
358 		}
359 		eprintf ("Position exceeds buffer length.\n");
360 	} else {
361 		r_cons_newline ();
362 	}
363 	return false;
364 }
365 
r_core_yank_hud_file(RCore * core,const char * input)366 R_API int r_core_yank_hud_file(RCore *core, const char *input) {
367 	char *buf = NULL;
368 	bool res = false;
369 	ut32 len = 0;
370 	if (!input || !*input) {
371 		return false;
372 	}
373 	for (input++; *input == ' '; input++) {
374 		/* nothing */
375 	}
376 	buf = r_cons_hud_file (input);
377 	len = buf? strlen ((const char *) buf) + 1: 0;
378 	res = r_core_yank_set_str (core, R_CORE_FOREIGN_ADDR, buf, len);
379 	free (buf);
380 	return res;
381 }
382 
r_core_yank_hud_path(RCore * core,const char * input,int dir)383 R_API int r_core_yank_hud_path(RCore *core, const char *input, int dir) {
384 	char *buf = NULL;
385 	ut32 len = 0;
386 	int res;
387 	for (input++; *input == ' '; input++) {
388 		/* nothing */
389 	}
390 	buf = r_cons_hud_path (input, dir);
391 	len = buf? strlen ((const char *) buf) + 1: 0;
392 	res = r_core_yank_set_str (core, R_CORE_FOREIGN_ADDR, buf, len);
393 	free (buf);
394 	return res;
395 }
396 
r_core_yank_hexpair(RCore * core,const char * input)397 R_API bool r_core_yank_hexpair(RCore *core, const char *input) {
398 	if (!input || !*input) {
399 		return false;
400 	}
401 	char *out = strdup (input);
402 	int len = r_hex_str2bin (input, (ut8 *)out);
403 	if (len > 0) {
404 		r_core_yank_set (core, core->offset, (ut8 *)out, len);
405 	}
406 	free (out);
407 	return true;
408 }
409 
r_core_yank_file_ex(RCore * core,const char * input)410 R_API bool r_core_yank_file_ex(RCore *core, const char *input) {
411 	ut64 len = 0, adv = 0, addr = 0;
412 	bool res = false;
413 
414 	if (!input) {
415 		return res;
416 	}
417 	// get the number of bytes to yank
418 	adv = consume_chars (input, ' ');
419 	len = r_num_math (core->num, input + adv);
420 	if (len == 0) {
421 		eprintf ("ERROR: Number of bytes read must be > 0\n");
422 		return res;
423 	}
424 	// get the addr/offset from in the file we want to read
425 	adv += find_next_char (input + adv, ' ');
426 	if (adv == 0) {
427 		eprintf ("ERROR: Address must be specified\n");
428 		return res;
429 	}
430 	adv++;
431 
432 	// XXX - bug, will fail if address needs to be computed and has spaces
433 	addr = r_num_math (core->num, input + adv);
434 
435 	adv += find_next_char (input + adv, ' ');
436 	if (adv == 0) {
437 		eprintf ("ERROR: File must be specified\n");
438 		return res;
439 	}
440 	adv++;
441 
442 	// grab the current file descriptor, so we can reset core and io state
443 	// after our io op is done
444 	return perform_mapped_file_yank (core, addr, len, input + adv);
445 }
446 
r_core_yank_file_all(RCore * core,const char * input)447 R_API int r_core_yank_file_all(RCore *core, const char *input) {
448 	ut64 adv = 0;
449 	if (!input) {
450 		return false;
451 	}
452 	adv = consume_chars (input, ' ');
453 	return perform_mapped_file_yank (core, 0, -1, input + adv);
454 }
455