""" summary: superficially modify the decompilation output description: modifies the decompilation output in a superficial manner, by removing some white spaces Note: this is rather crude, not quite "pythonic" code. level: intermediate """ import idautils import idc import ida_idaapi import ida_hexrays import ida_lines do_dbg = False def dbg(msg): if do_dbg: print(msg) pass def is_cident_char(c): return c.isalnum() or c == '_' def my_tag_skipcodes(l, storage): n = ida_lines.tag_skipcodes(l) if n > 0: dbg("Skipping %d chars ('%s')" % (n, l[0:n])) storage.append(l[0:n]) return l[n:] def remove_spaces(sl): dbg("*" * 80) l = sl.line global do_dbg # do_dbg = l.find("const char *") > -1 out = [] def push(c): dbg("Appending '%s'" % c) out.append(c) # skip initial spaces, do not compress them def eat_spaces(l): while True: l = my_tag_skipcodes(l, out) if not l: break c = l[0] if not c.isspace(): break push(c) l = l[1:] return l l = eat_spaces(l) # remove all spaces except in string and char constants delim = None # if not None, then we are skipping until 'delim' last = None # last seen character while True: dbg("-" * 60) dbg("l: '%s'" % l) dbg("d: '%s'" % delim) dbg("out: '%s'" % out) # go until comments l = my_tag_skipcodes(l, out) if l.startswith("//"): push(l) break nchars = ida_lines.tag_advance(l, 1) push(l[0:nchars]) l = l[nchars:] l = my_tag_skipcodes(l, out) if not l: break c = l[0] dbg("c: '%s', last: '%s', l: '%s'" % (c, last, l)) if delim: # we're inside a literal. if c == delim: delim = None # literal ended elif c == '"' or c == "'": delim = c # string/char literal started elif c.isspace(): end = l.lstrip() nptr = my_tag_skipcodes(end, out) dbg("end: '%s', nptr: '%s'" % (end, nptr)) # do not concatenate idents if not is_cident_char(last) or not is_cident_char(nptr[0]): l = end c = l[0] if l else '' dbg("new l: '%s'" % l) last = l[0] if l else '' sl.line = "".join(out) class vds6_hooks_t(ida_hexrays.Hexrays_Hooks): def func_printed(self, cfunc): for sl in cfunc.get_pseudocode(): remove_spaces(sl); return 0 # a plugin interface, boilerplate code class my_plugin_t(ida_idaapi.plugin_t): flags = ida_idaapi.PLUGIN_HIDE wanted_name = "Hex-Rays space remover (IDAPython)" wanted_hotkey = "" comment = "Sample plugin6 for Hex-Rays decompiler" help = "" def init(self): if ida_hexrays.init_hexrays_plugin(): self.vds6_hooks = vds6_hooks_t() self.vds6_hooks.hook() return ida_idaapi.PLUGIN_KEEP # keep us in the memory def term(self): self.vds6_hooks.unhook() def run(self, arg): pass def PLUGIN_ENTRY(): return my_plugin_t()