GithubHelp home page GithubHelp logo

Comments (13)

marc-etienne avatar marc-etienne commented on September 7, 2024

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:

void main_loop() {
  while(1) {
     apply_pending_ui_update();
     run_pending_analysis();
     run_pending_python_commands();
  }
}

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.

from ipyida.

fmagin avatar fmagin commented on September 7, 2024

I just learned that in the normal IDA Python you have the ability to interrupt a running python script. If you run something like while True: time.sleep(1) you get the popup "Running Python Script" and pressing Cancel in that Dialog Box interrupts the Code with a

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.

from ipyida.

marc-etienne avatar marc-etienne commented on September 7, 2024

You're right, there must be a way. I'll look into the IDAPython source to see how it's done.

from ipyida.

fmagin avatar fmagin commented on September 7, 2024

Okay, I think I am starting to understand how IDAPython handles this:
The (only) line that throws that exception is in the function execution_t::on_trace which is being set as the trace callback via PyEval_SetTrace in this line which gets called from the actual Python VM as far as I understand.

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

from ipyida.

tmr232 avatar tmr232 commented on September 7, 2024

We may be able to use sys.settrace, but it might incur a performance penalty. Worth checking out.

from ipyida.

fmagin avatar fmagin commented on September 7, 2024

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.

from ipyida.

tmr232 avatar tmr232 commented on September 7, 2024

We can probably head over and ask @minrk. The IPython community is generally friendly and helpful.

from ipyida.

minrk avatar minrk commented on September 7, 2024

Maybe we can find out how the Jupyter Notebook interrupts the kernel when you use the menu button and use that approach?

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.

from ipyida.

sfinktah avatar sfinktah commented on September 7, 2024

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?

@fmagin @tmr232 @marc-etienne

from ipyida.

fmagin avatar fmagin commented on September 7, 2024

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.

from ipyida.

sfinktah avatar sfinktah commented on September 7, 2024

@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.

from ipyida.

fmagin avatar fmagin commented on September 7, 2024

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.

from ipyida.

sfinktah avatar sfinktah commented on September 7, 2024

@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 ida_kernwin.execute_sync and if the evaluated callable is a generator it will terminate when the requesting client disconnects (providing the callable hit a yield), but that was just luck.

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 execute_sync command is new, and there is a hint that ida_kernwin.cancel_exec_request will cancel an execute_sync request if that request is establish in a certain way. unfortunately the documentation is a tad confusing (sounds like it was ported from C/C++, unless python has developed a new operator while I wasn't looking)

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.
"""

from ipyida.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.