【问题标题】:Wait for a prompt from a subprocess before sending stdin input在发送标准输入输入之前等待来自子进程的提示
【发布时间】:2019-06-16 14:43:24
【问题描述】:

我有一个 linux x86 二进制文件,它要求输入密码并打印出密码正确与否。我想用python来模糊输入。

下面是我运行二进制文件的屏幕截图,然后给它字符串“asdf”,并接收到字符串“不正确”

截图:

到目前为止,我已经尝试使用 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'

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

如何改进我的脚本才能成功地与这个二进制文件交互?

【问题讨论】:

    标签: python subprocess fuzzing


    【解决方案1】:

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

    Popen.communicate(input=None)

    与进程交互:向标准输入发送数据。从标准输出读取数据并 stderr,直到到达文件结尾。等待进程终止。 可选的输入参数应该是一个要发送给孩子的字符串 进程,或无,如果不应该向孩子发送数据。

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

    注意,如果你想向进程的标准输入发送数据,你需要 使用stdin=PIPE 创建 Popen 对象。同样,得到任何东西 除了结果元组中的 None 之外,您需要提供 stdout=PIPE 和/或stderr=PIPE

    因此,您没有向进程发送任何内容,而是一次读取 所有 stdout


    在您的情况下,您实际上不需要等待提示将数据发送到进程,因为流是异步工作的:进程只有在尝试读取其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'
    

    【讨论】:

    • 程序可以在提示之前刷新输入,就像getpass的情况一样。我怀疑这是为了防止天才用echo password | myprogram 发送他们的密码,并记录他们的密码。
    猜你喜欢
    • 2021-05-28
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多