From 996c09e8ef7fadc5fb98ba0afcffd348292e3b7e Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Thu, 26 Dec 2024 23:11:56 +0100 Subject: [PATCH] Enable basic tubes/process test on Windows Fix detecting EOF of receiving side in `process.can_recv_raw` by breaking the loop when the read thread terminates. --- docs/source/tubes/processes.rst | 4 -- docs/source/tubes/serial.rst | 4 -- pwnlib/tubes/process.py | 79 +++++++++++++++++++++++++++------ 3 files changed, 65 insertions(+), 22 deletions(-) diff --git a/docs/source/tubes/processes.rst b/docs/source/tubes/processes.rst index c4d891b35..a14377c0b 100644 --- a/docs/source/tubes/processes.rst +++ b/docs/source/tubes/processes.rst @@ -2,10 +2,6 @@ from pwn import * - # TODO: Remove global POSIX flag - import doctest - doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX'] - :mod:`pwnlib.tubes.process` --- Processes =========================================================== diff --git a/docs/source/tubes/serial.rst b/docs/source/tubes/serial.rst index 599ca35c4..d850a0483 100644 --- a/docs/source/tubes/serial.rst +++ b/docs/source/tubes/serial.rst @@ -2,10 +2,6 @@ from pwn import * - # TODO: Remove global POSIX flag - import doctest - doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX'] - :mod:`pwnlib.tubes.serialtube` --- Serial Ports =========================================================== diff --git a/pwnlib/tubes/process.py b/pwnlib/tubes/process.py index 71dcbca39..0111713a1 100644 --- a/pwnlib/tubes/process.py +++ b/pwnlib/tubes/process.py @@ -135,19 +135,22 @@ class process(tube): True >>> p.connected('send') False - >>> p.recvline() - b'Hello world\n' + >>> p.recvline() # doctest: +ELLIPSIS + b'Hello world...\n' >>> p.recvuntil(b',') b'Wow,' >>> p.recvregex(b'.*data') b' such data' - >>> p.recv() - b'\n' + >>> p.recv() # doctest: +ELLIPSIS + b'...\n' >>> p.recv() # doctest: +ELLIPSIS Traceback (most recent call last): ... EOFError + .. doctest:: + :options: +POSIX + >>> p = process('cat') >>> d = open('/dev/urandom', 'rb').read(4096) >>> p.recv(timeout=0.1) @@ -513,6 +516,9 @@ def program(self): Example: + .. doctest:: + :options: +POSIX +TODO + >>> p = process('/bin/true') >>> p.executable == '/bin/true' True @@ -528,6 +534,9 @@ def cwd(self): Example: + .. doctest:: + :options: +POSIX +TODO + >>> p = process('sh') >>> p.sendline(b'cd /tmp; echo AAA') >>> _ = p.recvuntil(b'AAA') @@ -767,9 +776,13 @@ def can_recv_raw(self, timeout): if IS_WINDOWS: with self.countdown(timeout=timeout): - while self.timeout and self._read_queue.empty(): + while self.timeout and self._read_queue.empty() and self._read_thread.is_alive(): time.sleep(0.01) - return not self._read_queue.empty() + if not self._read_queue.empty(): + return True + if not self._read_thread.is_alive(): + raise EOFError + return False try: if timeout is None: @@ -896,7 +909,10 @@ def maps(self): read, write, execute, private, shared, string Example: - + + .. doctest:: + :options: +POSIX +TODO + >>> p = process(['cat']) >>> p.sendline(b"meow") >>> p.recvline() @@ -976,7 +992,10 @@ def get_mapping(self, path_value, single=True): path_value. Example: - + + .. doctest:: + :options: +POSIX + >>> p = process(['cat']) >>> mapping = p.get_mapping('[stack]') >>> mapping.path == '[stack]' @@ -1019,6 +1038,9 @@ def stack_mapping(self, single=True): Example: + .. doctest:: + :options: +POSIX + >>> p = process(['cat']) >>> mapping = p.stack_mapping() >>> mapping.path @@ -1048,6 +1070,9 @@ def heap_mapping(self, single=True): Example: + .. doctest:: + :options: +POSIX + >>> p = process(['cat']) >>> p.sendline(b'meow') >>> p.recvline() @@ -1080,6 +1105,9 @@ def vdso_mapping(self, single=True): Example: + .. doctest:: + :options: +LINUX + >>> p = process(['cat']) >>> mapping = p.vdso_mapping() >>> mapping.path @@ -1109,6 +1137,9 @@ def vvar_mapping(self, single=True): Example: + .. doctest:: + :options: +LINUX + >>> p = process(['cat']) >>> mapping = p.vvar_mapping() >>> mapping.path @@ -1139,6 +1170,9 @@ def libc_mapping(self, single=True): Example: + .. doctest:: + :options: +POSIX + >>> p = process(['cat']) >>> p.sendline(b'meow') >>> p.recvline() @@ -1219,6 +1253,9 @@ def elf_mapping(self, single=True): Example: + .. doctest:: + :options: +POSIX + >>> p = process(['cat']) >>> p.sendline(b'meow') >>> p.recvline() @@ -1257,7 +1294,9 @@ def lib_size(self, path_value): Example: - >>> from pwn import * + .. doctest:: + :options: +POSIX + >>> p = process(['cat']) >>> libc_size = p.lib_size(p.libc.path) >>> hex(libc_size) # doctest: +SKIP @@ -1294,6 +1333,9 @@ def address_mapping(self, address): Example: + .. doctest:: + :options: +POSIX + >>> p = process(['cat']) >>> p.sendline(b'meow') >>> p.recvline() @@ -1363,11 +1405,14 @@ def libc(self): Example: - >>> p = process("/bin/cat") - >>> libc = p.libc - >>> libc # doctest: +SKIP - ELF('/lib64/libc-...so') - >>> p.close() + .. doctest:: + :options: +POSIX + + >>> p = process("/bin/cat") + >>> libc = p.libc + >>> libc # doctest: +SKIP + ELF('/lib64/libc-...so') + >>> p.close() """ from pwnlib.elf import ELF @@ -1442,6 +1487,9 @@ def leak(self, address, count=1): Example: + .. doctest:: + :options: +POSIX +TODO + >>> e = ELF(which('bash-static')) >>> p = process(e.path) @@ -1478,6 +1526,9 @@ def writemem(self, address, data): Let's write data to the beginning of the mapped memory of the ELF. + .. doctest:: + :options: +POSIX +TODO + >>> context.clear(arch='i386') >>> address = 0x100000 >>> data = cyclic(32)