import os from typing import Any import frontmatter import gradio as gr from gradio_client import Client, handle_file from tenacity import retry, stop_after_attempt, wait_fixed, before_log, after_log import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) SPACE_URL = "https://ejschwartz-ghidrafunctioncppexporter-space.hf.space/" @retry(stop=stop_after_attempt(10), wait=wait_fixed(120), before=before_log(logger, logging.INFO)) def _connect_client(url: str) -> Client: return Client(url) client = _connect_client(SPACE_URL) def _load_intro_text() -> str: readme_path = os.path.join(os.path.dirname(__file__), "README.md") try: post = frontmatter.load(readme_path) except (OSError, ValueError): return "Upload an executable file to get started." return post.content.strip() INTRO_TEXT = _load_intro_text() with gr.Blocks() as demo: intro = gr.Markdown(INTRO_TEXT) file_widget = gr.File(label="Executable file") with gr.Column(visible=False) as col: gr.Markdown( """ Great, you selected an executable! Now pick the function you would like to analyze. """ ) fun_dropdown = gr.Dropdown( label="Select a function", choices=["Woohoo!"], interactive=True ) gr.Markdown( """ Below you can find some information. """ ) extra_args = gr.Textbox(label="Extra args to export.bash", placeholder="emit_type_definitions false", value="") with gr.Row(visible=True): disassembly = gr.Code( label="Disassembly", lines=20, max_lines=20, ) original_decompile = gr.Code( language="c", label="Decompilation", lines=20, max_lines=20, ) examples_dir = os.path.join(os.path.dirname(__file__), "examples") examples = [f.path for f in os.scandir(examples_dir)] if os.path.isdir(examples_dir) else [] gr.Examples( examples=examples, inputs=file_widget, outputs=[disassembly, original_decompile], ) @file_widget.change(inputs=file_widget, outputs=[intro, col, fun_dropdown]) def file_change_fn(file): if file is None: return { intro: INTRO_TEXT, col: gr.update(visible=False), fun_dropdown: gr.update(choices=["Woohoo!"], value=None), } try: markdown_value, funs = client.predict( file=handle_file(file), api_name="/file_change_fn", ) except Exception as e: raise gr.Error(f"Unable to analyze binary with remote app: {e}") return { intro: markdown_value, col: gr.update(visible=True), fun_dropdown: gr.update(**funs), } @fun_dropdown.change(inputs=[fun_dropdown, extra_args], outputs=[disassembly, original_decompile]) @extra_args.submit(inputs=[fun_dropdown, extra_args], outputs=[disassembly, original_decompile]) def function_change_fn(selected_fun, extra_args): if selected_fun is None: return { disassembly: "", original_decompile: "", } try: disassembly_str, decompile_str = client.predict( selected_fun=selected_fun, extra_args=extra_args, api_name="/function_change_fn", ) except Exception as e: raise gr.Error(f"Unable to select function {selected_fun} from remote app: {e}") return { disassembly: disassembly_str, original_decompile: decompile_str, } demo.queue() demo.launch(server_name="0.0.0.0", server_port=7860, show_error=True, debug=True)