Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'dev' into allow_new_file_format
- Loading branch information
Showing
9 changed files
with
574 additions
and
481 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,108 +1,98 @@ | ||
## Command gef-remote ## | ||
## Command `gef-remote` | ||
|
||
It is possible to use `gef` in a remote debugging environment. Required files | ||
will be automatically downloaded and cached in a temporary directory (`/tmp/gef` | ||
on most Unix systems). Remember to manually delete the cache if you change the | ||
target file or `gef` will use the outdated version. | ||
[`target remote`](https://sourceware.org/gdb/onlinedocs/gdb/Remote-Debugging.html#Remote-Debugging) is the traditional GDB way of debugging process or system remotely. However this command by itself does a limited job (80's bandwith FTW) to collect more information about the target, making the process of debugging more cumbersome. GEF greatly improves that state with the `gef-remote` command. | ||
|
||
### With a local copy ### | ||
📝 **Note**: If using GEF, `gef-remote` **should** be your way or debugging remote processes. Maintainers will not provide support or help if you decide to use the traditional `target remote` command. | ||
|
||
If you want to remotely debug a binary that you already have, you simply need to | ||
tell to `gdb` where to find the debug information. | ||
`gef-remote` can function in 2 ways: | ||
- `remote` which is meant to enrich use of GDB `target remote` command, when connecting to a "real" gdbserver instance | ||
- `qemu-mode` when connecting to GDB stab of either `qemu-user` or `qemu-system`. | ||
|
||
The reason for this difference being that Qemu provides *a lot* less information that GEF can extract to enrich debugging. Whereas GDBServer allows to download remote file (therefore allowing to create a small identical environment), GDB stub in Qemu does not support file transfer. As a consequence, in order to use GEF in qemu mode, it is required to provide the binary being debugged. GEF will create a mock (limited) environment so that all its most useful features are available. | ||
|
||
### Remote mode | ||
|
||
#### `remote` | ||
|
||
If you want to remotely debug a binary that you already have, you simply need to tell to `gdb` where to find the debug information. | ||
|
||
For example, if we want to debug `uname`, we do on the server: | ||
|
||
``` | ||
$ gdbserver 0.0.0.0:1234 /bin/uname | ||
Process /bin/uname created; pid = 32280 | ||
$ gdbserver :1234 /tmp/default.out | ||
Process /tmp/default.out created; pid = 258932 | ||
Listening on port 1234 | ||
``` | ||
|
||
![](https://i.imgur.com/Zc4vnBd.png) | ||
![gef-remote-1](https://i.imgur.com/Zc4vnBd.png) | ||
|
||
And on the client, simply run `gdb`: | ||
On the client, when the original `gdb` would use `target remote`, GEF's syntax is roughly similar (shown running in debug mode for more verbose output, but you don't have to): | ||
|
||
``` | ||
$ gdb /bin/uname | ||
gef➤ target remote 192.168.56.1:1234 | ||
Process /bin/uname created; pid = 10851 | ||
Listening on port 1234 | ||
$ gdb -ex 'gef config gef.debug 1' | ||
GEF for linux ready, type `gef' to start, `gef config' to configure | ||
90 commands loaded and 5 functions added for GDB 10.2 using Python engine 3.8 | ||
gef➤ gef-remote localhost 1234 | ||
[=] [remote] initializing remote session with localhost:1234 under /tmp/tmp8qd0r7iw | ||
[=] [remote] Installing new objfile handlers | ||
[=] [remote] Enabling extended remote: False | ||
[=] [remote] Executing 'target remote localhost:1234' | ||
Reading /tmp/default.out from remote target... | ||
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead. | ||
Reading /tmp/default.out from remote target... | ||
Reading symbols from target:/tmp/default.out... | ||
[=] [remote] in remote_objfile_handler(target:/tmp/default.out)) | ||
[=] [remote] downloading '/tmp/default.out' -> '/tmp/tmp8qd0r7iw/tmp/default.out' | ||
Reading /lib64/ld-linux-x86-64.so.2 from remote target... | ||
Reading /lib64/ld-linux-x86-64.so.2 from remote target... | ||
[=] [remote] in remote_objfile_handler(/usr/lib/debug/.build-id/45/87364908de169dec62ffa538170118c1c3a078.debug)) | ||
[=] [remote] in remote_objfile_handler(target:/lib64/ld-linux-x86-64.so.2)) | ||
[=] [remote] downloading '/lib64/ld-linux-x86-64.so.2' -> '/tmp/tmp8qd0r7iw/lib64/ld-linux-x86-64.so.2' | ||
[=] [remote] in remote_objfile_handler(system-supplied DSO at 0x7ffff7fcd000)) | ||
[*] [remote] skipping 'system-supplied DSO at 0x7ffff7fcd000' | ||
0x00007ffff7fd0100 in _start () from target:/lib64/ld-linux-x86-64.so.2 | ||
[=] Setting up as remote session | ||
[=] [remote] downloading '/proc/258932/maps' -> '/tmp/tmp8qd0r7iw/proc/258932/maps' | ||
[=] [remote] downloading '/proc/258932/environ' -> '/tmp/tmp8qd0r7iw/proc/258932/environ' | ||
[=] [remote] downloading '/proc/258932/cmdline' -> '/tmp/tmp8qd0r7iw/proc/258932/cmdline' | ||
[...] | ||
``` | ||
|
||
Or | ||
And finally breaking into the program, showing the current context: | ||
|
||
``` | ||
$ gdb | ||
gef➤ file /bin/uname | ||
gef➤ target remote 192.168.56.1:1234 | ||
``` | ||
![gef-remote](https://i.imgur.com/IfsRDvK.png) | ||
|
||
### Without a local copy ### | ||
You will also notice the prompt has changed to indicate the debugging mode is now "remote". Besides that, all of GEF features are available: | ||
|
||
It is possible to use `gdb` internal functions to copy our targeted binary. | ||
![gef-remote-command](https://i.imgur.com/05epyX6.png) | ||
|
||
Following our previous example, if we want to debug `uname`, run `gdb` and | ||
connect to our `gdbserver`. To be able to locate the right process in the | ||
`/proc` structure, the command `gef-remote` requires 1 argument, the target | ||
host and port. The option `--pid` must be provided and indicate the process | ||
PID on the remote host, only if the extended mode (`--is-extended-remote`) | ||
is being used. | ||
|
||
``` | ||
$ gdb | ||
gef➤ gef-remote 192.168.56.1:1234 | ||
[+] Connected to '192.168.56.1:1234' | ||
[+] Downloading remote information | ||
[+] Remote information loaded, remember to clean '/tmp/gef/10851' when your session is over | ||
``` | ||
#### `remote-extended` | ||
|
||
As you can observe, if it cannot find the debug information, `gef` will try to | ||
automatically download the target file and store in the local temporary | ||
directory (on most Unix `/tmp`). If successful, it will then automatically load | ||
the debug information to `gdb` and proceed with the debugging. | ||
Extended mode works the same as `remote`. Being an extended session, gdbserver has not spawned or attached to any process. Therefore, all that's required is to add the `--pid` flag when calling `gef-remote`, along with the process ID of the process to debug. | ||
|
||
![gef-remote-autodownload](https://i.imgur.com/nLtvCxP.png) | ||
|
||
You can then reuse the downloaded file for your future debugging sessions, use | ||
it under IDA and such. This makes the entire remote debugging process | ||
(particularly for Android applications) a child's game. | ||
### Qemu mode | ||
|
||
### Handling remote libraries ### | ||
Qemu mode of `gef-remote` allows to connect to the [Qemu GDB stub](https://qemu-project.gitlab.io/qemu/system/gdb.html) which allows to live debug into either a binary (`qemu-user`) or even the kernel (`qemu-system`), of any architecture supported by GEF, which makes now even more sense 😉 And using it is very straight forward. | ||
|
||
Often times you are missing a specific library the remote process is using. | ||
To remedy this `gef-remote` can download remote libraries (and other files) if | ||
the remote target supports it (and the remote gdbserver has sufficient | ||
permissions). The `--download-lib LIBRARY` option can download a remote file | ||
specified by its filepath. Furthermore `--download-everything` downloads all | ||
remote libs found in the process's virtual memory map (`vmmap`). | ||
#### `qemu-user` | ||
|
||
Another issue with libraries is that even if you have the same libraries that | ||
are used remotely they might have different filepaths and GDB can't | ||
automatically find them and thereby can't resolve their symbols. The option | ||
`--update-solib` adds the previously (with `--dowload-everything`) downloaded | ||
libraries to the solib path so GDB can take full advantage of their symbols. | ||
1. Run `qemu-x86_64 :1234 /bin/ls` | ||
2. Use `--qemu-user` and `--qemu-binary /bin/ls` when starting `gef-remote` | ||
|
||
### QEMU-user mode ### | ||
![qemu-user](https://user-images.githubusercontent.com/590234/175072835-e276ab6c-4f75-4313-9e66-9fe5a3fd220e.png) | ||
|
||
Although GDB through QEMU-user works, QEMU only supports a limited subset of all | ||
commands existing in the `gdbremote` protocol. For example, commands such as | ||
`remote get` or `remote put` (to download and upload a file from remote target, | ||
respectively) are not supported. As a consequence, the default `remote` mode | ||
for `gef` will not work either, as `gef` won't be able to fetch the content of | ||
the remote procfs. | ||
|
||
To circumvent this and still enjoy `gef` features with QEMU-user, a simple stub | ||
can be artificially added, with the option `--qemu-mode` option of `gef-remote`. | ||
Note that you need to set the architecture to match the target binary first: | ||
|
||
``` | ||
$ qemu-arm -g 1234 ./my/arm/binary | ||
$ gdb-multiarch ./my/arm/binary | ||
gef➤ set architecture arm | ||
gef➤ gef-remote --qemu-mode localhost:1234 | ||
``` | ||
#### `qemu-system` | ||
|
||
To test locally, you can use the mini image linux x64 vm [here](https://mega.nz/file/ldQCDQiR#yJWJ8RXAHTxREKVmR7Hnfr70tIAQDFeWSYj96SvPO1k). | ||
1. Run `./run.sh` | ||
2. Use `--qemu-user` and `--qemu-binary vmlinuz` when starting `gef-remote` | ||
|
||
|
||
![qemu-system](https://user-images.githubusercontent.com/590234/175071351-8e06aa27-dc61-4fd7-9215-c345dcebcd67.png) | ||
|
||
|
||
![gef-qemu-user](https://i.imgur.com/A0xgEdR.png) | ||
|
||
When debugging a process in QEMU both the memory map of QEMU and of the process | ||
are being shown alongside. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.