NationalSecurityAgency / ghidra

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

Cannot connect to windgb via GADP #6008

Closed AddioElectronics closed 8 months ago

AddioElectronics commented 9 months ago

Describe the bug When trying to connect to a local process via windbg, ghidra never finishes connecting. After clicking connect, the windbg console says ghidra has connected, but in ghidra all I get are a few messages in the debug console, and the options pane has a blue "Connecting..." label that never stops.

Edit: While writing this I decided to try one more time just to get a fresh output from the debug console to copy, so I restarted ghidra and windbg, and now I am getting an actual error message. I'm not sure why, but I didn't get the error message the first 5 times I tried, now it is happening every time.

java.lang.RuntimeException: Agent terminated with error: Non-respawnable executor terminated unexpectedly
agent.dbgeng.dbgeng.err.DbgEngRuntimeException: None of the preferred interfaces are supported
    at agent.dbgeng.impl.dbgeng.DbgEngUtil.tryPreferredInterfaces(DbgEngUtil.java:74)
    at agent.dbgeng.impl.dbgeng.client.DebugClientInternal.tryPreferredInterfaces(DebugClientInternal.java:80)
    at agent.dbgeng.dbgeng.DbgEng.debugConnect(DbgEng.java:134)
    at agent.dbgeng.manager.impl.DbgManagerImpl.lambda$start$1(DbgManagerImpl.java:478)
    at agent.dbgeng.gadp.impl.DbgEngClientThreadExecutor.init(DbgEngClientThreadExecutor.java:50)
    at agent.dbgeng.gadp.impl.AbstractClientThreadExecutor.run(AbstractClientThreadExecutor.java:115)
    at java.base/java.lang.Thread.run(Thread.java:1583)

Here is the debug console output

Message Actions Time
AGENT: Listening for transport dt_socket at address: 8000 [] 16:22:15.252
AGENT: GADP Server listening on /127.0.0.1:60115 [] 16:22:15.511
AGENT: com.sun.jna.platform.win32.COM.COMException: The parameter is incorrect.(HRESULT: 80070057) (class agent.dbgeng.jna.dbgeng.client.WrapIDebugClient7) [] 16:22:15.741
AGENT: com.sun.jna.platform.win32.COM.COMException: The parameter is incorrect.(HRESULT: 80070057) (class agent.dbgeng.jna.dbgeng.client.WrapIDebugClient5) [] 16:22:15.742
AGENT: com.sun.jna.platform.win32.COM.COMException: The parameter is incorrect.(HRESULT: 80070057) (class agent.dbgeng.jna.dbgeng.client.WrapIDebugClient3) [] 16:22:15.742
AGENT: com.sun.jna.platform.win32.COM.COMException: The parameter is incorrect.(HRESULT: 80070057) (class agent.dbgeng.jna.dbgeng.client.WrapIDebugClient4) [] 16:22:15.742
AGENT: com.sun.jna.platform.win32.COM.COMException: The parameter is incorrect.(HRESULT: 80070057) (class agent.dbgeng.jna.dbgeng.client.WrapIDebugClient6) [] 16:22:15.742
AGENT: com.sun.jna.platform.win32.COM.COMException: The parameter is incorrect.(HRESULT: 80070057) (class agent.dbgeng.jna.dbgeng.client.WrapIDebugClient) [] 16:22:15.743
AGENT: com.sun.jna.platform.win32.COM.COMException: The parameter is incorrect.(HRESULT: 80070057) (class agent.dbgeng.jna.dbgeng.client.WrapIDebugClient2) [] 16:22:15.743
AGENT: INFO Using log config file: jar:file:/C:/ghidra_10.4_PUBLIC_20230928/ghidra_10.4_PUBLIC/Ghidra/Debug/Framework-Debugging/lib/Framework-Debugging.jar!/agent.log4j.xml (LoggingInitialization) [] 16:22:16.148
AGENT: INFO Using log file: null (LoggingInitialization) [] 16:22:16.149
Could not connect: java.lang.RuntimeException: Agent terminated with error: Non-respawnable executor terminated unexpectedly agent.dbgeng.dbgeng.err.DbgEngRuntimeException: None of the preferred interfaces are supported at agent.dbgeng.impl.dbgeng.DbgEngUtil.tryPreferredInterfaces(DbgEngUtil.java:74) at agent.dbgeng.impl.dbgeng.client.DebugClientInternal.tryPreferredInterfaces(DebugClientInternal.java:80) at agent.dbgeng.dbgeng.DbgEng.debugConnect(DbgEng.java:134) at agent.dbgeng.manager.impl.DbgManagerImpl.lambda$start$1(DbgManagerImpl.java:478) at agent.dbgeng.gadp.impl.DbgEngClientThreadExecutor.init(DbgEngClientThreadExecutor.java:50) at agent.dbgeng.gadp.impl.AbstractClientThreadExecutor.run(AbstractClientThreadExecutor.java:115) at java.base/java.lang.Thread.run(Thread.java:1583) [] 16:22:16.822

