pwntools icon indicating copy to clipboard operation
pwntools copied to clipboard

gdb.debug stops at every breakpoint, running slow

Open YeoJongHan opened this issue 1 year ago • 5 comments

Is it intended for the newly opened gdb terminal to keep displaying the "Breakpoint 1" message when it hits a breakpoint? How do i disable this or better yet, how do I gdb.debug without the new terminal opening as I just want it to print the values purely based off my python script?

When I ran gdb.debug a few months back, the same script managed to run through without any issues and without any delay. After the update of rpyc or gdb or pwntools (im not sure which is the cause), it would start displaying the breakpoints continuously, would run slowly, and may even be unable to run properly.

image

YeoJongHan avatar Aug 02 '24 10:08 YeoJongHan

I noticed it being slow too but can't remember if it ever was faster. There weren't any changes to the gdb api bridge that I'm aware of. Do you have an idea @mephi42?

I think gdb printing something whenever it hits a breakpoint is normal though. Can you provide a setup for reproduction of the issue please?

peace-maker avatar Aug 02 '24 12:08 peace-maker

I don't recall it being too long, or maybe I was using qiling at that time and mixed it up with pwntools.

Regardless, here is an example that I ran to test this issue.

https://github.com/YeoJongHan/inf/tree/main/dump1

YeoJongHan avatar Aug 02 '24 13:08 YeoJongHan

I also think that the breakpoint printing is normal. The annoying part for me is that it stops when the screen becomes full; I use tube.gdb.execute("set pagination off") to prevent that. Perhaps it would be good to add this to pwntools?

Performance-wise things can definitely be better. IMHO the biggest bottleneck is the polling loop in pwnlib/gdb_api_bridge.py. You can try reducing IDLE_TIME and see if it helps.

Ideally we should find a way to integrate the rpyc's event loop with that of gdb. An obvious solution to serve rpyc on a separate thread is unsafe w.r.t. GDB. But perhaps something like the following hybrid approach would work?

  • Keep the rpyc service as it is today, but make it private.
  • Introduce a good old boring TCP multi-threaded service - that's what the scripts will connect to from now on.
  • This service will proxy connections between scripts and rpyc.
  • Whenever it receives the data from the script, in addition to forwarding it to rpyc it will use gdb.post_event() to wake rpyc up.

I would be interesting for me to implement something like this, but I can't promise I'll have the time in the near future.

mephi42 avatar Aug 03 '24 11:08 mephi42

I have tried reducing IDLE_TIME in gdb_api_bridge.py but it didn't seem to noticeably reduce the time.

I notice two instances when it has significant delays:

  1. Start of gdb initialization - when a new debug terminal opens and gdb starts to run the binary, it tends to have a significant delay between the display of pwndbg prompt and the Breakpoint 1... message. I would assume it's because it takes some time for rpyc to initialize and start serving, but I'm not familiar with the code myself. image
  2. Delay going from breakpoint to breakpoint - I would think that this is the issue with the polling loop in gdb_api_bridge.py that @mephi42 mentioned.

YeoJongHan avatar Aug 04 '24 03:08 YeoJongHan

Regarding the slow initialization, could you please try https://github.com/Gallopsled/pwntools/pull/2435? I used this locally for a while, but never got around to submitting it.

mephi42 avatar Aug 04 '24 09:08 mephi42