| 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) |
|
|