pwnlib.tubes.process — Processes

class pwnlib.tubes.process.process(argv, shell=False, executable=None, cwd=None, env=None, timeout=pwnlib.timeout.Timeout.default, stdin=-1, stdout=<object object>, stderr=-2, level=None, close_fds=True, preexec_fn=<function process.<lambda>>, raw=True, aslr=None, setuid=None)[source]

Bases: pwnlib.tubes.tube.tube

Spawns a new process, and wraps it with a tube for communication.

Parameters:
  • argv (list) – List of arguments to pass to the spawned process.
  • shell (bool) – Set to True to interpret argv as a string to pass to the shell for interpretation instead of as argv.
  • executable (str) – Path t`o the binary to execute. If None, uses argv[0]. Cannot be used with shell.
  • cwd (str) – Working directory. Uses the current working directory by default.
  • env (dict) – Environment variables. By default, inherits from Python’s environment.
  • timeout (int) – Timeout to use on tube recv operations.
  • stdin (int) – File object or file descriptor number to use for stdin. By default, a pipe is used. A pty can be used instead by setting this to process.PTY. This will cause programs to behave in an interactive manner (e.g.., python will show a >>> prompt). If the application reads from /dev/tty directly, use a pty.
  • stdout (int) – File object or file descriptor number to use for stdout. By default, a pty is used so that any stdout buffering by libc routines is disabled. May also be subprocess.PIPE to use a normal pipe.
  • stderr (int) – File object or file descriptor number to use for stderr. By default, stdout is used. May also be subprocess.PIPE to use a separate pipe, although the tube wrapper will not be able to read this data.
  • close_fds (bool) – Close all open file descriptors except stdin, stdout, stderr. By default, True is used.
  • preexec_fn (callable) – Callable to invoke immediately before calling execve.
  • raw (bool) – Set the created pty to raw mode (i.e. disable echo and control characters). True by default. If no pty is created, this has no effect.
  • aslr (bool) –

    If set to False, disable ASLR via personality (setarch -R) and setrlimit (ulimit -s unlimited).

    This disables ASLR for the target process. However, the setarch changes are lost if a setuid binary is executed.

    The default value is inherited from context.aslr. See setuid below for additional options and information.

  • setuid (bool) –

    Used to control setuid status of the target binary, and the corresponding actions taken.

    By default, this value is None, so no assumptions are made.

    If True, treat the target binary as setuid. This modifies the mechanisms used to disable ASLR on the process if aslr=False. This is useful for debugging locally, when the exploit is a setuid binary.

    If False, prevent setuid bits from taking effect on the target binary. This is only supported on Linux, with kernels v3.5 or greater.

proc[source]

subprocess

Examples

>>> p = process(which('python3'))
>>> p.sendline("print('Hello world')")
>>> p.sendline("print('Wow, such data')")
>>> b'' == p.recv(timeout=0.01)
True
>>> p.shutdown('send')
>>> p.proc.stdin.closed
True
>>> p.connected('send')
False
>>> p.recvline()
b'Hello world\n'
>>> p.recvuntil(',')
b'Wow,'
>>> p.recvregex('.*data')
b' such data'
>>> p.recv()
b'\n'
>>> p.recv() 
Traceback (most recent call last):
...
EOFError
>>> p = process('cat')
>>> d = open('/dev/urandom', 'rb').read(4096)
>>> p.recv(timeout=0.1)
b''
>>> p.write(d)
>>> p.recvrepeat(0.1) == d
True
>>> p.recv(timeout=0.1)
b''
>>> p.shutdown('send')
>>> p.wait_for_close()
>>> p.poll()
0
>>> p = process('cat /dev/zero | head -c8', shell=True, stderr=open('/dev/null', 'w+'))
>>> p.recv()
b'\x00\x00\x00\x00\x00\x00\x00\x00'
>>> p = process(['python2', '-c', 'import os; print os.read(2, 1024)'],
...             preexec_fn=lambda: os.dup2(0, 2))
>>> p.sendline('hello')
>>> p.recvline()
b'hello\n'
>>> stack_smashing = ['python2', '-c', 'open("/dev/tty", "wb").write("stack smashing detected")']
>>> process(stack_smashing).recvall()
b'stack smashing detected'
>>> process(stack_smashing, stdout=process.PIPE).recvall()
b''
>>> getpass = ['python2', '-c', 'import getpass; print(getpass.getpass("XXX"))']
>>> p = process(getpass, stdin=process.PTY)
>>> p.recv()
b'XXX'
>>> p.sendline('hunter2')
>>> p.recvall()
b'\nhunter2\n'
>>> process('echo hello 1>&2', shell=True).recvall()
b'hello\n'
>>> process('echo hello 1>&2', shell=True, stderr=process.PIPE).recvall()
b''
>>> a = process(['cat', '/proc/self/maps']).recvall()
>>> b = process(['cat', '/proc/self/maps'], aslr=False).recvall()
>>> with context.local(aslr=False):
...    c = process(['cat', '/proc/self/maps']).recvall()
>>> a == b
False
>>> b == c
True
>>> process(['sh', '-c', 'ulimit -s'], aslr=0).recvline()
b'unlimited\n'
argv = None[source]

Arguments passed on argv

aslr = None[source]

Whether ASLR should be left on

communicate(stdin=None) → bytes tuple[source]

Calls subprocess.Popen.communicate() method on the process.

cwd = None[source]

Directory the process was created in

env = None[source]

Environment passed on envp

executable = None[source]

Full path to the executable

kill()[source]

Kills the process.

leak(address, count=0)[source]

Leaks memory within the process at the specified address.

Parameters:
  • address (int) – Address to leak memory at
  • count (int) – Number of bytes to leak at that address.
libc[source]

Returns an ELF for the libc for the current process. If possible, it is adjusted to the correct address automatically.

libs() → dict[source]

Return a dictionary mapping the path of each shared library loaded by the process to the address it is loaded at in the process’ address space.

If /proc/$PID/maps for the process cannot be accessed, the output of ldd alone is used. This may give inaccurate results if ASLR is enabled.

poll(block=False) → int[source]
Parameters:block (bool) – Wait for the process to exit

Poll the exit code of the process. Will return None, if the process has not yet finished and the exit code otherwise.

proc = None[source]

subprocess.Popen object

program[source]

Alias for executable, for backward compatibility

pty = None[source]

Which file descriptor is the controlling TTY

raw = None[source]

Whether the controlling TTY is set to raw mode