等待子进程的提示,然后发送标准输入

时间:2019-01-23 04:18:46

标签: python subprocess fuzzing

我有一个Linux x86二进制文件,要求输入密码,并会打印出密码是正确还是不正确。我想使用python来模糊输入。

下面是我运行二进制文件,然后给它提供字符串“ asdf”并收到字符串“ incorrect”的屏幕快照

屏幕截图:

Screenshot

到目前为止,我已经尝试使用Python3子流程模块来进行

  1. 将二进制文件作为子进程运行
  2. 收到提示输入密码的提示
  3. 发送字符串。
  4. 接收回复

这是我的剧本

p = subprocess.Popen("/home/pj/Desktop/L1/lab1",stdin=subprocess.PIPE, stdout=subprocess.PIPE)
print (p.communicate()[0])

运行该脚本的结果是

b'Please supply the code: \nIncorrect\n'

我希望只收到提示,但是在我有机会发送输入信息之前,二进制文件也会返回错误的响应。

如何改进脚本以成功与此二进制文件进行交互?

1 个答案:

答案 0 :(得分:1)

仔细阅读documentation(强调我的意思):

  

Popen.communicate(input=None)

     

与进程交互:将数据发送到stdin。从stdout读取数据并   stderr,直到到达文件末尾。等待进程终止。   可选的输入参数应该是要发送给子级的字符串   处理,如果没有数据发送给孩子,则为无。

     

communicate()返回一个元组(stdoutdata, stderrdata)

     

请注意,如果要将数据发送到流程的标准输入,则需要   用stdin=PIPE创建Popen对象。同样,得到任何东西   结果元组中除“无”外,您需要给stdout=PIPE   和/或stderr=PIPE

因此,您没有向进程发送任何内容,并且一次读取了stdout all


在您的情况下,您真的不需要等待提示将数据发送到流程,因为流是异步工作的:流程只有在尝试读取其STDIN时才会获取您的输入:

In [10]: p=subprocess.Popen(("bash", "-c","echo -n 'prompt: '; read -r data; echo $data"),stdin=subprocess.PIPE,stdout=subprocess.PIPE)

In [11]: p.communicate('foobar')
Out[11]: ('prompt: foobar\n', None)

如果您出于任何原因坚持等待提示(例如,您的进程也在提示之前检查输入,还期望其他内容),you need to read STDOUT manually and be VERY careful how much you read:由于Python的file.read被阻止,因此很简单read()将死锁,因为它等待EOF且子进程不会关闭STDOUT -因此不会产生EOF -直到它得到您的输入。如果输入或输出长度可能超过stdio的缓冲区长度(在您的特定情况下不太可能),请you also need to do stdout reading and stdin writing in separate threads

下面是一个使用pexpect的示例,它可以为您解决这个问题(我使用的是pexpect.fdexpect而不是pexpect.spawn suggested in the doc,因为它适用于所有平台):

In [1]: import pexpect.fdpexpect

In [8]: p=subprocess.Popen(("bash", "-c","echo -n 'prom'; sleep 5; echo 'pt: '; read -r data; echo $data"),stdin=subprocess.PIPE,stdout=subprocess.PIPE)

In [10]: o=pexpect.fdpexpect.fdspawn(p.stdout.fileno())

In [12]: o.expect("prompt: ")
Out[12]: 0

In [16]: p.stdin.write("foobar")    #you can communicate() here, it does the same as
                                    # these 3 steps plus protects from deadlock
In [17]: p.stdin.close()
In [18]: p.stdout.read()
Out[18]: 'foobar\n'