Last active
September 30, 2026 04:43
-
-
Save dlevi309/f3c13e7e4f76f9b620e00ef39d7630f9 to your computer and use it in GitHub Desktop.
IDA plugin to export every decompiled function individually
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from pathlib import Path | |
| from typing import Any | |
| import ida_funcs | |
| import ida_hexrays | |
| import ida_idaapi | |
| import ida_kernwin | |
| import ida_nalt | |
| import idaapi | |
| import idautils | |
| def sanitize_name(name: str) -> str: | |
| if (name.startswith("-[") or name.startswith("+[")) and name.endswith("]"): | |
| name = name[2:-1] | |
| return name.replace(" ", "--").replace(":", "-") | |
| def export_all_functions(output_dir: Path) -> None: | |
| output_dir.mkdir(parents=True, exist_ok=True) | |
| func_eas = list(idautils.Functions()) | |
| total = len(func_eas) | |
| for i, ea in enumerate(func_eas): | |
| name = ida_funcs.get_func_name(ea) | |
| progress = int(i * 100 / total) if total else 0 | |
| ida_kernwin.replace_wait_box(f"HIDECANCEL\nDecompiling {name} ({i + 1}/{total}, {progress}%)") | |
| try: | |
| cfunc = ida_hexrays.decompile(ea) | |
| if cfunc is None: | |
| continue | |
| text = str(cfunc) | |
| if len(text) < 400: | |
| continue | |
| (output_dir / f"{sanitize_name(name)}.c").write_text(text) | |
| except Exception as exc: | |
| print(f"Failed to decompile {name} at {hex(ea)}: {exc}") | |
| continue | |
| # Portions of this code was taken from https://github.com/EthanArbuckle/ida-objc-export-plugin | |
| class CSourceExport(ida_idaapi.plugin_t): | |
| flags = 0 | |
| comment = "Export every decompiled function individually" | |
| help = comment | |
| wanted_name = "Export Functions" | |
| wanted_hotkey = "Ctrl-Shift-E" | |
| def init(self) -> int: | |
| if idaapi.IDA_SDK_VERSION < 900: | |
| ida_kernwin.warning("C Source Export is only tested on IDA 9") | |
| return ida_idaapi.PLUGIN_OK | |
| def run(self, _: Any) -> None: | |
| try: | |
| if not ida_hexrays.init_hexrays_plugin(): | |
| return | |
| for_saving = True | |
| binary_name = ida_nalt.get_root_filename() | |
| output_file_dir_hint = f"{binary_name}_exported" | |
| if output_path := ida_kernwin.ask_file(for_saving, output_file_dir_hint, "Select output directory"): | |
| ida_kernwin.show_wait_box("HIDECANCEL\nExporting functions...") | |
| export_all_functions(Path(output_path)) | |
| except Exception as e: | |
| ida_kernwin.warning(f"Failed to generate source files: {e}") | |
| finally: | |
| ida_kernwin.hide_wait_box() | |
| def term(self) -> None: | |
| pass | |
| def PLUGIN_ENTRY() -> ida_idaapi.plugin_t: | |
| return CSourceExport() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment