Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to stop auto-analysis for script connected via ghidra_bridge #58

Open
JayFoxRox opened this issue Jun 11, 2021 · 1 comment
Open

Comments

@JayFoxRox
Copy link

I'd like to pause auto-analysis while doing some work via ghidra_bridge (which is excellent! Thanks!).
Currently my script does so many things that the Ghidra UI will freeze (UI won't render / be interactive) for more than an hour after my script ran, because it has to catch up on the auto-analysis. Fortunately the ghidra_bridge remains active during this time, so my script continues to work.

Normally the auto-analysis can be disabled using GhidraScript.getScriptAnalysisMode(). However, because ghidra_bridge is the script, and not the script(s) connected to it, that probably makes it impossible to handle it correctly.

Are there any known alternatives to disable auto-analysis?

If there is no alternative, then ghidra_bridge should expose auto-analysis mode selection.
I'm not sure how often that callback function is called, but there could also be a flag when creating the connection, or 2 different runner scripts to set the behavior; although this might also be a problem if multiple scripts connect at the same time.

There is https://ghidra.re/ghidra_docs/api/ghidra/program/flatapi/FlatProgramAPI.html#analyzeChanges(ghidra.program.model.listing.Program) to trigger manual updates, too. So disabling auto-updates is probably better than enabling them.

@justfoxing
Copy link
Owner

justfoxing commented Jun 13, 2021

Hmm, tricky.

Some notes:

Like you say, ghidra_bridge is the "script" from Ghidra's perspective, so it can't implement getScriptAnalysisMode usefully (amongst other things, the in-background execution mode returns immediately after spawning a thread, so Ghidra would think it could just resume analysis immediately; additionally, the getScriptAnalysisMode check happens before the ghidra_bridge server script starts, so there's no way to specify the behaviour from the client).

Possible solutions:

import ghidra_bridge

HOW_LONG_DOES_YOUR_ANALYSIS_TAKE = 200 # seconds

b = ghidra_bridge.GhidraBridge(namespace=globals())

# hack the remote response timeout, so the analysis callback doesn't timeout
def set_remote_bridge_timeout(connected_bridge, new_timeout):
    """ Gross hack to set the response timeout on the remote bridge end. """
    # get the remote bridge conn, by getting the frame inside local_eval, then the frame that called that (f_back), then the locals of the caller, which include the BridgeConn as self
    bc = connected_bridge.remote_eval("__import__('inspect').currentframe().f_back.f_locals['self']")
    bc.response_timeout = new_timeout
b.set_remote_bridge_timeout(b, HOW_LONG_DOES_YOUR_ANALYSIS_TAKE)

# get the remote classes needed to make an AnalysisWorker run
AnalysisWorker = ghidra.app.plugin.core.analysis.AnalysisWorker
AutoAnalysisManager = ghidra.app.plugin.core.analysis.AutoAnalysisManager

# define your AnalysisWorker to do your thing
class AWTest(AnalysisWorker):
    def getWorkerName(self):
        return "test AW from bridge"

    def analysisWorkerCallback(self, program, workercontext, monitor):
        #  call your heavy analysis from here
        # can callback to ghidra via the program arg or the flat api
        time.sleep(10) # test, to simulate doing a bunch of slow work
        print("aw yeah")
        print(program.getName()) # from ghidra, via program arg
        print(currentProgram.getName()) # from ghidra, via flat api
        return True

# grab the autoanalysis manager for the program
am = AutoAnalysisManager.getAnalysisManager(currentProgram)

# schedule the worker. we do this as remote_eval, because this doesn't return until the analysis is complete, so we set the timeout_override
b.remote_eval("am.scheduleWorker(AWTest(), None, True, getMonitor())", am=am, AWTest=AWTest, timeout_override=HOW_LONG_DOES_YOUR_ANALYSIS_TAKE+1)

Give that a try and let me know if it works or not. If it does work, I can think about if there's an ergonomic way of incorporating this into GhidraBridge so it's not quite as gross to build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants