Skip to content

Commit

Permalink
Handle context.newline correctly in tube.interactive()
Browse files Browse the repository at this point in the history
The `context.newline` or `self.newline` variable isn't obeyed when typing in interactive mode. It is used when sending and receiving lines through `tube.sendline` though, causing a mismatch.

The receiving end of the `tube.interactive()` already has handling of newlines, but the sending side does not.

Example:
```python
from pwn import *
io = process('cat')
io.newline = b'\r\n'
io.sendline(b'auto')
io.interactive()
```

```
$ python testinteractive.py DEBUG
[x] Starting local process '/usr/bin/cat' argv=[b'cat']
[+] Starting local process '/usr/bin/cat' argv=[b'cat'] : pid 19060
[DEBUG] Sent 0x6 bytes:
    b'auto\r\n'
[*] Switching to interactive mode
[DEBUG] Received 0x6 bytes:
    b'auto\r\n'
auto
$ test
[DEBUG] Sent 0x5 bytes:
    b'test\n'
[DEBUG] Received 0x5 bytes:
    b'test\n'
test
```

The expected outcome would be to send `b'test\r\n'.

The same problem arises in non-term mode (`PWNLIB_NOTERM=1`), where stdin is read in binary mode causing the OS line seperators to come through. Correctly replacing them with the `context.newline` setting allows to use the interactive input on windows hosts as well, without constantly sending `\r\n`.
  • Loading branch information
peace-maker committed Oct 27, 2022
1 parent 4ddb702 commit 642a3fc
Showing 1 changed file with 13 additions and 2 deletions.
15 changes: 13 additions & 2 deletions pwnlib/tubes/tube.py
Expand Up @@ -4,6 +4,7 @@

import abc
import logging
import os
import re
import six
import string
Expand Down Expand Up @@ -852,7 +853,7 @@ def interactive(self, prompt = term.text.bold_red('$') + ' '):
is much more usable, since we are using :mod:`pwnlib.term` to print a
floating prompt.
Thus it only works in while in :data:`pwnlib.term.term_mode`.
Thus it only works while in :data:`pwnlib.term.term_mode`.
"""

self.info('Switching to interactive mode')
Expand All @@ -879,11 +880,21 @@ def recv_thread():

try:
while not go.isSet():
os_linesep = os.linesep.encode()
if term.term_mode:
data = term.readline.readline(prompt = prompt, float = True)
else:
stdin = getattr(sys.stdin, 'buffer', sys.stdin)
data = stdin.read(1)
data = b''
if sys.stdin.isatty():
while not data.endswith(os_linesep):
new_byte = stdin.read(1)
if not new_byte:
break
data += new_byte
else:
data = stdin.read(1)
data = data.replace(os_linesep, self.newline)

if data:
try:
Expand Down

0 comments on commit 642a3fc

Please sign in to comment.