• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Gallopsled / pwntools / 3797606986

pending completion
3797606986

push

github-actions

GitHub
Merge branch 'dev' into rop_raw_list

3931 of 6599 branches covered (59.57%)

102 of 102 new or added lines in 15 files covered. (100.0%)

12074 of 16876 relevant lines covered (71.55%)

0.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.39
/pwnlib/util/proc.py
1
from __future__ import absolute_import
1✔
2
from __future__ import division
1✔
3

4
import errno
1✔
5
import socket
1✔
6
import time
1✔
7

8
import psutil
1✔
9

10
from pwnlib import tubes
1✔
11
from pwnlib.log import getLogger
1✔
12
from .net import sock_match
1✔
13
from pwnlib.timeout import Timeout
1✔
14

15
log = getLogger(__name__)
1✔
16

17
all_pids = psutil.pids
1✔
18

19
def pidof(target):
1✔
20
    """pidof(target) -> int list
21

22
    Get PID(s) of `target`.  The returned PID(s) depends on the type of `target`:
23

24
    - :class:`str`: PIDs of all processes with a name matching `target`.
25
    - :class:`pwnlib.tubes.process.process`: singleton list of the PID of `target`.
26
    - :class:`pwnlib.tubes.sock.sock`: singleton list of the PID at the
27
      remote end of `target` if it is running on the host.  Otherwise an
28
      empty list.
29

30
    Arguments:
31
        target(object):  The target whose PID(s) to find.
32

33
    Returns:
34
        A list of found PIDs.
35

36
    Example:
37
        >>> l = tubes.listen.listen()
38
        >>> p = process(['curl', '-s', 'http://127.0.0.1:%d'%l.lport])
39
        >>> pidof(p) == pidof(l) == pidof(('127.0.0.1', l.lport))
40
        True
41
    """
42
    if isinstance(target, tubes.ssh.ssh_channel):
1!
43
        return [target.pid]
×
44

45
    elif isinstance(target, tubes.sock.sock):
1✔
46
        local  = target.sock.getsockname()
1✔
47
        remote = target.sock.getpeername()
1✔
48
        match = sock_match(remote, local, target.family, target.type)
1✔
49
        return [c.pid for c in psutil.net_connections() if match(c)]
1✔
50

51
    elif isinstance(target, tuple):
1✔
52
        match = sock_match(None, target)
1✔
53
        return [c.pid for c in psutil.net_connections() if match(c)]
1✔
54

55
    elif isinstance(target, tubes.process.process):
1!
56
        return [target.proc.pid]
1✔
57

58
    else:
59
        return pid_by_name(target)
×
60

61
def pid_by_name(name):
1✔
62
    """pid_by_name(name) -> int list
63

64
    Arguments:
65
        name (str): Name of program.
66

67
    Returns:
68
        List of PIDs matching `name` sorted by lifetime, youngest to oldest.
69

70
    Example:
71
        >>> os.getpid() in pid_by_name(name(os.getpid()))
72
        True
73
    """
74
    def match(p):
1✔
75
        if p.status() == 'zombie':
1✔
76
            return False
1✔
77
        if p.name() == name:
1✔
78
            return True
1✔
79
        try:
1✔
80
            if p.exe() == name:
1!
81
                return True
×
82
        except Exception:
1✔
83
            pass
1✔
84
        return False
1✔
85

86
    processes = (p for p in psutil.process_iter() if match(p))
1✔
87

88
    processes = sorted(processes, key=lambda p: p.create_time(), reverse=True)
1✔
89

90
    return [p.pid for p in processes]
1✔
91

92
def name(pid):
1✔
93
    """name(pid) -> str
94

95
    Arguments:
96
        pid (int): PID of the process.
97

98
    Returns:
99
        Name of process as listed in ``/proc/<pid>/status``.
100

101
    Example:
102
        >>> p = process('cat')
103
        >>> name(p.pid)
104
        'cat'
105
    """
106
    return psutil.Process(pid).name()
1✔
107

108
def parent(pid):
1✔
109
    """parent(pid) -> int
110

111
    Arguments:
112
        pid (int): PID of the process.
113

114
    Returns:
115
        Parent PID as listed in ``/proc/<pid>/status`` under ``PPid``,
116
        or 0 if there is not parent.
117
    """
118
    try:
1✔
119
         return psutil.Process(pid).parent().pid
1✔
120
    except Exception:
1✔
121
         return 0
1✔
122

123
def children(ppid):
1✔
124
    """children(ppid) -> int list
125

126
    Arguments:
127
        pid (int): PID of the process.
128

129
    Returns:
130
        List of PIDs of whose parent process is `pid`.
131
    """
132
    return [p.pid for p in psutil.Process(ppid).children()]
×
133

134
def ancestors(pid):
1✔
135
    """ancestors(pid) -> int list
136

137
    Arguments:
138
        pid (int): PID of the process.
139

140
    Returns:
141
        List of PIDs of whose parent process is `pid` or an ancestor of `pid`.
142

143
    Example:
144
        >>> ancestors(os.getpid()) # doctest: +ELLIPSIS
145
        [..., 1]
146
    """
147
    pids = []
1✔
148
    while pid != 0:
1✔
149
         pids.append(pid)
1✔
150
         pid = parent(pid)
1✔
151
    return pids
1✔
152

153
def descendants(pid):
1✔
154
    """descendants(pid) -> dict
155

156
    Arguments:
157
        pid (int): PID of the process.
158

159
    Returns:
160
        Dictionary mapping the PID of each child of `pid` to it's descendants.
161

162
    Example:
163
        >>> d = descendants(os.getppid())
164
        >>> os.getpid() in d.keys()
165
        True
166
    """
167
    this_pid = pid
1✔
168
    allpids = all_pids()
1✔
169
    ppids = {}
1✔
170
    def _parent(pid):
1✔
171
         if pid not in ppids:
1✔
172
             ppids[pid] = parent(pid)
1✔
173
         return ppids[pid]
1✔
174
    def _children(ppid):
1✔
175
         return [pid for pid in allpids if _parent(pid) == ppid]
1✔
176
    def _loop(ppid):
1✔
177
         return {pid: _loop(pid) for pid in _children(ppid)}
1✔
178
    return _loop(pid)
1✔
179

180
def exe(pid):
1✔
181
    """exe(pid) -> str
182

183
    Arguments:
184
        pid (int): PID of the process.
185

186
    Returns:
187
        The path of the binary of the process. I.e. what ``/proc/<pid>/exe`` points to.
188

189
    Example:
190
        >>> exe(os.getpid()) == os.path.realpath(sys.executable)
191
        True
192
    """
193
    return psutil.Process(pid).exe()
1✔
194

195
def cwd(pid):
1✔
196
    """cwd(pid) -> str
197

198
    Arguments:
199
        pid (int): PID of the process.
200

201
    Returns:
202
        The path of the process's current working directory. I.e. what
203
        ``/proc/<pid>/cwd`` points to.
204

205
    Example:
206
        >>> cwd(os.getpid()) == os.getcwd()
207
        True
208
    """
209
    return psutil.Process(pid).cwd()
1✔
210

211
def cmdline(pid):
1✔
212
    """cmdline(pid) -> str list
213

214
    Arguments:
215
        pid (int): PID of the process.
216

217
    Returns:
218
        A list of the fields in ``/proc/<pid>/cmdline``.
219

220
    Example:
221
        >>> 'py' in ''.join(cmdline(os.getpid()))
222
        True
223
    """
224
    return psutil.Process(pid).cmdline()
1✔
225

226
def stat(pid):
1✔
227
    """stat(pid) -> str list
228

229
    Arguments:
230
        pid (int): PID of the process.
231

232
    Returns:
233
        A list of the values in ``/proc/<pid>/stat``, with the exception that ``(`` and ``)`` has been removed from around the process name.
234

235
    Example:
236
        >>> stat(os.getpid())[2]
237
        'R'
238
    """
