43 retval = g_hash_table_new_full(g_direct_hash,g_direct_equal,
52 if (rc <= 0 && errno) {
53 if (rc != EAGAIN && rc != EINTR) {
54 verror(
"fscanf: %s\n",strerror(errno));
62 verror(
"Bad line in rop_gadget stream!\n");
69 g_hash_table_insert(retval,(gpointer)rg->
start,rg);
80 g_hash_table_iter_init(&iter,retval);
81 while (g_hash_table_iter_next(&iter,NULL,&v)) {
85 g_hash_table_destroy(retval);
97 if (!(f = fopen(filename,
"r"))) {
98 verror(
"fopen(%s): %s\n",filename,strerror(errno));
102 retval = g_hash_table_new_full(g_direct_hash,g_direct_equal,
110 if (rc <= 0 && errno) {
111 if (rc != EAGAIN && rc != EINTR) {
112 verror(
"fscanf: %s\n",strerror(errno));
116 else if (rc == EOF) {
120 verror(
"Bad line in rop_gadget file %s (%d)!\n",filename,rc);
127 g_hash_table_insert(retval,(gpointer)rg->
start,rg);
140 g_hash_table_iter_init(&iter,retval);
141 while (g_hash_table_iter_next(&iter,NULL,&v)) {
145 g_hash_table_destroy(retval);
150 return "rop_checkret";
179 static struct probe_ops probe_ops_rop_checkret = {
225 struct probe *trigger,
struct probe *base) {
227 struct probe *rop_probe = rop_data->
rop_probe;
246 struct probe *trigger,
struct probe *base) {
261 int caller_should_free;
263 unsigned char *cbuf = NULL;
275 verror(
"could not read SP!\n");
280 verror(
"could not read IP!\n");
286 (
unsigned char *)&retaddr)) {
287 verror(
"could not read top of stack\n");
315 &caller_start,&caller_end,NULL)) {
316 verror(
"no safe disasm range contains retaddr 0x%"PRIxADDR"!\n",retaddr);
321 clen = caller_end - caller_start;
325 " containing retaddr at 0x%"PRIxADDR"!\n",
326 caller_start,caller_end,retaddr);
332 &cf_idata_list,caller_start,1)) {
334 " containing retaddr at 0x%"PRIxADDR"!\n",
335 caller_start,caller_end,retaddr);
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);
346 if (cf_idata->
offset >= (
OFFSET)(retaddr - caller_start))
349 if (i == array_list_len(cf_idata_list)
350 || cf_idata_prev == NULL) {
352 " possible false-positive violation!\n",
359 else if ((
OFFSET)(retaddr - caller_start)
360 != (cf_idata_prev->
offset + cf_idata_prev->
size)) {
370 " possible false-positive violation!\n",
383 " possible false-positive violation; only warning once!\n",
400 " possible false-positive violation; only warning once!\n",
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",
422 if (cf_idata_prev->
cf.
target >= current_start
423 && cf_idata_prev->
cf.
target < current_end) {
443 if (cbuf && caller_should_free)
446 array_list_deep_free(cf_idata_list);
452 struct probe *trigger,
struct probe *base) {
469 struct probe *trigger,
struct probe *base) {
481 struct probe *trigger,
struct probe *base) {
501 unsigned char *cbuf = NULL;
502 unsigned char *gbuf = NULL;
504 int cont_should_free = 0;
505 int gadget_should_free = 0;
509 struct probe *rop_probe;
510 ADDR gadget_ret_addr;
524 rop_probe =
probe_create(target,tid,&probe_ops_rop_checkret,namebuf,
528 rop_probe->
priv = rop_data;
537 &cont_start,&cont_end,NULL)) {
546 rg->
start,cont_start,cont_end);
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);
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);
569 verror(
"could not load gadget code in range 0x%"PRIxADDR
"-0x%"PRIxADDR
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",
582 if (array_list_len(cf_idata_list) == 0) {
583 verror(
"no RETs in gadget disasm!\n");
586 else if (array_list_len(cf_idata_list) > 1) {
587 verror(
"more than one RET in gadget disasm!\n");
594 gadget_ret_addr = rg->
start
598 for (i = 0; i < array_list_len(idata_list); ++
i) {
599 idata = (
struct inst_data *)array_list_item(idata_list,i);
604 else if (rg->
start < (cont_start + idata->
offset)) {
607 idata = (
struct inst_data *)array_list_item(idata_list,i);
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))
625 snprintf(namebuf,32,
"rop_checkret_entry_0x%"PRIxADDR,rg->
start);
633 verror(
"could not register %s!\n",namebuf);
636 snprintf(namebuf,32,
"rop_checkret_ret_0x%"PRIxADDR,gadget_ret_addr);
644 verror(
"could not register %s!\n",namebuf);
654 if (j < array_list_len(idata_list)) {
661 cont_addr = cont_start + idata->
offset;
665 snprintf(namebuf,32,
"rop_checkret_cont_0x%"PRIxADDR,cont_addr);
673 verror(
"could not register %s!\n",namebuf);
690 if (cbuf && cont_should_free)
692 if (gbuf && gadget_should_free)
695 array_list_deep_free(idata_list);
result_t probe_rop_checkret_ret_pre(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
GHashTable * rop_load_gadget_stream(FILE *stream)
result_t pre_handler(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
int disasm_generic(struct target *target, unsigned char *inst_buf, unsigned int buf_len, struct array_list **idata_list_saveptr, int noabort)
int probe_unregister(struct probe *probe, int force)
struct probe * cont_probe
probe_handler_t pre_handler
static uint64_t unsigned int i
struct probe * entry_probe
result_t probe_do_sink_post_handlers(struct probe *probe, tid_t tid, void *handler_data, struct probe *trigger, struct probe *base)
#define verror(format,...)
result_t probe_do_sink_pre_handlers(struct probe *probe, tid_t tid, void *handler_data, struct probe *trigger, struct probe *base)
unsigned char * target_read_addr(struct target *target, ADDR addr, unsigned long length, unsigned char *buf)
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)
const char *(* gettype)(struct probe *probe)
result_t(* probe_handler_t)(struct probe *probe, tid_t tid, void *handler_data, struct probe *trigger, struct probe *base)
#define vwarn(format,...)
REGVAL target_read_reg(struct target *target, tid_t tid, REG reg)
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)
int probe_hard_enable(struct probe *probe)
int probe_free(struct probe *probe, int force)
int probe_fini_rop_checkret(struct probe *probe)
GHashTable * rop_load_gadget_file(char *filename)
struct rop_checkret_status status
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)
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)
#define vdebug(devel, areas, flags, format,...)
result_t probe_rop_checkret_entry_pre(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
struct cf_inst_data::@12 cf
void * probe_summarize_rop_checkret(struct probe *probe)
void * calloc(size_t nmemb, size_t size)
result_t post_handler(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
result_t probe_rop_checkret_ret_post(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
result_t probe_rop_checkret_cont_post(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
void rop_gadget_free(void *value)
result_t probe_rop_checkret_cont_pre(struct probe *probe, tid_t tid, void *data, struct probe *trigger, struct probe *base)
const char * probe_gettype_rop_checkret(struct probe *probe)
int target_lookup_safe_disasm_range(struct target *target, ADDR addr, ADDR *start, ADDR *end, void **data)
probe_handler_t post_handler
struct rop_gadget * gadget
int probe_hard_disable(struct probe *probe, int force)
unsigned char * target_load_code(struct target *target, ADDR start, unsigned int len, int nocache, int force_copy, int *caller_free)