To Reproduce

I followed the instructions @d-millar provided here.

@dechamps I think you're pretty close, but I've said this before and been proven wrong. :)

I just ran the following test, which worked but which may be different enough from your case for there still to be problems.... (1) Started WIndbg x64 and launched Notepad.exe (2) On its console, ran ".server tcp:port=54321" (3) Launched Ghidra (4) From the "MS dbgeng.dll (WinDbg) local agent via GADP/TCP" options pane, entered: DebugConnect options (.server): tcp:Port=54321,Server=localhost all the other options were left to their defaults: Remote process server optons (untested): none Agent interface address: localhost TCP port: 0 Open agent's JDWP port: 8000 Suspend for JDWP: unchecked (5) After it connected, I had to open the Session node in the Objects tree by hand to trigger the recording, but...

I'll leave it at that for now. but obviously let me know if (a) this doesn't work for you, and (b) your use case fails with similar parameters. I can spin up a few more machines and do a more complicated test if need be.

Screenshots ghidra_windbg_gapd_error_01

Environment (please complete the following information):

Additional context

Here is another error I got just as I was exporting the debug console as CSV. It still managed to export though. Hopefully it helps you guys.

Cannot invoke "javax.swing.table.TableCellRenderer.getTableCellRendererComponent(javax.swing.JTable, Object, boolean, boolean, int, int)" because "headerRenderer" is null
java.lang.NullPointerException: Cannot invoke "javax.swing.table.TableCellRenderer.getTableCellRendererComponent(javax.swing.JTable, Object, boolean, boolean, int, int)" because "headerRenderer" is null
    at docking.widgets.table.GTableHeader.getToolTipText(GTableHeader.java:220)
    at java.desktop/javax.swing.ToolTipManager$insideTimerAction.actionPerformed(ToolTipManager.java:693)
    at java.desktop/javax.swing.Timer.fireActionPerformed(Timer.java:311)
    at java.desktop/javax.swing.Timer$DoPostEvent.run(Timer.java:243)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:117)
    at java.desktop/java.awt.WaitDispatchSupport$2.run(WaitDispatchSupport.java:191)
    at java.desktop/java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:236)
    at java.desktop/java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:234)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:319)
    at java.desktop/java.awt.WaitDispatchSupport.enter(WaitDispatchSupport.java:234)
    at java.desktop/java.awt.Dialog.show(Dialog.java:1079)
    at java.desktop/java.awt.Component.show(Component.java:1728)
    at java.desktop/java.awt.Component.setVisible(Component.java:1675)
    at java.desktop/java.awt.Window.setVisible(Window.java:1036)
    at java.desktop/java.awt.Dialog.setVisible(Dialog.java:1015)
    at docking.DockingDialog.setVisible(DockingDialog.java:353)
    at docking.DockingWindowManager.lambda$doShowDialog$6(DockingWindowManager.java:1801)
    at ghidra.util.Swing.doRun(Swing.java:292)
    at ghidra.util.Swing.runNow(Swing.java:208)
    at ghidra.util.Swing.runNow(Swing.java:163)
    at docking.DockingWindowManager.doShowDialog(DockingWindowManager.java:1805)
    at docking.DockingWindowManager.showDialog(DockingWindowManager.java:1754)
    at docking.widgets.table.GTable.promptUserForColumns(GTable.java:1195)
    at docking.widgets.table.GTable.doExportColumns(GTable.java:1279)
    at docking.widgets.table.GTable$9.actionPerformed(GTable.java:1388)
    at docking.PopupMenuHandler$1.run(PopupMenuHandler.java:63)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
d-millar commented 9 months ago

@AddioElectronics On the "good" news front, I was able to reproduce your results exactly. Will need a bit of time to diagnose, but...working on it!

AddioElectronics commented 9 months ago

Haha that is good. You guys are quick.

dragonmacher commented 9 months ago

I put in a fix for the second exception.

d-millar commented 9 months ago

@dragonmacher thanks! @AddioElectronics I think I understand the problem, but I don't have a fix yet. (Got sidetracked by a different problem which you will hit after this one - more on that in a minute.) Am pretty sure the problem is that the version of dbgeng.dll (or possibly one of its dependencies, e.g. dbgcore.dll, dbghelp.dll, dbgmodel.dll) being used by your copy of windbg is not the same as the version loaded accessed via JNA by Ghidra. Working on how to fix that....

d-millar commented 9 months ago

OK, this is not the end solution but, if you don't mind, maybe a test. Try running:

