I am currently trying to write (Python 2.7.3) kind of a wrapper for GDB, which will allow me to dynamically switch from scripted input to interactive communication with GDB.
So far I use
self.process = subprocess.Popen(["gdb vuln"], stdin = subprocess.PIPE, shell = True)
to start gdb within my script. (vuln
is the binary I want to examine)
Since a key feature of gdb is to pause the execution of the attached process and allow the user to inspect registers and memory on receiving SIGINT (STRG+C) I do need some way to pass a SIGINT signal to it.
Neither
self.process.send_signal(signal.SIGINT)
nor
os.kill(self.process.pid, signal.SIGINT)
or
os.killpg(self.process.pid, signal.SIGINT)
work for me.
When I use one of these functions there is no response. I suppose this problem arises from the use of shell=True
. However, at this point I am really out of ideas.
Even my old friend Google couldn't really help me out this time, so maybe you can help me. Thank's in advance.
Cheers, Mike
I looked deeper into the problem and found some interesting things. Maybe these findings will help someone in the future.
When calling
gdb vuln
using suprocess.Popen() it does in fact create three processes, where the pid returned is the one ofsh
(5180).Consequently sending a SIGINT to the process will in fact send SIGINT to
sh
.Besides, I continued looking for an answer and stumbled upon this post https://bugzilla.kernel.org/show_bug.cgi?id=9039
To keep it short, what is mentioned there is the following:
When pressing STRG+C while using gdb regularly SIGINT is in fact sent to the examined program (in this case
vuln
), then ptrace will intercept it and pass it to gdb. What this means is, that if I useself.process.send_signal(signal.SIGINT)
it will in fact never reach gdb this way.Temporary Workaround:
I managed to work around this problem by simply calling
subprocess.popen()
as follows:subprocess.Popen("killall -s INT " + self.binary, shell = True)
This is nothing more than a first workaround. When multiple applications with the same name are running might do some serious damage. Besides, it somehow fails, if
shell=True
is not set. If someone has a better fix (e.g. how to get the pid of the process startet by gdb), please let me know.Cheers, Mike
EDIT:
Thanks to Mark for pointing out to look at the ppid of the process. I managed to narrow down the process's to which SIGINT is sent using the following approach:
I have done something like the following in the past and if I recollect it seemed to work for me :
Here is what worked for me: