Skip to content

Commit 0f4e889

Browse files
committed
Remove PythonForWindows dependency
This loses the `readmem` and `writemem` feature, but that's not necessary for this basic process startup support.
1 parent de5e26f commit 0f4e889

File tree

3 files changed

+29
-64
lines changed

3 files changed

+29
-64
lines changed

pwnlib/tubes/process.py

Lines changed: 12 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@
1818
if IS_WINDOWS:
1919
import queue
2020
import threading
21-
import windows
22-
from windows.generated_def.winstructs import CREATE_SUSPENDED
23-
from windows.generated_def import ntstatus
24-
ntstatus_names = {int(v):k for k,v in ntstatus.__dict__.items() if k.startswith('STATUS') and v}
2521
else:
2622
import fcntl
2723
import pty
@@ -38,6 +34,8 @@
3834
from pwnlib.util.misc import which
3935
from pwnlib.util.misc import normalize_argv_env
4036
from pwnlib.util.packing import _need_bytes
37+
from pwnlib.util.proc import cwd
38+
from pwnlib.util.proc import memory_maps
4139

4240
log = getLogger(__name__)
4341

@@ -380,25 +378,13 @@ def __init__(self, argv = None,
380378
p.success('pid %i' % self.pid)
381379

382380
if IS_WINDOWS:
383-
class winprocess(windows.winobject.process.WinProcess):
384-
def __del__(self):
385-
# sys.path is not None -> check if python shutdown
386-
# workaround crash on shutdown trying to delete invalid WinProcess object
387-
if hasattr(sys, "path") and sys.path is not None:
388-
super(winprocess, self).__del__()
389-
390-
#: :class:`windows.winobject.process.WinProcess` object that provides insight into the process
391-
self.win_process = winprocess(pid=self.pid)
392381
self._read_thread = None
393382
self._read_queue = queue.Queue()
394383
if self.proc.stdout:
395384
# Read from stdout in a thread
396385
self._read_thread = threading.Thread(target=_read_in_thread, args=(self._read_queue, self.proc.stdout))
397386
self._read_thread.daemon = True
398387
self._read_thread.start()
399-
400-
if (creationflags & CREATE_SUSPENDED) == 0:
401-
self._wait_initialized()
402388
return
403389

404390
if self.pty is not None:
@@ -522,18 +508,6 @@ def __on_enoexec(self, exception):
522508
# we don't have a qemu which can run it.
523509
self.exception(exception)
524510

525-
def _check_initialized(self):
526-
# Accessing PEB until WinProcess is done initializing.
527-
try:
528-
self.win_process.peb.modules[1]
529-
return True
530-
except:
531-
return False
532-
533-
def _wait_initialized(self):
534-
while not self._check_initialized() and not self.win_process.is_exit:
535-
time.sleep(0.05)
536-
537511
@property
538512
def program(self):
539513
"""Alias for ``executable``, for backward compatibility.
@@ -566,10 +540,7 @@ def cwd(self):
566540
'/proc'
567541
"""
568542
try:
569-
if IS_WINDOWS:
570-
self._cwd = self.win_process.peb.ProcessParameters.contents.CurrentDirectory.DosPath.str
571-
else:
572-
self._cwd = os.readlink('/proc/%i/cwd' % self.pid)
543+
self._cwd = cwd(self.pid)
573544
except Exception:
574545
pass
575546

@@ -713,12 +684,8 @@ def poll(self, block = False):
713684
if returncode is not None and not self._stop_noticed:
714685
self._stop_noticed = time.time()
715686
signame = ''
716-
if IS_WINDOWS:
717-
if returncode in ntstatus_names:
718-
signame = ' (%s)' % (ntstatus_names[returncode])
719-
else:
720-
if returncode < 0:
721-
signame = ' (%s)' % (signal_names.get(returncode, 'SIG???'))
687+
if returncode < 0:
688+
signame = ' (%s)' % (signal_names.get(returncode, 'SIG???'))
722689

723690
self.info("Process %r stopped with exit code %d%s (pid %i)" % (self.display,
724691
returncode,
@@ -920,15 +887,7 @@ def libs(self):
920887
by the process to the address it is loaded at in the process' address
921888
space.
922889
"""
923-
if IS_WINDOWS:
924-
if not self._check_initialized():
925-
raise Exception("PEB not initialized while getting the loaded modules")
926-
return {module.name.lower(): module.baseaddr for module in self.win_process.peb.modules if module.name}
927-
928-
try:
929-
maps_raw = open('/proc/%d/maps' % self.pid).read()
930-
except IOError:
931-
maps_raw = None
890+
maps_raw = memory_maps(self.pid)
932891

933892
if not maps_raw:
934893
import pwnlib.elf.elf
@@ -938,18 +897,18 @@ def libs(self):
938897

939898
# Enumerate all of the libraries actually loaded right now.
940899
maps = {}
941-
for line in maps_raw.splitlines():
942-
if '/' not in line: continue
943-
path = line[line.index('/'):]
900+
for mapping in maps_raw:
901+
path = mapping.path
902+
if os.sep not in path: continue
944903
path = os.path.realpath(path)
945904
if path not in maps:
946905
maps[path]=0
947906

948907
for lib in maps:
949908
path = os.path.realpath(lib)
950-
for line in maps_raw.splitlines():
951-
if line.endswith(path):
952-
address = line.split('-')[0]
909+
for mapping in maps_raw:
910+
if mapping.path == path:
911+
address = mapping.addr.split('-')[0]
953912
maps[lib] = int(address, 16)
954913
break
955914

@@ -1058,11 +1017,6 @@ def leak(self, address, count=1):
10581017
>>> p.leak(e.address, 4)
10591018
b'\x7fELF'
10601019
"""
1061-
if IS_WINDOWS:
1062-
if not self._check_initialized():
1063-
self.error("PEB not initialized while reading memory")
1064-
return self.win_process.read_memory(address, count)
1065-
10661020
# If it's running under qemu-user, don't leak anything.
10671021
if 'qemu-' in os.path.realpath('/proc/%i/exe' % self.pid):
10681022
self.error("Cannot use leaker on binaries under QEMU.")
@@ -1108,11 +1062,6 @@ def writemem(self, address, data):
11081062
>>> io.recvall()
11091063
b'aaaabaaacaaadaaaeaaafaaagaaahaaa'
11101064
"""
1111-
if IS_WINDOWS:
1112-
if not self._check_initialized():
1113-
self.error("PEB not initialized while writing memory")
1114-
return self.win_process.write_memory(address, data)
1115-
11161065
if 'qemu-' in os.path.realpath('/proc/%i/exe' % self.pid):
11171066
self.error("Cannot use leaker on binaries under QEMU.")
11181067

pwnlib/util/proc.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,23 @@ def cmdline(pid):
223223
"""
224224
return psutil.Process(pid).cmdline()
225225

226+
def memory_maps(pid):
227+
"""memory_maps(pid) -> list
228+
229+
Arguments:
230+
pid (int): PID of the process.
231+
232+
Returns:
233+
A list of the memory mappings in the process.
234+
235+
Example:
236+
>>> maps = memory_maps(os.getpid())
237+
>>> [(m.path, m.perms) for m in maps if '[stack]' in m.path]
238+
[('[stack]', 'rw-p')]
239+
240+
"""
241+
return psutil.Process(pid).memory_maps(grouped=False)
242+
226243
def stat(pid):
227244
"""stat(pid) -> str list
228245

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ dependencies = [
5757
"pathlib2; python_version < '3.4'",
5858
"unix-ar; python_version >= '3'",
5959
"zstandard",
60-
"PythonForWindows; sys_platform == 'win32'",
6160
]
6261

6362
[project.urls]

0 commit comments

Comments
 (0)