Stackdb
Stackdb is a stackable, multi-target and -level source debugger and memory forensics library.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
rop_util.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, 2013, 2014 The University of Utah
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include <stdio.h>
20 #include <errno.h>
21 
22 #include "rop.h"
23 #include "probe_api.h"
24 #include "probe.h"
25 #include "target.h"
26 #include "target_api.h"
27 #include "disasm.h"
28 
29 void rop_gadget_free(void *value) {
30  struct rop_gadget *rg = (struct rop_gadget *)value;
31  if (rg->meta)
32  free(rg->meta);
33  free(rg);
34 }
35 
36 GHashTable *rop_load_gadget_stream(FILE *stream) {
37  GHashTable *retval;
38  struct rop_gadget *rg;
39  int rc;
40  GHashTableIter iter;
41  gpointer v;
42 
43  retval = g_hash_table_new_full(g_direct_hash,g_direct_equal,
44  /* Just free gadgets, not keys */
45  NULL,rop_gadget_free);
46 
47  rg = (struct rop_gadget *)calloc(1,sizeof(*rg));
48  errno = 0;
49  while (1) {
50  rc = fscanf(stream,"%"PRIxADDR",%"PRIxADDR" %as",
51  &rg->start,&rg->end,&rg->meta);
52  if (rc <= 0 && errno) {
53  if (rc != EAGAIN && rc != EINTR) {
54  verror("fscanf: %s\n",strerror(errno));
55  return retval;
56  }
57  }
58  else if (rc == EOF) {
59  goto out;
60  }
61  else if (rc < 2) {
62  verror("Bad line in rop_gadget stream!\n");
63  rg->meta = NULL;
64  free(rg);
65  rg = NULL;
66  goto errout;
67  }
68  else {
69  g_hash_table_insert(retval,(gpointer)rg->start,rg);
70  rg = (struct rop_gadget *)calloc(1,sizeof(*rg));
71  }
72  errno = 0;
73  }
74 
75  out:
76  free(rg);
77  return retval;
78 
79  errout:
80  g_hash_table_iter_init(&iter,retval);
81  while (g_hash_table_iter_next(&iter,NULL,&v)) {
82  rg = (struct rop_gadget *)v;
83  rop_gadget_free(rg);
84  }
85  g_hash_table_destroy(retval);
86  return NULL;
87 }
88 
89 GHashTable *rop_load_gadget_file(char *filename) {
90  GHashTable *retval;
91  FILE *f;
92  struct rop_gadget *rg;
93  int rc;
94  GHashTableIter iter;
95  gpointer v;
96 
97  if (!(f = fopen(filename,"r"))) {
98  verror("fopen(%s): %s\n",filename,strerror(errno));
99  return NULL;
100  }
101 
102  retval = g_hash_table_new_full(g_direct_hash,g_direct_equal,
103  /* Just free gadgets, not keys */
104  NULL,rop_gadget_free);
105 
106  rg = (struct rop_gadget *)calloc(1,sizeof(*rg));
107  while (1) {
108  rc = fscanf(f,"%"PRIxADDR",%"PRIxADDR" %as",
109  &rg->start,&rg->end,&rg->meta);
110  if (rc <= 0 && errno) {
111  if (rc != EAGAIN && rc != EINTR) {
112  verror("fscanf: %s\n",strerror(errno));
113  return retval;
114  }
115  }
116  else if (rc == EOF) {
117  goto out;
118  }
119  else if (rc < 2) {
120  verror("Bad line in rop_gadget file %s (%d)!\n",filename,rc);
121  rg->meta = NULL;
122  free(rg);
123  rg = NULL;
124  goto errout;
125  }
126  else {
127  g_hash_table_insert(retval,(gpointer)rg->start,rg);
128  rg = (struct rop_gadget *)calloc(1,sizeof(*rg));
129  }
130  }
131 
132  out:
133  free(rg);
134  fclose(f);
135 
136  return retval;
137 
138  errout:
139  fclose(f);
140  g_hash_table_iter_init(&iter,retval);
141  while (g_hash_table_iter_next(&iter,NULL,&v)) {
142  rg = (struct rop_gadget *)v;
143  rop_gadget_free(rg);
144  }
145  g_hash_table_destroy(retval);
146  return NULL;
147 }
148 
149 const char *probe_gettype_rop_checkret(struct probe *probe) {
150  return "rop_checkret";
151 }
152 
154  return &((struct rop_checkret_data *)(probe->priv))->status;
155 }
156 
158  struct rop_checkret_data *rop_data = \
159  (struct rop_checkret_data *)probe->priv;
160 
161  if (rop_data->cont_probe) {
162  probe_unregister(rop_data->cont_probe,0);
163  probe_free(rop_data->cont_probe,0);
164  }
165  if (rop_data->entry_probe) {
166  probe_unregister(rop_data->entry_probe,0);
167  probe_free(rop_data->entry_probe,0);
168  }
169  if (rop_data->ret_probe) {
170  probe_unregister(rop_data->ret_probe,0);
171  probe_free(rop_data->ret_probe,0);
172  }
173 
174  free(rop_data);
175 
176  return 0;
177 }
178 
179 static struct probe_ops probe_ops_rop_checkret = {
181  .summarize = probe_summarize_rop_checkret,
182  .fini = probe_fini_rop_checkret,
183 };
184 
185 /*
186  * How a ROP gadget can be:
187  * 1) gadget starts at real, and ends at real
188  * 2) gadget starts in mid of real instr, then ends with real ret
189  * 3) gadget starts in mid of real instr, then ends inside a real instr
190  *
191  *
192  * To probe a gadget:
193  *
194  - disasm all the way from the containing symbol, then
195  - disasm gadget instrs only
196  - if gadget is inside a "real" instr, break on head of real instr and
197  on gadget head
198  - if arrive at real head, remove both real head and gadget head,
199  single, and proceed.
200  - XXX: should we try to handle this in probe, or let a probe
201  handler's function do the gadget remove? Probably the latter for now.
202  - else break on head
203  - always break on ret instr too so we know where we're going back to
204  - but wait -- if gadget does not include any instrs that modify
205  memory or the stack, we already know the ret addr
206  - if real head, just note that the real path was used, and note the return
207  - if gadget head (or if real == gadgead head) used, note return address
208  - once have ret addr, disasm block of code including that ret addr --
209  if the instr prior to the ret addr was a call to the function
210  including the gadget, we're good
211 
212  - XXX: this leaves calls through jump tables; we'll have to add
213  support for tracing from a call site into a jump table, into more
214  jump tables, to the real thing, perhaps -- otherwise we'll never
215  even make it into libc
216 
217 
218  - XXX: need to make sure to disasm (or load code) before doing any
219  probe inserts, since right now we could potentilaly insert probes
220  before doing disasm. This would lead to bad disasm.
221  *
222  */
223 
225  struct probe *trigger,struct probe *base) {
226  struct rop_checkret_data *rop_data = (struct rop_checkret_data *)data;
227  struct probe *rop_probe = rop_data->rop_probe;
228 
229  rop_data->status.ingadget = 1;
230  rop_data->status.current_ret_addr = 0;
231  ++rop_data->status.total;
232 
233  /*
234  * If the gadget type is MID_MID, we need to insert the gadget's ret
235  * probe; the ret_post handler will then remove it after it has
236  * single stepped through the exit probe's original instruction.
237  */
238  if (rop_data->type == GADGET_TYPE_MID_MID)
239  probe_hard_enable(rop_data->ret_probe);
240 
241  return rop_probe->pre_handler(rop_data->rop_probe,tid,
242  rop_data->rop_probe->handler_data,probe,base);
243 }
244 
246  struct probe *trigger,struct probe *base) {
247  struct rop_checkret_data *rop_data = (struct rop_checkret_data *)data;
248 
249  /* Have to check if the ret addr atop the stack is the addr
250  * immediately following a call to the containing function
251  * (rop_data->cont_start).
252  */
253  struct target *target = probe->target;
254  REGVAL sp;
255  REGVAL ip;
256  ADDR retaddr;
257  ADDR current_start;
258  ADDR current_end;
259  ADDR caller_start;
260  ADDR caller_end;
261  int caller_should_free;
262  int clen;
263  unsigned char *cbuf = NULL;
264  struct array_list *cf_idata_list = NULL;
265  struct cf_inst_data *cf_idata = NULL;
266  struct cf_inst_data *cf_idata_prev = NULL;
267  int i;
268  int retval;
269 
270  if (!rop_data->status.ingadget)
271  return 0;
272 
273  sp = target_read_reg(target,tid,target->spregno);
274  if (errno) {
275  verror("could not read SP!\n");
276  goto errout;
277  }
278  ip = target_read_reg(target,tid,target->ipregno);
279  if (errno) {
280  verror("could not read IP!\n");
281  goto errout;
282  }
283 
284  /* Grab the return address on the top of the stack */
285  if (!target_read_addr(target,(ADDR)sp,sizeof(ADDR),
286  (unsigned char *)&retaddr)) {
287  verror("could not read top of stack\n");
288  goto errout;
289  }
290 
291  /*
292  * We have to figure out what the instruction prior to the retaddr
293  * is so we can check if it was a legitimate call. We cannot just
294  * assume it is a CALL instruction, so we have to disassemble the
295  * "safe" chunk of text altogether, then figure out the preceding
296  * instruction.
297  *
298  * If it's a call, we have to read the target address. If our
299  * current EIP (on the RET addr we're about to execute) is pointing
300  * into the same "safe" disasm block that the call is in, we call it
301  * good for now.
302  */
303 
304  /* Find the safe disasm block for our current IP; this should never
305  * error out; else how could we have setup the probes.
306  */
307  if (target_lookup_safe_disasm_range(target,ip,&current_start,&current_end,
308  NULL)) {
309  verror("no safe disasm range contains IP 0x%"PRIxADDR"!\n",ip);
310  goto errout;
311  }
312 
313  /* Find the safe disasm block for our retaddr. */
314  if (target_lookup_safe_disasm_range(target,retaddr,
315  &caller_start,&caller_end,NULL)) {
316  verror("no safe disasm range contains retaddr 0x%"PRIxADDR"!\n",retaddr);
317  goto errout;
318  }
319 
320  /* Load the code containing the return address... */
321  clen = caller_end - caller_start;
322  cbuf = target_load_code(target,caller_start,clen,0,0,&caller_should_free);
323  if (!cbuf) {
324  verror("could not load code in range 0x%"PRIxADDR"-0x%"PRIxADDR
325  " containing retaddr at 0x%"PRIxADDR"!\n",
326  caller_start,caller_end,retaddr);
327  goto errout;
328  }
329 
330  /* Disassemble... */
331  if (disasm_get_control_flow_offsets(target,INST_CF_ANY,cbuf,clen,
332  &cf_idata_list,caller_start,1)) {
333  verror("could not disassemble code in range 0x%"PRIxADDR"-0x%"PRIxADDR
334  " containing retaddr at 0x%"PRIxADDR"!\n",
335  caller_start,caller_end,retaddr);
336  goto errout;
337  }
338 
339  /* Look for the control flow instruction prior the return
340  * address...
341  */
342  for (i = 1; i < array_list_len(cf_idata_list); ++i) {
343  cf_idata_prev = (struct cf_inst_data *)array_list_item(cf_idata_list,i-1);
344  cf_idata = (struct cf_inst_data *)array_list_item(cf_idata_list,i);
345 
346  if (cf_idata->offset >= (OFFSET)(retaddr - caller_start))
347  break;
348  }
349  if (i == array_list_len(cf_idata_list)
350  || cf_idata_prev == NULL) {
351  vwarn("no CF instr before retaddr 0x%"PRIxADDR"; "
352  " possible false-positive violation!\n",
353  retaddr);
354 
355  rop_data->status.isfpviolation = 1;
356  ++rop_data->status.fpviolations;
357  goto violation;
358  }
359  else if ((OFFSET)(retaddr - caller_start)
360  != (cf_idata_prev->offset + cf_idata_prev->size)) {
361  //vwarn("no CF instr directly before retaddr 0x%"PRIxADDR"!\n",
362  // retaddr);
363 
364  goto violation;
365  }
366  else if (cf_idata_prev->type != INST_CALL
367  && cf_idata_prev->type != INST_JMP
368  && cf_idata_prev->type != INST_JCC) {
369  vwarn("no CALL/JMP/Jcc instr before retaddr 0x%"PRIxADDR";"
370  " possible false-positive violation!\n",
371  retaddr);
372 
373  rop_data->status.isfpviolation = 1;
374  ++rop_data->status.fpviolations;
375  goto violation;
376  }
377  else if (cf_idata_prev->type == INST_JMP) {
378  /* Do not warn about these, but count them up and list them
379  * later.
380  */
381  if (!rop_data->status.jmpfpviolations)
382  vwarn("JMP instr before retaddr 0x%"PRIxADDR";"
383  " possible false-positive violation; only warning once!\n",
384  retaddr);
385 
386  rop_data->status.isjmpfpviolation = 1;
387  ++rop_data->status.jmpfpviolations;
388 
389  rop_data->status.isfpviolation = 1;
390  ++rop_data->status.fpviolations;
391 
392  goto violation;
393  }
394  else if (cf_idata_prev->type == INST_JCC) {
395  /* Do not warn about these, but count them up and list them
396  * later.
397  */
398  if (!rop_data->status.jccfpviolations)
399  vwarn("Jcc instr before retaddr 0x%"PRIxADDR";"
400  " possible false-positive violation; only warning once!\n",
401  retaddr);
402 
403  rop_data->status.isjccfpviolation = 1;
404  ++rop_data->status.jccfpviolations;
405 
406  rop_data->status.isfpviolation = 1;
407  ++rop_data->status.fpviolations;
408 
409  goto violation;
410  }
411  else if (cf_idata_prev->cf.target == 0) {
412  vwarn("CALL/JMP instr before retaddr 0x%"PRIxADDR" does not have"
413  " static target; not triggering violation; triggering error!\n",
414  retaddr);
415  goto errout;
416  }
417 
418  /* If the target is inside our current safe disasm block containing
419  * the retaddr, it is a valid call through the gadget.
420  */
421  retval = 0;
422  if (cf_idata_prev->cf.target >= current_start
423  && cf_idata_prev->cf.target < current_end) {
424  rop_data->status.isviolation = 0;
425  }
426  else {
427  violation:
428  rop_data->status.isviolation = 1;
429  ++rop_data->status.violations;
430  }
431 
432  rop_data->status.current_ret_addr = retaddr;
433  retval = rop_data->rop_probe->post_handler(rop_data->rop_probe,tid,
434  rop_data->rop_probe->handler_data,
435  probe,base);
436  goto out;
437 
438 
439  errout:
440  retval = -1;
441 
442  out:
443  if (cbuf && caller_should_free)
444  free(cbuf);
445  if (cf_idata_list)
446  array_list_deep_free(cf_idata_list);
447 
448  return retval;
449 }
450 
452  struct probe *trigger,struct probe *base) {
453  struct rop_checkret_data *rop_data = (struct rop_checkret_data *)data;
454 
455  rop_data->status.ingadget = 0;
456  rop_data->status.isviolation = 0;
457  rop_data->status.current_ret_addr = 0;
458 
459  /*
460  * If this is a GADGET_TYPE_MID_MID, we remove the exit probe, too!
461  */
462  if (rop_data->type == GADGET_TYPE_MID_MID)
463  return 2;
464  else
465  return 0;
466 }
467 
469  struct probe *trigger,struct probe *base) {
470  struct rop_checkret_data *rop_data = (struct rop_checkret_data *)data;
471 
472  /* Have to hot-remove the probe inside this instruction before we
473  * execute it!
474  */
475  probe_hard_disable(rop_data->entry_probe,0);
476 
477  return 0;
478 }
479 
481  struct probe *trigger,struct probe *base) {
482  struct rop_checkret_data *rop_data = (struct rop_checkret_data *)data;
483 
484  /* Have to hot-insert the probe back into the instruction so it is
485  * ready for the next iteration.
486  */
487  probe_hard_enable(rop_data->entry_probe);
488 
489  return 0;
490 }
491 
493  struct rop_gadget *rg,
496  void *handler_data) {
497  struct array_list *idata_list = NULL;
498  struct array_list *cf_idata_list = NULL;
499  ADDR cont_start;
500  ADDR cont_end;
501  unsigned char *cbuf = NULL;
502  unsigned char *gbuf = NULL;
503  int clen,glen;
504  int cont_should_free = 0;
505  int gadget_should_free = 0;
506  struct inst_data *idata = NULL,*idata2;
507  char namebuf[32];
508  struct rop_checkret_data *rop_data;
509  struct probe *rop_probe;
510  ADDR gadget_ret_addr;
511  int i,j;
512  int aligned = 1;
513  ADDR cont_addr;
514 
515  /*
516  * Create the main rop probe. The rop probe is really just a
517  * pass-through (for future extensibility, testing out API, etc)
518  * that invokes the probe handlers the user supplies, OR of the
519  * probes attached to it (we assume that if the user does not supply
520  * handlers, it will attach more probes to this probe).
521  */
522  rop_data = (struct rop_checkret_data *)calloc(1,sizeof(*rop_data));
523  snprintf(namebuf,32,"rop_checkret_0x%"PRIxADDR,rg->start);
524  rop_probe = probe_create(target,tid,&probe_ops_rop_checkret,namebuf,
525  pre_handler ? pre_handler : probe_do_sink_pre_handlers,
526  post_handler ? post_handler : probe_do_sink_post_handlers,
527  handler_data,0,1);
528  rop_probe->priv = rop_data;
529  rop_data->rop_probe = rop_probe;
530  rop_data->gadget = rg;
531 
532  /*
533  * Get the containing safe disassemble-able range containing the
534  * start instruction of the gadget:
535  */
536  if (target_lookup_safe_disasm_range(target,rg->start,
537  &cont_start,&cont_end,NULL)) {
538  verror("no safe disasm range contains 0x%"PRIxADDR"!\n",rg->start);
539  goto errout;
540  }
541  rop_data->cont_start = cont_start;
542  rop_data->cont_end = cont_end;
543 
544  vdebug(3,LA_USER,LF_U_ALL,"safe disasm range for gadget 0x%"PRIxADDR":"
545  " 0x%"PRIxADDR",0x%"PRIxADDR"\n",
546  rg->start,cont_start,cont_end);
547 
548  clen = cont_end - cont_start;
549  cbuf = target_load_code(target,cont_start,clen,0,0,&cont_should_free);
550  if (!cbuf) {
551  verror("could not load code in range 0x%"PRIxADDR"-0x%"PRIxADDR
552  " containing gadget at 0x%"PRIxADDR"!\n",
553  cont_start,cont_end,rg->start);
554  goto errout;
555  }
556 
557  /* Disassemble containing range. */
558  if (disasm_generic(target,cbuf,clen,&idata_list,1)) {
559  verror("could not disassemble code in range 0x%"PRIxADDR"-0x%"PRIxADDR
560  " containing gadget at 0x%"PRIxADDR"!\n",
561  cont_start,cont_end,rg->start);
562  goto errout;
563  }
564 
565  /* Load and dissassemble gadget. */
566  glen = rg->end - rg->start;
567  gbuf = target_load_code(target,rg->start,glen,0,0,&gadget_should_free);
568  if (!gbuf) {
569  verror("could not load gadget code in range 0x%"PRIxADDR"-0x%"PRIxADDR
570  "!\n",rg->start,rg->end);
571  goto errout;
572  }
573 
574  /* Disassemble gadget, looking for exactly one RET. */
575  if (disasm_get_control_flow_offsets(target,INST_CF_RET,gbuf,glen,
576  &cf_idata_list,rg->start,1)) {
577  verror("could not disassemble code at 0x%"PRIxADDR"-0x%"PRIxADDR
578  " containing gadget at 0x%"PRIxADDR"!\n",
579  rg->start,rg->end,rg->start);
580  goto errout;
581  }
582  if (array_list_len(cf_idata_list) == 0) {
583  verror("no RETs in gadget disasm!\n");
584  goto errout;
585  }
586  else if (array_list_len(cf_idata_list) > 1) {
587  verror("more than one RET in gadget disasm!\n");
588  goto errout;
589  }
590  /*
591  * Really, the ret addr should always be the last byte of the
592  * gadget's range, but we don't have to assume this.
593  */
594  gadget_ret_addr = rg->start
595  + ((struct cf_inst_data *)array_list_item(cf_idata_list,0))->offset;
596 
597  /* Figure out if the gadget starts on an instr boundary. */
598  for (i = 0; i < array_list_len(idata_list); ++i) {
599  idata = (struct inst_data *)array_list_item(idata_list,i);
600  if (rg->start == (cont_start + idata->offset)) {
601  aligned = 1;
602  break;
603  }
604  else if (rg->start < (cont_start + idata->offset)) {
605  /* It's i - 1 since the gadget start is not aligned */
606  --i;
607  idata = (struct inst_data *)array_list_item(idata_list,i);
608  aligned = 0;
609  break;
610  }
611  }
612 
613  for (j = i; j < array_list_len(idata_list); ++j) {
614  idata2 = (struct inst_data *)array_list_item(idata_list,j);
615  if ((rg->end - 1) == (cont_start + idata2->offset))
616  break;
617  }
618 
619  /*
620  * Create the gadget probes; for now, do these no matter what.
621  * Later, we could try to anticipate what the retaddr is if we're
622  * sure that none of the gadget instrs will change control flow or
623  * mess with the stack.
624  */
625  snprintf(namebuf,32,"rop_checkret_entry_0x%"PRIxADDR,rg->start);
626  rop_data->entry_probe = probe_create(target,tid,NULL,namebuf,
628  NULL,
629  rop_data,0,0);
630  if (!probe_register_addr(rop_data->entry_probe,rg->start,
633  verror("could not register %s!\n",namebuf);
634  goto errout;
635  }
636  snprintf(namebuf,32,"rop_checkret_ret_0x%"PRIxADDR,gadget_ret_addr);
637  rop_data->ret_probe = probe_create(target,tid,NULL,namebuf,
640  rop_data,0,0);
641  if (!probe_register_addr(rop_data->ret_probe,gadget_ret_addr,
644  verror("could not register %s!\n",namebuf);
645  goto errout;
646  }
647 
648  /* Setup probes for which gadget it is! */
649  if (aligned) {
650  rop_data->type = GADGET_TYPE_REAL;
651  rop_data->cont_instr_start = rg->start;
652  }
653  else {
654  if (j < array_list_len(idata_list)) {
655  rop_data->type = GADGET_TYPE_MID_REAL;
656  }
657  else {
658  rop_data->type = GADGET_TYPE_MID_MID;
659  }
660 
661  cont_addr = cont_start + idata->offset;
662  rop_data->cont_instr_start = cont_addr;
663 
664  /* Add a probe on the real instr preceding the gadget. */
665  snprintf(namebuf,32,"rop_checkret_cont_0x%"PRIxADDR,cont_addr);
666  rop_data->cont_probe = probe_create(target,tid,NULL,namebuf,
669  rop_data,0,0);
670  if (!probe_register_addr(rop_data->cont_probe,cont_addr,
673  verror("could not register %s!\n",namebuf);
674  goto errout;
675  }
676 
677  /*
678  * Now, suddenly, if the gadget is MID_MID, we *remove* the
679  * probepoint for the exit probe. It gets dynamically inserted
680  * if we hit the gadget entry point probe, and it removes itself
681  * in its post handler.
682  */
683  if (rop_data->type == GADGET_TYPE_MID_MID)
684  probe_hard_disable(rop_data->ret_probe,0);
685  }
686 
687  return rop_probe;
688 
689  errout:
690  if (cbuf && cont_should_free)
691  free(cbuf);
692  if (gbuf && gadget_should_free)
693  free(gbuf);
694  if (idata_list)
695  array_list_deep_free(idata_list);
696  if (rop_data) {
697  if (rop_data->cont_probe) {
698  probe_unregister(rop_data->cont_probe,0);
699  probe_free(rop_data->cont_probe,0);
700  }
701  if (rop_data->entry_probe) {
702  probe_unregister(rop_data->entry_probe,0);
703  probe_free(rop_data->entry_probe,0);
704  }
705  if (rop_data->ret_probe) {
706  probe_unregister(rop_data->ret_probe,0);
707  probe_free(rop_data->ret_probe,0);
708  }
709  }
710  if (rop_probe)
711  probe_free(rop_probe,0);
712 
713  return NULL;
714 }
715 
result_t probe_rop_checkret_ret_pre(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: rop_util.c:245
SMOFFSET offset
Definition: disasm.h:35
GHashTable * rop_load_gadget_stream(FILE *stream)
Definition: rop_util.c:36
ADDR current_ret_addr
Definition: rop.h:44
result_t pre_handler(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: spf.c:903
int disasm_generic(struct target *target, unsigned char *inst_buf, unsigned int buf_len, struct array_list **idata_list_saveptr, int noabort)
Definition: disasm.c:47
int probe_unregister(struct probe *probe, int force)
Definition: probe.c:1137
struct probe * cont_probe
Definition: rop.h:89
uint8_t size
Definition: disasm.h:101
probe_handler_t pre_handler
Definition: probe.h:350
int32_t tid_t
Definition: common.h:36
Definition: rop.h:27
struct probe * ret_probe
Definition: rop.h:94
OFFSET offset
Definition: disasm.h:100
uint16_t fpviolations
Definition: rop.h:40
static uint64_t unsigned int i
inst_type_t type
Definition: disasm.h:99
uint8_t isjmpfpviolation
Definition: rop.h:34
uint8_t isviolation
Definition: rop.h:34
rop_gadget_t type
Definition: rop.h:78
ADDR cont_start
Definition: rop.h:79
struct probe * entry_probe
Definition: rop.h:92
struct probe * rop_probe
Definition: rop.h:97
result_t probe_do_sink_post_handlers(struct probe *probe, tid_t tid, void *handler_data, struct probe *trigger, struct probe *base)
Definition: probe.c:109
int32_t OFFSET
Definition: common.h:65
#define verror(format,...)
Definition: log.h:30
char * meta
Definition: rop.h:30
result_t probe_do_sink_pre_handlers(struct probe *probe, tid_t tid, void *handler_data, struct probe *trigger, struct probe *base)
Definition: probe.c:48
unsigned char * target_read_addr(struct target *target, ADDR addr, unsigned long length, unsigned char *buf)
Definition: target_api.c:1053
struct probe * probe_register_addr(struct probe *probe, ADDR addr, probepoint_type_t type, probepoint_style_t style, probepoint_whence_t whence, probepoint_watchsize_t watchsize, struct bsymbol *bsymbol)
Definition: probe.c:1393
const char *(* gettype)(struct probe *probe)
Definition: probe_api.h:96
result_t(* probe_handler_t)(struct probe *probe, tid_t tid, void *handler_data, struct probe *trigger, struct probe *base)
Definition: probe_api.h:70
#define vwarn(format,...)
Definition: log.h:33
void free(void *ptr)
Definition: debugserver.c:207
REGVAL target_read_reg(struct target *target, tid_t tid, REG reg)
Definition: target_api.c:1132
int disasm_get_control_flow_offsets(struct target *target, inst_cf_flags_t flags, unsigned char *inst_buf, unsigned int buf_len, struct array_list **offset_list, ADDR base, int noabort)
Definition: disasm.c:131
tid_t tid
Definition: probe.h:344
uint16_t total
Definition: rop.h:43
int probe_hard_enable(struct probe *probe)
Definition: probe.c:961
uint16_t jmpfpviolations
Definition: rop.h:41
int probe_free(struct probe *probe, int force)
Definition: probe.c:777
int probe_fini_rop_checkret(struct probe *probe)
Definition: rop_util.c:157
ADDR start
Definition: rop.h:28
GHashTable * rop_load_gadget_file(char *filename)
Definition: rop_util.c:89
uint8_t ingadget
Definition: rop.h:34
struct rop_checkret_status status
Definition: rop.h:100
ADDR cont_end
Definition: rop.h:80
struct probe * probe_rop_checkret(struct target *target, tid_t tid, struct rop_gadget *rg, probe_handler_t pre_handler, probe_handler_t post_handler, void *handler_data)
Definition: rop_util.c:492
Definition: probe.h:308
struct probe * probe_create(struct target *target, tid_t tid, struct probe_ops *pops, const char *name, probe_handler_t pre_handler, probe_handler_t post_handler, void *handler_data, int autofree, int tracked)
Definition: probe.c:729
uint8_t isfpviolation
Definition: rop.h:34
#define vdebug(devel, areas, flags, format,...)
Definition: log.h:302
ADDR end
Definition: rop.h:29
result_t probe_rop_checkret_entry_pre(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: rop_util.c:224
struct cf_inst_data::@12 cf
void * probe_summarize_rop_checkret(struct probe *probe)
Definition: rop_util.c:153
void * calloc(size_t nmemb, size_t size)
Definition: debugserver.c:200
result_t post_handler(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: spf.c:908
ADDR target
Definition: disasm.h:132
result_t probe_rop_checkret_ret_post(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: rop_util.c:451
result_t
Definition: common.h:25
result_t probe_rop_checkret_cont_post(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: rop_util.c:480
uint32_t REGVAL
Definition: common.h:66
Definition: log.h:76
struct target * target
Definition: probe.h:342
uint32_t ADDR
Definition: common.h:64
REG spregno
Definition: target_api.h:2507
uint8_t isjccfpviolation
Definition: rop.h:34
#define PRIxADDR
Definition: common.h:67
void rop_gadget_free(void *value)
Definition: rop_util.c:29
result_t probe_rop_checkret_cont_pre(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
Definition: rop_util.c:468
const char * probe_gettype_rop_checkret(struct probe *probe)
Definition: rop_util.c:149
#define LF_U_ALL
Definition: log.h:246
uint16_t violations
Definition: rop.h:39
ADDR cont_instr_start
Definition: rop.h:90
void * handler_data
Definition: probe.h:359
int target_lookup_safe_disasm_range(struct target *target, ADDR addr, ADDR *start, ADDR *end, void **data)
Definition: target.c:3825
void * priv
Definition: probe.h:318
uint16_t jccfpviolations
Definition: rop.h:42
REG ipregno
Definition: target_api.h:2508
probe_handler_t post_handler
Definition: probe.h:354
struct rop_gadget * gadget
Definition: rop.h:82
int probe_hard_disable(struct probe *probe, int force)
Definition: probe.c:912
unsigned char * target_load_code(struct target *target, ADDR start, unsigned int len, int nocache, int force_copy, int *caller_free)
Definition: target.c:3909