我目前正在尝试编写(Python 2.7.3)GDB的包装器,这将允许我从脚本输入动态切换到与GDB的交互式通信。
到目前为止,我使用
self.process = subprocess.Popen(["gdb vuln"], stdin = subprocess.PIPE, shell = True)
在我的脚本中启动gdb。 (vuln
是我要检查的二进制文件)
由于gdb的一个关键特性是暂停执行附加进程并允许用户在接收SIGINT(STRG + C)时检查寄存器和内存,我需要一些方法将SIGINT信号传递给它。
都不是
self.process.send_signal(signal.SIGINT)
也不是
os.kill(self.process.pid, signal.SIGINT)
或
os.killpg(self.process.pid, signal.SIGINT)
为我工作。
当我使用其中一个功能时,没有任何反应。我想这个问题来自shell=True
的使用。但是,在这一点上,我真的没有想法。
即使我的老朋友谷歌这次也无法真正帮助我,所以也许你可以帮助我。提前谢谢。
干杯,迈克
答案 0 :(得分:1)
我深入研究了这个问题并找到了一些有趣的东西。也许这些发现将有助于将来的某些人。
使用suprocess.Popen()调用gdb vuln
时,实际上会创建三个进程,其中返回的pid是sh
(5180)中的一个。
ps -a
5180 pts/0 00:00:00 sh
5181 pts/0 00:00:00 gdb
5183 pts/0 00:00:00 vuln
因此,向进程发送SIGINT实际上会将SIGINT发送到sh
。
此外,我继续寻找答案,偶然发现了这篇文章 https://bugzilla.kernel.org/show_bug.cgi?id=9039
为了简短起见,有以下内容:
当定期使用gdb时按STRG + C时,SIGINT实际上被发送到被检查程序(在本例中为vuln
),然后ptrace将拦截它并将其传递给gdb。
这意味着,如果我使用self.process.send_signal(signal.SIGINT)
,它实际上永远不会以这种方式到达gdb。
我设法通过简单地调用subprocess.popen()
来解决此问题,如下所示:
subprocess.Popen("killall -s INT " + self.binary, shell = True)
这只不过是第一个解决方法。当多个具有相同名称的应用程序正在运行时可能会造成严重损坏。此外,如果未设置shell=True
,它会以某种方式失败。
如果有人有更好的解决方法(例如如何通过gdb获取流程的pid),请告诉我。
干杯,迈克
感谢Mark指出要查看该过程的ppid。 我设法使用以下方法缩小了发送SIGINT的进程:
out = subprocess.check_output(['ps', '-Aefj'])
for line in out.splitlines():
if self.binary in line:
l = line.split(" ")
while "" in l:
l.remove("")
# Get sid and pgid of child process (/bin/sh)
sid = os.getsid(self.process.pid)
pgid = os.getpgid(self.process.pid)
#only true for target process
if l[4] == str(sid) and l[3] != str(pgid):
os.kill(pid, signal.SIGINT)
答案 1 :(得分:1)
这对我有用:
import signal
import subprocess
try:
p = subprocess.Popen(...)
p.wait()
except KeyboardInterrupt:
p.send_signal(signal.SIGINT)
p.wait()
答案 2 :(得分:0)
我过去做过类似的事情,如果我记得它似乎对我有用:
def detach_procesGroup():
os.setpgrp()
subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
preexec_fn=detach_processGroup)