"C:\however_you_get_to\java.exe" -XX:+ShowCodeDetailsInExceptionMessages -XX:+IgnoreUnrecognizedVMOptions -Djava.system.class.loader=ghidra.GhidraClassLoader -Xshare:off -Dfile.encoding=UTF8 -Duser.country=US -Duser.language=en -Dsun.java2d.pmoffscreen=false -Dsun.java2d.xrender=true -Dsun.java2d.d3d=false -Xdock:name=Ghidra -Dvisualvm.display.name=Ghidra -Djna.library.path="C:\Program File (x86)\Windows Kits\10\Debugger\x64" -classpath "C:\however_you_get_to\ghidra\Ghidra\Framework\Utility\bin\main;\Framework Utility\bin\default" ghidra.Ghidra ghidra.GhidraRun

Note: the two "however_you_get_to"'s that you'll have to replace. You may also have to check the path used for jna.library.path - should be wherever windbg lives.

If this works, you'll still have a problem. When the Objects Tree populates, you'll get Debugger->Sessions->[0]->Processes and nothing more. Select "Processes" and hit the Refresh button in the upper right corner of that window.

d-millar commented 9 months ago

Hmmmm, I keep thinking I can navigate a solution using -Djna.library.path but....I seemed destined for failure in that regard. Falling back to my stupid but generally functional solution:

(1) Figure out where your copies of "java.exe/javaw.exe" live. (2) Figure out where your copy of windbg lives. (3) Copy the five DLLs beginning with "dbg" (core/help/eng/model/CredentialProvider (if you have that)) from the directory where windbg lives to the directory where java & javaw live.

d-millar commented 9 months ago

Oh, one more note, I would run the "MS dbgeng.dll (WinDbg)" version rather than the "MS dbgeng.dll (WinDbg) via GADP" version, as the latter adds one more level of indirection and one more chance to confuse dbgeng.dll versions. The only time you really need the GADP version is if you're running the Ghidra agent (not windbg) and Ghidra on separate machines. Am also assuming you really need the Ghidra<->windbg connection, i.e. windbg running independently, for some reason. If not, just leave the parameters for "MS dbgeng.dll (WinDbg)" as "none"/"none", and launch your target using "Objects"->"Launch" or "Launch (X)".

Hope this helps (a little).

AddioElectronics commented 9 months ago

Oops my bad! Didn't expect an update from you so soon. Its a bit late right now so I'll have to try that out tomorrow and get back to you on that.

Man that must be a headache having to deal with all these different versions.

The reason I've been trying to use GADP and not IN-VM like I was initially trying is because after the application starts, it calls into a library which then seems to get another application to end the process, and restarts it with different parameters, which ends the debugging session. Or at least that's what I think is happening, because when I monitor it with Process Explorer it shows up as a child to another application, with "random" as a parameter instead of the "-debug" I gave it.

Is there any way to attach to an already running process without GADP?

And thanks, I appreciate the help.

AddioElectronics commented 9 months ago

Well thanks a lot man, I got debugging working.

Not sure how I missed "Attach" in the objects panel before, but that was pretty much all I was missing. I had actually copied the DLLs already because I read a post you had made in another issue.

One question though, I tried running the command you suggested while I was trying to get things working, but wasn't able to run it due to missing the class loader. In "Ghidra\Framework\Utility" I am missing the bin folder. The only thing inside Utility is lib\, license.txt, and Module.manifest. So I'm just wondering if there is anything important in there that could cause any issues in the future?

d-millar commented 9 months ago

Glad you got things working! Not near my computer at the moment but will check the "Ghidra\Framework\Utility" issue tomorrow. Looking at the path in my comments above, something definitely looks off. I may have messed things up copying the cmdline. Apologies!

ryanmkurtz commented 9 months ago

One question though, I tried running the command you suggested while I was trying to get things working, but wasn't able to run it due to missing the class loader. In "Ghidra\Framework\Utility" I am missing the bin folder. The only thing inside Utility is lib, license.txt, and Module.manifest. So I'm just wondering if there is anything important in there that could cause any issues in the future?

This is because you are running out of a prebuilt Ghidra release, and @d-millar is running out of Eclipse in development mode.

d-millar commented 9 months ago

@AddioElectronics My apologies - @ryanmkurtz is right on the mark there. The cmdline should have been more like:

"C:\Program Files\Java\jdk-17\bin\java" -Duser.home="your_home_dir" -Djava.system.class.loader=ghidra.GhidraClassLoader -Dfile.encoding=UTF8 -Duser.country=US -Duser.language=en -Duser.variant= -Dsun.java2d.opengl=false -Djna.library.path="C:\tmp" -Djava.library.path="C:\tmp" -Djdk.tls.client.protocols=TLSv1.2,TLSv1.3 -Dcpu.core.limit= -Dcpu.core.override= -Dfont.size.override= -Djna.library.path="C:\Program File (x86)\Windows Kits\10\Debugger\x64" -Xshare:off -Dsun.java2d.d3d=false -Dlog4j.skipJansi=true -cp "C:\where_ghidra_lives\Ghidra\Framework\Utility\lib\Utility.jar" ghidra.Ghidra ghidra.GhidraRun

AddioElectronics commented 8 months ago

Ahh ok, that clears things up. Well thanks again man. Cheers!