Skip to content

Commit

Permalink
Fix attaching to a gdbserver with tuple `gdb.attach(('0.0.0.0',12345)…
Browse files Browse the repository at this point in the history
…)` (#2291)

* Patch for #issues/2290

* Return listening process on `pidof(("0.0.0.0", 1234))`

Instead of returning the process which is connected to port 1234,
return the process which is listening on that port.

* Update CHANGELOG

---------

Co-authored-by: Peace-Maker <peacemakerctf@gmail.com>
  • Loading branch information
ckxckx and peace-maker authored Oct 28, 2024
1 parent 61804b1 commit 51cbdb4
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ The table below shows which release corresponds to each branch, and what date th
- [#2482][2482] Throw error when using `sni` and setting `server_hostname` manually in `remote`
- [#2478][2478] libcdb-cli: add `--offline-only`, refactor unstrip and add fetch parser for download libc-database
- [#2484][2484] Allow to disable caching
- [#2291][2291] Fix attaching to a gdbserver with tuple `gdb.attach(('0.0.0.0',12345))`

[2471]: https://github.com/Gallopsled/pwntools/pull/2471
[2358]: https://github.com/Gallopsled/pwntools/pull/2358
Expand All @@ -96,6 +97,7 @@ The table below shows which release corresponds to each branch, and what date th
[2482]: https://github.com/Gallopsled/pwntools/pull/2482
[2478]: https://github.com/Gallopsled/pwntools/pull/2478
[2484]: https://github.com/Gallopsled/pwntools/pull/2484
[2291]: https://github.com/Gallopsled/pwntools/pull/2291

## 4.14.0 (`beta`)

Expand Down
26 changes: 26 additions & 0 deletions pwnlib/gdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,8 @@ def attach(target, gdbscript = '', exe = None, gdb_args = None, ssh = None, sysr
Process name. The youngest process is selected.
:obj:`tuple`
Host, port pair of a listening ``gdbserver``
Tries to look up the target exe from the ``gdbserver`` commandline,
requires explicit ``exe`` argument if the target exe is not in the commandline.
:class:`.process`
Process to connect to
:class:`.sock`
Expand Down Expand Up @@ -1034,6 +1036,30 @@ def attach(target, gdbscript = '', exe = None, gdb_args = None, ssh = None, sysr
>>> io.sendline(b'echo Hello from bash && exit')
>>> io.recvall()
b'Hello from bash\n'
>>> server.close()
Attach to a gdbserver / gdbstub running on the local machine
by specifying the host and port tuple it is listening on.
(gdbserver always listens on 0.0.0.0)
>>> gdbserver = process(['gdbserver', '1.2.3.4:12345', '/bin/bash'])
>>> gdbserver.recvline_contains(b'Listening on port', timeout=10)
b'Listening on port 12345'
>>> pid = gdb.attach(('0.0.0.0', 12345), gdbscript='''
... tbreak main
... commands
... call puts("Hello from gdbserver debugger!")
... continue
... end
... ''')
>>> gdbserver.recvline(timeout=10) # doctest: +ELLIPSIS
b'Remote debugging from host 127.0.0.1, ...\n'
>>> gdbserver.recvline(timeout=10)
b'Hello from gdbserver debugger!\n'
>>> gdbserver.sendline(b'echo Hello from bash && exit')
>>> gdbserver.recvline(timeout=10)
b'Hello from bash\n'
>>> gdbserver.close()
Attach to processes running on a remote machine via an SSH :class:`.ssh` process
Expand Down
12 changes: 6 additions & 6 deletions pwnlib/util/net.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,17 +259,17 @@ def sockinfos(addr, f, t):
infos |= set(socket.getaddrinfo(sockaddr[0], sockaddr[1], socket.AF_INET6, t, proto, socket.AI_V4MAPPED))
return infos

if local is not None:
local = sockinfos(local, fam, typ)
remote = sockinfos(remote, fam, typ)
local = sockinfos(local, fam, typ)
if remote is not None:
remote = sockinfos(remote, fam, typ)

def match(c):
laddrs = sockinfos(c.laddr, c.family, c.type)
raddrs = sockinfos(c.raddr, c.family, c.type)
if not (raddrs & remote):
if not (laddrs & local):
return False
if local is None:
if remote is None:
return True
return bool(laddrs & local)
return bool(raddrs & remote)

return match
9 changes: 7 additions & 2 deletions pwnlib/util/proc.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ def pidof(target):
- :class:`pwnlib.tubes.sock.sock`: singleton list of the PID at the
remote end of `target` if it is running on the host. Otherwise an
empty list.
- :class:`pwnlib.tubes.ssh.ssh_channel`: singleton list of the PID of
`target` on the remote system.
- :class:`tuple`: singleton list of the PID at the local end of the
connection to `target` if it is running on the host. Otherwise an
empty list.
Arguments:
target(object): The target whose PID(s) to find.
Expand All @@ -38,7 +43,7 @@ def pidof(target):
>>> l = tubes.listen.listen()
>>> p = process(['curl', '-s', 'http://127.0.0.1:%d'%l.lport])
>>> pidof(p) == pidof(l) == pidof(('127.0.0.1', l.lport))
>>> pidof(p) == pidof(l) == pidof(('127.0.0.1', l.rport))
True
"""
if isinstance(target, tubes.ssh.ssh_channel):
Expand All @@ -51,7 +56,7 @@ def pidof(target):
return [c.pid for c in psutil.net_connections() if match(c)]

elif isinstance(target, tuple):
match = sock_match(None, target)
match = sock_match(target, None)
return [c.pid for c in psutil.net_connections() if match(c)]

elif isinstance(target, tubes.process.process):
Expand Down

0 comments on commit 51cbdb4

Please sign in to comment.