#pragma warning (disable: 4800) #include // Hex-Rays API pointer hexdsp_t *hexdsp = NULL; static bool inited = false; static bool invert_strcmp_enabled = false; //-------------------------------------------------------------------------- static bool idaapi do_toogle_strcmp_invert(void *ud) { vdui_t *vu = (vdui_t *)ud; invert_strcmp_enabled = !invert_strcmp_enabled; vu->refresh_view(false); return true; } //-------------------------------------------------------------------------- static void invert_strcmp(cfunc_t *cfunc) { struct strcmp_inverter_t : public ctree_visitor_t { private: cfunc_t *cfunc; public: strcmp_inverter_t(cfunc_t *cf) : ctree_visitor_t(CV_FAST), cfunc(cf) { } bool is_strcmp_expr(cexpr_t *expr) { // the expression should be a function call if ( expr->op != cot_call ) return false; // should have two arguments carglist_t &a = *expr->a; if ( a.size() != 2 ) return false; // should contain the string str[i]cmp char buf[MAXSTR]; if ( get_func_name(expr->x->obj_ea, buf, sizeof(buf)) == NULL ) return false; if ( stristr(buf, "strcmp") == NULL && stristr(buf, "stricmp") == NULL ) return false; return true; } int idaapi visit_insn(cinsn_t *ins) { // only interested in IF statements if ( ins->op != cit_if ) return 0; // now take the instance cif_t *cif = ins->cif; // must have an ELSE if ( cif->ielse == NULL ) return 0; // check if it's an strcmp() if ( !is_strcmp_expr(&cif->expr) ) return 0; // create a zero expression cexpr_t *y = new cexpr_t(); y->put_number(cfunc, 0, inf.cc.size_i); // create a new empty expression cexpr_t *x = new cexpr_t(); // now the if's expr (condition) is moved to this new condition x->swap(cif->expr); // now that the if's expr is an empty expression, let us properly populate it cif->expr.ea = x->ea; cif->expr.op = cot_eq; cif->expr.x = x; cif->expr.y = y; cif->expr.calc_type(false); // we changed the condition, so we should swap the THEN/ELSE branches too! qswap(cif->ithen, cif->ielse); return 0; // continue enumeration } }; strcmp_inverter_t tm(cfunc); tm.apply_to(&cfunc->body, NULL); } //-------------------------------------------------------------------------- // This callback handles various hexrays events. static int idaapi callback(void *, hexrays_event_t event, va_list va) { switch ( event ) { case hxe_right_click: { vdui_t &vu = *va_arg(va, vdui_t *); char s[100]; qsnprintf(s, sizeof(s), "%sable auto if (strcmp()) inversion", invert_strcmp_enabled ? "Dis" : "En"); add_custom_viewer_popup_item(vu.ct, s, "", do_toogle_strcmp_invert, &vu); } break; case hxe_maturity: { cfunc_t *cfunc = va_arg(va, cfunc_t *); ctree_maturity_t new_maturity = va_argi(va, ctree_maturity_t); if ( new_maturity == CMAT_FINAL ) // ctree is ready { if ( invert_strcmp_enabled ) invert_strcmp(cfunc); } } break; } return 0; } //-------------------------------------------------------------------------- // Initialize the plugin. int idaapi init(void) { if ( !init_hexrays_plugin() ) return PLUGIN_SKIP; // no decompiler install_hexrays_callback(callback, NULL); const char *hxver = get_hexrays_version(); msg("Hex-rays version %s has been detected, %s ready to use\n", hxver, PLUGIN.wanted_name); inited = true; return PLUGIN_KEEP; } //-------------------------------------------------------------------------- void idaapi term(void) { if ( inited ) { // clean up remove_hexrays_callback(callback, NULL); term_hexrays_plugin(); } } //-------------------------------------------------------------------------- void idaapi run(int) { // should not be called because of PLUGIN_HIDE } //-------------------------------------------------------------------------- static char comment[] = "Sample8 plugin for Hex-Rays decompiler"; //-------------------------------------------------------------------------- // // PLUGIN DESCRIPTION BLOCK // //-------------------------------------------------------------------------- plugin_t PLUGIN = { IDP_INTERFACE_VERSION, PLUGIN_HIDE, // plugin flags init, // initialize term, // terminate. this pointer may be NULL. run, // invoke plugin comment, // long comment about the plugin // it could appear in the status line // or as a hint "", // multiline help about the plugin "Hex-Rays strcmp-inverter", // the preferred short name of the plugin "" // the preferred hotkey to run the plugin };