pax_global_header 0000666 0000000 0000000 00000000064 13605755047 0014526 g ustar 00root root 0000000 0000000 52 comment=bcf25d957657414d025ff488889cdef8d4fcae06
voltron-master/ 0000775 0000000 0000000 00000000000 13605755047 0014066 5 ustar 00root root 0000000 0000000 voltron-master/.gitignore 0000664 0000000 0000000 00000000552 13605755047 0016060 0 ustar 00root root 0000000 0000000 ### Python ###
*.py[cod]
# C extensions
*.so
# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
__pycache__
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
nosetests.xml
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Rope
.ropeproject
.DS_Store
voltron-master/.travis.yml 0000664 0000000 0000000 00000002265 13605755047 0016204 0 ustar 00root root 0000000 0000000 language: python
matrix:
include:
- os: linux
sudo: required
dist: trusty
python: "3.3"
# - os: linux
# sudo: required
# dist: trusty
# python: "3.4"
# - os: linux
# sudo: required
# dist: trusty
# python: "3.5"
# - os: osx
# osx_image: xcode7.2
# language: generic
addons:
apt:
packages:
- build-essential
- gdb
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; brew install python ; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq ; sudo apt-get install lldb-3.4 ; fi
install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pip install mock pexpect nose ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then pip install mock pexpect nose --user; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pip install . ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then pip install . --user; fi
script:
- python --version
- mkdir ~/.voltron
- echo '{"general":{"debug_logging":true}}' >~/.voltron/config
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then python -m nose -sv tests/gdb_cli_tests.py ; fi
- python -m nose -sv tests/lldb_cli_tests.py
voltron-master/LICENSE 0000664 0000000 0000000 00000002060 13605755047 0015071 0 ustar 00root root 0000000 0000000 The MIT License (MIT)
Copyright (c) 2016 snare
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
voltron-master/README.md 0000664 0000000 0000000 00000021164 13605755047 0015351 0 ustar 00root root 0000000 0000000 Voltron
=======
[](https://travis-ci.org/snare/voltron/)
Voltron is an extensible debugger UI toolkit written in Python. It aims to improve the user experience of various debuggers (LLDB, GDB, VDB and WinDbg) by enabling the attachment of utility views that can retrieve and display data from the debugger host. By running these views in other TTYs, you can build a customised debugger user interface to suit your needs.
Voltron does not aim to be everything to everyone. It's not a wholesale replacement for your debugger's CLI. Rather, it aims to complement your existing setup and allow you to extend your CLI debugger as much or as little as you like. If you just want a view of the register contents in a window alongside your debugger, you can do that. If you want to go all out and have something that looks more like OllyDbg, you can do that too.
Built-in views are provided for:
- Registers
- Disassembly
- Stack
- Memory
- Breakpoints
- Backtrace
The author's setup looks something like this:

Any debugger command can be split off into a view and highlighted with a specified Pygments lexer:

More screenshots are [here](https://github.com/snare/voltron/wiki/Screenshots).
Support
-------
Voltron supports LLDB, GDB, VDB and WinDbg/CDB (via [PyKD](https://pykd.codeplex.com/)) and runs on macOS, Linux and Windows.
WinDbg support is still fairly new, please [open an issue](https://github.com/snare/voltron/issues) if you have problems.
The following architectures are supported:
| | lldb | gdb | vdb | windbg |
|---------|------|-----|-----|--------|
| x86 | ✓ | ✓ | ✓ | ✓ |
| x86_64 | ✓ | ✓ | ✓ | ✓ |
| arm | ✓ | ✓ | ✓ | ✗ |
| arm64 | ✓ | ✗ | ✗ | ✗ |
| powerpc | ✗ | ✓ | ✗ | ✗ |
Installation
------------
**Note:** Only macOS and Debian derivatives are fully supported by the install script. It should hopefully not fail on other Linux distros, but it won't try to install package dependencies. If you're using another distro, have a look at `install.sh` to work out what dependencies you might need to install before running it.
Download the source and run the install script:
$ git clone https://github.com/snare/voltron
$ cd voltron
$ ./install.sh
By default, the install script will install into the user's `site-packages` directory. If you want to install into the system `site-packages`, use the `-s` flag:
$ ./install.sh -s
You can also install into a virtual environment (for LLDB only) like this:
$ ./install.sh -v /path/to/venv -b lldb
If you are on Windows without a shell, have problems installing, or would prefer to install manually, please see the [manual installation documentation](https://github.com/snare/voltron/wiki/Installation).
Quick Start
-----------
1. If your debugger has an init script (`.lldbinit` for LLDB or `.gdbinit` for GDB) configure it to load Voltron when it starts by sourcing the `entry.py` entry point script. The full path will be inside the `voltron` package. For example, on macOS it might be */Library/Python/2.7/site-packages/voltron/entry.py*. The `install.sh` script will add this to your `.gdbinit` or `.lldbinit` file automatically if it detects GDB or LLDB in your path.
LLDB:
command script import /path/to/voltron/entry.py
GDB:
source /path/to/voltron/entry.py
2. Start your debugger and initialise Voltron manually if necessary.
On recent versions of LLDB you do not need to initialise Voltron manually:
$ lldb target_binary
On older versions of LLDB you need to call `voltron init` after you load the inferior:
$ lldb target_binary
(lldb) voltron init
GDB:
$ gdb target_binary
VDB:
$ ./vdbbin target_binary
> script /path/to/voltron/entry.py
WinDbg/CDB is only supported run via Bash with a Linux userland. The author tests with [Git Bash](https://git-for-windows.github.io) and [ConEmu](http://conemu.github.io). PyKD and Voltron can be loaded in one command when launching the debugger:
$ cdb -c '.load C:\path\to\pykd.pyd ; !py --global C:\path\to\voltron\entry.py' target_binary
3. In another terminal (I use iTerm panes) start one of the UI views. On LLDB, WinDbg and GDB the views will update immediately. On VDB they will not update until the inferior stops (at a breakpoint, after a step, etc):
$ voltron view register
$ voltron view stack
$ voltron view disasm
$ voltron view backtrace
4. Set a breakpoint and run your inferior.
(*db) b main
(*db) run
5. When the debugger hits the breakpoint, the views will be updated to reflect the current state of registers, stack, memory, etc. Views are updated after each command is executed in the debugger CLI, using the debugger's "stop hook" mechanism. So each time you step, or continue and hit a breakpoint, the views will update.
Documentation
-------------
See the [wiki](https://github.com/snare/voltron/wiki) on github.
FAQ
---
**Q.** Why am I getting an `ImportError` loading Voltron?
**A.** You might have multiple versions of Python installed and have installed Voltron using the wrong one. See the more detailed [installation instructions](https://github.com/snare/voltron/wiki/Installation).
**Q.** [GEF](https://github.com/hugsy/gef)? [PEDA](https://github.com/longld/peda)? [PwnDbg](https://github.com/pwndbg/pwndbg)? [fG's gdbinit](https://github.com/gdbinit/gdbinit)?
**A.** All super great extensions for GDB. These tools primarily provide sets of additional commands for exploitation tasks, but each also provides a "context" display with a view of registers, stack, code, etc, like Voltron. These tools print their context display in the debugger console each time the debugger stops. Voltron takes a different approach by embedding an RPC server implant in the debugger and enabling the attachment of views from other terminals (or even web browsers, or now [synchronising with Binary Ninja](https://github.com/snare/binja)), which allows the user to build a cleaner multi-window interface to their debugger. Voltron works great alongside all of these tools. You can just disable the context display in your GDB extension of choice and hook up some Voltron views, while still getting all the benefits of the useful commands added by these tools.
Bugs and Errata
---------------
See the [issue tracker](https://github.com/snare/voltron/issues) on github for more information or to submit issues.
If you're experiencing an `ImportError` loading Voltron, please ensure you've followed the [installation instructions](https://github.com/snare/voltron/wiki/Installation) for your platform.
### LLDB
On older versions of LLDB, the `voltron init` command must be run manually after loading the debug target, as a target must be loaded before Voltron's hooks can be installed. Voltron will attempt to automatically register its event handler, and it will inform the user if `voltron init` is required.
### WinDbg
More information about WinDbg/CDB support [here](https://github.com/snare/voltron/wiki/Installation#windbg).
### Misc
The authors primarily use Voltron with the most recent version of LLDB on macOS. We will try to test everything on as many platforms and architectures as possible before releases, but LLDB/macOS/x64 is going to be by far the most frequently-used combination. Hopefully Voltron doesn't set your pets on fire, but YMMV.
License
-------
See the [LICENSE](https://github.com/snare/voltron/blob/master/LICENSE) file.
If you use this and don't hate it, buy me a beer at a conference some time. This license also extends to other contributors - [richo](http://github.com/richo) definitely deserves a few beers for his contributions.
Credits
-------
Thanks to my former employers Assurance and Azimuth Security for giving me time to spend working on this.
Props to [richo](http://github.com/richo) for all his contributions to Voltron.
[fG!](http://github.com/gdbinit)'s gdbinit was the original inspiration for this project.
Thanks to [Willi](http://github.com/williballenthin) for implementing the VDB support.
Voltron now uses [Capstone](http://www.capstone-engine.org) for disassembly as well as the debugger hosts' internal disassembly mechanism. [Capstone](http://www.capstone-engine.org) is a powerful, open source, multi-architecture disassembler upon which the next generation of reverse engineering and debugging tools are being built. Check it out.
Thanks to [grazfather](http://github.com/grazfather) for ongoing contributions.
voltron-master/examples/ 0000775 0000000 0000000 00000000000 13605755047 0015704 5 ustar 00root root 0000000 0000000 voltron-master/examples/angularview/ 0000775 0000000 0000000 00000000000 13605755047 0020230 5 ustar 00root root 0000000 0000000 voltron-master/examples/angularview/angularview.py 0000664 0000000 0000000 00000001721 13605755047 0023127 0 ustar 00root root 0000000 0000000 import logging
import pygments
from voltron.plugin import *
from voltron.lexers import *
from voltron.api import *
from flask import *
log = logging.getLogger('api')
class AngularViewPlugin(WebPlugin):
name = 'angularview'
class FormatDisassemblyRequest(APIRequest):
_fields = {'disassembly': True}
def dispatch(self):
try:
res = FormatDisassemblyResponse(
disassembly=pygments.highlight(self.disassembly.strip(), LLDBIntelLexer(), pygments.formatters.HtmlFormatter()))
except Exception as e:
msg = "Exception formatting disassembly: {}".format(repr(e))
log.exception(msg)
res = APIGenericErrorResponse(msg)
return res
class FormatDisassemblyResponse(APIResponse):
_fields = {'disassembly': True}
class FormatDisassemblyPlugin(APIPlugin):
request = "format_disasm"
request_class = FormatDisassemblyRequest
response_class = FormatDisassemblyResponse
voltron-master/examples/angularview/static/ 0000775 0000000 0000000 00000000000 13605755047 0021517 5 ustar 00root root 0000000 0000000 voltron-master/examples/angularview/static/css/ 0000775 0000000 0000000 00000000000 13605755047 0022307 5 ustar 00root root 0000000 0000000 voltron-master/examples/angularview/static/css/solarized.css 0000664 0000000 0000000 00000010555 13605755047 0025023 0 ustar 00root root 0000000 0000000 /* Solarized Dark
For use with Jekyll and Pygments
http://ethanschoonover.com/solarized
SOLARIZED HEX ROLE
--------- -------- ------------------------------------------
base03 #002b36 background
base01 #586e75 comments / secondary content
base1 #93a1a1 body text / default code / primary content
orange #cb4b16 constants
red #dc322f regex, special keywords
blue #268bd2 reserved keywords
cyan #2aa198 strings, numbers
green #859900 operators, other keywords
*/
/*.highlight { background-color: #002b36; color: #93a1a1 }*/
.highlight { background-color: #073642; color: #93a1a1 }
.highlight .c { color: #586e75 } /* Comment */
.highlight .err { color: #93a1a1 } /* Error */
.highlight .g { color: #93a1a1 } /* Generic */
.highlight .k { color: #859900 } /* Keyword */
.highlight .l { color: #93a1a1 } /* Literal */
.highlight .n { color: #93a1a1 } /* Name */
.highlight .o { color: #859900 } /* Operator */
.highlight .x { color: #cb4b16 } /* Other */
.highlight .p { color: #93a1a1 } /* Punctuation */
.highlight .cm { color: #586e75 } /* Comment.Multiline */
.highlight .cp { color: #859900 } /* Comment.Preproc */
.highlight .c1 { color: #586e75 } /* Comment.Single */
.highlight .cs { color: #859900 } /* Comment.Special */
.highlight .gd { color: #2aa198 } /* Generic.Deleted */
.highlight .ge { color: #93a1a1; font-style: italic } /* Generic.Emph */
.highlight .gr { color: #dc322f } /* Generic.Error */
.highlight .gh { color: #cb4b16 } /* Generic.Heading */
.highlight .gi { color: #859900 } /* Generic.Inserted */
.highlight .go { color: #93a1a1 } /* Generic.Output */
.highlight .gp { color: #93a1a1 } /* Generic.Prompt */
.highlight .gs { color: #93a1a1; font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #cb4b16 } /* Generic.Subheading */
.highlight .gt { color: #93a1a1 } /* Generic.Traceback */
.highlight .kc { color: #cb4b16 } /* Keyword.Constant */
.highlight .kd { color: #268bd2 } /* Keyword.Declaration */
.highlight .kn { color: #859900 } /* Keyword.Namespace */
.highlight .kp { color: #859900 } /* Keyword.Pseudo */
.highlight .kr { color: #268bd2 } /* Keyword.Reserved */
.highlight .kt { color: #dc322f } /* Keyword.Type */
.highlight .ld { color: #93a1a1 } /* Literal.Date */
.highlight .m { color: #2aa198 } /* Literal.Number */
.highlight .s { color: #2aa198 } /* Literal.String */
.highlight .na { color: #93a1a1 } /* Name.Attribute */
.highlight .nb { color: #B58900 } /* Name.Builtin */
.highlight .nc { color: #268bd2 } /* Name.Class */
.highlight .no { color: #cb4b16 } /* Name.Constant */
.highlight .nd { color: #268bd2 } /* Name.Decorator */
.highlight .ni { color: #cb4b16 } /* Name.Entity */
.highlight .ne { color: #cb4b16 } /* Name.Exception */
.highlight .nf { color: #268bd2 } /* Name.Function */
.highlight .nl { color: #93a1a1 } /* Name.Label */
.highlight .nn { color: #93a1a1 } /* Name.Namespace */
.highlight .nx { color: #93a1a1 } /* Name.Other */
.highlight .py { color: #93a1a1 } /* Name.Property */
.highlight .nt { color: #268bd2 } /* Name.Tag */
.highlight .nv { color: #268bd2 } /* Name.Variable */
.highlight .ow { color: #859900 } /* Operator.Word */
.highlight .w { color: #93a1a1 } /* Text.Whitespace */
.highlight .mf { color: #2aa198 } /* Literal.Number.Float */
.highlight .mh { color: #2aa198 } /* Literal.Number.Hex */
.highlight .mi { color: #2aa198 } /* Literal.Number.Integer */
.highlight .mo { color: #2aa198 } /* Literal.Number.Oct */
.highlight .sb { color: #586e75 } /* Literal.String.Backtick */
.highlight .sc { color: #2aa198 } /* Literal.String.Char */
.highlight .sd { color: #93a1a1 } /* Literal.String.Doc */
.highlight .s2 { color: #2aa198 } /* Literal.String.Double */
.highlight .se { color: #cb4b16 } /* Literal.String.Escape */
.highlight .sh { color: #93a1a1 } /* Literal.String.Heredoc */
.highlight .si { color: #2aa198 } /* Literal.String.Interpol */
.highlight .sx { color: #2aa198 } /* Literal.String.Other */
.highlight .sr { color: #dc322f } /* Literal.String.Regex */
.highlight .s1 { color: #2aa198 } /* Literal.String.Single */
.highlight .ss { color: #2aa198 } /* Literal.String.Symbol */
.highlight .bp { color: #268bd2 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #268bd2 } /* Name.Variable.Class */
.highlight .vg { color: #268bd2 } /* Name.Variable.Global */
.highlight .vi { color: #268bd2 } /* Name.Variable.Instance */
.highlight .il { color: #2aa198 } /* Literal.Number.Integer.Long */
voltron-master/examples/angularview/static/css/style.css 0000664 0000000 0000000 00000000571 13605755047 0024164 0 ustar 00root root 0000000 0000000 .reg_label {
color: #b58900;
font-weight: bold;
}
.reg_highlight {
color: #dc322f;
}
.reg_normal {
}
#tile {
display:inline-block;
vertical-align: top;
background-color: #073642;
padding-left: 0.5em;
padding-right: 0.5em;
padding-top: 0.3em;
padding-bottom: 0.3em;
}
pre {
margin: 0;
}
#disasm {
background-color: #073642;
} voltron-master/examples/angularview/static/index.html 0000664 0000000 0000000 00000001757 13605755047 0023526 0 ustar 00root root 0000000 0000000
voltron
registers
{{reg.name}}{{reg.value}}
disassembly
voltron-master/examples/angularview/static/js/ 0000775 0000000 0000000 00000000000 13605755047 0022133 5 ustar 00root root 0000000 0000000 voltron-master/examples/angularview/static/js/app.js 0000664 0000000 0000000 00000000236 13605755047 0023252 0 ustar 00root root 0000000 0000000 angular.module('VoltronApp', [
'VoltronApp.controllers',
'VoltronApp.services'
])
.config(function($sceProvider) {
$sceProvider.enabled(false);
});
voltron-master/examples/angularview/static/js/controllers.js 0000664 0000000 0000000 00000005321 13605755047 0025040 0 ustar 00root root 0000000 0000000 function f_hex(number, pad)
{
return ("000000000000000000000000000000" + number.toString(16)).substr(-pad).toUpperCase();
}
angular.module('VoltronApp.controllers', []).
controller('voltronController', function($scope, voltronAPIservice)
{
$scope.version = null;
$scope.registers = [];
$scope.disassembly = null;
var state = null;
var new_regs = null;
var old_regs = [];
voltronAPIservice.version().success(function (response) {
$scope.version = response.data;
});
var format_registers = function(new_regs, old_regs, arch) {
fmt = []
if (arch == 'x86_64') {
regs = ['rip','rax','rbx','rcx','rdx','rbp','rsp','rdi','rsi','r8','r9','r10','r11','r12','r13','r14','r15']
for (i = 0; i < regs.length; i++) {
fmt.push({
name: (regs[i].length == 2 ? String.fromCharCode(160) + regs[i] : regs[i]),
value: f_hex(new_regs[regs[i]], 16),
class: (new_regs[regs[i]] != old_regs[regs[i]] ? "reg_highlight" : "reg_normal")
})
}
}
return fmt
}
var format_disasm = function(disasm) {
lines = disasm.split();
// trim lldb's "inferior`main:" so hljs works
if (lines[0].indexOf("`") > -1) {
lines.splice(0, 1);
}
return lines.join('\n');
}
var update = function() {
// get target info
voltronAPIservice.targets().success(function (response) {
targets = response.data.targets;
// make sure we have a target
if (targets[0]['arch'] != null) {
// update registers
voltronAPIservice.registers().success(function (response) {
// get new register values
new_regs = response.data.registers
// format registers
$scope.registers = format_registers(new_regs, old_regs, targets[0]['arch']);
// keep old registers
old_regs = new_regs;
});
// update disassembly
voltronAPIservice.disassemble(null, 32).success(function (response) {
$scope.disassembly = response.data.formatted;
});
}
});
}
var poll = function() {
// wait for the next state change
response = voltronAPIservice.wait(30).success(function (response) {
if (response.status == "success") {
update();
}
// wait for the next state change
poll();
});
};
// initial update
update();
// start waiting for debugger stops
poll();
}); voltron-master/examples/angularview/static/js/services.js 0000664 0000000 0000000 00000003372 13605755047 0024321 0 ustar 00root root 0000000 0000000 angular.module('VoltronApp.services', []).
factory('voltronAPIservice', function($http)
{
var voltronAPI = {};
function createRequest(requestType, data) {
return {type: "request", request: requestType, data: data}
}
voltronAPI.request = function(request) {
return $http({
method: 'POST',
url: '/api/request',
data: request
});
}
voltronAPI.disassemble_format = function(data) {
res = voltronAPI.request(createRequest('disassemble', {address: address, count: count}))
return $http({
method: 'POST',
url: '/api/request',
data: createRequest('format_disasm', {disassembly: res.data.disassembly})
});
}
voltronAPI.disassemble = function(address, count) {
return voltronAPI.request(createRequest('disassemble', {address: address, count: count}))
}
voltronAPI.command = function(command) {
return voltronAPI.request(createRequest('command', {command: command}))
}
voltronAPI.targets = function() {
return voltronAPI.request(createRequest('targets', {}))
}
voltronAPI.memory = function(address, length) {
return voltronAPI.request(createRequest('memory', {address: address, length: length}))
}
voltronAPI.registers = function() {
return voltronAPI.request(createRequest('registers', {}))
}
voltronAPI.stack = function(length) {
return voltronAPI.request(createRequest('stack', {length: length}))
}
voltronAPI.state = function() {
return voltronAPI.request(createRequest('state', {}))
}
voltronAPI.version = function() {
return voltronAPI.request(createRequest('version', {}))
}
return voltronAPI;
});
voltron-master/examples/client.py 0000664 0000000 0000000 00000003711 13605755047 0017536 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
"""
Example Voltron client.
Start your debugger as follows:
$ lldb /tmp/inferior
Voltron loaded.
Run `voltron init` after you load a target.
(lldb) target create "/tmp/inferior"
Current executable set to '/tmp/inferior' (x86_64).
(lldb) voltron init
Registered stop-hook
(lldb) b main
Breakpoint 1: where = inferior`main, address = 0x0000000100000cf0
(lldb) run
Process 13185 launched: '/Volumes/Data/Users/snare/code/voltron/repo/tests/inferior' (x86_64)
Process 13185 stopped
* thread #1: tid = 0x1ee63, 0x0000000100000cf0 inferior`main, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000cf0 inferior`main
inferior`main:
-> 0x100000cf0: push rbp
0x100000cf1: mov rbp, rsp
0x100000cf4: sub rsp, 0x50
0x100000cf8: mov dword ptr [rbp - 0x4], 0x0
Run this client in another terminal. Each time you `stepi` in the debugger,
the client will output the current RIP:
$ python client.py
Instruction pointer is: 0x100000CFF
Instruction pointer is: 0x100000D02
Instruction pointer is: 0x100000D06
Instruction pointer is: 0x100000D0D
Instruction pointer is: 0x100000D15
Instruction pointer is: 0x100000D1C
"""
import voltron
from voltron.core import Client
def main():
# Create a client and connect to the server
client = Client()
# Main event loop
while True:
# Wait for the debugger to stop again
res = client.perform_request('version', block=True)
if res.is_success:
# If nothing went wrong, get the instruction pointer and print it
res = client.perform_request('registers', registers=['rip'])
if res.is_success:
print("Instruction pointer is: 0x{:X}".format(res.registers['rip']))
else:
print("Failed to get registers: {}".format(res))
else:
print("Error waiting for the debugger to stop: {}".format(res))
break
if __name__ == "__main__":
main()
voltron-master/examples/command.py 0000664 0000000 0000000 00000003763 13605755047 0017705 0 ustar 00root root 0000000 0000000 """
Example command plugin
Copy this to your ~/.voltron/plugins directory. It will be loaded when
Voltron is initialised, and register a debugger command that works as follows:
$ lldb /tmp/inferior
Voltron loaded.
Run `voltron init` after you load a target.
(lldb) target create "/tmp/inferior"
Current executable set to '/tmp/inferior' (x86_64).
(lldb) b main
Breakpoint 1: where = inferior`main, address = 0x0000000100000cf0
(lldb) run
Process 12561 launched: '/tmp/inferior' (x86_64)
Process 12561 stopped
* thread #1: tid = 0x1d33f, 0x0000000100000cf0 inferior`main, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000cf0 inferior`main
inferior`main:
-> 0x100000cf0: push rbp
0x100000cf1: mov rbp, rsp
0x100000cf4: sub rsp, 0x50
0x100000cf8: mov dword ptr [rbp - 0x4], 0x0
(lldb) example
rax 0000000100000CF0
rbx 0000000000000000
rcx 00007FFF5FBFFA70
rdx 00007FFF5FBFF978
rbp 00007FFF5FBFF958
rsp 00007FFF5FBFF948
rdi 0000000000000001
rsi 00007FFF5FBFF968
rip 0000000100000CF0
r8 0000000000000000
r9 00007FFF5FBFEA08
r10 0000000000000032
r11 0000000000000246
r12 0000000000000000
r13 0000000000000000
r14 0000000000000000
r15 0000000000000000
Provided you stick to the adaptor API that is implemented in every *DBAdaptor
class, custom command plugins should work across all debugger hosts.
This is a quick example that will only work on an x86_64 target.
"""
import blessed
import voltron
from voltron.plugin import CommandPlugin
from voltron.command import VoltronCommand
class ExampleCommand(VoltronCommand):
def invoke(self, *args):
regs = voltron.debugger.registers()
reg_list = ['rax','rbx','rcx','rdx','rbp','rsp','rdi','rsi','rip',
'r8','r9','r10','r11','r12','r13','r14','r15']
for name in reg_list:
print("{t.bold}{:3} {t.normal}{:0=16X}".format(name, regs[name], t=blessed.Terminal()))
class ExampleCommandPlugin(CommandPlugin):
name = 'example'
command_class = ExampleCommand voltron-master/examples/view.py 0000664 0000000 0000000 00000004105 13605755047 0017230 0 ustar 00root root 0000000 0000000 """
Example Voltron view.
Copy this to your ~/.voltron/plugins directory. When the `voltron view` command
is executed, 'example' should be visible in the list of valid view names.
Start your debugger as follows:
$ lldb /tmp/inferior
Voltron loaded.
Run `voltron init` after you load a target.
(lldb) target create "/tmp/inferior"
Current executable set to '/tmp/inferior' (x86_64).
(lldb) voltron init
Registered stop-hook
(lldb) b main
Breakpoint 1: where = inferior`main, address = 0x0000000100000cf0
(lldb) run
Process 13185 launched: '/Volumes/Data/Users/snare/code/voltron/repo/tests/inferior' (x86_64)
Process 13185 stopped
* thread #1: tid = 0x1ee63, 0x0000000100000cf0 inferior`main, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000cf0 inferior`main
inferior`main:
-> 0x100000cf0: push rbp
0x100000cf1: mov rbp, rsp
0x100000cf4: sub rsp, 0x50
0x100000cf8: mov dword ptr [rbp - 0x4], 0x0
Run this view in another terminal (as follows). Each time you `stepi` in the
debugger, the view will update and display the current register values.
$ voltron view example
"""
from voltron.view import TerminalView
from voltron.plugin import ViewPlugin
class ExampleView(TerminalView):
def render(self, *args, **kwargs):
# Perform the request
res = self.client.perform_request('registers')
if res.is_success:
# Process the registers and set the body to the formatted list
reg_list = ['rax','rbx','rcx','rdx','rbp','rsp','rdi','rsi','rip',
'r8','r9','r10','r11','r12','r13','r14','r15']
lines = map(lambda x: '{:3}: {:016X}'.format(x, res.registers[x]), reg_list)
self.body = '\n'.join(lines)
else:
self.body = "Failed to get registers: {}".format(res)
# Set the title and info
self.title = '[example]'
self.info = 'some infoz'
# Let the parent do the rendering
super(ExampleView, self).render()
class ExampleViewPlugin(ViewPlugin):
name = 'example'
view_class = ExampleView
voltron-master/install.sh 0000775 0000000 0000000 00000024351 13605755047 0016100 0 ustar 00root root 0000000 0000000 #!/bin/bash
#
# Install Voltron for whichever debuggers are detected (only GDB and LLDB so
# far).
#
function usage {
cat </dev/null 2>&1
if [ $? -ne 0 ];
then
# If not, attempt to install it using ensurepip
echo "Attempting to install pip using 'ensurepip'."
${SUDO} ${LLDB_PYTHON} -m ensurepip $USER_MODE || return $?
fi
# Some really old pip installations default to the old pypi.python.org, which no longer works.
echo "Attempting to upgrade pip."
${SUDO} ${LLDB_PYTHON} -m pip install "pip>=$PIP_MIN_VER" $USER_MODE -U --index-url "$PYPI_URL"
if [ $? != 0 ];
then
# We may still fail here due to TLS incompatibility
# TLS 1.x got turned off 2018-04-11
# https://status.python.org/incidents/hdx7w97m5hr8
# Curl may be new enough to support TLS 1.2, so try to curl the pip installer from pypa.io
# It's able to download and install pip without TLS errors somehow
echo "Failed to upgrade pip."
echo "Attempting to fall back to installation via curl."
curl_get_pip || return $?
fi
}
function get_lldb_python_exe {
# Find the Python version used by LLDB
local lldb_pyver=$(${LLDB} -Q -x -b --one-line 'script import platform; print(".".join(platform.python_version_tuple()[:2]))'|tail -1)
local lldb_python=$(${LLDB} -Q -x -b --one-line 'script import sys; print(sys.executable)'|tail -1)
lldb_python=$(${LLDB} -Q -x -b --one-line 'script import sys; print(sys.executable)'|tail -1)
local lldb_python_basename=$(basename "${lldb_python}")
if [ "python" = "$lldb_python_basename" ];
then
lldb_python="${lldb_python/%$lldb_pyver/}${lldb_pyver}"
elif [ "lldb" = "$lldb_python_basename" ];
then
# newer lldb versions report sys.path as /path/to/lldb instead of python
# sys.exec_path still appears to be the parent path of bin/python though
local lldb_python_exec_prefix=$(${LLDB} -Q -x -b --one-line 'script import sys; print(sys.exec_prefix)'|tail -1)
lldb_python="$lldb_python_exec_prefix/bin/python"
lldb_python="${lldb_python/%$lldb_pyver/}${lldb_pyver}"
fi
echo "$lldb_python"
}
if [ "${BACKEND_GDB}" -eq 1 ]; then
# Find the Python version used by GDB
GDB_PYVER=$(${GDB} -batch -q --nx -ex 'pi import platform; print(".".join(platform.python_version_tuple()[:2]))')
GDB_PYTHON=$(${GDB} -batch -q --nx -ex 'pi import sys; print(sys.executable)')
GDB_PYTHON="${GDB_PYTHON/%$GDB_PYVER/}${GDB_PYVER}"
install_packages
if [ -z $USER_MODE ]; then
GDB_SITE_PACKAGES=$(${GDB} -batch -q --nx -ex 'pi import site; print(site.getsitepackages()[0])')
else
GDB_SITE_PACKAGES=$(${GDB} -batch -q --nx -ex 'pi import site; print(site.getusersitepackages())')
fi
# Install Voltron and dependencies
${SUDO} ${GDB_PYTHON} -m pip install -U $USER_MODE $DEV_MODE .
# Add Voltron to gdbinit
GDB_INIT_FILE="${HOME}/.gdbinit"
if [ -e ${GDB_INIT_FILE} ]; then
sed -i.bak '/voltron/d' ${GDB_INIT_FILE}
fi
if [ -z $DEV_MODE ]; then
GDB_ENTRY_FILE="$GDB_SITE_PACKAGES/voltron/entry.py"
else
GDB_ENTRY_FILE="$(pwd)/voltron/entry.py"
fi
echo "source $GDB_ENTRY_FILE" >> ${GDB_INIT_FILE}
fi
if [ "${BACKEND_LLDB}" -eq 1 ]; then
LLDB_PYTHON=$(get_lldb_python_exe) || quit "Failed to locate python interpreter." 1
ensure_pip || quit "Failed to install pip." 1
${LLDB_PYTHON} -m pip install --user --upgrade six || quit "Failed to install or upgrade 'six' python package." 1
if [ -n "${VENV}" ]; then
echo "Creating virtualenv..."
${LLDB_PYTHON} -m pip install --user virtualenv
${LLDB_PYTHON} -m virtualenv "${VENV}"
LLDB_PYTHON="${VENV}/bin/python"
LLDB_SITE_PACKAGES=$(find "${VENV}" -name site-packages)
elif [ -z "${USER_MODE}" ]; then
LLDB_SITE_PACKAGES=$(${LLDB} -Q -x -b --one-line 'script import site; print(site.getsitepackages()[0])'|tail -1) || quit "Failed to locate site-packages." 1
else
LLDB_SITE_PACKAGES=$(${LLDB} -Q -x -b --one-line 'script import site; print(site.getusersitepackages())'|tail -1) || quit "Failed to locate site-packages." 1
fi
install_packages || quit "Failed to install packages." 1
if [ "$LLDB_SITE_PACKAGES" == "$GDB_SITE_PACKAGES" ]; then
echo "Skipping installation for LLDB - same site-packages directory"
else
# Install Voltron and dependencies
${SUDO} ${LLDB_PYTHON} -m pip install -U $USER_MODE $DEV_MODE . || quit "Failed to install voltron." 1
fi
# Add Voltron to lldbinit
LLDB_INIT_FILE="${HOME}/.lldbinit"
if [ -e ${LLDB_INIT_FILE} ]; then
sed -i.bak '/voltron/d' ${LLDB_INIT_FILE}
fi
if [ -z "${DEV_MODE}" ]; then
LLDB_ENTRY_FILE="$LLDB_SITE_PACKAGES/voltron/entry.py"
else
LLDB_ENTRY_FILE="$(pwd)/voltron/entry.py"
fi
if [ -n "${VENV}" ]; then
echo "script import sys;sys.path.append('${LLDB_SITE_PACKAGES}')" >> ${LLDB_INIT_FILE}
fi
echo "command script import $LLDB_ENTRY_FILE" >> ${LLDB_INIT_FILE}
fi
if [ "${BACKEND_GDB}" -ne 1 ] && [ "${BACKEND_LLDB}" -ne 1 ]; then
# Find system Python
PYTHON=$(command -v python)
PYVER=$(${PYTHON} -c 'import platform; print(".".join(platform.python_version_tuple()[:2]))')
if [ -z $USER_MODE ]; then
PYTHON_SITE_PACKAGES=$(${PYTHON} -c 'import site; print(site.getsitepackages()[0])')
else
PYTHON_SITE_PACKAGES=$(${PYTHON} -c 'import site; print(site.getusersitepackages())')
fi
install_packages
# Install Voltron and dependencies
${SUDO} ${PYTHON} -m pip install -U $USER_MODE $DEV_MODE .
fi
set +x
echo "=============================================================="
if [ "${BACKEND_GDB}" -eq 1 ]; then
echo "Installed for GDB (${GDB}):"
echo " Python: $GDB_PYTHON"
echo " Packages directory: $GDB_SITE_PACKAGES"
echo " Added voltron to: $GDB_INIT_FILE"
echo " Entry point: $GDB_ENTRY_FILE"
fi
if [ "${BACKEND_LLDB}" -eq 1 ]; then
echo "Installed for LLDB (${LLDB}):"
echo " Python: $LLDB_PYTHON"
echo " Packages directory: $LLDB_SITE_PACKAGES"
echo " Added voltron to: $LLDB_INIT_FILE"
echo " Entry point: $LLDB_ENTRY_FILE"
fi
if [ "${BACKEND_GDB}" -ne 1 ] && [ "${BACKEND_LLDB}" -ne 1 ]; then
if [ -z "${GDB}" ] && [ -z "${LLDB}" ]; then
echo -n "Couldn't find any debuggers. "
else
echo -n "No debuggers selected. "
fi
echo "Installed using the Python in your path:"
echo " Python: $PYTHON"
echo " Packages directory: $PYTHON_SITE_PACKAGES"
echo " Did not add Voltron to any debugger init files."
fi
voltron-master/setup.cfg 0000664 0000000 0000000 00000000032 13605755047 0015702 0 ustar 00root root 0000000 0000000 [bdist_wheel]
universal=1
voltron-master/setup.py 0000775 0000000 0000000 00000007136 13605755047 0015612 0 ustar 00root root 0000000 0000000 from __future__ import print_function
import sys
import platform
import textwrap
from subprocess import check_output
from setuptools import setup, find_packages
def check_install():
"""
Try to detect the two most common installation errors:
1. Installing on macOS using a Homebrew version of Python
2. Installing on Linux using Python 2 when GDB is linked with Python 3
"""
if platform.system() == 'Darwin' and sys.executable != '/usr/bin/python':
print("*" * 79)
print(textwrap.fill(
"WARNING: You are not using the version of Python included with "
"macOS. If you intend to use Voltron with the LLDB included "
"with Xcode, or GDB installed with Homebrew, it will not work "
"unless it is installed using the system's default Python. If "
"you intend to use Voltron with a debugger installed by some "
"other method, it may be safe to ignore this warning. See the "
"following documentation for more detailed installation "
"instructions: "
"https://github.com/snare/voltron/wiki/Installation", 79))
print("*" * 79)
elif platform.system() == 'Linux':
try:
output = check_output([
"gdb", "-batch", "-q", "--nx", "-ex",
"pi print(sys.version_info.major)"
]).decode("utf-8")
gdb_python = int(output)
if gdb_python != sys.version_info.major:
print("*" * 79)
print(textwrap.fill(
"WARNING: You are installing Voltron using Python {0}.x "
"and GDB is linked with Python {1}.x. GDB will not be "
"able to load Voltron. Please install using Python {1} "
"if you intend to use Voltron with the copy of GDB that "
"is installed. See the following documentation for more "
"detailed installation instructions: "
"https://github.com/snare/voltron/wiki/Installation"
.format(sys.version_info.major, gdb_python), 79))
print("*" * 79)
except:
pass
check_install()
requirements = [
'scruffington>=0.3.6',
'flask',
'flask_restful',
'blessed',
'pygments',
'requests',
'requests_unixsocket',
'six',
'pysigset',
'pygments',
]
if sys.platform == 'win32':
requirements.append('cursor')
setup(
name="voltron",
version="0.1.7",
author="snare",
author_email="snare@ho.ax",
description="A debugger UI",
license="MIT",
keywords="voltron debugger ui gdb lldb vdb "
"vivisect vtrace windbg cdb pykd",
url="https://github.com/snare/voltron",
packages=find_packages(exclude=['tests', 'examples']),
install_requires=requirements,
package_data={'voltron': ['config/*']},
entry_points={
'console_scripts': ['voltron=voltron:main'],
'pygments.lexers': [
'lldb_intel = voltron.lexers:LLDBIntelLexer',
'lldb_att = voltron.lexers:LLDBATTLexer',
'gdb_intel = voltron.lexers:GDBIntelLexer',
'gdb_att = voltron.lexers:GDBATTLexer',
'vdb_intel = voltron.lexers:VDBIntelLexer',
'vdb_att = voltron.lexers:VDBATTLexer',
'windbg_intel = voltron.lexers:WinDbgIntelLexer',
'windbg_att = voltron.lexers:WinDbgATTLexer',
'capstone_intel = voltron.lexers:CapstoneIntelLexer',
],
'pygments.styles': [
'volarized = voltron.styles:VolarizedStyle',
]
},
zip_safe=False
)
voltron-master/tests/ 0000775 0000000 0000000 00000000000 13605755047 0015230 5 ustar 00root root 0000000 0000000 voltron-master/tests/Vagrantfile 0000664 0000000 0000000 00000001464 13605755047 0017422 0 ustar 00root root 0000000 0000000 Vagrant.configure(2) do |config|
config.vm.hostname = "voltron"
config.vm.box = "ubuntu/trusty64"
config.vm.provider :virtualbox do |v|
v.memory = 1024
v.linked_clone = true
end
config.vm.network "forwarded_port", guest: 5555, host: 5556
config.vm.synced_folder "../", "/voltron"
config.vm.synced_folder "~/shared", "/shared"
config.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get upgrade -y
apt-get install -y \
build-essential \
gdb \
zsh \
python3-pip \
lldb-3.8
pip3 install six --upgrade
su - vagrant -c "cd /voltron ; ./install.sh"
mkdir -p /home/vagrant/.voltron
chown vagrant:vagrant /home/vagrant/.voltron -R
cat >/home/vagrant/.voltron/config <