239
    with open('/proc/%d/stat' % pid) as fd:
1✔
240
         s = fd.read()
1✔
241
    # filenames can have ( and ) in them, dammit
242
    i = s.find('(')
1✔
243
    j = s.rfind(')')
1✔
244
    name = s[i+1:j]
1✔
245
    return s[:i].split() + [name] + s[j+1:].split()
1✔
246

247
def starttime(pid):
1✔
248
    """starttime(pid) -> float
249

250
    Arguments:
251
        pid (int): PID of the process.
252

253
    Returns:
254
        The time (in seconds) the process started after system boot
255

256
    Example:
257
        >>> starttime(os.getppid()) <= starttime(os.getpid())
258
        True
259
    """
260
    return psutil.Process(pid).create_time() - psutil.boot_time()
1✔
261

262
def status(pid):
1✔
263
    """status(pid) -> dict
264

265
    Get the status of a process.
266

267
    Arguments:
268
        pid (int): PID of the process.
269

270
    Returns:
271
        The contents of ``/proc/<pid>/status`` as a dictionary.
272
    """
273
    out = {}
1✔
274
    try:
1✔
275
        with open('/proc/%d/status' % pid) as fd:
1✔
276
            for line in fd:
1✔
277
                if ':' not in line:
1!
278
                    continue
×
279
                i = line.index(':')
1✔
280
                key = line[:i]
1✔
281
                val = line[i + 2:-1] # initial :\t and trailing \n
1✔
282
                out[key] = val
1✔
283
    except OSError as e:
×
284
        if e.errno == errno.ENOENT:
×
285
            raise ValueError('No process with PID %d' % pid)
×
286
        else:
287
            raise
×
288
    return out
1✔
289

290
def tracer(pid):
1✔
291
    """tracer(pid) -> int
292

293
    Arguments:
294
        pid (int): PID of the process.
295

296
    Returns:
297
        PID of the process tracing `pid`, or None if no `pid` is not being traced.
298

299
    Example:
300
        >>> tracer(os.getpid()) is None
301
        True
302
    """
303
    tpid = int(status(pid)['TracerPid'])
1✔
304
    return tpid if tpid > 0 else None
1✔
305

306
def state(pid):
1✔
307
    """state(pid) -> str
308

309
    Arguments:
310
        pid (int): PID of the process.
311

312
    Returns:
313
        State of the process as listed in ``/proc/<pid>/status``.  See `proc(5)` for details.
314

315
    Example:
316
        >>> state(os.getpid())
317
        'R (running)'
318
    """
319
    return status(pid)['State']
1✔
320

321
def wait_for_debugger(pid, debugger_pid=None):
1✔
322
    """wait_for_debugger(pid, debugger_pid=None) -> None
323

324
    Sleeps until the process with PID `pid` is being traced.
325
    If debugger_pid is set and debugger exits, raises an error.
326

327
    Arguments:
328
        pid (int): PID of the process.
329

330
    Returns:
331
        None
332
    """
333
    t = Timeout()
1✔
334
    with t.countdown(timeout=15):
1✔
335
        with log.waitfor('Waiting for debugger') as l:
1✔
336
            while t.timeout and tracer(pid) is None:
1✔
337
                if debugger_pid:
1!
338
                    debugger = psutil.Process(debugger_pid)
1✔
339
                    try:
1✔
340
                        debugger.wait(0.01)
1✔
341
                    except psutil.TimeoutExpired:
1✔
342
                        pass
1✔
343
                    else:
344
                        debugger_pid = 0
×
345
                        break
×
346
                else:
347
                    time.sleep(0.01)
×
348

349
            if tracer(pid):
1!
350
                l.success()
1✔
351
            elif debugger_pid == 0:
×
352
                l.failure("debugger exited! (maybe check /proc/sys/kernel/yama/ptrace_scope)")
×
353
            else:
354
                l.failure('Debugger did not attach to pid %d within 15 seconds', pid)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc