Regression: gdb.debug fails with command-lines containing whitespaces
Hi,
As shown below, #2377 introduced a regression. Also of interest regarding the change is the last workaround below.
Since fish is known to conflict with gdb in various ways, maybe revert the change and force a SHELL=/bin/sh environment; or flat out inform users that fish isn't supported.
from pwn import *
io = gdb.debug(['/bin/ls', ' '])
io.interactive()
Output
[+] Starting local process '/bin/gdbserver': pid 2333898
[*] Process '/bin/gdbserver' stopped with exit code 1 (pid 2333898)
[ERROR] gdbserver did not output its pid (maybe chmod +x?): b"can't handle command-line argument containing whitespace\n"
Traceback (most recent call last):
File "/home/<redacted>/opt/virtualenvs/pwn/lib/python3.11/site-packages/pwnlib/gdb.py", line 386, in _gdbserver_port
gdbserver.pid = int(process_created.split()[-1], 0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: invalid literal for int() with base 0: b'whitespace'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/<redacted>/src/phoenix/amd64/heap0/s.py", line 3, in <module>
io = gdb.debug(['/bin/ls', ' '])
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/<redacted>/opt/virtualenvs/pwn/lib/python3.11/site-packages/pwnlib/context/__init__.py", line 1690, in setter
return function(*a, **kw)
^^^^^^^^^^^^^^^^^^
File "/home/<redacted>/opt/virtualenvs/pwn/lib/python3.11/site-packages/pwnlib/gdb.py", line 702, in debug
gdb_port = _gdbserver_port(gdbserver, ssh)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/<redacted>/opt/virtualenvs/pwn/lib/python3.11/site-packages/pwnlib/gdb.py", line 388, in _gdbserver_port
log.error('gdbserver did not output its pid (maybe chmod +x?): %r', process_created)
File "/home/<redacted>/opt/virtualenvs/pwn/lib/python3.11/site-packages/pwnlib/log.py", line 439, in error
raise PwnlibException(message % args)
pwnlib.exception.PwnlibException: gdbserver did not output its pid (maybe chmod +x?): b"can't handle command-line argument containing whitespace\n"
Workarounds
- Revert the patch
- Prevent entering the
elsebranch:gdb.debug(args, env={'a': 'b'})
Ah, damn. Reverting is the way then. We have an error message suggesting setting the SHELL variable if gdbserver hangs now, which should help people running into this.
We can think of adding the environment variable automatically if we detect /bin/sh to point to fish and SHELL pointing to next? @k4lizen I don't like that we'd magically change the environment.
@antifob Thanks for investigating it! Btw, is there a usecase for passing whitespace in a command line argument like that?
So the problem boils down to the fact that starting gdbserver like this works:
['/usr/bin/gdbserver', '--multi', '--no-disable-randomization', 'localhost:0', bytearray(b'/bin/ls'), bytearray(b' ')]
and also this works
['/usr/bin/gdbserver', '--multi', '--no-disable-randomization', '--wrapper', '/usr/bin/env', '-i', b'a=b', '--', 'localhost:0', bytearray(b'/bin/ls'), bytearray(b' ')]
while starting it like this doesn't
['/usr/bin/gdbserver', '--multi', '--no-disable-randomization', '--no-startup-with-shell', 'localhost:0', bytearray(b'/bin/ls'), bytearray(b' ')]
and gdbserver reports the can't handle command-line argument containing whitespace\n error.
@peace-maker I don't understand why gdbserver is fine with whitespace sometimes and not at other times, maybe it should be reported to them?
We can think of adding the environment variable automatically if we detect /bin/sh to point to fish and SHELL pointing to next?
What? You mean "if we detect SHELL pointing to fish"?
I don't like that we'd magically change the environment.
We could print an informational message about it.
is there a usecase for passing whitespace in a command line argument like that?
In this case, I was working on a payload passed via a command-line argument that contained a whitespace.
[...] starting gdbserver like this works: [...]
Although it looks weird, the first one appears a better choice.
maybe it should be reported to them?
It appears to be related to this ticket: https://sourceware.org/bugzilla/show_bug.cgi?id=28392 Source: https://github.com/bminor/binutils-gdb/blob/5524062fadf58b8895abc9b0d30c25dd2591df23/gdb/testsuite/gdb.base/inferior-args.exp#L181
@antifob Thanks for investigating it! Btw, is there a usecase for passing whitespace in a command line argument like that?
I have the same issue. I have whitespaces in my arguments, but they are properly escaped.
Consider ls -hal or ls -h -a -l, of which both work just fine.
Same with ls -hal some-path.
BUT
ls -hal "path with whitespaces"
causes the exception. That's just weird. One could argue that this is a shortcoming of gdb. Still, I find it disturbing, that removing the patch mentioned above, does not cause that trouble.
Minimal example:
cd /tmp
mkdir humble_path
mkdir "path with spaces"
#
python3 - << EOF
from pwn import *
with process([b'/usr/bin/gdbserver', b'--multi', b'--no-disable-randomization', b'--no-startup-with-shell', b'localhost:0', b'ls', b'-hal', b'"path with whitespaces"']) as io:
print(io.recv())
EOF
# prints b"can't handle command-line argument containing whitespace\nExiting\n"
# now without '--no-startup-with-shell'
python3 - << EOF
from pwn import *
with process([b'/usr/bin/gdbserver', b'--multi', b'--no-disable-randomization', b'localhost:0', b'ls', b'-hal', b'"path with whitespaces"']) as io:
print(io.recv())
EOF
# just works fine...
# and so does any other path of course
python3 - << EOF
from pwn import *
with process([b'/usr/bin/gdbserver', b'--multi', b'--no-disable-randomization', b'--no-startup-with-shell', b'localhost:0', b'ls', b'-hal', b'humble_path']) as io:
print(io.recv())
EOF
#
rm humble_path
rm "path with spaces"