From 3406fb1e8705e14ffbfd7ccf6db568566f6f5912 Mon Sep 17 00:00:00 2001 From: clearbluejar <3752074+clearbluejar@users.noreply.github.com> Date: Wed, 10 Jan 2024 12:15:58 +0000 Subject: [PATCH] Update output folder structure --- .ghidra_projects/.placeholder | 0 ghidrecomp/decompile.py | 32 +++++++++++++++++++++++--------- ghidrecomp/utility.py | 6 +++--- tests/test_gdt.py | 18 +++++++++++++----- 4 files changed, 39 insertions(+), 17 deletions(-) delete mode 100644 .ghidra_projects/.placeholder diff --git a/.ghidra_projects/.placeholder b/.ghidra_projects/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/ghidrecomp/decompile.py b/ghidrecomp/decompile.py index 9d6f790..7b63e5b 100644 --- a/ghidrecomp/decompile.py +++ b/ghidrecomp/decompile.py @@ -130,11 +130,25 @@ def decompile(args: Namespace): print(f'Starting decompliations: {args}') bin_path = Path(args.bin) - project_location = Path(args.project_path) thread_count = args.thread_count - output_path = Path(args.output_path) / bin_path.name + output_path = Path(args.output_path) + bin_output_path = output_path / bin_path.name + decomp_path = bin_output_path / 'decomps' output_path.mkdir(exist_ok=True, parents=True) + bin_output_path.mkdir(exist_ok=True, parents=True) + decomp_path.mkdir(exist_ok=True, parents=True) + + + if args.project_path == 'ghidra_projects': + project_location = output_path / args.project_path + else: + project_location = Path(args.project_path) + + if args.symbols_path == 'symbols': + symbols_path = output_path / args.symbols_path + else: + symbols_path = Path(args.symbols_path) # turn on verbose launcher = HeadlessPyhidraLauncher(True) @@ -159,7 +173,7 @@ def decompile(args: Namespace): if args.sym_file_path: set_pdb(program, args.sym_file_path) else: - setup_symbol_server(args.symbols_path) + setup_symbol_server(symbols_path) set_remote_pdbs(program, True) @@ -206,7 +220,7 @@ def decompile(args: Namespace): if args.cppexport: print(f"Decompiling {len(all_funcs)} functions using Ghidra's CppExporter") - c_file = Path(args.output_path) / Path(bin_path.name + '.c') + c_file = decomp_path / Path(bin_path.name + '.c') start = time() decompile_to_single_file(c_file, program) print(f'Decompiled {len(all_funcs)} functions for {program.name} in {time() - start}') @@ -221,7 +235,7 @@ def decompile(args: Namespace): start = time() with concurrent.futures.ThreadPoolExecutor(max_workers=thread_count) as executor: futures = (executor.submit(decompile_func, func, decompilers, thread_id % thread_count, monitor=monitor) - for thread_id, func in enumerate(all_funcs) if args.skip_cache or not (output_path / (get_filename(func) + '.c')).exists()) + for thread_id, func in enumerate(all_funcs) if args.skip_cache or not (decomp_path / (get_filename(func) + '.c')).exists()) for future in concurrent.futures.as_completed(futures): decompilations.append(future.result()) @@ -235,20 +249,20 @@ def decompile(args: Namespace): # Save all decomps start = time() with concurrent.futures.ThreadPoolExecutor(max_workers=thread_count) as executor: - futures = (executor.submit((output_path / (name + '.c')).write_text, decomp) + futures = (executor.submit((decomp_path / (name + '.c')).write_text, decomp) for name, decomp, sig in decompilations) for future in concurrent.futures.as_completed(futures): pass - print(f'Wrote {completed} decompilations for {program.name} to {output_path} in {time() - start}') + print(f'Wrote {completed} decompilations for {program.name} to {decomp_path} in {time() - start}') # Generate callgrpahs for functions if args.callgraphs: start = time() completed = 0 - callgraph_path = output_path / 'callgraphs' + callgraph_path = bin_output_path / 'callgraphs' callgraphs_completed_path = callgraph_path / 'completed_callgraphs.json' if callgraphs_completed_path.exists(): callgraphs_completed = json.loads(callgraphs_completed_path.read_text()) @@ -289,4 +303,4 @@ def decompile(args: Namespace): print(f'Wrote {completed} callgraphs for {program.name} to {callgraph_path} in {time() - start}') print(f'{len(all_funcs) - completed} callgraphs already existed.') - return (all_funcs, decompilations, output_path, str(program.compiler), str(program.languageID), callgraphs) + return (all_funcs, decompilations, bin_output_path, str(program.compiler), str(program.languageID), callgraphs) diff --git a/ghidrecomp/utility.py b/ghidrecomp/utility.py index 2185666..e5b0641 100644 --- a/ghidrecomp/utility.py +++ b/ghidrecomp/utility.py @@ -22,16 +22,16 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument('bin', help='Path to binary used for analysis') parser.add_argument('--cppexport', action='store_true', help='Use Ghidras CppExporter to decompile to single file') parser.add_argument('--filter', dest='filters', action='append', help='Regex match for function name') - parser.add_argument('--project-path', help='Path to base ghidra projects ', default='.ghidra_projects') + parser.add_argument('--project-path', help='Path to base ghidra projects ', default='ghidra_projects') parser.add_argument('--gdt', help='Additional GDT to apply', nargs='?', action='append') - parser.add_argument('-o', '--output-path', help='Location for all decompilations', default='decompilations') + parser.add_argument('-o', '--output-path', help='Location for all decompilations', default='ghidrecomps') parser.add_argument("-v", "--version", action="version", version=__version__) parser.add_argument("--skip-cache", action='store_true', help='Skip cached and genearate new decomp and callgraphs.') group = parser.add_mutually_exclusive_group() group.add_argument('--sym-file-path', help='Specify single pdb symbol file for bin') - group.add_argument('-s', '--symbols-path', help='Path for local symbols directory', default='.symbols') + group.add_argument('-s', '--symbols-path', help='Path for local symbols directory', default='symbols') group.add_argument('--skip-symbols', help='Do not apply symbols', action='store_true') parser.add_argument('-t', '--thread-count', type=int, diff --git a/tests/test_gdt.py b/tests/test_gdt.py index b934206..0d1f04a 100644 --- a/tests/test_gdt.py +++ b/tests/test_gdt.py @@ -82,10 +82,18 @@ def test_apply_gdt(shared_datadir: Path): args = parser.parse_args([f"{bin_path.absolute()}"]) - project_location = Path(args.project_path) - output_path = Path(args.output_path) / bin_path.name - output_path.mkdir(exist_ok=True, parents=True) - + output_path = Path(args.output_path) + + if args.project_path == 'ghidra_projects': + project_location = output_path / args.project_path + else: + project_location = Path(args.project_path) + + if args.symbols_path == 'symbols': + symbols_path = output_path / args.symbols_path + else: + symbols_path = Path(args.symbols_path) + # turn on verbose pyhidra.start(True) @@ -98,7 +106,7 @@ def test_apply_gdt(shared_datadir: Path): program: "Program" = flat_api.getCurrentProgram() - setup_symbol_server(args.symbols_path) + setup_symbol_server(symbols_path) set_remote_pdbs(program, True)