pwnlib.tubes.process
— Processes¶
-
class
pwnlib.tubes.process.
process
(argv=None, shell=False, executable=None, cwd=None, env=None, stdin=-1, stdout=<pwnlib.tubes.process.PTY object>, stderr=-2, close_fds=True, preexec_fn=<function <lambda>>, raw=True, aslr=None, setuid=None, where='local', display=None, alarm=None, *args, **kwargs)[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 to the binary to execute. If
None
, usesargv[0]
. Cannot be used withshell
. - cwd (str) – Working directory. Uses the current working directory by default.
- env (dict) – Environment variables. By default, inherits from Python’s environment.
- 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 toPTY
. 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 bePIPE
to use a normal pipe. - stderr (int) – File object or file descriptor number to use for
stderr
. By default,STDOUT
is used. May also bePIPE
to use a separate pipe, although thepwnlib.tubes.tube.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 viapersonality
(setarch -R
) andsetrlimit
(ulimit -s unlimited
).This disables ASLR for the target process. However, the
setarch
changes are lost if asetuid
binary is executed.The default value is inherited from
context.aslr
. Seesetuid
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 assetuid
. This modifies the mechanisms used to disable ASLR on the process ifaslr=False
. This is useful for debugging locally, when the exploit is asetuid
binary.If
False
, preventsetuid
bits from taking effect on the target binary. This is only supported on Linux, with kernels v3.5 or greater. - where (str) – Where the process is running, used for logging purposes.
- display (list) – List of arguments to display, instead of the main executable name.
- alarm (int) – Set a SIGALRM alarm timeout on the process.
Examples
>>> p = process('python2') >>> p.sendline("print 'Hello world'") >>> p.sendline("print 'Wow, such data'"); >>> '' == p.recv(timeout=0.01) True >>> p.shutdown('send') >>> p.proc.stdin.closed True >>> p.connected('send') False >>> p.recvline() 'Hello world\n' >>> p.recvuntil(',') 'Wow,' >>> p.recvregex('.*data') ' such data' >>> p.recv() '\n' >>> p.recv() Traceback (most recent call last): ... EOFError
>>> p = process('cat') >>> d = open('/dev/urandom').read(4096) >>> p.recv(timeout=0.1) '' >>> p.write(d) >>> p.recvrepeat(0.1) == d True >>> p.recv(timeout=0.1) '' >>> 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() '\x00\x00\x00\x00\x00\x00\x00\x00'
>>> p = process(['python','-c','import os; print os.read(2,1024)'], ... preexec_fn = lambda: os.dup2(0,2)) >>> p.sendline('hello') >>> p.recvline() 'hello\n'
>>> stack_smashing = ['python','-c','open("/dev/tty","wb").write("stack smashing detected")'] >>> process(stack_smashing).recvall() 'stack smashing detected'
>>> process(stack_smashing, stdout=PIPE).recvall() ''
>>> getpass = ['python','-c','import getpass; print getpass.getpass("XXX")'] >>> p = process(getpass, stdin=PTY) >>> p.recv() 'XXX' >>> p.sendline('hunter2') >>> p.recvall() '\nhunter2\n'
>>> process('echo hello 1>&2', shell=True).recvall() 'hello\n'
>>> process('echo hello 1>&2', shell=True, stderr=PIPE).recvall() ''
>>> 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() 'unlimited\n'
>>> io = process(['sh','-c','sleep 10; exit 7'], alarm=2) >>> io.poll(block=True) == -signal.SIGALRM True
>>> binary = ELF.from_assembly('nop', arch='mips') >>> p = process(binary.path)
-
can_recv_raw
(timeout) → bool[source]¶ Should not be called directly. Returns True, if there is data available within the timeout, but ignores the buffer on the object.
-
communicate
(stdin = None) → str[source]¶ Calls
subprocess.Popen.communicate()
method on the process.
-
connected_raw
(direction)[source]¶ connected(direction = ‘any’) -> bool
Should not be called directly. Returns True iff the tube is connected in the given direction.
-
leak
(address, count=1)[source]¶ Leaks memory within the process at the specified address.
Parameters: Example
>>> e = ELF('/bin/bash') >>> p = process(e.path)
In order to make sure there’s not a race condition against the process getting set up…
>>> p.sendline('echo hello') >>> p.recvuntil('hello') 'hello'
Now we can leak some data!
>>> p.leak(e.address, 4) '\x7fELF'
-
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 ofldd
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.
-
recv_raw
(numb) → str[source]¶ Should not be called directly. Receives data without using the buffer on the object.
Unless there is a timeout or closed connection, this should always return data. In case of a timeout, it should return None, in case of a closed connection it should raise an
exceptions.EOFError
.
-
send_raw
(data)[source]¶ Should not be called directly. Sends data to the tube.
Should return
exceptions.EOFError
, if it is unable to send any more, because of a close tube.
-
shutdown_raw
(direction)[source]¶ Should not be called directly. Closes the tube for further reading or writing.
-
corefile
[source]¶ Returns a corefile for the process.
If the process is alive, attempts to create a coredump with GDB.
If the process is dead, attempts to locate the coredump created by the kernel.
-
cwd
[source]¶ Directory that the process is working in.
Example
>>> p = process('sh') >>> p.sendline('cd /tmp; echo AAA') >>> _ = p.recvuntil('AAA') >>> p.cwd == '/tmp' True >>> p.sendline('cd /proc; echo BBB;') >>> _ = p.recvuntil('BBB') >>> p.cwd '/proc'
-
libc
[source]¶ Returns an ELF for the libc for the current process. If possible, it is adjusted to the correct address automatically.
-
proc
= None[source]¶ subprocess.Popen
object that backs this process
-
program
[source]¶ Alias for
executable
, for backward compatibility.Example
>>> p = process('true') >>> p.executable == '/bin/true' True >>> p.executable == p.program True
-
stderr
[source]¶ Shorthand for
self.proc.stderr
See:
process.proc
-
stdin
[source]¶ Shorthand for
self.proc.stdin
See:
process.proc
-
stdout
[source]¶ Shorthand for
self.proc.stdout
See:
process.proc