Gallopsled/pwntools

Process stderr not captured on Windows

Closed this issue · 0 comments

When spawning a local process on Windows, the stderr is not captured.

Pwntools version

PS C:\Users\test\Desktop > pip freeze | findstr pwntools
pwntools==4.14.1

Systeminfo

OS Name:                   Microsoft Windows 10 Pro
OS Version:                10.0.19045 N/A Build 19045

(Same behavior on Windows 11)

PoC

from pwn import *

with open("./child.py", "w") as f:
    f.write("import sys\n")
    f.write("print('stdout')\n")
    f.write("print('stderr', file=sys.stderr)\n")

p = process(["py", "child.py"])
p.interactive()

Expected behavior

PS C:\Users\test\Desktop > py .\test.py DEBUG
[x] Starting local process 'C:\\Windows\\py.EXE' argv=[b'py', b'child.py'] 
[+] Starting local process 'C:\\Windows\\py.EXE' argv=[b'py', b'child.py'] : pid 4468
[*] Switching to interactive mode
[DEBUG] Received 0x10 bytes:
    b'stdout\r\n'
    b'stderr\r\n'
stdout
stderr
[*] Process 'C:\\Windows\\py.EXE' stopped with exit code 0 (pid 4468)
[*] Interrupted

Actual behavior

PS C:\Users\test\Desktop > py .\test.py DEBUG
[x] Starting local process 'C:\\Windows\\py.EXE' argv=[b'py', b'child.py'] 
[+] Starting local process 'C:\\Windows\\py.EXE' argv=[b'py', b'child.py'] : pid 7116
[*] Switching to interactive mode
[DEBUG] Received 0x8 bytes:
    b'stdout\r\n'
stdout
[*] Process 'C:\\Windows\\py.EXE' stopped with exit code 0 (pid 7116)
[*] Interrupted

Probable cause

On Windows, stdout is set to PIPE, and stderr is set to STDOUT:

stdout = PTY if not IS_WINDOWS else PIPE,
stderr = STDOUT,

However, stderr is then set to stdout (PIPE):

# Avoid the need to have to deal with the STDOUT magic value.
if stderr is STDOUT:
stderr = stdout

Since stderr is PIPE, it is no longer redirected to stdout.

Workaround

Set stderr to float(subprocess.STDOUT)

p = process(["py", "child.py"], stderr=float(subprocess.STDOUT))