├── docs ├── requirements.txt ├── commands │ ├── help.md │ ├── reset-cache.md │ ├── xfiles.md │ ├── patch.md │ ├── ropper.md │ ├── canary.md │ ├── nop.md │ ├── is-syscall.md │ ├── memory.md │ ├── vmmap.md │ ├── aslr.md │ ├── got.md │ ├── assemble.md │ ├── xinfo.md │ ├── ksymaddr.md │ ├── elf-info.md │ ├── capstone-disassemble.md │ ├── trace-run.md │ ├── tmux-setup.md │ ├── entry-break.md │ ├── edit-flags.md │ ├── format-string-helper.md │ ├── checksec.md │ ├── hijack-fd.md │ ├── process-status.md │ ├── stub.md │ ├── scan.md │ ├── print-format.md │ ├── shellcode.md │ ├── config.md │ ├── xor-memory.md │ ├── functions.md │ ├── eval.md │ ├── unicorn-emulate.md │ ├── set-permission.md │ ├── theme.md │ ├── search-pattern.md │ ├── highlight.md │ ├── registers.md │ ├── pattern.md │ ├── hexdump.md │ ├── ida-interact.md │ ├── name-break.md │ ├── syscall-args.md │ ├── process-search.md │ ├── aliases.md │ ├── pie.md │ ├── dereference.md │ ├── heap-analysis-helper.md │ ├── gef-remote.md │ ├── heap.md │ ├── pcustom.md │ └── context.md ├── screenshots.md ├── config.md ├── commands.md ├── api.md ├── index.md └── faq.md ├── .readthedocs.yml ├── tests ├── binaries │ ├── default.c │ ├── checksec-no-nx.c │ ├── checksec-no-pie.c │ ├── checksec-no-canary.c │ ├── bss.c │ ├── heap.c │ ├── heap-analysis.c │ ├── canary.c │ ├── pattern.c │ ├── format-string-helper.c │ ├── heap-non-main.c │ ├── heap-fastbins.c │ ├── set-permission.c │ └── Makefile ├── run-remote.sh ├── perf │ └── context_times.sh ├── helpers.py └── runtests.py ├── scripts └── compile_gdb_py2.sh ├── LICENSE ├── .gitignore ├── README.md └── mkdocs.yml /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs==1.0.4 -------------------------------------------------------------------------------- /docs/commands/help.md: -------------------------------------------------------------------------------- 1 | ## Command help ## 2 | 3 | Displays the help menu for the commands loaded. 4 | 5 | ![help](https://i.imgur.com/cvMoI3P.png) 6 | -------------------------------------------------------------------------------- /docs/commands/reset-cache.md: -------------------------------------------------------------------------------- 1 | ## Command reset-cache 2 | 3 | This is an obsolete function to reset GEF internal memoize cache, which does not 4 | need to be called from the command line anymore. 5 | 6 | This command will disappear soon... 7 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | mkdocs: 4 | configuration: mkdocs.yml 5 | fail_on_warning: true 6 | 7 | formats: all 8 | 9 | build: 10 | image: latest 11 | 12 | python: 13 | version: 3.7 14 | install: 15 | - requirements: docs/requirements.txt 16 | -------------------------------------------------------------------------------- /docs/commands/xfiles.md: -------------------------------------------------------------------------------- 1 | ## Command xfiles ## 2 | 3 | `xfiles` is a more convenient representation of the GDB native command, `info 4 | files` allowing you to filter by pattern given in argument. For example, if you 5 | only want to show the code sections (i.e. `.text`): 6 | 7 | ![xfiles-example](http://i.imgur.com/lelnJ5B.png) 8 | -------------------------------------------------------------------------------- /tests/binaries/default.c: -------------------------------------------------------------------------------- 1 | /** 2 | * default.c 3 | * -*- mode: c -*- 4 | * -*- coding: utf-8 -*- 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | int main(int argc, char** argv, char** envp) 13 | { 14 | printf("Hello World!\n"); 15 | return EXIT_SUCCESS; 16 | } 17 | -------------------------------------------------------------------------------- /docs/commands/patch.md: -------------------------------------------------------------------------------- 1 | ## Command patch ## 2 | 3 | Patch the specified values to the specified address. 4 | 5 | This command is automatically aliased to the standard WinDBG commands: `eb`, 6 | `ew`, `ed`, `eq`, and `ea`. 7 | 8 | ```bash 9 | gef➤ patch byte $eip 0x90 10 | gef➤ eb 0x8048000 0x41 11 | gef➤ ea 0xbffffd74 "This is a double-escaped string\\x00" 12 | ``` 13 | 14 | -------------------------------------------------------------------------------- /docs/commands/ropper.md: -------------------------------------------------------------------------------- 1 | ## Command ropper 2 | 3 | `ropper` is a gadget finding tool, easily installable via `pip`. It provides a 4 | very convenient `--search` function to search gadgets from a regular 5 | expression: 6 | 7 | ![ropper](https://pbs.twimg.com/media/Cm4f4i5VIAAP-E2.jpg:large) 8 | 9 | `ropper` comes with a full set of options, all documented from the `--help` menu. 10 | -------------------------------------------------------------------------------- /tests/binaries/checksec-no-nx.c: -------------------------------------------------------------------------------- 1 | /** 2 | * -*- mode: c -*- 3 | * -*- coding: utf-8 -*- 4 | * 5 | * checksec-no-canary.c 6 | * 7 | * @author: @_hugsy_ 8 | * @licence: WTFPL v.2 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | int main(int argc, char** argv, char** envp) 18 | { 19 | return EXIT_SUCCESS; 20 | } 21 | -------------------------------------------------------------------------------- /tests/binaries/checksec-no-pie.c: -------------------------------------------------------------------------------- 1 | /** 2 | * -*- mode: c -*- 3 | * -*- coding: utf-8 -*- 4 | * 5 | * checksec-no-pie.c 6 | * 7 | * @author: @_hugsy_ 8 | * @licence: WTFPL v.2 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | int main(int argc, char** argv, char** envp) 18 | { 19 | return EXIT_SUCCESS; 20 | } 21 | -------------------------------------------------------------------------------- /tests/binaries/checksec-no-canary.c: -------------------------------------------------------------------------------- 1 | /** 2 | * -*- mode: c -*- 3 | * -*- coding: utf-8 -*- 4 | * 5 | * checksec-no-canary.c 6 | * 7 | * @author: @_hugsy_ 8 | * @licence: WTFPL v.2 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | int main(int argc, char** argv, char** envp) 18 | { 19 | return EXIT_SUCCESS; 20 | } 21 | -------------------------------------------------------------------------------- /scripts/compile_gdb_py2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | sudo apt update 6 | sudo apt install build-essential libncurses5-dev texinfo -y 7 | cd /tmp 8 | curl http://ftp.gnu.org/gnu/gdb/gdb-7.12.1.tar.gz | tar xzf - 9 | cd gdb-7.12.1 10 | ./configure --prefix=/opt --with-python=python2 11 | make all 12 | sudo make install 13 | 14 | echo 15 | echo "[+] gdb+py2 can be found as /opt/bin/gdb" 16 | echo 17 | 18 | exit 0 -------------------------------------------------------------------------------- /tests/binaries/bss.c: -------------------------------------------------------------------------------- 1 | /** 2 | * default.c 3 | * -*- mode: c -*- 4 | * -*- coding: utf-8 -*- 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | char msg[0x100]; 13 | 14 | int main(int argc, char** argv, char** envp) 15 | { 16 | strncpy(msg, "Hello world!", sizeof(msg)); 17 | __asm__ volatile("int3;" : : : ); 18 | return EXIT_SUCCESS; 19 | } 20 | -------------------------------------------------------------------------------- /tests/binaries/heap.c: -------------------------------------------------------------------------------- 1 | /** 2 | * -*- mode: c -*- 3 | * -*- coding: utf-8 -*- 4 | * 5 | * heap.c 6 | * 7 | * @author: @_hugsy_ 8 | * @licence: WTFPL v.2 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | int main(int argc, char** argv, char** envp) 18 | { 19 | void* p1 = malloc(0x20); 20 | __asm__ volatile("int3;" : : : ); 21 | (void)p1; 22 | return EXIT_SUCCESS; 23 | } 24 | -------------------------------------------------------------------------------- /docs/commands/canary.md: -------------------------------------------------------------------------------- 1 | ## Command canary ## 2 | 3 | If the currently debugged process was compiled with the Smash Stack Protector 4 | (SSP) - i.e. the `-fstack-protector` flag was passed to the compiler, this 5 | command will display the value of the canary. This makes it convenient to avoid 6 | manually searching for this value in memory. 7 | 8 | The command `canary` does not take any arguments. 9 | ``` 10 | gef➤ canary 11 | ``` 12 | 13 | ![gef-canary](https://i.imgur.com/kPmsod2.png) 14 | -------------------------------------------------------------------------------- /docs/commands/nop.md: -------------------------------------------------------------------------------- 1 | ## Command nop ## 2 | 3 | The `nop` command allows you to easily skip instructions. 4 | 5 | ``` 6 | gef➤ nop [-b NUM_BYTES] [-h] [LOCATION] 7 | ``` 8 | 9 | `LOCATION` indicates the address of the instruction to bypass. If not 10 | specified, it will use the current value of the program counter. 11 | 12 | If `-b ` is entered, gef will explicitly patch the specified number of 13 | bytes. Otherwise it will patch the _whole_ instruction at the target location. 14 | -------------------------------------------------------------------------------- /docs/commands/is-syscall.md: -------------------------------------------------------------------------------- 1 | ## Command is-syscall ## 2 | 3 | `gef` can be used to determine whether the instruction to be executed next is a system call. 4 | 5 | To use it, simply run 6 | ``` 7 | gef➤ is-syscall 8 | ``` 9 | 10 | If it is a system call, 11 | ``` 12 | gef➤ is-syscall 13 | [+] Current instruction is a syscall 14 | ``` 15 | 16 | Check this asciicast for visual example: 17 | [![asciicast](https://asciinema.org/a/FU11vmLtlYVBgRhKLaqSPd4Od.png)](https://asciinema.org/a/FU11vmLtlYVBgRhKLaqSPd4Od) 18 | -------------------------------------------------------------------------------- /docs/commands/memory.md: -------------------------------------------------------------------------------- 1 | ## Command memory ## 2 | 3 | As long as the 'memory' section is enabled in your context layout (which it is 4 | by default), you can register addresses, lengths, and grouping size. 5 | 6 | ![memory watch](http://i.imgur.com/NXYwSwW.png) 7 | 8 | ### Adding a watch 9 | `memory watch
[SIZE] [(qword|dword|word|byte)]` 10 | 11 | ### Removing a watch 12 | `memory unwatch
` 13 | 14 | ### Listing watches 15 | `memory list` 16 | 17 | ### Clearing watches 18 | `memory clear` 19 | 20 | -------------------------------------------------------------------------------- /tests/binaries/heap-analysis.c: -------------------------------------------------------------------------------- 1 | /** 2 | * -*- mode: c -*- 3 | * -*- coding: utf-8 -*- 4 | * 5 | * heap-analysis.c 6 | * 7 | * @author: @Grazfather 8 | * @licence: WTFPL v.2 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | int main(int argc, char** argv, char** envp) 15 | { 16 | void* p1 = malloc(0x10); 17 | void* p2 = calloc(0x20, 1); 18 | memset(p1, 'A', 0x10); 19 | memset(p2, 'B', 0x20); 20 | p1 = realloc(p1, 0x30); 21 | free(p2); 22 | return EXIT_SUCCESS; 23 | } 24 | -------------------------------------------------------------------------------- /tests/binaries/canary.c: -------------------------------------------------------------------------------- 1 | /** 2 | * canary.c 3 | * -*- mode: c -*- 4 | * -*- coding: utf-8 -*- 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | void greetz(char* buf) 15 | { 16 | char name[8] = {0,}; 17 | strcpy(name, buf); 18 | printf("Hello %s\n", name); 19 | } 20 | 21 | 22 | int main(int argc, char** argv, char** envp) 23 | { 24 | if(argc < 2) 25 | return EXIT_FAILURE; 26 | 27 | greetz(argv[1]); 28 | return EXIT_SUCCESS; 29 | } 30 | -------------------------------------------------------------------------------- /tests/binaries/pattern.c: -------------------------------------------------------------------------------- 1 | /** 2 | * pattern.c 3 | * -*- mode: c -*- 4 | * -*- coding: utf-8 -*- 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | void greetz(char* buf) 15 | { 16 | char name[8] = {0,}; 17 | strcpy(name, buf); 18 | printf("Hello %s\n", name); 19 | } 20 | 21 | 22 | int main(int argc, char** argv, char** envp) 23 | { 24 | if(argc < 2) 25 | return EXIT_FAILURE; 26 | 27 | greetz(argv[1]); 28 | return EXIT_SUCCESS; 29 | } 30 | -------------------------------------------------------------------------------- /tests/binaries/format-string-helper.c: -------------------------------------------------------------------------------- 1 | /** 2 | * bof.c 3 | * -*- mode: c -*- 4 | * -*- coding: utf-8 -*- 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | void greetz(char* buf) 15 | { 16 | char name[256] = {0,}; 17 | strcpy(name, buf); 18 | printf("Hello"); 19 | printf(name); 20 | printf("\n"); 21 | } 22 | 23 | 24 | int main(int argc, char** argv, char** envp) 25 | { 26 | if(argc < 2) 27 | return EXIT_FAILURE; 28 | 29 | greetz(argv[1]); 30 | return EXIT_SUCCESS; 31 | } 32 | -------------------------------------------------------------------------------- /docs/commands/vmmap.md: -------------------------------------------------------------------------------- 1 | ## Command vmmap ## 2 | 3 | `vmmap` displays the entire memory space mapping. 4 | 5 | ![vmmap-example](https://i.imgur.com/iau8SwS.png) 6 | 7 | Interestingly, it helps finding secret gems: as an aware reader might have 8 | seen, memory mapping differs from one architecture to another (this is one of 9 | the main reasons I started `GEF` in a first place). For example, you can learn 10 | that ELF running on SPARC architectures always have their `.data` and `heap` 11 | sections set as Read/Write/Execute. 12 | 13 | `vmmap` accepts one argument, a pattern to grep interesting results: 14 | 15 | ![vmmap-grep](http://i.imgur.com/ZFF4QVf.png) 16 | -------------------------------------------------------------------------------- /docs/commands/aslr.md: -------------------------------------------------------------------------------- 1 | ## Command aslr ## 2 | 3 | Easily check, enable or disable ASLR on the debugged binary. 4 | 5 | Check the status: 6 | ``` 7 | gef➤ aslr 8 | ASLR is currently disabled 9 | ``` 10 | 11 | Activate ASLR: 12 | ``` 13 | gef➤ aslr on 14 | [+] Enabling ASLR 15 | gef➤ aslr 16 | ASLR is currently enabled 17 | ``` 18 | 19 | De-activate ASLR: 20 | ``` 21 | gef➤ aslr off 22 | [+] Disabling ASLR 23 | ``` 24 | 25 | **Note**: This command cannot affect a process that has already been loaded, to 26 | which GDB attached to later. The only way to disable this randomization is by 27 | setting the kernel setting `/proc/sys/kernel/randomize_va_space` to 0.. 28 | -------------------------------------------------------------------------------- /tests/binaries/heap-non-main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * -*- mode: c -*- 3 | * -*- coding: utf-8 -*- 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | void *thread() 11 | { 12 | void* p1 = malloc(0x18); 13 | void* p2 = malloc(0x18); 14 | free(p1); 15 | __asm__ volatile("int3;" : : : ); 16 | (void)p2; 17 | 18 | return NULL; 19 | } 20 | 21 | int main(int argc, char** argv, char** envp) 22 | { 23 | void* p1 = malloc(0x10); 24 | 25 | pthread_t thread1; 26 | pthread_create(&thread1, NULL, thread, NULL); 27 | pthread_join(thread1, NULL); 28 | 29 | (void)p1; 30 | return EXIT_SUCCESS; 31 | } 32 | -------------------------------------------------------------------------------- /docs/commands/got.md: -------------------------------------------------------------------------------- 1 | ## Command got ## 2 | 3 | Display the current state of GOT table of the running process. 4 | 5 | The `got` command optionally takes function names and filters 6 | the output displaying only the matching functions. 7 | ``` 8 | gef➤ got 9 | ``` 10 | 11 | ![gef-got](https://i.imgur.com/554ebM3.png) 12 | 13 | The applied filter partially matches the name of the functions, so 14 | you can do something like this. 15 | ``` 16 | gef➤ got str 17 | gef➤ got print 18 | gef➤ got read 19 | ``` 20 | 21 | ![gef-got-one-filter](https://i.imgur.com/IU715CG.png) 22 | 23 | Example of multiple partial filters: 24 | ``` 25 | gef➤ got str get 26 | ``` 27 | 28 | ![gef-got-multi-filter](https://i.imgur.com/7L2uLt8.png) 29 | -------------------------------------------------------------------------------- /tests/binaries/heap-fastbins.c: -------------------------------------------------------------------------------- 1 | /** 2 | * -*- mode: c -*- 3 | * -*- coding: utf-8 -*- 4 | * 5 | * heap.c 6 | * 7 | * @author: @_hugsy_ 8 | * @licence: WTFPL v.2 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | int main(int argc, char** argv, char** envp) 18 | { 19 | void* p1 = malloc(0x10); 20 | void* p2 = malloc(0x20); 21 | void* p3 = malloc(0x30); 22 | memset(p1, 'A', 0x10); 23 | memset(p2, 'B', 0x20); 24 | memset(p3, 'C', 0x30); 25 | free(p2); 26 | __asm__ volatile("int3;"); 27 | (void)p1; 28 | (void)p3; 29 | return EXIT_SUCCESS; 30 | } 31 | -------------------------------------------------------------------------------- /docs/commands/assemble.md: -------------------------------------------------------------------------------- 1 | ## Command assemble ## 2 | 3 | If you have installed [`keystone`](http://www.keystone-engine.org/), then `gef` will provide 4 | a convenient command to assemble native instructions directly to opcodes of the 5 | architecture you are currently debugging. 6 | 7 | Call it via `assemble` or its alias `asm`: 8 | 9 | ``` 10 | gef➤ asm [INSTRUCTION [; INSTRUCTION ...]] 11 | ``` 12 | 13 | ![gef-assemble](https://i.imgur.com/ShuPF6h.png) 14 | 15 | Using the `-l LOCATION` option, `gef` will write the assembly code generated by 16 | `keystone` directly to the memory location specified. This makes it extremely 17 | convenient to simply overwrite opcodes. 18 | 19 | ![gef-assemble-overwrite](https://i.imgur.com/CvJv36q.png) 20 | -------------------------------------------------------------------------------- /docs/commands/xinfo.md: -------------------------------------------------------------------------------- 1 | ## Command xinfo ## 2 | 3 | `xinfo` displays all the information known to `gef` about the specific address 4 | given as argument: 5 | 6 | ![xinfo-example](https://pbs.twimg.com/media/CCSW9JkW4AAx8gD.png:large) 7 | 8 | **Important note** : For performance reasons, `gef` caches certain results. 9 | `gef` will try to automatically refresh its own cache to avoid relying on 10 | obsolete information of the debugged process. However, in some dodgy scenario, 11 | `gef` might fail detecting some new events making its cache partially obsolete. 12 | If you notice an inconsistency on your memory mapping, you might want to force 13 | `gef` flushing its cache and fetching brand new data, by running the command 14 | `reset-cache`. 15 | -------------------------------------------------------------------------------- /docs/commands/ksymaddr.md: -------------------------------------------------------------------------------- 1 | ## Command ksymaddr ## 2 | 3 | `ksymaddr` helps locate a kernel symbol by its name. 4 | 5 | The syntax is straight forward: 6 | 7 | ``` 8 | ksymaddr 9 | ``` 10 | 11 | For example, 12 | 13 | ``` 14 | gef➤ ksymaddr commit_creds 15 | [+] Found matching symbol for 'commit_creds' at 0xffffffff8f495740 (type=T) 16 | [*] Found partial match for 'commit_creds' at 0xffffffff8f495740 (type=T): commit_creds 17 | [*] Found partial match for 'commit_creds' at 0xffffffff8fc71ee0 (type=R): __ksymtab_commit_creds 18 | [*] Found partial match for 'commit_creds' at 0xffffffff8fc8d008 (type=r): __kcrctab_commit_creds 19 | [*] Found partial match for 'commit_creds' at 0xffffffff8fc9bfcd (type=r): __kstrtab_commit_creds 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/commands/elf-info.md: -------------------------------------------------------------------------------- 1 | ## Command elf-info ## 2 | 3 | `elf-info` (alias `elf`) provides some basic information on the currently 4 | loaded ELF binary: 5 | 6 | ``` 7 | gef➤ elf 8 | Magic : 7f 45 4c 46 9 | Class : 0x2 - 64-bit 10 | Endianness : 0x1 - Little-Endian 11 | Version : 0x1 12 | OS ABI : 0x0 - System V 13 | ABI Version : 0x0 14 | Type : 0x2 - Executable 15 | Machine : 0x3e - x86-64 16 | Program Header Table : 0x0000000000000040 17 | Section Header Table : 0x0000000000000c98 18 | Header Table : 0x0000000000000040 19 | ELF Version : 0x1 20 | Header size : 0 (0x0) 21 | Entry point : 0x0000000000400460 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/commands/capstone-disassemble.md: -------------------------------------------------------------------------------- 1 | ## Command capstone-disassemble ## 2 | 3 | If you have installed the [`capstone`](http://capstone-engine.org) library and 4 | its Python bindings, you can use it to disassemble any memory in your debugging 5 | session. This plugin was created to offer an alternative to `GDB`'s disassemble 6 | function which sometimes gets things mixed up. 7 | 8 | You can use its alias `cs-disassemble` or just `cs` with the location to 9 | disassemble at. If not specified, it will use `$pc`. 10 | 11 | ``` 12 | gef➤ cs main 13 | ``` 14 | 15 | ![cs-disassemble](https://i.imgur.com/wypt7Fo.png) 16 | 17 | Disassemble more instructions 18 | ``` 19 | gef➤ cs length=20 20 | ``` 21 | 22 | Show instructions before $pc 23 | ``` 24 | gef➤ cs nb_prev=3 25 | ``` 26 | -------------------------------------------------------------------------------- /docs/commands/trace-run.md: -------------------------------------------------------------------------------- 1 | ## Command trace-run ## 2 | 3 | The `trace-run` command is meant to be provide a visual appreciation directly 4 | in IDA disassembler of the path taken by a specific execution. It should be 5 | used with the IDA script 6 | [`ida_color_gdb_trace.py`](https://github.com/hugsy/stuff/blob/master/ida_scripts/ida_color_gdb_trace.py) 7 | 8 | It will trace and store all values taken by `$pc` during the execution flow, 9 | from its current value, until the value provided as argument. 10 | 11 | ``` 12 | gef> trace-run 13 | ``` 14 | 15 | ![trace-run-1](https://i.imgur.com/yaOGste.png) 16 | 17 | By using the script `ida_color_gdb_trace.py` on the text file generated, it will 18 | color the path taken: 19 | 20 | ![trace-run-2](http://i.imgur.com/oAGoSMQ.png) 21 | 22 | -------------------------------------------------------------------------------- /tests/binaries/set-permission.c: -------------------------------------------------------------------------------- 1 | /** 2 | * -*- mode: c -*- 3 | * -*- coding: utf-8 -*- 4 | * 5 | * set-permission.c 6 | * 7 | * @author: @_hugsy_ 8 | * @licence: WTFPL v.2 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | int main(int argc, char** argv, char** envp) 18 | { 19 | void *p = mmap((void *)0x1337000, 20 | getpagesize(), 21 | PROT_READ|PROT_WRITE, 22 | MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, 23 | -1, 24 | 0); 25 | 26 | if( p == (void *)-1) 27 | return EXIT_FAILURE; 28 | 29 | __asm__ volatile("int3 ;" : : :); 30 | 31 | return EXIT_SUCCESS; 32 | } 33 | -------------------------------------------------------------------------------- /docs/commands/tmux-setup.md: -------------------------------------------------------------------------------- 1 | ## Command tmux-setup 2 | 3 | In the purpose of always making debugging sessions easier while being more 4 | effective, `GEF` integrates two commands: 5 | 6 | * `tmux-setup` 7 | * `screen-setup` 8 | 9 | Those commands will check whether GDB is being spawn from inside a `tmux` 10 | (resp. `screen`) session, and if so, will split the pane vertically, and 11 | configure the context to be redirected to the new pane, looking something like: 12 | 13 | ![](https://i.imgur.com/Khk3xGl.png) 14 | 15 | To set it up, simply enter 16 | ``` 17 | gef➤ tmux-setup 18 | ``` 19 | 20 | **Note**: Although `screen-setup` provides a similar setup, the structure of 21 | `screen` does not allow a very clean way to do this. Therefore, if possible, it 22 | would be recommended to use the `tmux-setup` command instead. 23 | -------------------------------------------------------------------------------- /docs/commands/entry-break.md: -------------------------------------------------------------------------------- 1 | ## Command entry-break ## 2 | 3 | The `entry-break` (alias `start`) command's goal is to find and break at the 4 | most obvious entry point available in the binary. Since the binary will start 5 | running, some of the `PLT` entries will also be resolved, making further 6 | debugging easier. 7 | 8 | It will perform the following actions: 9 | 10 | 1. Look up a `main` symbol. If found, set a temporary breakpoint and go. 11 | 2. Otherwise, it will look up for `__libc_start_main`. If found, set a 12 | temporary breakpoint and go. 13 | 3. Finally, if the previous two symbols are not found, it will get the entry 14 | point from the ELF header, set a breakpoint and run. This case should never 15 | fail if the ELF binary has a valid structure. 16 | 17 | ![entry-break-example](https://i.imgur.com/zXSERMh.png) 18 | -------------------------------------------------------------------------------- /docs/commands/edit-flags.md: -------------------------------------------------------------------------------- 1 | ## Command edit-flags ## 2 | 3 | The `edit-flags` command (alias: `flags`) provides a quick and comprehensible 4 | way to view and edit the flag register for the architectures that support it. 5 | Without argument, the command will simply return a human-friendly display of the 6 | register flags. 7 | 8 | One or many arguments can be provided, following the syntax below: 9 | ``` 10 | gef➤ flags [(+|-|~)FLAGNAME ...] 11 | ``` 12 | Where `FLAGNAME` is the name of the flag (case insensitive), and `+|-|~` indicates 13 | the action on whether to set, unset, or toggle the flag. 14 | 15 | For instance, on x86 architecture, if we don't want to take a conditional jump 16 | (e.g. a `jz` instruction), but we want to have the Carry flag set, simply go with: 17 | 18 | ``` 19 | gef➤ flags -ZERO +CARRY 20 | ``` 21 | ![flags](https://i.imgur.com/ro7iC5m.png) 22 | -------------------------------------------------------------------------------- /docs/commands/format-string-helper.md: -------------------------------------------------------------------------------- 1 | ## Command format-string-helper ## 2 | 3 | The `format-string-helper` command will create a `GEF` specific type of 4 | breakpoints dedicated to detecting potentially insecure format string when 5 | using the GlibC library. 6 | 7 | It will use this new breakpoint against several targets, including: 8 | 9 | * `printf()` 10 | * `sprintf()` 11 | * `fprintf()` 12 | * `snprintf()` 13 | * `vsnprintf()` 14 | 15 | Just call the command to enable this functionality. 16 | 17 | `fmtstr-helper` is a shorter alias. 18 | 19 | ``` 20 | gef➤ fmtstr-helper 21 | ``` 22 | 23 | Then start the binary execution. 24 | ``` 25 | gef➤ r 26 | ``` 27 | 28 | If a potentially insecure entry is found, the breakpoint will trigger, stop the 29 | process execution, display the reason for trigger and the associated context. 30 | 31 | ![fmtstr-helper-example](https://i.imgur.com/INU3KGn.png) 32 | 33 | -------------------------------------------------------------------------------- /docs/commands/checksec.md: -------------------------------------------------------------------------------- 1 | ## Command checksec ## 2 | 3 | The `checksec` command is inspired from 4 | [`checksec.sh`](http://www.trapkit.de/tools/checksec.html). It provides a 5 | convenient way to determine which security protections are enabled in a binary. 6 | 7 | You can use the command on the currently debugged process: 8 | ``` 9 | gef➤ checksec 10 | [+] checksec for '/vagrant/test-bin' 11 | Canary: No 12 | NX Support: Yes 13 | PIE Support: No 14 | No RPATH: Yes 15 | No RUNPATH: Yes 16 | Partial RelRO: Yes 17 | Full RelRO: No 18 | ``` 19 | 20 | Or specify directly the binary to check, for example: 21 | 22 | ```bash 23 | $ gdb -ex "checksec ./tests/test-x86" 24 | ``` 25 | -------------------------------------------------------------------------------- /tests/run-remote.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Bash script to automate running the tests running from any remote machine 4 | # (assumes GDB+Python3, requires sudo NOPASSWD) 5 | # 6 | # On the host, run: 7 | # $ bash -c "$(curl https://raw.githubusercontent.com/hugsy/gef/master/tests/run-remote.sh)" 8 | # 9 | 10 | set -e 11 | 12 | pushd . 13 | rm -fr /tmp/gef-tests && mkdir /tmp/gef-tests 14 | cd /tmp/gef-tests 15 | sudo apt update 16 | sudo apt upgrade -y 17 | sudo apt install gdb git cmake gcc g++ pkg-config libglib2.0-dev libssl-dev python3-pip python3-setuptools python3-dev python3 make -y 18 | sudo rm -fr -- /tmp/{keystone,capstone,unicorn} 19 | sh -c "$(curl https://raw.githubusercontent.com/hugsy/stuff/master/update-trinity.sh)" 20 | export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib 21 | sudo pip3 install -U ropper cryptography 22 | git clone https://github.com/hugsy/gef.git 23 | cd gef 24 | tests/runtests.py 25 | 26 | popd 27 | -------------------------------------------------------------------------------- /docs/commands/hijack-fd.md: -------------------------------------------------------------------------------- 1 | ## Command hijack-fd ## 2 | 3 | `gef` can be used to modify file descriptors of the debugged process. The new 4 | file descriptor can point to a file, a pipe, a socket, a device etc. 5 | 6 | To use it, simply run 7 | ``` 8 | gef➤ hijack-fd FDNUM NEWFILE 9 | ``` 10 | 11 | For instance, 12 | ``` 13 | gef➤ hijack-fd 1 /dev/null 14 | ``` 15 | Will modify the current process file descriptors to redirect STDOUT to 16 | `/dev/null`. 17 | 18 | Check this asciicast for visual example: 19 | [![asciicast](https://asciinema.org/a/2o9bhveyikb1uvplwakjftxlq.png)](https://asciinema.org/a/2o9bhveyikb1uvplwakjftxlq) 20 | 21 | This command also supports connecting to an ip:port if it is provided as an argument. For example 22 | ``` 23 | gef➤ hijack-fd 0 localhost:8888 24 | ``` 25 | Will redirect STDIN to localhost:8888 26 | 27 | There is also an example at: 28 | [![asciicast](https://asciinema.org/a/0dizAXevliwGYboibPUJmJntO.png)](https://asciinema.org/a/0dizAXevliwGYboibPUJmJntO) -------------------------------------------------------------------------------- /docs/commands/process-status.md: -------------------------------------------------------------------------------- 1 | ## Command process-status ## 2 | 3 | > This command replaces the old commands `pid` and `fd`. 4 | 5 | `process-status` provides an exhaustive description of the current running 6 | process, by extending the information provided by GDB `info proc` command, with 7 | all the information from the `procfs` structure. 8 | 9 | ``` 10 | gef➤ ps -s zsh 11 | 22879 12 | gef➤ attach 22879 13 | [...] 14 | gef➤ status 15 | [+] Process Information 16 | PID → 22879 17 | Executable → /bin/zsh 18 | Command line → '-zsh' 19 | [+] Parent Process Information 20 | Parent PID → 4475 21 | Command line → 'tmux new -s cool vibe 22 | [+] Children Process Information 23 | PID → 26190 (Name: '/bin/sleep', CmdLine: 'sleep 100000') 24 | [+] File Descriptors: 25 | /proc/22879/fd/0 → /dev/pts/4 26 | /proc/22879/fd/1 → /dev/pts/4 27 | /proc/22879/fd/2 → /dev/pts/4 28 | /proc/22879/fd/10 → /dev/pts/4 29 | [+] File Descriptors: 30 | No TCP connections 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/commands/stub.md: -------------------------------------------------------------------------------- 1 | ## Command stub ## 2 | 3 | The `stub` command allows you stub out functions, optionally specifying the 4 | return value. 5 | 6 | ``` 7 | gef➤ stub [-h] [-r RETVAL] [LOCATION] 8 | ``` 9 | 10 | `LOCATION` indicates the address of the function to bypass. If not 11 | specified, gef will consider the instruction at the program counter to be the 12 | start of the function. 13 | 14 | If `-r RETVAL` is provided, gef will set the return value to the provided 15 | value. Otherwise it will set the return value to 0. 16 | 17 | For example, it is trivial to bypass `fork()` calls. Since the return value is 18 | set to 0, it will in fact drop us into the "child" process. It must be noted 19 | that this is a different behaviour from the classic `set follow-fork-mode 20 | child` since here we do not spawn a new process, we only trick the parent 21 | process into thinking it has become the child. 22 | 23 | ### Example ### 24 | 25 | Patching `fork()` calls: 26 | 27 | * Without stub: 28 | ![fork execution](http://i.imgur.com/TjnTDot.png) 29 | 30 | * With stub: 31 | ![stubbed fork](http://i.imgur.com/CllTnRH.png) 32 | -------------------------------------------------------------------------------- /docs/commands/scan.md: -------------------------------------------------------------------------------- 1 | ## Command scan ## 2 | 3 | `scan` Search for addresses that are located in a memory mapping (haystack) that 4 | belonging to another (needle). 5 | 6 | ``` 7 | gef➤ scan stack libc 8 | [+] Searching for addresses in 'stack' that point to 'libc' 9 | [stack]: 0x00007fffffffd6a8│+0x1f6a8: 0x00007ffff77cf482 → "__tunable_get_val" 10 | [stack]: 0x00007fffffffd6b0│+0x1f6b0: 0x00007ffff77bff78 → 0x0000001200001ab2 11 | [stack]: 0x00007fffffffd758│+0x1f758: 0x00007ffff77cd9d0 → 0x6c5f755f72647800 12 | [stack]: 0x00007fffffffd778│+0x1f778: 0x00007ffff77bda6c → 0x0000090900000907 13 | [stack]: 0x00007fffffffd7d8│+0x1f7d8: 0x00007ffff77cd9d0 → 0x6c5f755f72647800 14 | [...] 15 | ``` 16 | 17 | 18 | `scan` requires two arguments, the first is the memory section that will be 19 | searched and the second is what will be searched for. The arguments are grepped 20 | against the processes memory mappings (just like [vmmap](./vmmap.md) 21 | to determine the memory ranges to search. 22 | 23 | To check mappings without a path associated, an address range (start-end) can be used. 24 | 25 | ![scan-address](https://i.imgur.com/ExJC2p7.png) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 crazy rabbidz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/commands/print-format.md: -------------------------------------------------------------------------------- 1 | ## Command print-format ## 2 | 3 | The command `print-format` (alias `pf`) will dump an arbitrary location as an 4 | array of bytes following the syntax of the programming language 5 | specified. Currently, the output language supported are 6 | 7 | - Python (`py` - default) 8 | - C (`c`) 9 | - Assembly (`asm`) 10 | - Javascript (`js`) 11 | 12 | 13 | ``` 14 | gef➤ print-format -h 15 | [+] print-format [-f FORMAT] [-b BITSIZE] [-l LENGTH] [-c] [-h] LOCATION 16 | -f FORMAT specifies the output format for programming language, avaliable value is py, c, js, asm (default py). 17 | -b BITSIZE sepecifies size of bit, avaliable values is 8, 16, 32, 64 (default is 8). 18 | -l LENGTH specifies length of array (default is 256). 19 | -c The result of data will copied to clipboard (requires xclip) 20 | LOCATION specifies where the address of bytes is stored. 21 | ``` 22 | 23 | For example this command will dump 10 bytes from `$rsp` and copy the result to the clipboard. 24 | 25 | ``` 26 | gef➤ print-format -f py -b 8 -l 10 -c $rsp 27 | [+] Copied to clipboard 28 | buf = [0x87, 0xfa, 0xa3, 0xf7, 0xff, 0x7f, 0x0, 0x0, 0x30, 0xe6] 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/commands/shellcode.md: -------------------------------------------------------------------------------- 1 | ## Command shellcode ## 2 | 3 | `shellcode` is a command line client for @JonathanSalwan shellcodes database. It 4 | can be used to search and download directly via `GEF` the shellcode you're 5 | looking for. Two primitive subcommands are available, `search` and `get` 6 | 7 | ``` 8 | gef➤ shellcode search arm 9 | [+] Showing matching shellcodes 10 | 901 Linux/ARM Add map in /etc/hosts file - 79 bytes 11 | 853 Linux/ARM chmod("/etc/passwd", 0777) - 39 bytes 12 | 854 Linux/ARM creat("/root/pwned", 0777) - 39 bytes 13 | 855 Linux/ARM execve("/bin/sh", [], [0 vars]) - 35 bytes 14 | 729 Linux/ARM Bind Connect UDP Port 68 15 | 730 Linux/ARM Bindshell port 0x1337 16 | [...] 17 | gef➤ shellcode get 698 18 | [+] Downloading shellcode id=698 19 | [+] Shellcode written as '/tmp/sc-EfcWtM.txt' 20 | gef➤ system cat /tmp/sc-EfcWtM.txt 21 | /* 22 | Title: Linux/ARM - execve("/bin/sh", [0], [0 vars]) - 27 bytes 23 | Date: 2010-09-05 24 | Tested on: ARM926EJ-S rev 5 (v5l) 25 | Author: Jonathan Salwan - twitter: @jonathansalwan 26 | 27 | shell-storm.org 28 | 29 | Shellcode ARM without 0x20, 0x0a and 0x00 30 | [...] 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /docs/commands/config.md: -------------------------------------------------------------------------------- 1 | ## Command config ## 2 | 3 | In addition to reading its config from _~/.gef.rc~, `gef` can also be 4 | configured at runtime with the `gef config` command. 5 | 6 | To view all settings for all commands loaded: 7 | ``` 8 | gef➤ gef config 9 | ``` 10 | ![gef-config](https://i.imgur.com/bd2ZqsU.png) 11 | 12 | Or to get one setting value: 13 | ``` 14 | gef➤ gef config pcustom.struct_path 15 | ``` 16 | 17 | Of course you can edit the values. For example, if you want the screen to be 18 | cleared before displaying the current context when reaching a breakpoing: 19 | ``` 20 | gef➤ gef config context.clear_screen 1 21 | ``` 22 | 23 | To save the current settings for `GEF` to the file system to have those options 24 | persist across all your future `GEF` sessions, simply run: 25 | ``` 26 | gef➤ gef save 27 | [+] Configuration saved to '/home/vagrant/.gef.rc' 28 | ``` 29 | 30 | Upon startup, if `gef` finds a file `${HOME}/.gef.rc`, it will automatically 31 | loads its values. 32 | 33 | To reload the settings during the session, just run: 34 | ``` 35 | gef➤ gef restore 36 | [+] Configuration from '/home/hugsy/.gef.rc' restored 37 | ``` 38 | 39 | You can tweak this configuration file outside your `gdb` session to suit your 40 | needs. 41 | -------------------------------------------------------------------------------- /docs/commands/xor-memory.md: -------------------------------------------------------------------------------- 1 | ## Command xor-memory 2 | 3 | This command is used to XOR a block of memory. 4 | 5 | Its syntax is: 6 | ``` 7 | xor-memory
8 | ``` 9 | 10 | The first argument (`display` or `patch`) is the action to perform: 11 | 12 | 1. `display` will only show an hexdump of the result of the XOR-ed memory block, without writing the debuggee's memory. 13 | 14 | gef➤ xor display $rsp 16 1337 15 | [+] Displaying XOR-ing 0x7fff589b67f8-0x7fff589b6808 with '1337' 16 | ────────────────────────────────[ Original block ]──────────────────────────────────── 17 | 0x00007fff589b67f8 46 4e 40 00 00 00 00 00 00 00 00 00 00 00 00 00 FN@............. 18 | ────────────────────────────────[ XOR-ed block ]────────────────────────────────────── 19 | 0x00007fff589b67f8 55 79 53 37 13 37 13 37 13 37 13 37 13 37 13 37 UyS7.7.7.7.7.7.7 20 | 21 | 2. `patch` will overwrite the memory with the xor-ed content. 22 | 23 | gef➤ xor patch $rsp 16 1337 24 | [+] Patching XOR-ing 0x7fff589b67f8-0x7fff589b6808 with '1337' 25 | gef➤ hexdump byte $rsp 16 26 | 0x00007fff589b67f8 55 79 53 37 13 37 13 37 13 37 UyS7.7.7.7 27 | -------------------------------------------------------------------------------- /docs/commands/functions.md: -------------------------------------------------------------------------------- 1 | ## Command functions ## 2 | 3 | The `functions` command will list all of the [convenience functions](https://sourceware.org/gdb/onlinedocs/gdb/Convenience-Funs.html) provided by GEF. 4 | 5 | * `$_base(name=current_file)` -- Return the base address of the matching section (default current file). 6 | * `$_bss(offset=0)` -- Return the current bss base address plus the given offset. 7 | * `$_got(offset=0)` -- Return the current bss base address plus the given offset. 8 | * `$_heap(offset=0)` -- Return the current heap base address plus an optional offset. 9 | * `$_stack(offset=0)` -- Return the current stack base address plus an optional offset. 10 | 11 | 12 | These functions can be used as arguments to other commands to dynamically calculate values. 13 | 14 | ``` 15 | gef➤ deref $_heap() l4 16 | 0x0000000000602000│+0x00: 0x0000000000000000 ← $r8 17 | 0x0000000000602008│+0x08: 0x0000000000000021 ("!"?) 18 | 0x0000000000602010│+0x10: 0x0000000000000000 ← $rax, $rdx 19 | 0x0000000000602018│+0x18: 0x0000000000000000 20 | gef➤ deref $_heap(0x20) l4 21 | 0x0000000000602020│+0x00: 0x0000000000000000 ← $rsi 22 | 0x0000000000602028│+0x08: 0x0000000000020fe1 23 | 0x0000000000602030│+0x10: 0x0000000000000000 24 | 0x0000000000602038│+0x18: 0x0000000000000000 25 | ``` 26 | -------------------------------------------------------------------------------- /docs/commands/eval.md: -------------------------------------------------------------------------------- 1 | ## Command $ ## 2 | 3 | The `$` command attempts to mimic WinDBG `?` command. 4 | 5 | When provided one argument, it will evaluate the expression, and try to display 6 | the result with various formats: 7 | 8 | ``` 9 | gef➤ $ $pc+1 10 | 93824992252977 11 | 0x555555559431 12 | 0b10101010101010101010101010101011001010000110001 13 | b'UUUU\x941' 14 | b'1\x94UUUU' 15 | 16 | gef➤ $ -0x1000 17 | -4096 18 | 0xfffffffffffff000 19 | 0b1111111111111111111111111111111111111111111111111111000000000000 20 | b'\xff\xff\xff\xff\xff\xff\xf0\x00' 21 | b'\x00\xf0\xff\xff\xff\xff\xff\xff' 22 | ``` 23 | 24 | With two arguments, it will simply compute the delta between them: 25 | 26 | ``` 27 | gef➤ vmmap libc 28 | Start End Offset Perm 29 | 0x00007ffff7812000 0x00007ffff79a7000 0x0000000000000000 r-x /lib/x86_64-linux-gnu/libc-2.24.so 30 | 0x00007ffff79a7000 0x00007ffff7ba7000 0x0000000000195000 --- /lib/x86_64-linux-gnu/libc-2.24.so 31 | 0x00007ffff7ba7000 0x00007ffff7bab000 0x0000000000195000 r-- /lib/x86_64-linux-gnu/libc-2.24.so 32 | 0x00007ffff7bab000 0x00007ffff7bad000 0x0000000000199000 rw- /lib/x86_64-linux-gnu/libc-2.24.so 33 | 34 | gef➤ $ 0x00007ffff7812000 0x00007ffff79a7000 35 | -1658880 36 | 1658880 37 | 38 | gef➤ $ 1658880 39 | 1658880 40 | 0x195000 41 | 0b110010101000000000000 42 | b'\x19P\x00' 43 | b'\x00P\x19' 44 | ``` 45 | -------------------------------------------------------------------------------- /docs/commands/unicorn-emulate.md: -------------------------------------------------------------------------------- 1 | ## Command unicorn-emulate ## 2 | 3 | If you have installed [`unicorn`](http://unicorn-engine.org) emulation engine 4 | and its Python bindings, `gef` integrates a new command to emulate instructions 5 | of your current debugging context ! 6 | 7 | This command, `unicorn-emulate` (or its alias `emu`) will replicate the current 8 | memory mapping (including the page permissions) for you, and by default (i.e. 9 | without any additional argument), it will emulate the execution of the 10 | instruction about to be executed (i.e. the one pointed by `$pc`) and display 11 | which register(s) is(are) tainted by it. 12 | 13 | Use `-h` for help 14 | ``` 15 | gef➤ emu -h 16 | ``` 17 | 18 | For example, the following command will execute only the next 2 instructions: 19 | ``` 20 | gef➤ emu -n 2 21 | ``` 22 | 23 | And show this: 24 | ![emu](https://i.imgur.com/DmVH6o1.png) 25 | 26 | In this example, we can see that after executing 27 | ``` 28 | 0x80484db xor eax,eax 29 | 0x80484dd add esp,0x18 30 | ``` 31 | The registers `eax` and `esp` are tainted (modified). 32 | 33 | A convenient option is `-o /path/to/file.py` that will generate a pure Python 34 | script embedding your current execution context, ready to be re-used outside 35 | `gef`!! This can be useful for dealing with obfuscation or solve crackmes if 36 | powered with a SMT for instance. 37 | 38 | 39 | -------------------------------------------------------------------------------- /tests/binaries/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | DEBUG = 1 3 | CFLAGS += -Wall 4 | SOURCES = $(wildcard *.c) 5 | COMPILED = $(SOURCES:.c=.o) 6 | LINKED = $(SOURCES:.c=.out) 7 | LDFLAGS = 8 | EXTRA_FLAGS = 9 | 10 | ifeq ($(TARGET), x86) 11 | CFLAGS += -m32 12 | endif 13 | 14 | ifeq ($(DEBUG), 1) 15 | CFLAGS += -DDEBUG=1 -ggdb -O0 16 | else 17 | CFLAGS += -O1 18 | endif 19 | 20 | 21 | .PHONY : all clean 22 | 23 | all: $(LINKED) 24 | 25 | 26 | %.out : %.c 27 | @echo "[+] Building '$@'" 28 | @$(CC) $(CFLAGS) $(EXTRA_FLAGS) -o $@ $? $(LDFLAGS) 29 | 30 | clean : 31 | @echo "[+] Cleaning stuff" 32 | @rm -f $(COMPILED) $(LINKED) 33 | 34 | format-string-helper.out: EXTRA_FLAGS := -Wno-format-security 35 | 36 | checksec-no-canary.out: EXTRA_FLAGS := -fno-stack-protector 37 | 38 | # NOTE: If compiling with a older GCC (older than 4.8.4 maybe?) then use `-fno-pie` 39 | checksec-no-pie.out: EXTRA_FLAGS := -no-pie 40 | 41 | checksec-no-nx.out: EXTRA_FLAGS := -z execstack 42 | 43 | pattern.out: EXTRA_FLAGS := -D_FORTIFY_SOURCE=0 -fno-stack-protector 44 | 45 | canary.out: EXTRA_FLAGS := -fstack-protector-all 46 | 47 | heap-non-main.out: EXTRA_FLAGS := -pthread 48 | 49 | heap-tcache.out: EXTRA_FLAGS := -Wno-unused-label 50 | 51 | default.out: EXTRA_FLAGS := -fstack-protector-all -fpie -pie 52 | -------------------------------------------------------------------------------- /docs/commands/set-permission.md: -------------------------------------------------------------------------------- 1 | ## Command set-permission ## 2 | 3 | 4 | This command was added to facilitate the exploitation process, by changing the 5 | permission rights on a specific page directly from the debugger. 6 | 7 | By default, `GDB` does not allow you to do that, so the command will modify a 8 | code section of the binary being debugged, and add a native mprotect syscall 9 | stub. For example, for x86, the following stub will be inserted: 10 | 11 | ``` 12 | pushad 13 | mov eax, mprotect_syscall_num 14 | mov ebx, address_of_the_page 15 | mov ecx, size_of_the_page 16 | mov edx, permission_to_set 17 | int 0x80 18 | popad 19 | ``` 20 | 21 | A breakpoint is added following this stub, which when hit will restore the 22 | original context, allowing you to resume execution. 23 | 24 | `mprotect` is an alias for `set-permission`. As an example, to set the `stack` as 25 | READ|WRITE|EXECUTE on this binary, 26 | 27 | ![mprotect-before](https://i.imgur.com/RRYHxzW.png) 28 | 29 | Simply run 30 | 31 | ``` 32 | gef➤ mprotect 0xfffdd000 33 | ``` 34 | 35 | Et voilà ! `gef` will use the memory runtime information to correctly adjust the protection 36 | of the entire section. 37 | 38 | ![mprotect-after](https://i.imgur.com/9MvyQi8.png) 39 | 40 | Or for a full demo video on a PowerPC VM: 41 | [![asciicast](https://asciinema.org/a/54noulja01k3cgctawjeio8xl.png)](https://asciinema.org/a/54noulja01k3cgctawjeio8xl) 42 | 43 | -------------------------------------------------------------------------------- /docs/commands/theme.md: -------------------------------------------------------------------------------- 1 | ## Command theme 2 | 3 | Customize `GEF` by changing its color scheme. 4 | 5 | ``` 6 | gef➤ theme 7 | context_title_message : red bold 8 | default_title_message : red bold 9 | default_title_line : green bold 10 | context_title_line : green bold 11 | disable_color : 0 12 | xinfo_title_message : blue bold 13 | ``` 14 | 15 | ### Changing colors 16 | 17 | You have the possibility to change the coloring properties of `GEF` display with 18 | the `theme` command. The command accepts 2 arguments, the name of the property 19 | to update, and its new coloring value. 20 | 21 | Colors can be one of the following: 22 | 23 | - red 24 | - green 25 | - blue 26 | - yellow 27 | - gray 28 | - pink 29 | 30 | Color also accepts the following attributes: 31 | 32 | - bold 33 | - underline 34 | - highlight 35 | - blink 36 | 37 | Any other will value simply be ignored. 38 | 39 | ``` 40 | gef➤ theme context_title_message blue bold foobar 41 | gef➤ theme 42 | context_title_message : blue bold 43 | default_title_message : red bold 44 | default_title_line : green bold 45 | context_title_line : green bold 46 | disable_color : 0 47 | xinfo_title_message : blue bold 48 | ``` 49 | -------------------------------------------------------------------------------- /docs/commands/search-pattern.md: -------------------------------------------------------------------------------- 1 | ## Command search-pattern ## 2 | 3 | `gef` allows you to search for a specific pattern at runtime in all the segments 4 | of your process memory layout. The command `search-pattern`, alias `grep`, aims 5 | to be straight-forward to use: 6 | ``` 7 | gef➤ search-pattern MyPattern 8 | ``` 9 | 10 | ![grep](https://i.imgur.com/YNzsFvk.png) 11 | 12 | It will provide an easily understandable to spot occurences of the specified 13 | pattern, including the section it/they was/were found, and the permission 14 | associated to that section. 15 | 16 | `search-pattern` can also be used to search for addresses. To do so, simply 17 | ensure that your pattern starts with `0x` and is a valid hex address. For 18 | example: 19 | 20 | ``` 21 | gef➤ search-pattern 0x4005f6 22 | ``` 23 | 24 | ![grep-address](https://i.imgur.com/dg1gUB5.png) 25 | 26 | The `search-pattern` command can also be used as a way to search for 27 | cross-references to an address. For this reason, the alias `xref` also points 28 | to the command `search-pattern`. Therefore the command above is equivalent to 29 | `xref 0x4005f6` which makes it more intuitive to use. 30 | 31 | ### Searching in a specific range ### 32 | Sometimes, you may need to search for a very common pattern. To limit the search space, you can also specify an address range or the section to be checked. 33 | 34 | ``` 35 | gef➤ search-pattern 0x4005f6 little libc 36 | gef➤ search-pattern 0x4005f6 little 0x603100-0x603200 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/commands/highlight.md: -------------------------------------------------------------------------------- 1 | ## Command highlight ## 2 | 3 | This command sets up custom highlighting for user set strings. 4 | 5 | Syntax: 6 | 7 | ``` 8 | highlight (add|remove|list|clear) 9 | ``` 10 | 11 | Alias: 12 | 13 | - `hl` 14 | 15 | ## Adding matches 16 | 17 | The following will add `41414141`/`'AAAA'` as yellow, and `42424242`/`'BBBB'` 18 | as blue: 19 | 20 | ``` 21 | gef➤ hl add 41414141 yellow 22 | gef➤ hl add 42424242 blue 23 | gef➤ hl add AAAA yellow 24 | gef➤ hl add BBBB blue 25 | ``` 26 | 27 | ## Removing matches 28 | 29 | To remove a match, target it by the original string used, ex.: 30 | 31 | ``` 32 | gef➤ hl rm 41414141 33 | ``` 34 | 35 | ## Listing matches 36 | 37 | To list all matches with their colors: 38 | 39 | ``` 40 | gef➤ hl list 41 | 41414141 | yellow 42 | 42424242 | blue 43 | AAAA | yellow 44 | BBBB | blue 45 | ``` 46 | 47 | ## Clearing all matches 48 | 49 | To clear all matches currently setup: 50 | 51 | ``` 52 | gef➤ hl clear 53 | ``` 54 | 55 | ## RegEx support 56 | 57 | RegEx support is disabled by default, this is done for performance reasons. 58 | 59 | To enable regular expressions on text matches: 60 | 61 | ``` 62 | gef➤ gef config highlight.regex True 63 | ``` 64 | 65 | To check the current status: 66 | 67 | ``` 68 | gef➤ gef config highlight.regex 69 | highlight.regex (bool) = True 70 | ``` 71 | 72 | ## Performance 73 | 74 | _**NOTE:** Adding many matches may slow down debugging while using GEF. 75 | This includes enabling RegEx support._ 76 | 77 | ## Colors 78 | 79 | To find a list of supported colors, check the 80 | [theme](./theme.md#changing-colors) documentation. 81 | 82 | -------------------------------------------------------------------------------- /docs/commands/registers.md: -------------------------------------------------------------------------------- 1 | ## Command registers 2 | 3 | The `registers` command will print all the registers and dereference any 4 | pointers. It does not take any argument. 5 | 6 | 7 | Example on a MIPS host: 8 | ``` 9 | gef> reg 10 | $zero : 0x00000000 11 | $at : 0x00000001 12 | $v0 : 0x7fff6cd8 -> 0x77e5e7f8 -> <__libc_start_main+200>: bnez v0,0x77e5e8a8 13 | $v1 : 0x77ff4490 14 | $a0 : 0x00000001 15 | $a1 : 0x7fff6d94 -> 0x7fff6e85 -> "/root/demo-mips" 16 | $a2 : 0x7fff6d9c -> 0x7fff6e91 -> "SHELL=/bin/bash" 17 | $a3 : 0x00000000 18 | $t0 : 0x77fc26a0 -> 0x0 19 | $t1 : 0x77fc26a0 -> 0x0 20 | $t2 : 0x77fe5000 -> "_dl_fini" 21 | $t3 : 0x77fe5000 -> "_dl_fini" 22 | $t4 : 0xf0000000 23 | $t5 : 0x00000070 24 | $t6 : 0x00000020 25 | $t7 : 0x7fff6bc8 -> 0x0 26 | $s0 : 0x00000000 27 | $s1 : 0x00000000 28 | $s2 : 0x00000000 29 | $s3 : 0x00500000 30 | $s4 : 0x00522f48 31 | $s5 : 0x00522608 32 | $s6 : 0x00000000 33 | $s7 : 0x00000000 34 | $t8 : 0x0000000b 35 | $t9 : 0x004008b0 ->
: addiu sp,sp,-32 36 | $k0 : 0x00000000 37 | $k1 : 0x00000000 38 | $s8 : 0x00000000 39 | $status : 0x0000a413 40 | $badvaddr : 0x77e7a874 -> <__cxa_atexit>: lui gp,0x15 41 | $cause : 0x10800024 42 | $pc : 0x004008c4 -> : li v0,2 43 | $sp : 0x7fff6ca0 -> 0x77e4a834 -> 0x29bd 44 | $hi : 0x000001a5 45 | $lo : 0x00005e17 46 | $fir : 0x00739300 47 | $fcsr : 0x00000000 48 | $ra : 0x77e5e834 -> <__libc_start_main+260>: lw gp,16(sp) 49 | $gp : 0x00418b20 50 | ``` 51 | -------------------------------------------------------------------------------- /docs/commands/pattern.md: -------------------------------------------------------------------------------- 1 | ## Command pattern ## 2 | 3 | This command will create or search a [De 4 | Bruijn](https://en.wikipedia.org/wiki/De_Bruijn_sequence) cyclic pattern to 5 | facilitate determining offsets in memory. 6 | 7 | It should be noted that for better compatibility, the algorithm implemented in 8 | `GEF` is the same as the one in `pwntools`, and can therefore be used in 9 | conjunction. 10 | 11 | ### create 12 | 13 | The sub-command `create` allows to create a new pattern: 14 | 15 | ``` 16 | gef➤ pattern create 128 17 | [+] Generating a pattern of 128 bytes 18 | aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaab 19 | [+] Saved as '$_gef0' 20 | ``` 21 | 22 | Ths pattern can be used as as input later on. To generate this input, `GEF` 23 | takes into account the size of architecture (16, 32 or 64 bits), to generate 24 | it. 25 | 26 | The equivalent command with `pwntools` is 27 | ```python 28 | from pwn import * 29 | p = cyclic(128, n=8) 30 | ``` 31 | where `n` is the number of bytes of the architecture (8 for 64 bits, 4 for 32). 32 | 33 | 34 | ### search 35 | 36 | The `search` sub-command seeks the value given as argument, trying to find it in 37 | the De Bruijn sequence 38 | ``` 39 | gef➤ pattern search 0x6161616161616167 40 | [+] Searching '0x6161616161616167' 41 | [+] Found at offset 48 (little-endian search) likely 42 | [+] Found at offset 41 (big-endian search) 43 | ``` 44 | 45 | Note that registers can also be passed as values: 46 | ``` 47 | gef➤ pattern search $rbp 48 | [+] Searching '$rbp' 49 | [+] Found at offset 32 (little-endian search) likely 50 | [+] Found at offset 25 (big-endian search) 51 | ``` 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | .vscode -------------------------------------------------------------------------------- /tests/perf/context_times.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bail out early on an unexpected error 4 | set -e 5 | 6 | time_gef_context() { 7 | # Run twice to minimize jitter 8 | gdb -ex 'start' -ex 'pi import profile' -ex "pi profile.run(\"gdb.execute('context')\", sort=\"cumtime\")" -ex 'quit' ../binaries/pattern.out >/dev/null 2>&1 9 | gdb -ex 'start' -ex 'pi import profile' -ex "pi profile.run(\"gdb.execute('context')\", sort=\"cumtime\")" -ex 'quit' ../binaries/pattern.out 2>&1 | get_context_time 10 | } 11 | 12 | get_context_time() { 13 | grep "gdb.execute('context')" | tr -s ' ' | cut -d ' ' -f 5 14 | } 15 | 16 | log_this_revision() { 17 | rev=`git log -1 --pretty="format:%h"` 18 | printf $rev 19 | title=`git log -1 --pretty="format:%s"` 20 | printf ",\"$title\"" 21 | rv=`$1` 22 | echo ,$rv 23 | } 24 | 25 | log_command() { 26 | log_this_revision "$1" >> stats.csv 27 | } 28 | 29 | clear_stats() { 30 | if [ -e "stats.csv" ]; then 31 | rm stats.csv 32 | fi 33 | } 34 | 35 | get_current_branch_or_commit() { 36 | b=`git branch | grep '\* '` 37 | case "$b" in 38 | *HEAD*) 39 | echo "$b" | tr -d ')' | cut -f 5 -d ' ';; 40 | *) 41 | echo "$b" | cut -f 2 -d ' ';; 42 | esac 43 | } 44 | 45 | run_on_git_revisions() { 46 | start_ref=$1 47 | end_ref=$2 48 | test_command=$3 49 | 50 | orig_rev=`get_current_branch_or_commit` 51 | revs=`git rev-list --reverse ${start_ref}..${end_ref}` 52 | 53 | for rev in $revs; do 54 | echo "Checking out: $(git log --oneline -1 $rev)" 55 | git checkout --quiet $rev 56 | log_command $test_command 57 | git reset --hard --quiet 58 | done 59 | 60 | echo "Restoring original commit/branch: $orig_rev" 61 | git checkout --quiet $orig_rev 62 | } 63 | 64 | if [ $# == "2" ]; then 65 | clear_stats 66 | run_on_git_revisions $1 $2 "time_gef_context" 67 | else 68 | echo "usage: $0 first_commit last_commit" 69 | fi 70 | -------------------------------------------------------------------------------- /docs/commands/hexdump.md: -------------------------------------------------------------------------------- 1 | ## Command hexdump ## 2 | 3 | Imitation of the WinDBG command. 4 | 5 | This command takes 4 optional arguments: 6 | 7 | - The format for representing the data (by default, byte) 8 | - A value/address/symbol used as the location to print the hexdump from (by default, $sp) 9 | - The number of qword/dword/word/bytes to display (by default, 64 if the format is byte, 16 otherwise) 10 | - The direction of output lines (by default, from low to high addresses) 11 | 12 | The command provides WinDBG compatible aliases by default: 13 | 14 | - `hexdump qword` -> `dq` 15 | - `hexdump dword` -> `dd` 16 | - `hexdump word` -> `dw` 17 | - `hexdump byte` -> `db` 18 | 19 | `hexdump byte` will also try to display the ASCII character values if the byte 20 | is printable (similarly to the `hexdump -C` command on Linux). 21 | 22 | The syntax is as following: 23 | 24 | ``` 25 | hexdump [qword|dword|word|byte] [LOCATION] [[L][SIZE]] [REVERSE] 26 | ``` 27 | 28 | Examples: 29 | 30 | * Display 4 QWORD from `$pc`: 31 | 32 | ``` 33 | gef➤ dq $pc l4 34 | 0x7ffff7a5c1c0+0000 │ 0x4855544155415641 35 | 0x7ffff7a5c1c0+0008 │ 0x0090ec814853cd89 36 | 0x7ffff7a5c1c0+0010 │ 0x377d6f058b480000 37 | 0x7ffff7a5c1c0+0018 │ 0x748918247c894800 38 | ``` 39 | 40 | * Display 32 bytes from a location in the stack: 41 | 42 | ``` 43 | gef➤ db 0x00007fffffffe5e5 l32 44 | 0x00007fffffffe5e5 2f 68 6f 6d 65 2f 68 75 67 73 79 2f 63 6f 64 65 /home/hugsy/code 45 | 0x00007fffffffe5f5 2f 67 65 66 2f 74 65 73 74 73 2f 77 69 6e 00 41 /gef/tests/win.A 46 | ``` 47 | 48 | * Display 8 WORD from `$sp` in reverse order: 49 | ``` 50 | gef➤ dw 8 r 51 | 0x00007fffffffe0ee│+0x000e 0x0000 52 | 0x00007fffffffe0ec│+0x000c 0x7fff 53 | 0x00007fffffffe0ea│+0x000a 0xffff 54 | 0x00007fffffffe0e8│+0x0008 0xe3f5 55 | 0x00007fffffffe0e6│+0x0006 0x0000 56 | 0x00007fffffffe0e4│+0x0004 0x0000 57 | 0x00007fffffffe0e2│+0x0002 0x0000 58 | 0x00007fffffffe0e0│+0x0000 0x0001 59 | ``` 60 | -------------------------------------------------------------------------------- /docs/commands/ida-interact.md: -------------------------------------------------------------------------------- 1 | ## Command ida-interact ## 2 | 3 | `gef` provides a simple XML-RPC client designed to communicate with a server 4 | running inside a specific IDA Python plugin, called `ida_gef.py` (which 5 | can be downloaded freely 6 | [here](https://raw.githubusercontent.com/hugsy/gef/master/scripts/ida_gef.py)). 7 | 8 | Simply download this script, and run it inside IDA. When the server is running, 9 | you will see a text in the Output Window such as: 10 | 11 | ``` 12 | [+] Creating new thread for XMLRPC server: Thread-1 13 | [+] Starting XMLRPC server: 0.0.0.0:1337 14 | [+] Registered 6 functions. 15 | ``` 16 | 17 | This indicates that the XML-RPC server is ready and listening. 18 | 19 | `gef` can interact with it via the command `ida-interact`. This command receives 20 | as first argument the name of the function to execute, all the other arguments 21 | are the arguments of the remote function. 22 | 23 | To enumerate the functions available, simply run 24 | ``` 25 | gef➤ ida-interact -h 26 | ``` 27 | ![gef-ida-help](https://i.imgur.com/JFNBfjY.png) 28 | 29 | Now, to execute an RPC, invoke the command `ida-interact` on the desired method, 30 | with its arguments (if required). 31 | 32 | For example: 33 | ``` 34 | gef➤ ida ida.set_color 0x40061E 35 | ``` 36 | will edit the remote IDB and set the background color of the location 0x40061E 37 | with the color 0x005500 (default value). 38 | 39 | Another convenient example is to add comment inside IDA directly from `gef`: 40 | ``` 41 | gef➤ ida ida.add_comment 0x40060C "<<<--- stack overflow" 42 | [+] Success 43 | ``` 44 | 45 | Result: 46 | 47 | ![gef-ida-example](https://i.imgur.com/jZ2eWG4.png) 48 | 49 | Please use the `--help` argument to see all the methods available and their 50 | syntax. 51 | 52 | It is also note-worthy that [Binary Ninja](https://binary.ninja) support has be added: 53 | ![](https://pbs.twimg.com/media/CzSso9bUAAArL1f.jpg:large), by using the 54 | script 55 | [`binja_gef.py`](https://raw.githubusercontent.com/hugsy/gef/master/scripts/binja_gef.py). 56 | -------------------------------------------------------------------------------- /docs/commands/name-break.md: -------------------------------------------------------------------------------- 1 | ## Command name-break ## 2 | 3 | The command `name-break` (alias `nb`) can be used to set a breakpoint on 4 | a location with a name assigned to it. 5 | 6 | Everytime this breakpoint is hit, the specified name will also be shown 7 | in the `extra` section to make it easier to keep an overview when using 8 | multiple breakpoints in a stripped binary. 9 | 10 | `name-break [LOCATION]` 11 | 12 | `LOCATION` may be a linespec, address, or explicit location, same as specified 13 | for `break`. If `LOCATION` isn't specified, it will create the breakpoint at the current 14 | instruction pointer address. 15 | 16 | Examples: 17 | 18 | - `nb first *0x400ec0` 19 | - `nb "main func" main` 20 | - `nb read_secret *main+149` 21 | - `nb check_heap` 22 | 23 | Example output: 24 | 25 | ``` 26 | ─────────────────────────────────────────────────────────────────────────── code:x86:64 ──── 27 | 0x400e04 add eax, 0xfffbe6e8 28 | 0x400e09 dec ecx 29 | 0x400e0b ret 30 | → 0x400e0c push rbp 31 | 0x400e0d mov rbp, rsp 32 | 0x400e10 sub rsp, 0x50 33 | 0x400e14 mov QWORD PTR [rbp-0x48], rdi 34 | 0x400e18 mov QWORD PTR [rbp-0x50], rsi 35 | 0x400e1c mov rax, QWORD PTR fs:0x28 36 | ───────────────────────────────────────────────────────────────────────────────── stack ──── 37 | 0x00007fffffffe288│+0x0000: 0x0000000000401117 → movzx ecx, al ← $rsp 38 | 0x00007fffffffe290│+0x0008: 0x00007fffffffe4b8 → 0x00007fffffffe71d → "/ctf/t19/srv_copy" 39 | 0x00007fffffffe298│+0x0010: 0x0000000100000000 40 | 0x00007fffffffe2a0│+0x0018: 0x0000000000000000 41 | 0x00007fffffffe2a8│+0x0020: 0x0000000000000004 42 | 0x00007fffffffe2b0│+0x0028: 0x0000000000000000 43 | ───────────────────────────────────────────────────────────────────────────────── extra ──── 44 | [+] Hit breakpoint *0x400e0c (check_entry) 45 | ──────────────────────────────────────────────────────────────────────────────────────────── 46 | gef➤ 47 | ``` 48 | -------------------------------------------------------------------------------- /docs/commands/syscall-args.md: -------------------------------------------------------------------------------- 1 | ## Command syscall-args ## 2 | 3 | Often it is troublesome to have to refer to syscall tables everytime we encounter a system call instruction. 4 | `gef` can be used to determine the system call being invoked and the arguments being passed to it. Requires [gef-extras](http://github.com/hugsy/gef-extras). 5 | 6 | To use it, simply run 7 | ``` 8 | gef➤ syscall-args 9 | ``` 10 | 11 | For instance, 12 | ``` 13 | ───────────────────────────────────────────────────────────────────────────────────────────────────────[ registers ]──── 14 | $rax : 0x0000000000000001 15 | $rbx : 0x0000000000000045 16 | $rcx : 0x00000000fbad2a84 17 | $rdx : 0x0000000000000045 18 | $rsp : 0x00007fffffffdbf8 → 0x00007ffff786f4bd → <_IO_file_write+45> test rax, rax 19 | $rbp : 0x0000555555775510 → "alarm@192.168.0.100\t\t how2heap\t\t\t\t\t\t\t [...]" 20 | $rsi : 0x0000555555775510 → "alarm@192.168.0.100\t\t how2heap\t\t\t\t\t\t\t [...]" 21 | $rdi : 0x0000000000000001 22 | $rip : 0x00007ffff78de132 → syscall 23 | $r8 : 0x0000555555783b44 → 0x0000000000000066 ("f"?) 24 | $r9 : 0x0000000000000000 25 | $r10 : 0x0000000000002000 26 | $r11 : 0x00007fffffffb940 → 0x7669006666757473 ("stuff"?) 27 | $r12 : 0x00007ffff7bab760 → 0x00000000fbad2a84 28 | $r13 : 0x0000000000000045 29 | $r14 : 0x00007ffff7ba6760 → 0x0000000000000000 30 | $r15 : 0x0000000000000045 31 | $eflags: [carry PARITY adjust ZERO sign trap INTERRUPT direction overflow resume virtualx86 identification] 32 | $cs: 0x0033 $gs: 0x0000 $ss: 0x002b $es: 0x0000 $fs: 0x0000 $ds: 0x0000 33 | 34 | ... 35 | 36 | gef➤ syscall-args 37 | [+] Detected syscall write 38 | write(unsigned int fd, const char *buf, size_t count) 39 | [+] Parameter Register Value 40 | fd $rdi 0x1 41 | buf $rsi 0x555555775510 → "file1\t\t file2\t\t\t\t\t\t\t [...]" 42 | count $rdx 0x45 43 | ``` 44 | 45 | Check this asciicast for visual example: 46 | [![asciicast](https://asciinema.org/a/gNwy6khs3rkQAPyv1CMrFAnlf.png)](https://asciinema.org/a/gNwy6khs3rkQAPyv1CMrFAnlf) 47 | -------------------------------------------------------------------------------- /docs/screenshots.md: -------------------------------------------------------------------------------- 1 | # Screenshots 2 | 3 | 4 | 5 | 6 | This page illustrates a few of the possibilities available to you when using `GEF`. 7 | 8 | ## Multi-architecture support 9 | 10 | `GEF` was designed to support any architecture supported by GDB via an easily extensible architecture API. 11 | 12 | Currently `GEF` supports the following architectures: 13 | 14 | - Intel x86 (32b & 64b) 15 | - ARM (v6/v7) 16 | - AARCH64 17 | - MIPS/MIPS64 18 | - PowerPC 19 | - SPARC/SPARCv9 20 | 21 | 22 | ## Features 23 | 24 | ### Embedded hexdump view 25 | 26 | To this day, GDB doesn't come with a hexdump-like view. Well `GEF` fixes that for you via the `hexdump` command: 27 | 28 | ![hexdump](https://i.imgur.com/mJUq6T2.png) 29 | 30 | 31 | ### Dereferencing data or registers 32 | 33 | No more endless manual pointer dereferencing `x/x` style. Just use `dereference` for that. Or for a comprehensive view of the registers, `registers` might become your best friend: 34 | 35 | ![mipsel-deref-regs](https://i.imgur.com/f5ZaWDC.png) 36 | 37 | 38 | ### Heap analysis 39 | 40 | #### Detailed view of Glibc Chunks 41 | 42 | ![x86-heap-chunks](https://i.imgur.com/zBSTUHb.png) 43 | 44 | 45 | #### Automatic detection of UaF during runtime 46 | 47 | ![x86-heap-helper-uaf](https://i.imgur.com/NfV5Cu9.png) 48 | 49 | 50 | ### Display ELF information 51 | 52 | #### ELF structure 53 | 54 | ![arm-elf-info](https://i.imgur.com/qOL8CnL.png) 55 | 56 | 57 | #### Security settings 58 | 59 | ![mips-elf-checksec](https://i.imgur.com/aanY2uK.png) 60 | 61 | 62 | ### Automatic vulnerable string detection 63 | 64 | ![aarch64-fmtstr](https://i.imgur.com/iF4l1R5.png) 65 | 66 | 67 | ### Code emulation with Unicorn-Engine (x86-64) 68 | 69 | ![x86-unicorn](https://i.imgur.com/emhEsol.png) 70 | 71 | 72 | ### Comprehensive address space layout display 73 | 74 | ![mips-vmmap](https://i.imgur.com/TbC1kNa.png) 75 | 76 | 77 | ### Defining arbitrary custom structures 78 | 79 | ![sparc-arb-struct](https://i.imgur.com/dEMUuP7.png) 80 | 81 | 82 | ### Highlight custom strings 83 | 84 | ![highlight-command](https://i.imgur.com/UwSPXrV.png) 85 | 86 | 87 | -------------------------------------------------------------------------------- /docs/commands/process-search.md: -------------------------------------------------------------------------------- 1 | ## Command process-search 2 | 3 | `process-search` (aka `ps`) is a convenience command to list and filter process 4 | on the host. It is aimed at making the debugging process a little easier when 5 | targeting forking process (such as tcp/listening daemon that would fork upon new 6 | connection). 7 | 8 | Without argument, it will return all processes reachable by user: 9 | ``` 10 | gef➤ ps 11 | 1 root 0.0 0.4 ? /sbin/init 12 | 2 root 0.0 0.0 ? [kthreadd] 13 | 3 root 0.0 0.0 ? [ksoftirqd/0] 14 | 4 root 0.0 0.0 ? [kworker/0:0] 15 | 5 root 0.0 0.0 ? [kworker/0:0H] 16 | 6 root 0.0 0.0 ? [kworker/u2:0] 17 | 7 root 0.0 0.0 ? [rcu_sched] 18 | 8 root 0.0 0.0 ? [rcuos/0] 19 | 9 root 0.0 0.0 ? [rcu_bh] 20 | 10 root 0.0 0.0 ? [rcuob/0] 21 | 11 root 0.0 0.0 ? [migration/0] 22 | [...] 23 | ``` 24 | 25 | Or to filter with pattern: 26 | ``` 27 | gef➤ ps bash 28 | 22590 vagrant 0.0 0.8 pts/0 -bash 29 | ``` 30 | 31 | `ps` also accepts options: 32 | 33 | * `-s` (for `smart`) will discard a number of process (belonging to different 34 | user, pattern used as an argument and not command, etc.) 35 | * `-a` (for `attach`) will automatically attach to the first process found 36 | 37 | So, for example, if your targeted process is called `/home/foobar/plop`, but the 38 | existing instance is used through `socat`, like 39 | 40 | ``` 41 | $ socat tcp-l:1234,fork,reuseaddr exec:/home/foobar/plop 42 | ``` 43 | 44 | Every time a new connection is opened to tcp/1234, `plop` will be forked, and 45 | `gef` can easily attach to it with the command 46 | 47 | ``` 48 | gef➤ ps -as plop 49 | ``` 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gef-legacy 2 | 3 | This repository contains the legacy version of GEF (aka `gef-legacy` or `gef-py2`), which is a fork a the original [`gef`](https://github.com/hugsy/gef-legacy) project, meant for running on GDB+Python2 only. 4 | 5 | The main reason for this fork was the long time planned end of life of [Python 2](https://pythonclock.org/) which should discourage maintaining Python2 projects. 6 | 7 | However since GDB + Python2 continues to be used (old Linuxes, IoT devices, etc.), it was decided to keep the existing features that GEF provides to GDB. `gef-legacy` will provide great help and most basic functions will be working flawlessly (proper context display, pointer dereferencing, `checksec`, etc.) but will lack the most advanced features. 8 | 9 | `gef-legacy` developers will not add new features to the code, but functional bugs can be reported and will be fixed. Also no new architecture will be added. 10 | 11 | For questions, poke the devs on the Discord channel. 12 | 13 | In short, try **NOT** to rely on this version of GEF: whenever possible you might prefer using "normal" GEF with its remote debugging functionalities. This version of GEF should be your last resort for having a descent debugging experience. 14 | 15 | 16 | 17 | ## Current status ## 18 | 19 | | Documentation | License | Compatibility | Chat | Validation test | 20 | | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | --------------- | 21 | | [![Documentation Status](https://readthedocs.org/projects/gef-legacy/badge/?version=latest)](https://gef-legacy.readthedocs.io/en/latest/?badge=latest) | [![MIT](https://img.shields.io/packagist/l/doctrine/orm.svg?maxAge=2592000?style=plastic)](https://github.com/hugsy/gef-legacy/blob/master/LICENSE) | [![Python 2](https://img.shields.io/badge/Python-2-green.svg)](https://github.com/hugsy/gef-legacy/) | [![Discord](https://img.shields.io/badge/Discord-GDB--GEF-yellow)](https://discord.gg/HCS8Hg7) | Soon | 22 | -------------------------------------------------------------------------------- /docs/commands/aliases.md: -------------------------------------------------------------------------------- 1 | ## Command aliases ## 2 | 3 | List the aliases defined by `GEF`. 4 | 5 | ``` 6 | gef➤ aliases 7 | [+] Aliases defined: 8 | fmtstr-helper → format-string-helper 9 | telescope → dereference 10 | dps → dereference 11 | dq → hexdump qword 12 | dd → hexdump dword 13 | dw → hexdump word 14 | dc → hexdump byte 15 | cs-dis → capstone-disassemble 16 | ctx → context 17 | start-break → entry-break 18 | ps → process-search 19 | [...] 20 | ``` 21 | 22 | ### Creating/deleting aliases 23 | 24 | `GEF` defines its own aliasing mechanism which overrides the traditional 25 | alias that GDB provides through the built-in command `alias`. 26 | 27 | Users can create/modify/delete aliases by editing the `GEF` configuration file, 28 | located at `~/.gef.rc`. The aliases must be in the "`aliases`" section of the 29 | configuration file. 30 | 31 | Creating a new alias is as simple as creating a new entry in this section: 32 | 33 | ``` 34 | $ nano ~/.gef.rc 35 | [...] 36 | [aliases] 37 | my-new-alias = gdb-or-gef-command 38 | ``` 39 | 40 | #### Bringing some PEDA and WinDBG flavours into GEF 41 | 42 | For example, for those (like me) who use WinDBG and like its bindings, they can 43 | be integrated into GDB via GEF aliases like this: 44 | 45 | ``` 46 | $ nano ~/.gef.rc 47 | [...] 48 | [aliases] 49 | # some windbg aliases 50 | dps = dereference 51 | dq = hexdump qword 52 | dd = hexdump dword 53 | dw = hexdump word 54 | dc = hexdump byte 55 | dt = pcustom 56 | bl = info breakpoints 57 | bp = break 58 | be = enable breakpoints 59 | bd = disable breakpoints 60 | bc = delete breakpoints 61 | tbp = tbreak 62 | tba = thbreak 63 | pa = advance 64 | ptc = finish 65 | t = stepi 66 | p = nexti 67 | g = gef run 68 | uf = disassemble 69 | ``` 70 | 71 | Note that many of these aliases are already supported by `GEF` (e.g. `eb`). 72 | 73 | Or here are some `PEDA` aliases for people used to using `PEDA` who made the 74 | smart move to `GEF`. 75 | 76 | ``` 77 | # some peda aliases 78 | telescope = dereference 79 | start = entry-break 80 | stack = dereference $sp 10 81 | argv = show args 82 | kp = info stack 83 | findmem = search-pattern 84 | ``` 85 | 86 | The aliases will be loaded next time you load GDB (and `GEF`). Or you can force 87 | `GEF` to reload the settings with the command: 88 | 89 | ``` 90 | gef➤ gef restore 91 | ``` 92 | -------------------------------------------------------------------------------- /docs/commands/pie.md: -------------------------------------------------------------------------------- 1 | ## Command pie ## 2 | 3 | The `pie` command provides a useful way to set breakpoint to a PIE enabled binary. 4 | `pie` command then provides what we call "PIE breakpoint". A PIE breakpoint is just 5 | a virtual breakpoint which will be set to real breakpoint when the process is attaching. 6 | A PIE breakpoint's address is the offset from binary base address. 7 | 8 | Note that you need to use ENTIRE PIE COMMAND SERIES to support PIE breakpoint, especially the 9 | "attaching" commands provided by `pie` command, like `pie attach`, `pie run`, etc. 10 | 11 | Usage is just: 12 | ``` 13 | gef➤ pie 14 | ``` 15 | 16 | 17 | ### `pie breakpoint` command ### 18 | 19 | This command sets a new PIE breakpoint. It can be used like normal `breakpoint` command 20 | in gdb. The location is just the offset from the base address. Breakpoint will not be 21 | set immediately after this command. Instead, it will be set when you use `pie attach`, 22 | `pie run`, `pie remote` to actually attach to a process, so it can resolve the right base 23 | address. 24 | 25 | Usage: 26 | ``` 27 | gef➤ pie breakpoint 28 | ``` 29 | 30 | ### `pie info` command ### 31 | 32 | Since PIE breakpoint is not real breakpoint, this command provide a way to observe the 33 | state of all PIE breakpoints. 34 | 35 | This is just like `info breakpoint` in gdb. 36 | ``` 37 | gef➤ pie info 38 | VNum Num Addr 39 | 1 N/A 0xdeadbeef 40 | ``` 41 | 42 | The VNum is the virtual number, which is the number of the PIE breakpoint. The Num is the 43 | number of the according real breakpoint number in gdb. Address is the PIE breakpoint's 44 | address. 45 | 46 | You can ignore VNum argument to get info of all PIE breakpoints. 47 | 48 | Usage: 49 | ``` 50 | gef➤ pie info [VNum] 51 | 52 | ``` 53 | 54 | 55 | ### `pie delete` command ### 56 | 57 | This command deletes a PIE breakpoint given a VNum of that PIE breakpoint. 58 | 59 | Usage: 60 | ``` 61 | gef➤ pie delete 62 | ``` 63 | 64 | 65 | ### `pie attach` command ### 66 | 67 | The same as gdb's `attach` command. Always use this command instead of raw `attach` 68 | if you have PIE breakpoint. This will set real breakpoint when attaching. 69 | 70 | The usage is just the same as `attach`. 71 | 72 | ### `pie remote` command ### 73 | The same as gdb's `remote` command. Always use this command instead of raw `remote` 74 | if you have PIE breakpoint. This will set real breakpoint when attaching. 75 | 76 | The usage is just the same as `remote`. 77 | 78 | ### `pie run` command ### 79 | The same as gdb's `run` command. Always use the command instead of raw `run` if you 80 | have PIE breakpoint. This will set real breakpoint when attaching. 81 | 82 | The usage is just the same as `run`. 83 | -------------------------------------------------------------------------------- /docs/commands/dereference.md: -------------------------------------------------------------------------------- 1 | ## Command dereference 2 | 3 | The `dereference` command (also aliased `telescope` for PEDA former users) aims 4 | to simplify the dereferencing of an address in GDB to determine the content it 5 | actually points to. 6 | 7 | It is a useful convienence function to spare to process of manually tracking 8 | values with successive `x/x` in GDB. 9 | 10 | `dereference` takes two optional arguments, an address (or symbol or register, etc) 11 | to dereference (by default, `$sp`) and the number of consecutive addresses to 12 | dereference (by default, `10`): 13 | 14 | ``` 15 | gef➤ dereference 16 | 0x00007fffffffdec0│+0x0000: 0x00007ffff7ffe190 → 0x0000555555554000 → jg 0x555555554047 ← $rsp, $r13 17 | 0x00007fffffffdec8│+0x0008: 0x00007ffff7ffe730 → 0x00007ffff7fd3000 → 0x00010102464c457f 18 | 0x00007fffffffded0│+0x0010: 0x00007ffff7faa000 → 0x00007ffff7de9000 → 0x03010102464c457f 19 | 0x00007fffffffded8│+0x0018: 0x00007ffff7ffd9f0 → 0x00007ffff7fd5000 → 0x00010102464c457f 20 | 0x00007fffffffdee0│+0x0020: 0x00007fffffffdee0 → [loop detected] 21 | 0x00007fffffffdee8│+0x0028: 0x00007fffffffdee0 → 0x00007fffffffdee0 → [loop detected] 22 | 0x00007fffffffdef0│+0x0030: 0x00000000f7fa57e3 23 | 0x00007fffffffdef8│+0x0038: 0x0000555555755d60 → 0x0000555555554a40 → cmp BYTE PTR [rip+0x201601], 0x0 # 0x555555756048 24 | 0x00007fffffffdf00│+0x0040: 0x0000000000000004 25 | 0x00007fffffffdf08│+0x0048: 0x0000000000000001 26 | ``` 27 | 28 | Here is an example with arguments: 29 | 30 | ``` 31 | gef➤ telescope $rbp+0x10 8 32 | 0x00007fffffffdf40│+0x0000: 0x00007ffff7fa5760 → 0x00000000fbad2887 33 | 0x00007fffffffdf48│+0x0008: 0x00000001f7e65b63 34 | 0x00007fffffffdf50│+0x0010: 0x0000000000000004 35 | 0x00007fffffffdf58│+0x0018: 0x0000000000000000 36 | 0x00007fffffffdf60│+0x0020: 0x00007fffffffdfa0 → 0x0000555555554fd0 → push r15 37 | 0x00007fffffffdf68│+0x0028: 0x0000555555554980 → xor ebp, ebp 38 | 0x00007fffffffdf70│+0x0030: 0x00007fffffffe080 → 0x0000000000000001 39 | 0x00007fffffffdf78│+0x0038: 0x0000000000000000 40 | ``` 41 | 42 | It also optionally accepts a second argument, the number of consecutive 43 | addresses to dereference (by default, `10`). 44 | 45 | For example, if you want to dereference all the stack entries inside a function 46 | context (on a 64bit architecture): 47 | 48 | ``` 49 | gef➤ p ($rbp - $rsp)/8 50 | $3 = 4 51 | gef➤ dereference 5 52 | 0x00007fffffffe170│+0x0000: 0x0000000000400690 → push r15 ← $rsp 53 | 0x00007fffffffe178│+0x0008: 0x0000000000400460 → xor ebp, ebp 54 | 0x00007fffffffe180│+0x0010: 0x00007fffffffe270 → 0x1 55 | 0x00007fffffffe188│+0x0018: 0x1 56 | 0x00007fffffffe190│+0x0020: 0x0000000000400690 → push r15 ← $rbp 57 | ``` 58 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: GEF-Legacy - GDB Enhanced Features (for GDB-Python2) documentation 2 | theme: readthedocs 3 | nav: 4 | - Home: index.md 5 | - Configuration: config.md 6 | - Frequently Asked Questions: faq.md 7 | - Extending GEF: api.md 8 | - Features: commands.md 9 | - Screenshots: screenshots.md 10 | - Command aliases: commands/aliases.md 11 | - Command aslr: commands/aslr.md 12 | - Command assemble: commands/assemble.md 13 | - Command canary: commands/canary.md 14 | - Command capstone-disassemble: commands/capstone-disassemble.md 15 | - Command checksec: commands/checksec.md 16 | - Command config: commands/config.md 17 | - Command context: commands/context.md 18 | - Command dereference: commands/dereference.md 19 | - Command edit-flags: commands/edit-flags.md 20 | - Command elf-info: commands/elf-info.md 21 | - Command entry-break: commands/entry-break.md 22 | - Command eval: commands/eval.md 23 | - Command format-string-helper: commands/format-string-helper.md 24 | - Command functions: commands/functions.md 25 | - Command gef-remote: commands/gef-remote.md 26 | - Command got: commands/got.md 27 | - Command heap-analysis-helper: commands/heap-analysis-helper.md 28 | - Command heap: commands/heap.md 29 | - Command help: commands/help.md 30 | - Command hexdump: commands/hexdump.md 31 | - Command highlight: commands/highlight.md 32 | - Command hijack-fd: commands/hijack-fd.md 33 | - Command ida-interact: commands/ida-interact.md 34 | - Command is-syscall: commands/is-syscall.md 35 | - Command ksymaddr: commands/ksymaddr.md 36 | - Command memory: commands/memory.md 37 | - Command name-break: commands/name-break.md 38 | - Command nop: commands/nop.md 39 | - Command patch: commands/patch.md 40 | - Command pattern: commands/pattern.md 41 | - Command pcustom: commands/pcustom.md 42 | - Command pie: commands/pie.md 43 | - Command print-format: commands/print-format.md 44 | - Command process-search: commands/process-search.md 45 | - Command process-status: commands/process-status.md 46 | - Command registers: commands/registers.md 47 | - Command reset-cache: commands/reset-cache.md 48 | - Command ropper: commands/ropper.md 49 | - Command scan: commands/scan.md 50 | - Command search-pattern: commands/search-pattern.md 51 | - Command set-permission: commands/set-permission.md 52 | - Command shellcode: commands/shellcode.md 53 | - Command stub: commands/stub.md 54 | - Command syscall-args: commands/syscall-args.md 55 | - Command theme: commands/theme.md 56 | - Command tmux-setup: commands/tmux-setup.md 57 | - Command trace-run: commands/trace-run.md 58 | - Command unicorn-emulate: commands/unicorn-emulate.md 59 | - Command vmmap: commands/vmmap.md 60 | - Command xfiles: commands/xfiles.md 61 | - Command xinfo: commands/xinfo.md 62 | - Command xor-memory: commands/xor-memory.md 63 | -------------------------------------------------------------------------------- /docs/commands/heap-analysis-helper.md: -------------------------------------------------------------------------------- 1 | ## Command heap-analysis-helper ## 2 | 3 | `heap-analysis-helper` command aims to help the process of idenfitying Glibc 4 | heap inconsistencies by tracking and analyzing allocations and deallocations of 5 | chunks of memory. 6 | 7 | Currently, the following issues can be tracked: 8 | 9 | * NULL free 10 | * Use-after-Free 11 | * Double Free 12 | * Heap overlap 13 | 14 | The helper can simply be activated by running the command `heap-analysis-helper`. 15 | 16 | ``` 17 | gef➤ heap-analysis 18 | [+] Tracking malloc() 19 | [+] Tracking free() 20 | [+] Disabling hardware watchpoints (this may increase the latency) 21 | [+] Dynamic breakpoints correctly setup, GEF will break execution if a possible vulnerabity is found. 22 | [+] To disable, clear the malloc/free breakpoints (`delete breakpoints`) and restore hardware breakpoints (`set can-use-hw-watchpoints 1`) 23 | ``` 24 | 25 | The helper will create specifically crafted breakoints to keep tracks of 26 | allocation, which allows to discover *potential* vulnerabilities. Once 27 | activated, one can disable the heap analysis breakpoints simply by clearing the 28 | `__GI___libc_free()` et `__GI___libc_malloc()`. It is also possible to 29 | enable/disable manually punctual checks via the `gef config` command. 30 | 31 | The following settings are accepted: 32 | 33 | * `check_null_free`: to break execution when a free(NULL) is encountered 34 | (disabled by default); 35 | * `check_double_free`: to break execution when a double free is encountered; 36 | 37 | ![double-free](https://i.imgur.com/S7b4FJa.png) 38 | 39 | * `check_weird_free`: to execution when `free()` is called against a 40 | non-tracked pointer; 41 | * `check_uaf`: to break execution when a possible Use-after-Free condition is 42 | found. 43 | 44 | ![uaf](https://i.imgur.com/NfV5Cu9.png) 45 | 46 | Just like the format string vulnerability helper, the `heap-analysis-helper` 47 | can fail to detect complex heap scenarios and/or provide some false positive 48 | alerts. Each finding must of course be ascertained manually. 49 | 50 | The `heap-analysis-helper` can also be used to simply track allocation and 51 | liberation of chunks of memory. One can simply enable the tracking by setting 52 | all the configurations stated above to False: 53 | 54 | ``` 55 | gef➤ gef config heap-analysis-helper.check_double_free False 56 | gef➤ gef config heap-analysis-helper.check_free_null False 57 | gef➤ gef config heap-analysis-helper.check_weird_free False 58 | gef➤ gef config heap-analysis-helper.check_uaf False 59 | ``` 60 | 61 | Then `gef` will not notify you of any inconsistency detected, but simply display 62 | a clear message when a chunk is allocated/freed. 63 | 64 | ![heap-track](https://i.imgur.com/68NGTvw.png) 65 | 66 | To get information regarding the currently tracked chunks, use the `show` 67 | subcommand: 68 | 69 | ``` 70 | gef➤ heap-analysis-helper show 71 | ``` 72 | 73 | ![heap-analysis-helper-show](http://i.imgur.com/0I4jBWJ.png) 74 | -------------------------------------------------------------------------------- /docs/commands/gef-remote.md: -------------------------------------------------------------------------------- 1 | ## Command gef-remote ## 2 | 3 | It is possible to use `gef` in a remote debugging environment. Required files 4 | will be automatically downloaded and cached in a temporary directory (`/tmp/gef` on most 5 | Unix systems). Remember to manually delete the cache if you change the target file or 6 | `gef` will use the outdated version. 7 | 8 | 9 | ### With a local copy ### 10 | 11 | If you want to remotely debug a binary that you already have, you simply need to 12 | tell to `gdb` where to find the debug information. 13 | 14 | For example, if we want to debug `uname`, we do on the server: 15 | ``` 16 | $ gdbserver 0.0.0.0:1234 /bin/uname 17 | Process /bin/uname created; pid = 32280 18 | Listening on port 1234 19 | ``` 20 | ![](https://i.imgur.com/Zc4vnBd.png) 21 | 22 | And on the client, simply run `gdb`: 23 | 24 | ``` 25 | $ gdb /bin/uname 26 | gef➤ target remote 192.168.56.1:1234 27 | Process /bin/uname created; pid = 10851 28 | Listening on port 1234 29 | ``` 30 | 31 | Or 32 | 33 | ``` 34 | $ gdb 35 | gef➤ file /bin/uname 36 | gef➤ target remote 192.168.56.1:1234 37 | ``` 38 | 39 | 40 | ### Without a local copy ### 41 | 42 | It is possible to use `gdb` internal functions to copy our targeted binary. 43 | 44 | Following our previous example, if we want to debug `uname`, run `gdb` and 45 | connect to our `gdbserver`. To be able to locate the right process in the 46 | `/proc` structure, the command `gef-remote` requires 1 argument, the target 47 | host and port. The option `-p` must be provided and indicate the process PID 48 | on the remote host, only if the extended mode (`-E`) is being used. 49 | 50 | ``` 51 | $ gdb 52 | gef➤ gef-remote 192.168.56.1:1234 53 | [+] Connected to '192.168.56.1:1234' 54 | [+] Downloading remote information 55 | [+] Remote information loaded, remember to clean '/tmp/gef/10851' when your session is over 56 | ``` 57 | 58 | As you can observe, if it cannot find the debug information, `gef` will try to 59 | automatically download the target file and store in the local temporary 60 | directory (on most Unix `/tmp`). If successful, it will then automatically load 61 | the debug information to `gdb` and proceed with the debugging. 62 | 63 | ![gef-remote-autodownload](https://i.imgur.com/8JHpOTV.png) 64 | 65 | You can then reuse the downloaded file for your future debugging sessions, use it under IDA 66 | and such. This makes the entire remote debugging process (particularly for Android applications) 67 | a child's game. 68 | 69 | 70 | ### QEMU-user mode ### 71 | 72 | Although GDB through QEMU-user works, QEMU only supports a limited subset of all 73 | commands existing in the `gdbremote` protocol. For example, commands such as 74 | `remote get` or `remote put` (to download and upload a file from remote target, 75 | respectively) are not supported. As a consequence, the default `remote` mode 76 | for `gef` will not work either, as `gef` won't be able to fetch the content of 77 | the remote procfs. 78 | 79 | To circumvent this and still enjoy `gef` features with QEMU-user, a simple stub 80 | can be artificially added, with the option `-q` option of `gef-remote`. Note 81 | that you need to set the architecture properly first: 82 | 83 | ``` 84 | $ qemu-arm -g 1234 ./my/arm/binary 85 | $ gdb-multiarch ./my/arm/binary 86 | gef➤ set architecture arm 87 | gef➤ gef-remote -q localhost:1234 88 | ``` 89 | 90 | ![gef-qemu-user](http://i.imgur.com/JtEQndv.png) 91 | -------------------------------------------------------------------------------- /docs/config.md: -------------------------------------------------------------------------------- 1 | ## Install GEF 2 | 3 | There is **NO mandatory dependency** to have `gef` running contrarily to other projects. 4 | A simple recent GDB compiled with Python scripting support will do. 5 | 6 | 7 | ### Pre-requisites 8 | Only [GDB 7.7 and higher](https://www.gnu.org/s/gdb) is required. It must be 9 | compiled with Python 2 or 3 support. 10 | 11 | All recent distributions of Linux now embeds a GDB version compiled with at 12 | least Python 2 (although more and more are migrating towards Python 3). 13 | 14 | You can verify it with the following command: 15 | 16 | ```bash 17 | $ gdb -nx -ex 'pi print(sys.version)' -ex quit 18 | ``` 19 | 20 | This should display your version of Python compiled with `gdb`. 21 | 22 | For example, with Python2 23 | ```bash 24 | $ gdb -nx -ex 'pi print(sys.version)' -ex quit 25 | 2.7.3 (default, Mar 18 2014, 06:31:17) 26 | [GCC 4.6.3] 27 | ``` 28 | 29 | Or Python3 30 | ```bash 31 | $ gdb -nx -ex 'pi print(sys.version)' -ex quit 32 | 3.4.0 (default, Apr 11 2014, 13:08:40) 33 | [GCC 4.8.2] 34 | ``` 35 | 36 | If you see an error here, it means that your GDB installation does not support Python. 37 | 38 | **Note**: If your GDB is compiled with Python3, `GEF` will assume that your 39 | environment locales are in UTF-8 (which is the standard). If you use on purpose 40 | another locales, you may expect `Unicode` exceptions preventing many commands to 41 | work as expected. Please set up your locales to `UTF-8` to have `GEF` running 42 | smoothly. 43 | 44 | 45 | ### Setup from repository 46 | 47 | The best way to use `GEF` is through cloning the git repository from GitHub, and 48 | then sourcing the file from your `~/.gdbinit`. 49 | 50 | ```bash 51 | $ git clone https://github.com/hugsy/gef.git # or git pull to update 52 | $ echo 'source /path/to/gef.py' >> ~/.gdbinit 53 | ``` 54 | 55 | ### One-time setup script 56 | 57 | If you only need `GEF` for a one-time environment (VMs, etc.) that do not 58 | have/need `git` installed, just go with: 59 | 60 | ```bash 61 | $ curl -s -L https://github.com/hugsy/gef/raw/master/scripts/gef.sh | sh 62 | ``` 63 | 64 | ### Optional dependencies 65 | 66 | A few commands were added to `GEF` to extend its capabilities. It is 67 | highly recommended to install the following modules (but not required): 68 | 69 | - [`capstone`](https://github.com/aquynh/capstone) - disassembly engine 70 | - [`Ropper`](https://github.com/sashs/Ropper) - an improved version of [`ROPgadget`](https://github.com/JonathanSalwan/ROPgadget) 71 | - [`unicorn`](https://github.com/unicorn-engine/unicorn) - emulation engine 72 | - [`keystone`](https://github.com/keystone-engine/keystone) - assembly engine 73 | 74 | Some of those modules can be installed through `python-pip`. The following 75 | commands will work for most distributions, but substitute `pip3` for versions of `gdb` compiled with Python 3: 76 | ```bash 77 | $ pip install capstone 78 | $ pip install ropper 79 | ``` 80 | 81 | Please refer to each project for installation and troubleshooting guides. As 82 | `gef` works out of the box, please do not send issues to this project if you 83 | have problems while installing those modules. 84 | 85 | `gef` will assume the module installations are valid. Otherwise, it will 86 | automatically disable all the `gef` commands that require this invalid module. 87 | 88 | 89 | ### Check setup 90 | 91 | To check that `GEF` has been correctly installed, simply start a new `gdb` 92 | session against any binary. 93 | ```bash 94 | $ gdb -q /bin/ls 95 | ``` 96 | 97 | You should see the following header and prompt 98 | ```bash 99 | $ gdb -q /bin/ls 100 | gef loaded, `gef help' to start, `gef config' to configure 101 | 37 commands loaded (15 sub-commands), using Python engine 3.5 102 | Reading symbols from /bin/ls...(no debugging symbols found)...done. 103 | gef➤ 104 | ``` 105 | -------------------------------------------------------------------------------- /docs/commands/heap.md: -------------------------------------------------------------------------------- 1 | ## Command heap ## 2 | 3 | The `heap` command provides information on the heap chunk specified as argument. For 4 | the moment, it only supports GlibC heap format (see 5 | [this link](http://code.woboq.org/userspace/glibc/malloc/malloc.c.html#malloc_chunk) 6 | for `malloc` structure information). Syntax to the subcommands is straight forward: 7 | 8 | ``` 9 | gef➤ heap 10 | ``` 11 | 12 | 13 | ### `heap chunks` command ### 14 | 15 | Displays all the chunks from the `heap` section. 16 | 17 | ``` 18 | gef➤ heap chunks 19 | ``` 20 | 21 | In some cases, the allocation will start immediately from start of the page. If 22 | so, specify the base address of the first chunk as follow: 23 | 24 | ``` 25 | gef➤ heap chunks 26 | ``` 27 | 28 | ![heap-chunks](https://i.imgur.com/2Ew2fA6.png) 29 | 30 | 31 | ### `heap chunk` command ### 32 | 33 | This command gives visual information of a Glibc malloc-ed chunked. Simply 34 | provide the address to the user memory pointer of the chunk to show the 35 | information related to a specific chunk: 36 | 37 | ``` 38 | gef➤ heap chunk 39 | ``` 40 | 41 | ![heap-chunk](https://i.imgur.com/SAWNptW.png) 42 | 43 | 44 | 45 | ### `heap arenas` command ### 46 | 47 | Multi-threaded programs have different arenas, and the knowledge of the 48 | `main_arena` is not enough. `gef` therefore provides the `arena` sub-commands 49 | to help you list all the arenas allocated in your program **at the moment you 50 | call the command**. 51 | 52 | ![heap-arenas](https://i.imgur.com/ajbLiCF.png) 53 | 54 | 55 | 56 | ### `heap set-arena` command ### 57 | 58 | In cases where the debug symbol are not present (e.g. statically stripped 59 | binary), it is possible to instruct GEF to find the `main_arena` at a different 60 | location with the command: 61 | 62 | ``` 63 | gef➤ heap set-arena 64 | ``` 65 | 66 | If the arena address is correct, all `heap` commands will be functional, and use 67 | the specified address for `main_arena`. 68 | 69 | 70 | ### `heap bins` command ### 71 | 72 | Glibc uses bints for keeping tracks of `free`d chunks. This is because making 73 | allocations through `sbrk` (requiring a syscall) is costly. Glibc uses those 74 | bins to remember formerly allocated chunks. Because bins are structured in 75 | single or doubly linked list, I found that quite painful to always interrogate 76 | `gdb` to get a pointer address, dereference it, get the value chunk, etc... So 77 | I decided to implement the `heap bins` sub-command, which allows to get info 78 | on: 79 | 80 | - `fastbins` 81 | - `bins` 82 | - `unsorted` 83 | - `small bins` 84 | - `large bins` 85 | 86 | 87 | #### `heap bins fast` command #### 88 | 89 | When exploiting heap corruption vulnerabilities, it is sometimes convenient to 90 | know the state of the `fastbinsY` array. 91 | 92 | The `fast` sub-command helps by displaying the list of fast chunks in this 93 | array. Without any other argument, it will display the info of the `main_arena` 94 | arena. It accepts an optional argument, the address of another arena (which you 95 | can easily find using `heap arenas`). 96 | 97 | ``` 98 | gef➤ heap bins fast 99 | [+] FastbinsY of arena 0x7ffff7dd5b20 100 | Fastbin[0] 0x00 101 | Fastbin[1] → FreeChunk(0x600310) → FreeChunk(0x600350) 102 | Fastbin[2] 0x00 103 | Fastbin[3] 0x00 104 | Fastbin[4] 0x00 105 | Fastbin[5] 0x00 106 | Fastbin[6] 0x00 107 | Fastbin[7] 0x00 108 | Fastbin[8] 0x00 109 | Fastbin[9] 0x00 110 | ``` 111 | 112 | 113 | #### Other `heap bins X` command #### 114 | 115 | All the other subcommands for the `heap bins` work the same way as `fast`. If 116 | no argument is provided, `gef` will fall back to `main_arena`. Otherwise, it 117 | will use the address pointed as the base of the `malloc_state` structure and 118 | print out information accordingly. 119 | -------------------------------------------------------------------------------- /docs/commands/pcustom.md: -------------------------------------------------------------------------------- 1 | ## Command pcustom ## 2 | 3 | `gef` provides a way to create and apply to the currently debugged environment, 4 | any new structure (in the C-struct way). On top of simply displaying known 5 | and user-defined structures, it also allows to apply those structures to the 6 | current context. It intends to mimic the very useful 7 | [WinDBG `dt`](https://msdn.microsoft.com/en-us/library/windows/hardware/ff542772(v=vs.85).aspx) 8 | command. 9 | 10 | This is achieved via the command `pcustom` (for `print custom`), or you can use 11 | its alias, `dt` (in reference to the WinDBG command). 12 | 13 | ### Configuration 14 | 15 | New structures can be stored in the location given by the configuration setting: 16 | ``` 17 | gef➤ gef config pcustom.struct_path 18 | ``` 19 | By default, this location is in `$TEMP/gef/structs` (e.g. `/tmp/user/1000/gef/structs`). 20 | The structure can be created as a simple `ctypes` structure, in a file called 21 | `.py`. 22 | 23 | You can naturally set this path to a new location 24 | ``` 25 | gef➤ gef config pcustom.struct_path /my/new/location 26 | ``` 27 | And save this change so you can re-use it directly next time you use `gdb` 28 | ``` 29 | gef➤ gef save 30 | [+] Configuration saved to '~/.gef.rc' 31 | ``` 32 | 33 | 34 | ### Using user-defined structures 35 | 36 | You can list existing custom structures via 37 | ``` 38 | gef➤ dt -l 39 | [+] Listing custom structures: 40 | → struct5 41 | → struct6 42 | ``` 43 | 44 | To create or edit a structure, use `dt -e` to spawn your EDITOR 45 | with the targeted structure. If the file does not exist, `gef` will nicely 46 | create the tree and file, and fill it with a `ctypes` template that you can use 47 | straight away! 48 | ``` 49 | gef➤ dt mystruct_t -e 50 | [+] Creating '/tmp/gef/structs/mystruct_t.py' from template 51 | ``` 52 | 53 | The code can be defined just as any Python (using `ctypes`) code. 54 | 55 | ``` 56 | from ctypes import * 57 | 58 | ''' 59 | typedef struct { 60 | int age; 61 | char name[256]; 62 | int id; 63 | } person_t; 64 | ''' 65 | 66 | class person_t(Structure): 67 | _fields_ = [ 68 | ("age", c_int), 69 | ("name", c_char * 256), 70 | ("id", c_int), 71 | ] 72 | 73 | _values_ = [ 74 | # You can define a function to substitute the value 75 | ("age", lambda age: "Old" if age > 40 else "Young"), 76 | # Or alternatively a list of 2-tuples 77 | ("id", [ 78 | (0, "root"), 79 | (1, "normal user"), 80 | (None, "Invalid person") 81 | ]) 82 | ] 83 | ``` 84 | 85 | `pcustom` requires at least one argument, which is the name of the 86 | structure. With only one argument, `pcustom` will dump all the fields of this 87 | structure. 88 | 89 | ``` 90 | gef➤ dt person_t 91 | +0000 age c_int (0x4) → Young 92 | +0004 name c_char_Array_256 (0x100) 93 | +0104 id c_int (0x1) → normal user 94 | ``` 95 | 96 | 97 | 98 | By providing an address or a GDB symbol, `gef` will apply this user-defined 99 | structure to the specified address: 100 | 101 | ![gef-pcustom-with-address](https://i.imgur.com/vWGnu5g.png) 102 | 103 | This means that we can now create very easily new user-defined structures 104 | 105 | Watch the demonstration video on Asciinema: 106 | 107 | [![asciicast](https://asciinema.org/a/bhsguibtf4iqyyuomp3vy8iv2.png)](https://asciinema.org/a/bhsguibtf4iqyyuomp3vy8iv2) 108 | 109 | Additionally, if you have successfully configured your IDA settings (see command 110 | `ida-interact`), you can also directly import the structure(s) that was(were) 111 | reverse-engineered in IDA directly in your GDB session: 112 | 113 | ![ida-structure-examples](https://i.imgur.com/Tnsf6nt.png) 114 | 115 | And then use the command `ida ImportStructs` to import all the structures, or 116 | `ida ImportStruct ` to only import a specific one: 117 | 118 | ``` 119 | gef➤ ida ImportStructs 120 | [+] Success 121 | ``` 122 | 123 | Which will become: 124 | 125 | ![ida-structure-imported](https://i.imgur.com/KVhyopO.png) 126 | 127 | -------------------------------------------------------------------------------- /tests/helpers.py: -------------------------------------------------------------------------------- 1 | import re 2 | import os 3 | import subprocess 4 | 5 | PATH_TO_DEFAULT_BINARY = "./tests/binaries/default.out" 6 | STRIP_ANSI_DEFAULT = True 7 | 8 | 9 | def which(program): 10 | """Locate a command on the filesystem.""" 11 | def is_exe(fpath): 12 | return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 13 | 14 | fpath = os.path.split(program)[0] 15 | if fpath: 16 | if is_exe(program): 17 | return program 18 | else: 19 | for path in os.environ["PATH"].split(os.pathsep): 20 | path = path.strip('"') 21 | exe_file = os.path.join(path, program) 22 | if is_exe(exe_file): 23 | return exe_file 24 | 25 | raise IOError("Missing file `{:s}`".format(program)) 26 | 27 | try: 28 | gdb = os.getenv("GDB") 29 | if not gdb: 30 | raise IOError("nop") 31 | GDB = which(gdb) 32 | print("Using '{}'".format(GDB)) 33 | except IOError: 34 | GDB = which("gdb") 35 | print("Using '{}'".format(GDB)) 36 | 37 | def ansi_clean(s): 38 | ansi_escape = re.compile(r"(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]") 39 | return ansi_escape.sub("", s) 40 | 41 | 42 | def gdb_run_cmd(cmd, before=None, after=None, target=PATH_TO_DEFAULT_BINARY, strip_ansi=STRIP_ANSI_DEFAULT): 43 | """Execute a command inside GDB. `before` and `after` are lists of commands to be executed 44 | before (resp. after) the command to test.""" 45 | command = [ 46 | GDB, "-q", "-nx", 47 | "-ex", "source /tmp/gef.py", 48 | "-ex", "gef config gef.debug True" 49 | ] 50 | 51 | if before: 52 | for _ in before: command += ["-ex", _] 53 | 54 | command += ["-ex", cmd] 55 | 56 | if after: 57 | for _ in after: command += ["-ex", _] 58 | 59 | command += ["-ex", "quit", "--", target] 60 | 61 | lines = subprocess.check_output(command, stderr=subprocess.STDOUT).strip().splitlines() 62 | result = b"\n".join(lines).decode("utf-8") 63 | 64 | if strip_ansi: 65 | result = ansi_clean(result) 66 | 67 | return result 68 | 69 | 70 | def gdb_run_silent_cmd(cmd, before=None, after=None, target=PATH_TO_DEFAULT_BINARY, strip_ansi=STRIP_ANSI_DEFAULT): 71 | """Disable the output and run entirely the `target` binary.""" 72 | if not before: 73 | before = [] 74 | 75 | before += ["gef config context.clear_screen False", 76 | "gef config context.layout '-code -stack'", 77 | "run"] 78 | return gdb_run_cmd(cmd, before, after, target, strip_ansi) 79 | 80 | 81 | def gdb_run_cmd_last_line(cmd, before=None, after=None, target=PATH_TO_DEFAULT_BINARY, strip_ansi=STRIP_ANSI_DEFAULT): 82 | """Execute a command in GDB, and return only the last line of its output.""" 83 | return gdb_run_cmd(cmd, before, after, target, strip_ansi).splitlines()[-1] 84 | 85 | 86 | def gdb_start_silent_cmd(cmd, before=None, after=None, target=PATH_TO_DEFAULT_BINARY, strip_ansi=STRIP_ANSI_DEFAULT): 87 | """Execute a command in GDB by starting an execution context. This command disables the `context` 88 | and sets a tbreak at the most convenient entry point.""" 89 | if not before: 90 | before = [] 91 | 92 | before += ["gef config context.clear_screen False", 93 | "gef config context.layout '-code -stack'", 94 | "entry-break"] 95 | return gdb_run_cmd(cmd, before, after, target, strip_ansi) 96 | 97 | 98 | def gdb_start_silent_cmd_last_line(cmd, before=None, after=None, target=PATH_TO_DEFAULT_BINARY, strip_ansi=STRIP_ANSI_DEFAULT): 99 | """Execute `gdb_start_silent_cmd()` and return only the last line of its output.""" 100 | return gdb_start_silent_cmd(cmd, before, after, target, strip_ansi).splitlines()[-1] 101 | 102 | 103 | def gdb_test_python_method(meth, before="", after="", target=PATH_TO_DEFAULT_BINARY, strip_ansi=STRIP_ANSI_DEFAULT): 104 | cmd = "pi {}print({});{}".format(before+";" if before else "", meth, after) 105 | return gdb_start_silent_cmd(cmd, target=target, strip_ansi=strip_ansi) 106 | -------------------------------------------------------------------------------- /docs/commands.md: -------------------------------------------------------------------------------- 1 | # Features # 2 | 3 | This section will explain in details some non-trivial commands available in `GEF` 4 | with examples and screenshots to make it easier to reproduce. 5 | 6 | __Note__: if you consider the documentation to be imprecise/incomplete, 7 | file an [Issue](https://github.com/hugsy/gef/issues/86) or better, 8 | create a a [Pull Request](https://github.com/hugsy/gef/pulls) to the project to help 9 | improve it. 10 | 11 | | Command | Description | 12 | |:-----------|----------------:| 13 | |aliases | GEF defined aliases| 14 | |aslr | View/modify GDB ASLR behavior.| 15 | |assemble | Inline code assemble. Architecture can be set in GEF runtime config (default is x86). (alias: asm) | 16 | |capstone-disassemble | Use capstone disassembly framework to disassemble code. (alias: cs-dis) | 17 | |checksec | Checksec.sh(http://www.trapkit.de/tools/checksec.html) port. | 18 | |context | Display execution context. (alias: ctx)| 19 | |dereference | Dereference recursively an address and display information (alias: telescope, dps)| 20 | |edit-flags | Edit flags in a human friendly way (alias: flags)| 21 | |elf-info | Display ELF header informations.| 22 | |entry-break | Tries to find best entry point and sets a temporary breakpoint on it. (alias: start-break)| 23 | |format-string-helper | Exploitable format-string helper: this command will set up specific breakpoints at well-known dangerous functions (printf, snprintf, etc.), and check if the pointer holding the format string is writable, and susceptible to format string attacks if an attacker can control its content. (alias: fmtstr-helper)| 24 | |functions | List the convenience functions provided by GEF.| 25 | |gef-remote | gef wrapper for the `target remote` command. This command will automatically download the target binary in the local temporary directory (defaut /tmp) and then source it. Additionally, it will fetch all the /proc/PID/maps and loads all its information.| 26 | |heap | Base command to get information about the Glibc heap structure.| 27 | |heap-analysis-helper | Tracks dynamic heap allocation through malloc/free to try to detect heap vulnerabilities.| 28 | |hexdump | Display arranged hexdump (according to architecture endianness) of memory range.| 29 | |highlight | Highlight text using custom matches.| 30 | |hijack-fd | ChangeFdCommand: redirect file descriptor during runtime.| 31 | |ida-interact | IDA Interact: set of commands to interact with IDA via a XML RPC service deployed via the IDA script `ida_gef.py`. It should be noted that this command can also be used to interact with Binary Ninja (using the script `binja_gef.py`) using the same interface. (alias: binaryninja-interact, bn, binja)| 32 | |is-syscall | Tells whether the next instruction to be executed is a system call.| 33 | |ksymaddr | Solve kernel symbols from kallsyms table.| 34 | |memory | Add memory watches to the context view.| 35 | |nop | Patch the instruction pointed by parameters with NOP. If the return option is specified, it will set the return register to the specific value.| 36 | |patch | Write specified values to the specified address.| 37 | |pattern | This command will create or search a De Bruijn cyclic pattern to facilitate determining the offset in memory. The algorithm used is the same as the one used by pwntools, and can therefore be used in conjunction.| 38 | |pcustom | Dump user defined structure. This command attempts to reproduce WinDBG awesome `dt` command for GDB and allows to apply structures (from symbols or custom) directly to an address. Custom structures can be defined in pure Python using ctypes, and should be stored in a specific directory, whose path must be stored in the `pcustom.struct_path` configuration setting. (alias: dt)| 39 | |pie | Base command to support PIE breakpoints. PIE breakpoints is that you can set to a PIE binary, and use pie series commands to attach or create a new process, and it will automatically set the real breakpoint when the binary is running. 40 | |process-search | List and filter process. (alias: ps)| 41 | |process-status | Extends the info given by GDB `info proc`, by giving an exhaustive description of the process status.| 42 | |registers | Display full details on one, many or all registers value from current architecture.| 43 | |reset-cache | Reset cache of all stored data.| 44 | |ropper | Ropper (http://scoding.de/ropper) plugin| 45 | |scan | Search for addresses that are located in a memory mapping (haystack) that belonging to another (needle). (alias: lookup)| 46 | |search-pattern | SearchPatternCommand: search a pattern in memory. (alias: grep)| 47 | |set-permission | Change a page permission. By default, it will change it to RWX. (alias: mprotect)| 48 | |shellcode | ShellcodeCommand uses @JonathanSalwan simple-yet-awesome shellcode API to download shellcodes.| 49 | |stub | Stub out the specified function.| 50 | |syscall-args | Gets the syscall name and arguments based on the register values in the current state.| 51 | |trace-run | Create a runtime trace of all instructions executed from $pc to LOCATION specified.| 52 | |unicorn-emulate | Use Unicorn-Engine to emulate the behavior of the binary, without affecting the GDB runtime. By default the command will emulate only the next instruction, but location and number of instruction can be changed via arguments to the command line. By default, it will emulate the next instruction from current PC. (alias: emulate)| 53 | |vmmap | Display virtual memory mapping| 54 | |xfiles | Shows all libraries (and sections) loaded by binary (The truth is out there).| 55 | |xinfo | Get virtual section information for specific address| 56 | |xor-memory | XOR a block of memory.| 57 | -------------------------------------------------------------------------------- /docs/commands/context.md: -------------------------------------------------------------------------------- 1 | ## Command context ## 2 | 3 | ![gef-context](https://i.imgur.com/aZiG8Yb.png) 4 | 5 | 6 | `gef` (not unlike `PEDA` or `fG! famous gdbinit`) provides comprehensive context 7 | menu when hitting a breakpoint. 8 | 9 | * The register context box displays current register values. Values in red 10 | indicate that this register has had its value changed since the last 11 | time execution stopped. It makes it convenient to track values. Register 12 | values can be also accessed and/or dereferenced through the `reg` command. 13 | 14 | * The stack context box shows the 10 (by default but can be tweaked) entries in 15 | memory pointed by the stack pointer register. If those values are pointers, 16 | they are successively dereferenced. 17 | 18 | * The code context box shows the 10 (by default but can be tweaked) next 19 | instructions to be executed. 20 | 21 | 22 | ### Editing context layout ### 23 | 24 | `gef` allows you to configure your own setup for the display, by re-arranging 25 | the order with which contexts will be displayed. 26 | 27 | ``` 28 | gef➤ gef config context.layout 29 | ``` 30 | 31 | There are currently 6 sections that can be displayed: 32 | 33 | * `legend` : a text explanation of the color code 34 | * `regs` : the state of registers 35 | * `stack` : the content of memory pointed by `$sp` register 36 | * `code` : the code being executed 37 | * `args` : if stopping at a function calls, print the call arguments 38 | * `source` : if compiled with source, this will show the corresponding line 39 | of source code 40 | * `threads` : all the threads 41 | * `trace` : the execution call trace 42 | * `extra` : if an automatic behavior is detected (vulnerable format string, 43 | heap vulnerability, etc.) it will be displayed in this pane 44 | * `memory` : peek into arbitrary memory locations 45 | 46 | To hide a section, simply use the `context.layout` setting, and prepend the 47 | section name with `-` or just omit it. 48 | 49 | ``` 50 | gef➤ gef config context.layout "-legend regs stack code args -source -threads -trace extra memory" 51 | ``` 52 | This configuration will not display the `source`, `threads`, and `trace` sections. 53 | 54 | The `memory` pane will display the content of all locations specified by the 55 | `memory` command. For instance, 56 | 57 | ``` 58 | gef➤ memory watch $sp 0x40 byte 59 | ``` 60 | 61 | will print a hexdump version of 0x40 bytes of the stack. This command makes it 62 | convenient for tracking the evolution of arbitrary locations in memory. Tracked 63 | locations can be removed one by one using `memory unwatch`, or altogether with 64 | `memory reset`. 65 | 66 | The size of most sections are also customizable: 67 | 68 | * `nb_lines_stack` configures how many lines of the stack to show. 69 | * `nb_lines_backtrack` configures how many lines of the backtrace to show. 70 | * `nb_lines_code` and `nb_lines_code_prev` configure how many lines to show 71 | after and before the PC, respectively. 72 | * `context.nb_lines_threads` determines the number of lines to display inside 73 | the thread pane. This is convenient when debugging heavily multi-threaded 74 | applications (apache2, firefox, etc.). It receives an integer as value: if 75 | this value is `-1` then all threads state will be displayed. Otherwise, if the 76 | value is set to `N`, then at most `N` thread states will be shown. 77 | 78 | To have the stack displayed with the largest stack addresses on top (i.e., grow the 79 | stack downward), enable the following setting: 80 | ``` 81 | gef➤ gef config context.grow_stack_down True 82 | ``` 83 | 84 | If the saved instruction pointer is not within the portion of the stack being displayed, 85 | then a section is created that includes the saved ip and depending on the architecture 86 | the frame pointer. 87 | ``` 88 | 0x00007fffffffc9e8│+0x00: 0x00007ffff7a2d830 → <__main+240> mov edi, eax ($current_frame_savedip) 89 | 0x00007fffffffc9e0│+0x00: 0x00000000004008c0 → <__init+0> push r15 ← $rbp 90 | . . . (440 bytes skipped) 91 | 0x00007fffffffc7e8│+0x38: 0x0000000000000000 92 | 0x00007fffffffc7e0│+0x30: 0x0000000000000026 ("&"?) 93 | 0x00007fffffffc7d8│+0x28: 0x0000000001958ac0 94 | 0x00007fffffffc7d0│+0x20: 0x00007ffff7ffa2b0 → 0x5f6f7364765f5f00 95 | 0x00007fffffffc7c8│+0x18: 0x00007fff00000000 96 | 0x00007fffffffc7c0│+0x10: 0x00007fffffffc950 → 0x0000000000000000 97 | 0x00007fffffffc7b8│+0x08: 0x0000000000000000 98 | 0x00007fffffffc7b0│+0x00: 0x00007fffffffc7e4 → 0x0000000000000000 ← $rsp 99 | ``` 100 | 101 | ### Redirecting context output to another tty/file ### 102 | 103 | By default, the `gef` context will be displayed on the current TTY. This can be 104 | overridden by setting `context.redirect` variable to have the context sent to 105 | another section. 106 | 107 | To do so, select the TTY/file/socket/etc. you want the context redirected to 108 | with `gef config`. 109 | 110 | Enter the command `tty` in the prompt: 111 | ``` 112 | $ tty 113 | /dev/pts/0 114 | ``` 115 | 116 | Then tell `gef` about it! 117 | ``` 118 | gef➤ gef config context.redirect /dev/pts/0 119 | ``` 120 | 121 | Enjoy: 122 | ![gef-context-redirect-section](https://i.imgur.com/sWlX37q.png) 123 | 124 | 125 | To go back to normal, remove the value: 126 | ``` 127 | gef➤ gef config context.redirect "" 128 | ``` 129 | 130 | ### Display individual sections ### 131 | 132 | You can display a single section by specifying it as an argument: 133 | ``` 134 | gef➤ context regs 135 | ``` 136 | 137 | Multiple sections can be provided, even if they are not part of the current layout: 138 | ``` 139 | gef➤ context regs stack 140 | ``` 141 | 142 | ### Examples ### 143 | 144 | * Display the code section first, then register, and stack, hiding everything else: 145 | ``` 146 | gef➤ gef config context.layout "code regs stack" 147 | ``` 148 | 149 | * Stop showing the context sections when breaking: 150 | ``` 151 | gef➤ gef config context.enable 0 152 | ``` 153 | 154 | * Clear the screen before showing the context sections when breaking: 155 | ``` 156 | gef➤ gef config context.clear_screen 1 157 | ``` 158 | 159 | * Don't dereference the registers in the `regs` section (more compact): 160 | ``` 161 | gef➤ gef config context.show_registers_raw 1 162 | ``` 163 | 164 | * Don't 'peek' into the start of functions that are called. 165 | ``` 166 | gef➤ gef config context.peek_calls False 167 | ``` 168 | 169 | * Hide specific registers from the registers view. 170 | ``` 171 | gef➤ gef config context.ignore_registers "$cs $ds $gs" 172 | ``` 173 | -------------------------------------------------------------------------------- /docs/api.md: -------------------------------------------------------------------------------- 1 | # Extending GEF # 2 | 3 | `GEF` intends to provide a battery-included, quickly installable and crazy fast 4 | debugging environment sitting on top of GDB. 5 | 6 | But it most importantly provides all the primitives required to allow hackers to 7 | quickly create their own commands. This page intends to summarize how to 8 | create advanced GDB commands in moments using `GEF` as a library. 9 | 10 | A [dedicated repository](https://github.com/hugsy/gef-extras) was born to host 11 | [external scripts](https://github.com/hugsy/gef-extras/tree/master/scripts). This 12 | repo is open to all for contributions, no restrictions and the most valuable 13 | ones will be integrated into `gef.py`. 14 | 15 | ## Quick start ## 16 | 17 | Here is the most basic skeleton for creating a new `GEF` command named `newcmd`: 18 | 19 | ```python 20 | class NewCommand(GenericCommand): 21 | """Dummy new command.""" 22 | _cmdline_ = "newcmd" 23 | _syntax_ = "{:s}".format(_cmdline_) 24 | 25 | @only_if_gdb_running # not required, ensures that the debug session is started 26 | def do_invoke(self, argv): 27 | # do anything allowed by gef, for example show the current running 28 | # architecture as Python object: 29 | print(" = {}".format(current_arch) ) 30 | # or showing the current $pc 31 | print("pc = {:#x}".format(current_arch.pc)) 32 | return 33 | 34 | register_external_command(NewCommand()) 35 | ``` 36 | 37 | Yes, that's it! 38 | 39 | Loading it in `GEF` is as easy as 40 | ``` 41 | gef➤ source /path/to/newcmd.py 42 | [+] Loading 'NewCommand' 43 | ``` 44 | 45 | We can call it: 46 | 47 | ![](https://camo.githubusercontent.com/d41c1c0c0267916f4749800906d201fe5d328db5/687474703a2f2f692e696d6775722e636f6d2f306734416543622e706e67) 48 | 49 | 50 | ## Detailed explanation ## 51 | 52 | Our new command must be a class that inherits from GEF's `GenericCommand`. The 53 | *only* requirements are: 54 | 55 | * a `_cmdline_` attribute (the command to type on the GDB prompt). 56 | * a `_syntax_` attribute, which GEF will use to auto-generate the help menu. 57 | * a method `do_invoke(self, args)` which will be executed when the command 58 | is invoked. `args` is a list of the command line args provided when invoked. 59 | 60 | We make GEF aware of this new command by registering it in the `__main__` 61 | section of the script, by invoking the global function 62 | `register_external_command()`. 63 | 64 | Now you have a new GEF command which you can load, either from cli: 65 | ``` 66 | gef➤ source /path/to/newcmd.py 67 | ``` 68 | or add to your `~/.gdbinit`: 69 | ``` 70 | $ echo source /path/to/newcmd.py >> ~/.gdbinit 71 | ``` 72 | 73 | ## API ## 74 | 75 | Some of the most important parts of the API for creating new commands are 76 | mentioned (but not limited to) below. To see the full help of a function, open 77 | GDB and GEF, and use the embedded Python interpreter's `help` command. For 78 | example: 79 | 80 | ``` 81 | gef➤ pi help(Architecture) 82 | ``` 83 | 84 | or even from outside GDB: 85 | 86 | ```bash 87 | $ gdb -q -ex 'pi help(hexdump)' -ex quit 88 | ``` 89 | 90 | 91 | ### Globals ### 92 | 93 | ``` 94 | register_external_command() 95 | ``` 96 | > Procedure to add the new GEF command 97 | 98 | 99 | ``` 100 | current_arch 101 | ``` 102 | > Global variable associated with the architecture of the currently debugged 103 | > process. The variable is an instance of the `Architecture` class (see below). 104 | 105 | ``` 106 | read_memory(addr, length=0x10) 107 | ``` 108 | > Returns a `length` long byte array with a copy of the process memory read 109 | > from `addr`. 110 | 111 | ``` 112 | write_memory(addr, buffer, length=0x10) 113 | ``` 114 | > Writes `buffer` to memory at address `addr`. 115 | 116 | 117 | ``` 118 | read_int_from_memory(addr) 119 | ``` 120 | > Reads the size of an integer from `addr`, and unpacks it correctly (based on 121 | > the current arch's endianness) 122 | 123 | ``` 124 | read_cstring_from_memory(addr) 125 | ``` 126 | > Return a NULL-terminated array of bytes, from `addr`. 127 | 128 | 129 | ``` 130 | get_register(register_name) 131 | ``` 132 | > Returns the value of given register. 133 | 134 | 135 | ``` 136 | get_process_maps() 137 | ``` 138 | > Returns an array of Section objects (see below) corresponding to the current 139 | > memory layout of the process. 140 | 141 | 142 | ``` 143 | gef_disassemble(addr, nb_insn, from_top=False) 144 | ``` 145 | > Disassemble `nb_insn` instructions after `addr`. If `from_top` is False 146 | > (default), it will also disassemble the `nb_insn` instructions before `addr`. 147 | > Return an iterator of Instruction objects (see below). 148 | 149 | 150 | ``` 151 | ok(msg) 152 | info(msg) 153 | warn(msg) 154 | err(msg) 155 | ``` 156 | > Logging functions 157 | 158 | 159 | ``` 160 | gef_on_continue_hook 161 | gef_on_continue_unhook 162 | ``` 163 | > Takes a callback function FUNC as parameter: add/remove a call to FUNC 164 | > when GDB continues execution. 165 | 166 | ``` 167 | gef_on_stop_hook 168 | gef_on_stop_unhook 169 | ``` 170 | > Takes a callback function FUNC as parameter: add/remove a call to FUNC 171 | > when GDB stops execution (breakpoints, watchpoints, interrupt, signal, etc.). 172 | 173 | ``` 174 | gef_on_new_hook 175 | gef_on_new_unhook 176 | ``` 177 | > Takes a callback function FUNC as parameter: add/remove a call to FUNC 178 | > when GDB loads a new binary. 179 | 180 | ``` 181 | gef_on_exit_hook 182 | gef_on_exit_unhook 183 | ``` 184 | > Takes a callback function FUNC as parameter: add/remove a call to FUNC 185 | > when GDB exits an inferior. 186 | 187 | 188 | ### Decorators ### 189 | 190 | ``` 191 | @only_if_gdb_running 192 | ``` 193 | > Modifies a function to only execute if a GDB session is running. A GDB 194 | > session is running if: 195 | > 196 | > * a PID exists for the targeted binary 197 | > * GDB is running on a coredump of a binary 198 | 199 | 200 | ``` 201 | @only_if_gdb_target_local 202 | ``` 203 | > Checks if the current GDB session is local i.e. not debugging using GDB 204 | > `remote`. 205 | 206 | 207 | ``` 208 | @only_if_gdb_version_higher_than( (MAJOR, MINOR) ) 209 | ``` 210 | > Checks if the GDB version is higher or equal to the MAJOR and MINOR provided 211 | > as arguments (both as Integers). This is required since some commands/API of 212 | > GDB are only present in the very latest version of GDB. 213 | 214 | 215 | ### Classes ### 216 | 217 | For exhaustive documentation, run 218 | ```bash 219 | $ gdb -q -ex 'pi help()' -ex quit 220 | ``` 221 | 222 | #### Generic #### 223 | 224 | New GEF commands **must** inherit `GenericCommand`, have `_cmdline_` and 225 | `_syntax_` attrivutes, and have a instance method `do_invoke(args)` defined. 226 | 227 | Other than that, new commands can enjoy all the GEF abstract layer 228 | representation classes, such as: 229 | 230 | * `Instruction` : GEF representation of instruction as pure Python objects. 231 | * `Address`: GEF representation of memory addresses. 232 | * `Section`: GEF representation of process memory sections. 233 | * `Permission`: Page permission object. 234 | * `Elf`: [ELF](http://www.skyfree.org/linux/references/ELF_Format.pdf) parsing 235 | object. 236 | 237 | #### Architectures #### 238 | 239 | * `Architecture` : Generic metaclass for the architectures supported by GEF. 240 | * `ARM` 241 | * `AARCH64` 242 | * `X86` 243 | * `X86_64` 244 | * `PowerPC` 245 | * `PowerPC64` 246 | * `SPARC` 247 | * `SPARC64` 248 | * `MIPS` 249 | 250 | 251 | #### Heap #### 252 | 253 | * `GlibcArena` : Glibc arena class 254 | * `GlibcChunk` : Glibc chunk class. 255 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # GEF - GDB Enhanced Features # 2 | 3 | [![ReadTheDocs](https://readthedocs.org/projects/gef/badge/?version=master)](https://gef.readthedocs.org/en/master/) [![MIT](https://img.shields.io/packagist/l/doctrine/orm.svg?maxAge=2592000?style=plastic)](https://github.com/hugsy/gef/blob/master/LICENSE) [![Python 2 & 3](https://img.shields.io/badge/Python-2%20%26%203-green.svg)](https://github.com/hugsy/gef/) [![IRC](https://img.shields.io/badge/freenode-%23%23gef-yellowgreen.svg)](https://webchat.freenode.net/?channels=##gef) [![CircleCI status](https://circleci.com/gh/hugsy/gef/tree/master.svg?style=shield)](https://circleci.com/gh/hugsy/gef/tree/master) 4 | 5 | `GEF` (pronounced ʤɛf - "Jeff") is a kick-ass set of commands for X86, ARM, MIPS, PowerPC and SPARC to make GDB cool again for exploit dev. It is aimed to be used mostly by exploit developers and reverse-engineers, to provide additional features to GDB using the Python API to assist during the process of dynamic analysis and exploit development. 6 | 7 | It has full support for both Python2 and Python3 indifferently (as more and more 8 | distros start pushing `gdb` compiled with Python3 support). 9 | 10 | ![gef-context](https://i.imgur.com/E3EuQPs.png) 11 | 12 | 13 | *Some* of `GEF` features include: 14 | 15 | * **One** single GDB script. 16 | * Entirely **OS Agnostic**, **NO** dependencies: `GEF` is battery-included and is installable in 2 seconds (unlike [PwnDBG](https://github.com/pwndbg/pwndbg)). 17 | * **Fast** limiting the number of dependencies and optimizing code to make the 18 | commands as fast as possible (unlike _PwnDBG_). 19 | * Provides more than **50** commands to drastically change your experience in 20 | GDB. 21 | * **Easily** extendable to create other commands by providing more comprehensible 22 | layout to GDB Python API. 23 | * Works consistently on both Python2 and Python3. 24 | * Built around an architecture abstraction layer, so all commands work in any 25 | GDB-supported architecture such as x86-32/64, ARMv5/6/7, AARCH64, SPARC, MIPS, 26 | PowerPC, etc. (unlike [PEDA](https://github.com/longld/peda)) 27 | * Suited for real-life apps debugging, exploit development, just as much as 28 | CTF (unlike _PEDA_ or _PwnDBG_) 29 | 30 | Check out the [Screenshot page](./screenshots.md) for more. 31 | 32 | 33 | ## Setup ## 34 | 35 | ### Quick install ### 36 | 37 | Simply make sure you have [GDB 7.7 or higher](https://www.gnu.org/s/gdb). 38 | 39 | ```bash 40 | # via the install script 41 | $ wget -q -O- https://github.com/hugsy/gef/raw/master/scripts/gef.sh | sh 42 | 43 | # manually 44 | $ wget -O ~/.gdbinit-gef.py -q https://github.com/hugsy/gef/raw/master/gef.py 45 | $ echo source ~/.gdbinit-gef.py >> ~/.gdbinit 46 | ``` 47 | 48 | ### Run ### 49 | 50 | Then just start playing (for local files): 51 | 52 | ```bash 53 | $ gdb -q /path/to/my/bin 54 | gef➤ gef help 55 | ``` 56 | 57 | Or (for remote debugging): 58 | 59 | ```bash 60 | remote:~ $ gdbserver 0.0.0.0:1234 /path/to/file 61 | Running as PID: 666 62 | ``` 63 | 64 | And: 65 | 66 | ```bash 67 | local:~ $ gdb -q 68 | gef➤ gef-remote -t your.ip.address:1234 -p 666 69 | ``` 70 | 71 | ### Update ### 72 | 73 | If your host/VM is connected to the Internet, you can update `gef` easily to the 74 | latest version (even without `git` installed). with 75 | `python /path/to/gef.py --update` 76 | 77 | ```bash 78 | $ python ~/.gdbinit-gef.py --update 79 | Updated 80 | ``` 81 | 82 | This will deploy the latest version of `gef`'s _master_ branch from Github. 83 | If no updates are available, `gef` will respond `No update` instead. 84 | 85 | 86 | ### Install via Git ### 87 | 88 | To install from Git, simply clone this repository and specify the path to 89 | `gef.py` inside the `~/.gdbinit` file: 90 | 91 | ```bash 92 | $ git clone https://github.com/hugsy/gef.git 93 | $ echo source `pwd`/gef/gef.py >> ~/.gdbinit 94 | ``` 95 | 96 | If you like living on the edge, you can then switch to the `dev` branch: 97 | 98 | ```bash 99 | $ git checkout dev 100 | ``` 101 | 102 | 103 | ## Dependencies ## 104 | 105 | There are **none**: `GEF` works out of the box! 106 | 107 | However, to enjoy all the coolest features from some commands, it is recommended 108 | to install: 109 | 110 | - [`capstone`](https://github.com/aquynh/capstone) 111 | - [`keystone`](https://github.com/keystone-engine/keystone) 112 | - [`unicorn`](https://github.com/unicorn-engine/unicorn) 113 | - [`Ropper`](https://github.com/sashs/ropper) 114 | 115 | 116 | For a quick installation, simply use the `pip` packaged version: 117 | 118 | ```bash 119 | # for Python2.x 120 | $ pip2 install capstone unicorn keystone-engine ropper 121 | 122 | # for Python3.x 123 | $ pip3 install capstone unicorn keystone-engine ropper 124 | ``` 125 | 126 | Just make sure you are using the `pip` corresponding to the version of Python 127 | your GDB was compiled with. If you are experiencing issues installing them, 128 | post an issue on the GitHub of the respective projects. If your bug is not 129 | related to `GEF`, you will not get an answer. 130 | 131 | 132 | ## Additional commands ## 133 | 134 | GEF was built to also provide a solid base for external scripts. The 135 | repository [`gef-extras`](https://github.com/hugsy/gef-extras) is an open 136 | repository where anyone can freely submit their own commands to extend GDB via 137 | GEF's API. 138 | 139 | To benefit from it: 140 | ```bash 141 | # via the install script 142 | $ wget -q -O- https://github.com/hugsy/gef/raw/master/scripts/gef-extras.sh | sh 143 | 144 | # manually 145 | # clone the repo 146 | $ https://github.com/hugsy/gef-extras.git 147 | # specify gef to load this directory 148 | $ gdb -ex 'gef config gef.extra_plugins_dir "/path/to/gef-extras/scripts"' -ex 'gef save' -ex quit 149 | [+] Configuration saved 150 | ``` 151 | 152 | You can also use the structures defined from this repository: 153 | ```bash 154 | $ gdb -ex 'gef config pcustom.struct_path "/path/to/gef-extras/structs"' -ex 'gef save' -ex quit 155 | [+] Configuration saved 156 | ``` 157 | 158 | There, you're now fully equipped epic pwnage with **all** GEF's goodness!! 159 | 160 | 161 | ## Bugs & Feedbacks ## 162 | 163 | To discuss `gef`, `gdb`, exploitation or other topics, feel free to join the 164 | `##gef` channel on the Freenode IRC network. You can also talk to me (`hugsy`) on the 165 | channel. For those who do not have an IRC client (like `weechat` or `irssi`), 166 | simply [click here](https://webchat.freenode.net/?channels=##gef). 167 | 168 | For bugs or feature requests, just 169 | go [here](https://github.com/hugsy/gef/issues) and provide a thorough description 170 | if you want help. 171 | 172 | _Side Note_: `GEF` fully relies on the GDB API and other Linux-specific sources 173 | of information (such as `/proc/`). As a consequence, some of the features 174 | might not work on custom or hardened systems such as GrSec. 175 | 176 | ## Contribution ## 177 | 178 | `gef` was created and maintained by myself, 179 | [`@_hugsy_`](https://twitter.com/_hugsy_), but kept fresh thanks to [all 180 | the contributors](https://github.com/hugsy/gef/graphs/contributors). 181 | 182 | Or if you just like the tool, feel free to drop a simple *"thanks"* on IRC, 183 | Twitter or other, it is **always** very appreciated. 184 | 185 | 186 | ## Open-Source Rewards ## 187 | 188 | I love Open-Source, and just like 189 | my [other projects](https://proxenet.readthedocs.io/en/latest/#contributing) 190 | I've decided to offer a :beer: 4 :bug: (a.k.a *beer4bugs*) bounty for 191 | `GEF`, to thank everybody who helps keeping the project living and always 192 | better. 193 | 194 | The rule is simple, provide a (substantial) contribution to `GEF`, such as: 195 | 196 | 1. Submitting a Pull-Request for a new feature/command. 197 | 2. Submitting a Pull-Request for a new architecture support. 198 | 3. Or sending a relevant issue request (like a bug, crash, or else). 199 | 200 | Poke me on the IRC `##gef` channel about it, and next time we meet in person 201 | (like at a conference), I'll be happy to pay you a beer. 202 | 203 | I do also accept beers if you think that the tool is cool! :wink: 204 | 205 | Cheers :beers: 206 | 207 | # Happy Hacking # 208 | -------------------------------------------------------------------------------- /docs/faq.md: -------------------------------------------------------------------------------- 1 | # Frequently Asked Questions # 2 | 3 | ## Why use GEF over PEDA? ## 4 | 5 | [PEDA](https://github.com/longld/peda) is a fantastic tool that provides similar 6 | commands to make the exploitation development process smoother. 7 | 8 | However, PEDA suffers from a major drawbacks, which the code is too 9 | fundamentally linked to Intel architectures (x86-32 and x86-64). On the other 10 | hand, GEF not only supports all the architecture supported by GDB (currently 11 | x86, ARM, AARCH64, MIPS, PowerPC, SPARC) but is designed to integrate new 12 | architectures very easily as well! 13 | 14 | Also, PEDA development has been quite idle for a few years now, and many new 15 | interesting features a debugger can provide simply do not exist. 16 | 17 | ## What if my GDB is < 7.7 ? ## 18 | 19 | GDB was introduced with its Python support early 2011 with the release of 20 | GDB 7. A (very) long way has gone since and the Python API has been massively 21 | improved, and GEF is taking advantage of them to provide the coolest features 22 | with as little performance impact as possible. 23 | 24 | Therefore, it is highly recommended to run GEF with the latest version of 25 | GDB. However, all functions should work on a GDB 7.7 and up. If not, send 26 | a [bug report](https://github.com/hugsy/gef/issues) and provide as much details 27 | as possible. 28 | 29 | If you are running an obsolete version, GEF will show a error and message and 30 | exit. You can still use GDB the normal way. 31 | 32 | Some pre-compiled static binaries for both recent GDB and GDBServer can be 33 | downloaded from the [`gdb-static`](https://github.com/hugsy/gdb-static) repository. 34 | 35 | _Note_: although some Ubuntu versions are marked as version 7.7 they are 36 | actually compiled with some missing features that will make `GEF` complain of an 37 | error. Before lodging a bug report, make sure to update your GDB (via APT is 38 | fine), or better install `gdb-multiarch` (the package `gdb64` will work as well, 39 | but is considered obsolete). 40 | 41 | ## I cannot get GEF setup!! ## 42 | 43 | GEF will work on any GDB 7.7+ compiled with Python support. You can view 44 | that commands that failed to load using `gef missing`, but this will not affect 45 | GEF generally. 46 | 47 | If you experience problems setting it up on your host, first go to the 48 | IRC channel [`freenode##gef`](https://webchat.freenode.net/?channels=##gef) for 49 | that. You will find great people there willing to help. 50 | 51 | Note that the GitHub issue section is to be used to **report bugs** and 52 | **GEF issues** (like unexpected crash, improper error handling, weird edge case, 53 | etc.), not a place to ask for help. 54 | 55 | But fear not, GDB 7.7 corresponds to the latest packaged version of Ubuntu 56 | 14.04. Any version higher or equal will work just fine. So you might actually 57 | only need to run `apt install gdb` to get the full-force of GEF. 58 | 59 | ## I get a SegFault when starting GDB with GEF ## 60 | 61 | A long standing bug in the `readline` library can make `gef` crash GDB 62 | when displaying certain characters (SOH/ETX). As a result, this would SIGSEGV 63 | GDB as `gef` is loading, a bit like this: 64 | 65 | ``` 66 | root@debian-aarch64:~# gdb -q ./test-bin-aarch64 67 | GEF ready, type `gef' to start, `gef config' to configure 68 | 53 commands loaded, using Python engine 3.4 69 | [*] 5 commands could not be loaded, run `gef missing` to know why. 70 | [+] Configuration from '/root/.gef.rc' restored 71 | Reading symbols from ./bof-aarch64...(no debugging symbols found)...done. 72 | Segmentation fault (core dumped) 73 | ``` 74 | 75 | If so, this can be fixed easily by setting the `gef.readline_compat` variable to 76 | `True` in the `~/.gef.rc` file. Something like this: 77 | 78 | ``` 79 | root@debian-aarch64:~# nano ~/.gef.rc 80 | [...] 81 | [gef] 82 | readline_compat = True 83 | ``` 84 | 85 | You can now use all features of `gef` even on versions of GDB compiled against 86 | old `readline` library. 87 | 88 | 89 | ## Does GEF prevent the use of other GDB plugins? ## 90 | 91 | Definitely not! You can use any other GDB plugin on top of it for an even better 92 | debugging experience. 93 | 94 | Some interesting plugins highly recommended too: 95 | 96 | - [!exploitable](https://github.com/jfoote/exploitable/) 97 | - [Voltron](https://github.com/snare/voltron) 98 | 99 | ![voltron](https://pbs.twimg.com/media/CsSkk0EUkAAJVPJ.jpg:large) 100 | Src: [@rick2600: terminator + gdb + gef + voltron cc: @snare @_hugsy_](https://twitter.com/rick2600/status/775926070566490113) 101 | 102 | 103 | ## GEF says missing modules, but I'm sure I've installed them, what's up with that? ## 104 | 105 | 99.999% of the time, this happens because the module(s) were **not** installed 106 | for the Python version GDB is compiled to work with! For example, GDB is 107 | compiled for Python3 support, but the module(s) was(were) installed using `pip2` 108 | (and therefore Python2). 109 | 110 | To verify this, you can simply start GDB with GEF, which will show you the 111 | Python version currently supported by your GDB, or run the command: 112 | 113 | ```bash 114 | $ gdb -q -nx -ex 'pi print (sys.version)' -ex quit 115 | 3.5.2+ (default, Dec 13 2016, 14:16:35) 116 | [GCC 6.2.1 20161124] 117 | ``` 118 | 119 | It immediately shows that GDB was compiled for Python3. You have to install the 120 | modules (such as `capstone`, `keystone`, etc.) for this version and it will 121 | work, guaranteed. 122 | 123 | And if this does not work, it is simply that the modules was not installed 124 | properly. To avoid incorrect behavior, if importing the Python module fails, 125 | GEF will simply discard altogether the command that uses it, and it will be 126 | shown when running the `gef missing` command. 127 | 128 | To see the proper stacktrace, simply open a Python interpreter and try importing 129 | the module. This will show you an error. 130 | 131 | 132 | ## I want to contribute, where should I head first? ## 133 | 134 | I would suggest thoroughly reading this documentation, just having a look to the 135 | [CONTRIBUTE](https://github.com/hugsy/gef/blob/master/.github/CONTRIBUTING.md) 136 | file of the project to give you pointers. 137 | 138 | Also a good thing would be to join the `##gef` IRC channel 139 | on [Freenode](https://webchat.freenode.net/?channels=##gef) to get in touch with 140 | the people involved/using it. 141 | 142 | 143 | ## I think I've found a bug, how can I help fixing it? ## 144 | 145 | `gef` is only getting better through people (like you!) using it, but most 146 | importantly reporting unexpected behavior. 147 | 148 | In most locations, Python exceptions will be properly intercepted. If not, `gef` 149 | wraps all commands with a generic exception handler, to disturb as little as 150 | possible your debugging session. If it happens, you'll only get to see a message 151 | like this: 152 | ![gef-exception](http://i.imgur.com/J7dUnXV.png) 153 | 154 | By switching to debug mode, `gef` will give much more information: 155 | ``` 156 | gef➤ gef config gef.debug 1 157 | ``` 158 | ![gef-debug](http://i.imgur.com/SGe8oFF.png) 159 | 160 | If you think fixing it is in your skills, then send a [Pull 161 | Request](https://github.com/hugsy/gef/pulls) with your patched version, 162 | explaining your bug, and what was your solution for it. 163 | 164 | Otherwise, you can open an [issue](https://github.com/hugsy/gef/issues), give a 165 | thorough description of your bug and copy/paste the content from above. This 166 | will greatly help for solving the issue. 167 | 168 | 169 | ## I get weird issues/characters using GDB + Python3, what's up? ## 170 | 171 | Chances are you are not using UTF-8. Python3 172 | is [highly relying on UTF-8](http://www.diveintopython3.net/strings.html) to 173 | display correctly characters of any alphabet 174 | and 175 | [also some cool emojis](http://unicode.org/emoji/charts/full-emoji-list.html). When 176 | GDB is compiled with Python3, GEF will assume that your current charset is UTF-8 177 | (for instance, `en_US.UTF-8`). Use your `$LANG` environment variable to tweak 178 | this setting. 179 | 180 | In addition, some unexpected results were observed when your local is not set to 181 | English. If you aren't sure, simply run `gdb` like this: 182 | 183 | ``` 184 | $ LC_ALL=en_US.UTF-8 gdb /path/to/your/binary 185 | ``` 186 | 187 | ## GDB crashes on ARM memory corruption with `gdb_exception_RETURN_MASK_ERROR` ## 188 | 189 | This issue is **NOT** GEF related, but GDB's, or more precisely some versions of 190 | GDB packaged with Debian/Kali for ARM 191 | 192 | > 193 | > Original Issue and Mitigation 194 | > 195 | > gdb version 7.12, as distributed w/ Raspbian/Kali rolling (only distro's 196 | > tested,) throws an exception while disassembling ARM binaries when using gef. 197 | > This is not a gef problem, this is a gdb problem. gef is just the tool that 198 | > revealed the gdb dain bramage! (The issue was not observed using vanilla 199 | > gdb/peda/pwndbg) This issue was first noted when using si to step through a 200 | > simple ARM assembly program (noted above) when instead of exiting cleanly, 201 | > gdb's disassembly failed with a SIGABRT and threw an exception: 202 | > 203 | > `gdb_exception_RETURN_MASK_ERROR` 204 | > 205 | > This turns out to be a known problem (regression) with gdb, and affects 206 | > gef users running the ARM platform (Raspberry Pi). 207 | > 208 | > The mitigation is for ARM users to compile gdb from source and run the latest 209 | > version, 8.1 as of this writing. 210 | > 211 | 212 | **Do not file an issue**, again it is **NOT** a bug from GEF, or neither from GDB 213 | Python API. Therefore, there is nothing GEF's developers can do about that. The 214 | correct solution as mentioned above is to recompile your GDB with a newer 215 | (better) version. 216 | 217 | The whole topic was already internally discussed, so please refer to 218 | the [issue #206](https://github.com/hugsy/gef/issues/206) for the whole story. 219 | -------------------------------------------------------------------------------- /tests/runtests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | # 3 | # Run tests by spawning a gdb instance for every command. 4 | # 5 | 6 | from __future__ import print_function 7 | 8 | import os 9 | import subprocess 10 | import sys 11 | import tempfile 12 | import unittest 13 | import re 14 | 15 | from helpers import gdb_run_cmd, \ 16 | gdb_run_silent_cmd, \ 17 | gdb_start_silent_cmd, \ 18 | gdb_start_silent_cmd_last_line, \ 19 | gdb_test_python_method 20 | 21 | 22 | 23 | class GefUnitTestGeneric(unittest.TestCase): 24 | """Generic class for command testing, that defines all helpers""" 25 | 26 | @staticmethod 27 | def assertNoException(buf): #pylint: disable=invalid-name 28 | if not ("Python Exception <" not in buf 29 | and "Traceback" not in buf 30 | and "'gdb.error'" not in buf 31 | and "Exception raised" not in buf 32 | and "failed to execute properly, reason:" not in buf): 33 | raise AssertionError("Detected error in gdb output") 34 | 35 | @staticmethod 36 | def assertFailIfInactiveSession(buf): #pylint: disable=invalid-name 37 | if "No debugging session active" not in buf: 38 | raise AssertionError("No debugging session inactive warning") 39 | 40 | @staticmethod 41 | def assertRegex(buf, regex): #pylint: disable=invalid-name 42 | p = re.compile(regex, re.IGNORECASE) 43 | if p.search(buf) is None: 44 | raise AssertionError("Cannot find pattern '{}' in '{}'".format(regex, buf)) 45 | 46 | 47 | 48 | class TestGefCommands(GefUnitTestGeneric): #pylint: disable=too-many-public-methods 49 | """Tests GEF GDB commands.""" 50 | 51 | def test_cmd_canary(self): 52 | self.assertFailIfInactiveSession(gdb_run_cmd("canary")) 53 | res = gdb_start_silent_cmd("canary", target="tests/binaries/canary.out") 54 | self.assertNoException(res) 55 | self.assertIn("Found AT_RANDOM at", res) 56 | self.assertIn("The canary of process ", res) 57 | return 58 | 59 | def test_cmd_capstone_disassemble(self): 60 | self.assertFailIfInactiveSession(gdb_run_cmd("capstone-disassemble")) 61 | res = gdb_start_silent_cmd("capstone-disassemble") 62 | self.assertNoException(res) 63 | self.assertTrue(len(res.splitlines()) > 1) 64 | return 65 | 66 | def test_cmd_checksec(self): 67 | cmd = "checksec" 68 | res = gdb_run_cmd(cmd) 69 | self.assertNoException(res) 70 | 71 | target = "tests/binaries/checksec-no-canary.out" 72 | res = gdb_run_cmd(cmd, target=target) 73 | self.assertIn("Canary : x", res) 74 | 75 | target = "tests/binaries/checksec-no-nx.out" 76 | res = gdb_run_cmd(cmd, target=target) 77 | self.assertIn("NX : x", res) 78 | 79 | target = "tests/binaries/checksec-no-pie.out" 80 | res = gdb_run_cmd(cmd, target=target) 81 | self.assertIn("PIE : x", res) 82 | return 83 | 84 | def test_cmd_dereference(self): 85 | self.assertFailIfInactiveSession(gdb_run_cmd("dereference")) 86 | 87 | res = gdb_start_silent_cmd("dereference $sp") 88 | self.assertNoException(res) 89 | self.assertTrue(len(res.splitlines()) > 2) 90 | self.assertIn("$rsp", res) 91 | 92 | res = gdb_start_silent_cmd("dereference 0x0") 93 | self.assertNoException(res) 94 | self.assertIn("Unmapped address", res) 95 | return 96 | 97 | def test_cmd_edit_flags(self): 98 | # force enable flag 99 | res = gdb_start_silent_cmd_last_line("edit-flags +carry") 100 | self.assertNoException(res) 101 | self.assertIn("CARRY ", res) 102 | # force disable flag 103 | res = gdb_start_silent_cmd_last_line("edit-flags -carry") 104 | self.assertNoException(res) 105 | self.assertIn("carry ", res) 106 | # toggle flag 107 | res = gdb_start_silent_cmd_last_line("edit-flags ~carry") 108 | self.assertNoException(res) 109 | self.assertIn("CARRY ", res) 110 | return 111 | 112 | def test_cmd_elf_info(self): 113 | res = gdb_run_cmd("elf-info") 114 | self.assertNoException(res) 115 | self.assertIn("7f 45 4c 46", res) 116 | return 117 | 118 | def test_cmd_entry_break(self): 119 | res = gdb_run_cmd("entry-break") 120 | self.assertNoException(res) 121 | return 122 | 123 | def test_cmd_format_string_helper(self): 124 | cmd = "format-string-helper" 125 | target = "tests/binaries/format-string-helper.out" 126 | res = gdb_run_cmd(cmd, 127 | after=["set args testtest", 128 | "run",], 129 | target=target) 130 | self.assertNoException(res) 131 | self.assertIn("Possible insecure format string:", res) 132 | return 133 | 134 | def test_cmd_functions(self): 135 | cmd = "functions" 136 | res = gdb_run_cmd(cmd) 137 | self.assertNoException(res) 138 | self.assertIn("$_heap", res) 139 | return 140 | 141 | def test_cmd_got(self): 142 | cmd = "got" 143 | target = "tests/binaries/format-string-helper.out" 144 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd, target=target)) 145 | res = gdb_start_silent_cmd(cmd, target=target) 146 | self.assertIn("printf", res) 147 | self.assertIn("strcpy", res) 148 | 149 | res = gdb_start_silent_cmd("got printf", target=target) 150 | self.assertIn("printf", res) 151 | self.assertNotIn("strcpy", res) 152 | return 153 | 154 | def test_cmd_heap_arenas(self): 155 | cmd = "heap arenas" 156 | target = "tests/binaries/heap.out" 157 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd, target=target)) 158 | res = gdb_start_silent_cmd(cmd, target=target) 159 | self.assertNoException(res) 160 | self.assertIn("Arena (base=", res) 161 | return 162 | 163 | def test_cmd_heap_set_arena(self): 164 | cmd = "heap set-arena main_arena" 165 | target = "tests/binaries/heap.out" 166 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd, target=target)) 167 | res = gdb_run_silent_cmd(cmd, target=target, after=["heap arenas",]) 168 | self.assertNoException(res) 169 | self.assertIn("Arena (base=", res) 170 | return 171 | 172 | def test_cmd_heap_chunk(self): 173 | cmd = "heap chunk p1" 174 | target = "tests/binaries/heap.out" 175 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd, target=target)) 176 | res = gdb_run_silent_cmd(cmd, target=target) 177 | self.assertNoException(res) 178 | self.assertIn("NON_MAIN_ARENA flag: ", res) 179 | return 180 | 181 | def test_cmd_heap_chunks(self): 182 | cmd = "heap chunks" 183 | target = "tests/binaries/heap.out" 184 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd, target=target)) 185 | res = gdb_run_silent_cmd(cmd, target=target) 186 | self.assertNoException(res) 187 | self.assertIn("Chunk(addr=", res) 188 | self.assertIn("top chunk", res) 189 | return 190 | 191 | def test_cmd_heap_bins_fast(self): 192 | cmd = "heap bins fast" 193 | target = "tests/binaries/heap-fastbins.out" 194 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd, target=target)) 195 | res = gdb_run_silent_cmd(cmd, target=target) 196 | self.assertNoException(res) 197 | self.assertIn("Fastbins[idx=0, size=0x10]", res) 198 | return 199 | 200 | def test_cmd_heap_bins_non_main(self): 201 | cmd = 'python gdb.execute("heap bins fast {}".format(get_main_arena().next))' 202 | target = "tests/binaries/heap-non-main.out" 203 | res = gdb_run_silent_cmd(cmd, target=target) 204 | self.assertNoException(res) 205 | self.assertIn("size=0x20, flags=PREV_INUSE|NON_MAIN_ARENA", res) 206 | return 207 | 208 | def test_cmd_heap_analysis(self): 209 | cmd = "heap-analysis-helper" 210 | target = "tests/binaries/heap-analysis.out" 211 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd)) 212 | res = gdb_start_silent_cmd(cmd, after=["continue"], target=target) 213 | self.assertNoException(res) 214 | self.assertIn("Tracking", res) 215 | self.assertIn("correctly setup", res) 216 | self.assertIn("malloc(16)=", res) 217 | self.assertIn("calloc(32)=", res) 218 | addr = int(res.split("calloc(32)=")[1].split("\n")[0], 0) 219 | self.assertRegex(res, r"realloc\(.+, 48") 220 | self.assertIn("free({:#x}".format(addr), res) 221 | return 222 | 223 | def test_cmd_hexdump(self): 224 | self.assertFailIfInactiveSession(gdb_run_cmd("hexdump $pc")) 225 | res = gdb_start_silent_cmd("hexdump qword $pc") 226 | self.assertNoException(res) 227 | res = gdb_start_silent_cmd("hexdump dword $pc l1") 228 | self.assertNoException(res) 229 | res = gdb_start_silent_cmd("hexdump word $pc l5 reverse") 230 | self.assertNoException(res) 231 | res = gdb_start_silent_cmd("hexdump byte $sp l32") 232 | self.assertNoException(res) 233 | return 234 | 235 | def test_cmd_keystone_assemble(self): 236 | valid_cmds = [ 237 | "assemble nop; xor eax, eax; int 0x80", 238 | "assemble -a arm -m arm add r0, r1, r2", 239 | "assemble -a mips -m mips32 add $v0, 1", 240 | "assemble -a sparc -m sparc32 set 0, %o0", 241 | "assemble -a arm64 -m little_endian add x29, sp, 0; mov w0, 0; ret" 242 | ] 243 | for cmd in valid_cmds: 244 | res = gdb_start_silent_cmd(cmd) 245 | self.assertNoException(res) 246 | self.assertTrue(len(res.splitlines()) > 1) 247 | return 248 | 249 | def test_cmd_patch(self): 250 | self.assertFailIfInactiveSession(gdb_run_cmd("patch")) 251 | return 252 | 253 | def test_cmd_patch_byte(self): 254 | res = gdb_start_silent_cmd_last_line("patch byte $pc 0xcc", after=["display/8bx $pc",]) 255 | self.assertNoException(res) 256 | self.assertRegex(res, r"0xcc\s*0x[^c]{2}") 257 | return 258 | 259 | def test_cmd_patch_word(self): 260 | res = gdb_start_silent_cmd_last_line("patch word $pc 0xcccc", after=["display/8bx $pc",]) 261 | self.assertNoException(res) 262 | self.assertRegex(res, r"(0xcc\s*)(\1)0x[^c]{2}") 263 | return 264 | 265 | def test_cmd_patch_dword(self): 266 | res = gdb_start_silent_cmd_last_line("patch dword $pc 0xcccccccc", after=["display/8bx $pc",]) 267 | self.assertNoException(res) 268 | self.assertRegex(res, r"(0xcc\s*)(\1\1\1)0x[^c]{2}") 269 | return 270 | 271 | def test_cmd_patch_qword(self): 272 | res = gdb_start_silent_cmd_last_line("patch qword $pc 0xcccccccccccccccc", after=["display/8bx $pc",]) 273 | self.assertNoException(res) 274 | self.assertRegex(res, r"(0xcc\s*)(\1\1\1\1\1\1)0xcc") 275 | return 276 | 277 | def test_cmd_patch_qword_symbol(self): 278 | target = "tests/binaries/bss.out" 279 | before = gdb_run_silent_cmd("deref $sp 1", target=target) 280 | after = gdb_run_silent_cmd("patch qword $sp &msg", after=["deref $sp 1",], target=target) 281 | self.assertNoException(before) 282 | self.assertNoException(after) 283 | self.assertNotIn("Hello world!", before) 284 | self.assertIn("Hello world!", after) 285 | return 286 | 287 | def test_cmd_patch_string(self): 288 | res = gdb_start_silent_cmd_last_line("patch string $sp \"Gef!Gef!Gef!Gef!\"", after=["grep Gef!Gef!Gef!Gef!",]) 289 | self.assertNoException(res) 290 | self.assertIn("Gef!Gef!Gef!Gef!", res) 291 | return 292 | 293 | def test_cmd_pattern(self): 294 | cmd = "pattern create 32" 295 | target = "tests/binaries/pattern.out" 296 | res = gdb_run_cmd(cmd, target=target) 297 | self.assertNoException(res) 298 | self.assertIn("aaaaaaaabaaaaaaacaaaaaaadaaaaaaa", res) 299 | 300 | cmd = "pattern search $rbp" 301 | target = "tests/binaries/pattern.out" 302 | res = gdb_run_cmd(cmd, before=["set args aaaaaaaabaaaaaaacaaaaaaadaaaaaaa", "run"], target=target) 303 | self.assertNoException(res) 304 | self.assertIn("Found at offset", res) 305 | return 306 | 307 | def test_cmd_print_format(self): 308 | self.assertFailIfInactiveSession(gdb_run_cmd("print-format")) 309 | res = gdb_start_silent_cmd("print-format $rsp") 310 | self.assertNoException(res) 311 | self.assertTrue("buf = [" in res) 312 | res = gdb_start_silent_cmd("print-format -f js $rsp") 313 | self.assertNoException(res) 314 | self.assertTrue("var buf = [" in res) 315 | res = gdb_start_silent_cmd("print-format -f iDontExist $rsp") 316 | self.assertNoException(res) 317 | self.assertTrue("Language must be :" in res) 318 | return 319 | 320 | def test_cmd_process_status(self): 321 | self.assertFailIfInactiveSession(gdb_run_cmd("process-status")) 322 | res = gdb_start_silent_cmd("process-status") 323 | self.assertNoException(res) 324 | self.assertIn("Process Information", res) 325 | self.assertIn("No child process", res) 326 | self.assertIn("No open connections", res) 327 | return 328 | 329 | def test_cmd_registers(self): 330 | self.assertFailIfInactiveSession(gdb_run_cmd("registers")) 331 | res = gdb_start_silent_cmd("registers") 332 | self.assertNoException(res) 333 | self.assertIn("$rax", res) 334 | self.assertIn("$eflags", res) 335 | return 336 | 337 | def test_cmd_reset_cache(self): 338 | res = gdb_start_silent_cmd("reset-cache") 339 | self.assertNoException(res) 340 | return 341 | 342 | def test_cmd_ropper(self): 343 | cmd = "ropper" 344 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd)) 345 | cmd = "ropper --search \"pop %; pop %; ret\"" 346 | res = gdb_run_silent_cmd(cmd) 347 | self.assertNoException(res) 348 | self.assertNotIn(": error:", res) 349 | self.assertTrue(len(res.splitlines()) > 2) 350 | return 351 | 352 | def test_cmd_scan(self): 353 | cmd = "scan libc stack" 354 | target = "tests/binaries/checksec-no-pie.out" 355 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd)) 356 | res = gdb_start_silent_cmd(cmd, target=target) 357 | self.assertNoException(res) 358 | self.assertIn(target, res) 359 | 360 | target = "tests/binaries/default.out" 361 | res = gdb_start_silent_cmd("scan binary libc", target=target) 362 | self.assertNoException(res) 363 | self.assertIn("__libc_start_main", res) 364 | 365 | return 366 | 367 | def test_cmd_search_pattern(self): 368 | self.assertFailIfInactiveSession(gdb_run_cmd("grep /bin/sh")) 369 | res = gdb_start_silent_cmd("grep /bin/sh") 370 | self.assertNoException(res) 371 | self.assertIn("0x", res) 372 | return 373 | 374 | def test_cmd_set_permission(self): 375 | self.assertFailIfInactiveSession(gdb_run_cmd("set-permission")) 376 | target = "tests/binaries/set-permission.out" 377 | 378 | res = gdb_run_silent_cmd("set-permission 0x1337000", after=["vmmap",], target=target) 379 | self.assertNoException(res) 380 | line = [ l for l in res.splitlines() if "0x0000000001337000" in l ][0] 381 | line = line.split() 382 | self.assertEqual(line[0], "0x0000000001337000") 383 | self.assertEqual(line[1], "0x0000000001338000") 384 | self.assertEqual(line[2], "0x0000000000000000") 385 | self.assertEqual(line[3], "rwx") 386 | 387 | res = gdb_run_silent_cmd("set-permission 0x1338000", target=target) 388 | self.assertNoException(res) 389 | self.assertIn("Unmapped address", res) 390 | return 391 | 392 | def test_cmd_shellcode(self): 393 | res = gdb_start_silent_cmd("shellcode") 394 | self.assertNoException(res) 395 | self.assertIn("Missing sub-command (search|get)", res) 396 | return 397 | 398 | def test_cmd_shellcode_search(self): 399 | cmd = "shellcode search execve /bin/sh" 400 | res = gdb_start_silent_cmd(cmd) 401 | self.assertNoException(res) 402 | self.assertIn("setuid(0) + execve(/bin/sh) 49 bytes", res) 403 | return 404 | 405 | def test_cmd_shellcode_get(self): 406 | res = gdb_start_silent_cmd("shellcode get 77") 407 | self.assertNoException(res) 408 | self.assertIn("Shellcode written to ", res) 409 | return 410 | 411 | def test_cmd_stub(self): 412 | cmd = "stub printf" 413 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd)) 414 | res = gdb_start_silent_cmd(cmd) 415 | self.assertNoException(res) 416 | return 417 | 418 | def test_cmd_theme(self): 419 | res = gdb_run_cmd("theme") 420 | self.assertNoException(res) 421 | possible_themes = [ 422 | "context_title_line" 423 | "dereference_base_address" 424 | "context_title_message" 425 | "disable_color" 426 | "dereference_code" 427 | "dereference_string" 428 | "default_title_message", 429 | "default_title_line" 430 | "dereference_register_value", 431 | "xinfo_title_message", 432 | ] 433 | for t in possible_themes: 434 | # testing command viewing 435 | res = gdb_run_cmd("theme {}".format(t)) 436 | self.assertNoException(res) 437 | 438 | # testing command setting 439 | v = "blue blah 10 -1 0xfff bold" 440 | res = gdb_run_cmd("theme {} {}".format(t, v)) 441 | self.assertNoException(res) 442 | return 443 | 444 | def test_cmd_trace_run(self): 445 | cmd = "trace-run" 446 | res = gdb_run_cmd(cmd) 447 | self.assertFailIfInactiveSession(res) 448 | 449 | cmd = "trace-run $pc+1" 450 | res = gdb_start_silent_cmd(cmd, 451 | before=["gef config trace-run.tracefile_prefix /tmp/gef-trace-"]) 452 | self.assertNoException(res) 453 | self.assertIn("Tracing from", res) 454 | return 455 | 456 | def test_cmd_unicorn_emulate(self): 457 | cmd = "emu -n 1" 458 | res = gdb_run_cmd(cmd) 459 | self.assertFailIfInactiveSession(res) 460 | 461 | res = gdb_start_silent_cmd(cmd) 462 | self.assertNoException(res) 463 | self.assertIn("Final registers", res) 464 | return 465 | 466 | def test_cmd_vmmap(self): 467 | self.assertFailIfInactiveSession(gdb_run_cmd("vmmap")) 468 | res = gdb_start_silent_cmd("vmmap") 469 | self.assertNoException(res) 470 | self.assertTrue(len(res.splitlines()) > 1) 471 | 472 | res = gdb_start_silent_cmd("vmmap stack") 473 | self.assertNoException(res) 474 | self.assertTrue(len(res.splitlines()) > 1) 475 | return 476 | 477 | def test_cmd_xfiles(self): 478 | self.assertFailIfInactiveSession(gdb_run_cmd("xfiles")) 479 | res = gdb_start_silent_cmd("xfiles") 480 | self.assertNoException(res) 481 | self.assertTrue(len(res.splitlines()) >= 3) 482 | return 483 | 484 | def test_cmd_xinfo(self): 485 | self.assertFailIfInactiveSession(gdb_run_cmd("xinfo $sp")) 486 | res = gdb_start_silent_cmd("xinfo") 487 | self.assertIn("At least one valid address must be specified", res) 488 | 489 | res = gdb_start_silent_cmd("xinfo $sp") 490 | self.assertNoException(res) 491 | self.assertTrue(len(res.splitlines()) >= 7) 492 | return 493 | 494 | def test_cmd_xor_memory(self): 495 | cmd = "xor-memory display $sp 0x10 0x41" 496 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd)) 497 | res = gdb_start_silent_cmd(cmd) 498 | self.assertNoException(res) 499 | self.assertIn("Original block", res) 500 | self.assertIn("XOR-ed block", res) 501 | 502 | cmd = "xor-memory patch $sp 0x10 0x41" 503 | res = gdb_start_silent_cmd(cmd) 504 | self.assertNoException(res) 505 | self.assertIn("Patching XOR-ing ", res) 506 | return 507 | 508 | def test_cmd_highlight(self): 509 | 510 | cmds = [ 511 | "highlight add 41414141 yellow", 512 | "highlight add 42424242 blue", 513 | "highlight add 43434343 green", 514 | "highlight add 44444444 pink", 515 | 'patch string $rsp "AAAABBBBCCCCDDDD"', 516 | "hexdump qword $rsp 2" 517 | ] 518 | 519 | res = gdb_start_silent_cmd('', after=cmds, strip_ansi=False) 520 | 521 | self.assertNoException(res) 522 | self.assertIn("\033[33m41414141\x1b[0m", res) 523 | self.assertIn("\033[34m42424242\x1b[0m", res) 524 | self.assertIn("\033[32m43434343\x1b[0m", res) 525 | self.assertIn("\033[35m44444444\x1b[0m", res) 526 | 527 | 528 | class TestGefFunctions(GefUnitTestGeneric): 529 | """Tests GEF internal functions.""" 530 | 531 | def test_func_get_memory_alignment(self): 532 | res = gdb_test_python_method("get_memory_alignment(in_bits=False)") 533 | self.assertIn(res.splitlines()[-1], ("4", "8")) 534 | return 535 | 536 | def test_func_set_arch(self): 537 | res = gdb_test_python_method("current_arch.arch, current_arch.mode", before="set_arch()") 538 | res = (res.splitlines()[-1]) 539 | self.assertIn("X86", res) 540 | return 541 | 542 | def test_func_which(self): 543 | res = gdb_test_python_method("which('gdb')") 544 | lines = res.splitlines() 545 | self.assertIn("/gdb", lines[-1]) 546 | res = gdb_test_python_method("which('__IDontExist__')") 547 | self.assertIn("Missing file `__IDontExist__`", res) 548 | return 549 | 550 | def test_func_get_filepath(self): 551 | res = gdb_test_python_method("get_filepath()", target="/bin/ls") 552 | self.assertNoException(res) 553 | subprocess.call(["cp", "/bin/ls", "/tmp/foo bar"]) 554 | res = gdb_test_python_method("get_filepath()", target="/tmp/foo bar") 555 | self.assertNoException(res) 556 | subprocess.call(["rm", "/tmp/foo bar"]) 557 | return 558 | 559 | def test_func_get_pid(self): 560 | res = gdb_test_python_method("get_pid()", target="/bin/ls") 561 | self.assertNoException(res) 562 | self.assertTrue(int(res.splitlines()[-1])) 563 | return 564 | 565 | class TestGdbFunctions(GefUnitTestGeneric): 566 | """Tests gdb convenience functions added by GEF.""" 567 | 568 | def test_func_pie(self): 569 | cmd = "x/s $_pie()" 570 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd)) 571 | res = gdb_start_silent_cmd(cmd) 572 | self.assertNoException(res) 573 | self.assertIn("\\177ELF", res) 574 | 575 | cmd = "x/s $_pie(1)" 576 | res = gdb_start_silent_cmd(cmd) 577 | self.assertNoException(res) 578 | self.assertNotIn("\\177ELF", res) 579 | self.assertIn("ELF", res) 580 | return 581 | 582 | def test_func_heap(self): 583 | cmd = "deref $_heap()" 584 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd, target="tests/binaries/heap.out")) 585 | res = gdb_run_silent_cmd(cmd, target="tests/binaries/heap.out") 586 | self.assertNoException(res) 587 | self.assertIn("+0x0048:", res) 588 | 589 | cmd = "deref $_heap(0x10+0x10)" 590 | res = gdb_run_silent_cmd(cmd, target="tests/binaries/heap.out") 591 | self.assertNoException(res) 592 | self.assertIn("+0x0048:", res) 593 | return 594 | 595 | def test_func_got(self): 596 | cmd = "deref $_got()" 597 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd, target="tests/binaries/heap.out")) 598 | res = gdb_run_silent_cmd(cmd, target="tests/binaries/heap.out") 599 | self.assertNoException(res) 600 | self.assertIn("malloc", res) 601 | return 602 | 603 | def test_func_bss(self): 604 | cmd = "deref $_bss()" 605 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd, target="tests/binaries/bss.out")) 606 | res = gdb_run_silent_cmd(cmd, target="tests/binaries/bss.out") 607 | self.assertNoException(res) 608 | self.assertIn("Hello world!", res) 609 | return 610 | 611 | def test_func_stack(self): 612 | cmd = "deref $_stack()" 613 | self.assertFailIfInactiveSession(gdb_run_cmd(cmd)) 614 | res = gdb_start_silent_cmd(cmd) 615 | self.assertNoException(res) 616 | self.assertRegex(res, r"\+0x0*20: *0x0000000000000000\n") 617 | return 618 | 619 | 620 | class TestGefMisc(GefUnitTestGeneric): 621 | """Tests external functionality.""" 622 | 623 | def test_update(self): 624 | tempdir = tempfile.mkdtemp() 625 | update_gef = os.path.join(tempdir, "gef.py") 626 | subprocess.call(["cp", "/tmp/gef.py", update_gef]) 627 | status = subprocess.call(["python2.7", update_gef, "--update"]) 628 | self.assertEqual(status, 0) 629 | return 630 | 631 | 632 | def run_tests(name=None): 633 | runner = unittest.TextTestRunner(verbosity=3) 634 | unittest.main(testRunner=runner) 635 | 636 | 637 | if __name__ == "__main__": 638 | sys.exit(run_tests()) 639 | --------------------------------------------------------------------------------