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 有改动的消息,结果一直没有,就不会返回给主进程结果。
问题解决
-
主进程写入时发送换行符,以及使用
flush()来告知本次写入完毕
p = Popen('./wtf', stdin=PIPE, stdout=PIPE) # payload = 'a' * 10 p.stdin.write( payload + '\n' ) p.stdin.flush() output = p.stdout.readline() -
主进程使用 communicate 来发送消息
p = Popen('./wtf', stdin=PIPE, stdout=PIPE) output = p.communicate(input=payload) -
如果 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,最后作为输入。