-
Notifications
You must be signed in to change notification settings - Fork 73
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
IDA blocking while python commands are executed #12
Comments
I agree this is frustrating problem sometimes, but IMO it would be quite difficult to implement in IPyIDA. IDA is a single threaded application and so is Python. Furthermore, both runs on the same thread. It could be a feature request for Hex-Rays support. From what I understand, IDA's main loop looks like:
Even if we hack it with real (non-python) threads, it the IDA API wouldn't be thread-safe anyway so it would come with it's set of problems too. |
I just learned that in the normal IDA Python you have the ability to interrupt a running python script. If you run something like Traceback (most recent call last):
File "<string>", line 1, in <module>
KeyboardInterrupt: User interrupted So basically that feature for the IPython shell would perfectly suffice and it seems to be possible to do. |
You're right, there must be a way. I'll look into the IDAPython source to see how it's done. |
Okay, I think I am starting to understand how IDAPython handles this: The idea behind all that stuff is explained at the start of the code that deals with it (here) What I don't understand yet is how it would be possible to trigger this from ipyida |
We may be able to use sys.settrace, but it might incur a performance penalty. Worth checking out. |
I have been thinking about this a bit and also had to deal with it when writing https://github.com/ernw/binja-ipython. I could use multiple threads there and just inject an exception into the other thread, but this probably wont work here. In general, at least to my knowledge, you can't interrupt a kernel that was for example started in a notebook and than attached to with a console from the console either, so this is more of a general problem with IPython. Maybe we can find out how the Jupyter Notebook interrupts the kernel when you use the menu button and use that approach? Potentially the kernel exposes some function that handles this and can be called from wherever but I am not that familiar with the IPython internals. Might be worth it to ask on their mailing list. |
We can probably head over and ask @minrk. The IPython community is generally friendly and helpful. |
Ultimately it comes down to this method where we send signals in unix. This works in the notebook because the kernel is a subprocess, so we have a handle on the KernelManager. This is also why you lose this capability when you connect an additional console - the console doesn't have a handle on the process, only a network connection to the kernel. We have a special mechanism via Windows APIs for interrupt events, and it involves cooperation of both the client and the kernel. |
Sorry, I've read all posts from the experts, and I hate to be "that guy", but ipyida is isn't usable without an Abort function. I realise that this is hard on many levels, the most obvious being that the UI thread immediately locks up so there's no way to process an interrupt request. But setting that aside, and assuming the abort trigger is dispatched from an external source (lets just assume that such a signal can be sent), what barriers are there in getting IDA to co-operate? What has to be reverse engineered and hooked in IDA? (I'm talking Windows here, as I assume this is not such a killer issue on other platforms). And I'm assuming that the signal won't be able to be sent from ipyida itself... but assuming a signal could be sent... what needs to be done? |
I am not using IDA much anymore because I moved to Ghidra, but the https://github.com/justfoxing/jfx_bridge_ida might be something that also serves your use case. I assume that if I need to an IPython environment with IDA again I will use that, I have good experiences with the https://github.com/justfoxing/ghidra_bridge project that uses the same underlying RPC implementation. |
@fmagin Interesting... I personally couldn't use Ghdira because it's so terribly horrific to look at, but if I had the time I would love to do an IDA remix of it (shortcuts & GUI reskin). Not that IDA is that great to look at, but at least it doesn't use capitals for it's disassembly. I have a lot of respect for it's decompiler too, on the few occasions I've compared it to some rather ugly decompiles in IDA, it's produced some quite beautiful code with minimal information. I'll check out justfoxing. I could probably live with IDA's inbuilt python console if I could actually read the tiny writing. |
This is getting somewhat off topic, but there are already various keyboard configs out for Ghidra so it matches the IDA shortcuts. I have been using https://github.com/nullteilerfrei/reversing-class/blob/master/ghIDA.kbxml , but there isn't much of a difference between them anyway. Somewhat on topic again: My experience with a Jupyter Kotlin kernel for Ghidra has shown me that while the jupyter-console or qtconsole refuses to send an interrupt signal, you can just create your own connection to send an interrupt signal and it works: GhidraJupyter/ghidra-jupyter-kotlin@eeffad0#diff-3b084b06f9eeb6adc5ec48c8205f434301daabefe3071971db39f4aa26b0a6dd This might only work because the Kotlin Kernel uses multiple threads though, so it could be fundamentally impossible with the Jupyter Python kernel. I do recall that IDA changed something related to threading in the last few years, so maybe there is hope. But at the end of the day neither Python nor IDA support this scenario very well, so I doubt it will ever get better than a bunch of hacks to make it tolerable. |
@fmagin Hmm... I wish I knew how it actually interrupted a kernel it didn't start. In "something completely different" I ended up making a web-ui for IDA as a demo for https://github.com/sfinktah/idarest75/ ... which while very pretty, will suffer from the identical inability to interrupt a running command. Commands are executed via As far as I can see, the main difference in "new" IDA regarding threads, is that it now prevents you from running non-thread-safe functions from any other thread but main. Possible the aforementioned I am still suspicious that this will only remove the request from the queue (if it hasn't already run). MFF_NOWAIT = _ida_kernwin.MFF_NOWAIT
"""
Do not wait for the request to be executed. the caller should ensure
that the request is not destroyed until the execution completes. if
not, the request will be ignored. the request must be created using
the 'new' operator to use it with this flag. it can be used in
'cancel_exec_request()' . This flag can be used to delay the code
execution until the next UI loop run even from the main thread.
""" |
I am aware that this is an issue with regular Python in IDA too, so I am assuming this is an issue with IDA itself,but it might be possible to work around it with the IPython hooking capabilities.
When running any command in the Python shell the IDA GUI is not usable until the command terminates. At least in my case when using angr it happens fairly often that I accidentally run commands which will take basically forever (state exploration without proper limits).
My idea was to find some way to set a timeout on any executed cell in IPython by leveraging the hooking points[0] or code transformations[1] IPython provides.
The ways to implement timeouts in Python[2] seem to be either by using multiprocessing or signal handling, the latter of which is not available on non-UNIX systems. I haven't found a way yet to do this properly via multi processing (or maybe multi threading?) but any input would be appreciated.
[0] https://ipython.readthedocs.io/en/5.x/api/generated/IPython.core.hooks.html
[1] https://ipython.readthedocs.io/en/5.x/config/inputtransforms.html
[2] https://stackoverflow.com/questions/492519/timeout-on-a-function-call
The text was updated successfully, but these errors were encountered: