如何使用shell = true

时间:2015-06-18 20:27:00

标签: python gdb subprocess popen sigint

我目前正在尝试编写(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的使用。但是,在这一点上,我真的没有想法。 即使我的老朋友谷歌这次也无法真正帮助我,所以也许你可以帮助我。提前谢谢。

干杯,迈克

3 个答案:

答案 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)