NationalSecurityAgency / ghidra

Ghidra is a software reverse engineering (SRE) framework
https://www.nsa.gov/ghidra
Apache License 2.0
51.96k stars 5.9k forks source link

Ghidra emulator stops working when stumbled upon LOCK instruction #6630

Open nogitsune-youkai opened 5 months ago

nogitsune-youkai commented 5 months ago

Describe the bug When emulating software which runs in VM, ghidra apparently can't emulate properly LOCK instruction. Is it a bug or i'm doing something wrong?

To Reproduce Steps to reproduce the behavior:

  1. Simply launch emulator and emulate program

Expected behavior LOCK instruction should be emulated without issues.

Environment (please complete the following information):

Additional context Full error log:

Sleigh userop 'LOCK' is not in the library ghidra.pcode.exec.ComposedPcodeUseropLibrary@21f3ab2b
ghidra.pcode.exec.PcodeExecutionException: Sleigh userop 'LOCK' is not in the library ghidra.pcode.exec.ComposedPcodeUseropLibrary@21f3ab2b
    at ghidra.pcode.exec.PcodeExecutor.step(PcodeExecutor.java:275)
    at ghidra.pcode.exec.PcodeExecutor.finish(PcodeExecutor.java:178)
    at ghidra.pcode.exec.PcodeExecutor.execute(PcodeExecutor.java:160)
    at ghidra.pcode.exec.PcodeExecutor.execute(PcodeExecutor.java:135)
    at ghidra.pcode.emu.DefaultPcodeThread.executeInstruction(DefaultPcodeThread.java:584)
    at ghidra.pcode.emu.DefaultPcodeThread.stepInstruction(DefaultPcodeThread.java:415)
    at ghidra.trace.model.time.schedule.Stepper$Enum$1.tick(Stepper.java:25)
    at ghidra.trace.model.time.schedule.TickStep.execute(TickStep.java:74)
    at ghidra.trace.model.time.schedule.Step.execute(Step.java:182)
    at ghidra.trace.model.time.schedule.Sequence.execute(Sequence.java:392)
    at ghidra.trace.model.time.schedule.TraceSchedule.finish(TraceSchedule.java:400)
    at ghidra.app.plugin.core.debug.service.emulation.DebuggerEmulationServicePlugin.doEmulateFromCached(DebuggerEmulationServicePlugin.java:723)
    at ghidra.app.plugin.core.debug.service.emulation.DebuggerEmulationServicePlugin.doEmulate(DebuggerEmulationServicePlugin.java:771)
    at ghidra.app.plugin.core.debug.service.emulation.DebuggerEmulationServicePlugin$EmulateTask.compute(DebuggerEmulationServicePlugin.java:262)
    at ghidra.app.plugin.core.debug.service.emulation.DebuggerEmulationServicePlugin$EmulateTask.compute(DebuggerEmulationServicePlugin.java:252)
    at ghidra.app.plugin.core.debug.service.emulation.DebuggerEmulationServicePlugin$AbstractEmulateTask.run(DebuggerEmulationServicePlugin.java:239)
    at ghidra.util.task.Task.monitoredRun(Task.java:134)
    at ghidra.util.task.TaskRunner.lambda$startTaskThread$0(TaskRunner.java:106)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: ghidra.pcode.exec.SleighLinkException: Sleigh userop 'LOCK' is not in the library ghidra.pcode.exec.ComposedPcodeUseropLibrary@21f3ab2b
    at ghidra.pcode.exec.PcodeExecutor.onMissingUseropDef(PcodeExecutor.java:578)
    at ghidra.pcode.emu.DefaultPcodeThread$PcodeThreadExecutor.onMissingUseropDef(DefaultPcodeThread.java:203)
    at ghidra.pcode.exec.PcodeExecutor.executeCallother(PcodeExecutor.java:562)
    at ghidra.pcode.exec.PcodeExecutor.stepOp(PcodeExecutor.java:249)
    at ghidra.pcode.emu.DefaultPcodeThread$PcodeThreadExecutor.stepOp(DefaultPcodeThread.java:180)
    at ghidra.pcode.exec.PcodeExecutor.step(PcodeExecutor.java:268)
    ... 20 more
nsadeveloper789 commented 5 months ago

You'll need to define for the emulator what the LOCK pcode userop means. See https://github.com/NationalSecurityAgency/ghidra/blob/master/GhidraDocs/GhidraClass/Debugger/B4-Modeling.md. That tutorial goes into quite a bit more than you need, but essentialy, create a custom userop library that defines LOCK, then use a script to install an emulator with that library into the UI.

nsadeveloper789 commented 5 months ago

Essentially, the same solution as found here, but for a different processor: https://github.com/NationalSecurityAgency/ghidra/issues/6089. It's very possible your definition is effectively a NOP.

nogitsune-youkai commented 5 months ago

Ok. Thank you, i'll look into it

Marisa-Chan commented 1 month ago

Essentially, the same solution as found here, but for a different processor: #6089. It's very possible your definition is effectively a NOP.

It's all great, but it will be really easy if it's just open "jython" window of active emulation tool and do something like:

def useropNOP():
  pass

and then do something like: getCurrentEmulator().registerSimpleUserOp("LOCK", useropNOP)

and continue emulation process instead of diving into java and Ghidra developing for hours, because simple LOCK/UNLOCK has no simple "nop" implementation and implementing it is really hard way, especially you do not have much time for it.

Maybe if it's not really possible to make easy way, then just bundle example script which will add nopped LOCK/UNLCOK with graphical launch(or how to do this?) of emulator? Or script which will implement NOP for LOCK/UNLOCK on the fly in active graphical emulation?

Or may be just add "SKIP unknown" option for emulator?

P.s. after of 5 hours of trying to implement this things such stupid way I give up and go will look for just patch emulator to skip it.