Skip to content

Pwnable.kr wtf 题目总结

复制本地路径 | 在线编辑

题目很简单很简单,但是 Python 中父子进程的这个 pipe buffer 让我卡了很久。所以就直接讲父子进程的 pipe buffer 问题。

问题描述

使用 subprocess 并且使用 stdin 后,进程就卡死了:

p = Popen('./wtf', stdin=PIPE, stdout=PIPE)
# payload = 'a' * 10
p.stdin.write( payload )
# hang, no response...
output = p.stdout.readline()

问题原因

Python 的 subprocess 在使用的过程中需要注意参数 stdin/stdout/stderr

使用 subprocess.PIPE 的情况,主进程向子进程写入内容,除非写满否则会阻塞在 PIPE 上,所以子进程一直等待主进程写入,即等待这个 PIPE 有改动的消息,结果一直没有,就不会返回给主进程结果。

问题解决

  1. 主进程写入时发送换行符,以及使用 flush() 来告知本次写入完毕

    p = Popen('./wtf', stdin=PIPE, stdout=PIPE)
    # payload = 'a' * 10
    p.stdin.write( payload + '\n' )
    p.stdin.flush()
    output = p.stdout.readline()
    

  2. 主进程使用 communicate 来发送消息

    p = Popen('./wtf', stdin=PIPE, stdout=PIPE)
    output = p.communicate(input=payload)
    

  3. 如果 write 的内容超过了 PIPE 默认的 buffer size,也可以,但不推荐这样

    p = Popen('./wtf', stdin=PIPE, stdout=PIPE)
    # payload = 'a' * 4097
    p.stdin.write( payload )
    output = p.stdout.readline()
    

其他事项

从结果看,最后需要 decode('hex'),所以如果输入 11,那么实际上输入是 3131

对于 Python3,我们现在有 b'11',遍历每个字节用 hex(i)[2:] 转换为 16 进制到 payload,最后作为输入。