FFFF lldbinit/lldbinit.py at master · syto203/lldbinit · GitHub
[go: up one dir, main page]

Skip to content

Latest commit

 

History

History
4388 lines (3768 loc) · 133 KB

lldbinit.py

File metadata and controls

4388 lines (3768 loc) · 133 KB
'''
.____ .____ ________ __________.__ _______ ._____________
| | | | \______ \\______ \__|\ \ |__\__ ___/
| | | | | | \| | _/ |/ | \| | | |
| |___| |___ | ` \ | \ / | \ | | |
|_______ \_______ \/_______ /______ /__\____|__ /__| |____|
\/ \/ \/ \/ \/ LLDBINIT v1.0
A gdbinit clone for LLDB aka how to make LLDB a bit more useful and less crappy
(c) Deroko 2014, 2015, 2016
(c) fG! 2017, 2018 - reverser@put.as - https://reverse.put.as
https://github.com/gdbinit/lldbinit
No original license by Deroko so I guess this is do whatever you want with this
as long you keep original credits and sources references.
Original lldbinit code by Deroko @ https://github.com/deroko/lldbinit
gdbinit available @ https://github.com/gdbinit/Gdbinit
Huge thanks to Deroko for his original effort!
To list all implemented commands use 'lldbinitcmds' command.
How to install it:
------------------
cp lldbinit.py /Library/Python/2.7/site-packages
in $HOME/.lldbinit add:
command script import lldbinit
or
cp lldbinit.py ~
echo "command script import ~/lldbinit.py" >>~/.lldbinit
or
just copy it somewhere and use **command script import path_to_script** when you want to load it.
TODO:
-----
- better ARM support and testing - this version is focused on x86/x64
- shortcut to dump memory to file
- check sbthread class: stepoveruntil for example
- help for aliases
- error checking on many return values for lldb objects (target, frame, thread, etc) - verify if frame value is valid on the beginning of each command?
- add source window?
- add threads window?
- remove that ugly stop information (deroko's trick doesn't seem to work anymore, lldb forces that over our captured input?)
BUGS:
-----
- Disassembler output with API GetInstructions is all wrong for code not in main executable
The reason is that the section information is bad
context = frame.GetSymbolContext(lldb.eSymbolContextEverything)
print context
Module: file = "/usr/lib/system/libsystem_blocks.dylib", arch = "x86_64"
Symbol: id = {0x0000000e}, range = [0x00000000000008ec-0x000000000000096c), mangled="_Block_release"
So even if we pass the correct base_addr the disassembly will be all wrong
-> 0x7fff9566c0d0: e8 73 f2 ff ff call 0x7fff9566b348 ; tiny_free_no_lock
Disassembly operand we get 0x19348
x libsystem_malloc.dylib[0x1a0d0]: call 0x19348
Module: file = "/usr/lib/system/libsystem_malloc.dylib", arch = "x86_64"
Symbol: id = {0x000000c7}, range = [0x0000000000019e36-0x000000000001a129), name="free_tiny"
LLDB design:
------------
lldb -> debugger -> target -> process -> thread -> frame(s)
-> thread -> frame(s)
'''
if __name__ == "__main__":
print("Run only as script from lldb... Not as standalone program")
try:
import lldb
except:
pass
import sys
import re
import os
import thread
import time
import struct
import argparse
import subprocess
import tempfile
try:
from keystone import *
CONFIG_KEYSTONE_AVAILABLE = 1
except:
CONFIG_KEYSTONE_AVAILABLE = 0
pass
#
# User configurable options
#
CONFIG_ENABLE_COLOR = 1
CONFIG_DISPLAY_DISASSEMBLY_BYTES = 1
CONFIG_DISASSEMBLY_LINE_COUNT = 8
CONFIG_USE_CUSTOM_DISASSEMBLY_FORMAT = 1
CONFIG_DISPLAY_STACK_WINDOW = 0
CONFIG_DISPLAY_FLOW_WINDOW = 1
CONFIG_ENABLE_REGISTER_SHORTCUTS = 1
CONFIG_DISPLAY_DATA_WINDOW = 0
# removes the offsets and modifies the module name position
# reference: https://lldb.llvm.org/formats.html
CUSTOM_DISASSEMBLY_FORMAT = "\"{${function.initial-function}{${function.name-without-args}} @ {${module.file.basename}}:\n}{${function.changed}\n{${function.name-without-args}} @ {${module.file.basename}}:\n}{${current-pc-arrow} }${addr-file-or-load}: \""
BLACK = 0
RED = 1
GREEN = 2
YELLOW = 3
BLUE = 4
MAGENTA = 5
CYAN = 6
WHITE = 7
COLOR_REGNAME = GREEN
COLOR_REGVAL = BLACK
COLOR_REGVAL_MODIFIED = RED
COLOR_SEPARATOR = BLUE
COLOR_CPUFLAGS = RED
COLOR_HIGHLIGHT_LINE = RED
#
# Don't mess after here unless you know what you are doing!
#
DATA_WINDOW_ADDRESS = 0
old_eax = 0
old_ecx = 0
old_edx = 0
old_ebx = 0
old_esp = 0
old_ebp = 0
old_esi = 0
old_edi = 0
old_eip = 0
old_eflags = 0
old_cs = 0
old_ds = 0
old_fs = 0
old_gs = 0
old_ss = 0
old_es = 0
old_rax = 0
old_rcx = 0
old_rdx = 0
old_rbx = 0
old_rsp = 0
old_rbp = 0
old_rsi = 0
old_rdi = 0
old_r8 = 0
old_r9 = 0
old_r10 = 0
old_r11 = 0
old_r12 = 0
old_r13 = 0
old_r14 = 0
old_r15 = 0
old_rflags = 0
old_rip = 0
old_arm_r0 = 0
old_arm_r1 = 0
old_arm_r2 = 0
old_arm_r3 = 0
old_arm_r4 = 0
old_arm_r5 = 0
old_arm_r6 = 0
old_arm_r7 = 0
old_arm_r8 = 0
old_arm_r9 = 0
old_arm_r10 = 0
old_arm_r11 = 0
old_arm_r12 = 0
old_arm_sp = 0
old_arm_lr = 0
old_arm_pc = 0
old_arm_cpsr = 0
arm_type = "thumbv7-apple-ios"
GlobalListOutput = []
Int3Dictionary = {}
crack_cmds = []
crack_cmds_noret = []
All_Registers = [ "rip", "rax", "rbx", "rbp", "rsp", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "eip", "eax", "ebx", "ebp", "esp", "edi", "esi", "edx", "ecx" ]
def __lldb_init_module(debugger, internal_dict):
''' we can execute commands using debugger.HandleCommand which makes all output to default
lldb console. With GetCommandinterpreter().HandleCommand() we can consume all output
with SBCommandReturnObject and parse data before we send it to output (eg. modify it);
'''
# don't load if we are in Xcode since it is not compatible and will block Xcode
if os.getenv('PATH').startswith('/Applications/Xcode'):
return
'''
If I'm running from $HOME where .lldbinit is located, seems like lldb will load
.lldbinit 2 times, thus this dirty hack is here to prevent doulbe loading...
if somebody knows better way, would be great to know :)
'''
var = lldb.debugger.GetInternalVariableValue("stop-disassembly-count", lldb.debugger.GetInstanceName())
if var.IsValid():
var = var.GetStringAtIndex(0)
if var == "0":
return
res = lldb.SBCommandReturnObject()
# settings
lldb.debugger.GetCommandInterpreter().HandleCommand("settings set target.x86-disassembly-flavor intel", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("settings set prompt \"(lldbinit) \"", res)
#lldb.debugger.GetCommandInterpreter().HandleCommand("settings set prompt \"\033[01;31m(lldb) \033[0m\"", res);
lldb.debugger.GetCommandInterpreter().HandleCommand("settings set stop-disassembly-count 0", res)
if CONFIG_USE_CUSTOM_DISASSEMBLY_FORMAT == 1:
lldb.debugger.GetCommandInterpreter().HandleCommand("settings set disassembly-format " + CUSTOM_DISASSEMBLY_FORMAT, res)
# the hook that makes everything possible :-)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.HandleHookStopOnTarget HandleHookStopOnTarget", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.HandleHookStopOnTarget ctx", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.HandleHookStopOnTarget context", res)
# commands
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.lldbinitcmds lldbinitcmds", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.IphoneConnect iphone", res)
#
# dump memory commands
#
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.db db", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.dw dw", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.dd dd", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.dq dq", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.DumpInstructions u", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.findmem findmem", res)
#
# Settings related commands
#
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.enable enable", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.disable disable", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.contextcodesize contextcodesize", res)
# a few settings aliases
lldb.debugger.GetCommandInterpreter().HandleCommand("command alias enablesolib enable solib", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command alias disablesolib disable solib", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command alias enableaslr enable aslr", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command alias disableaslr disable aslr", res)
#
# Breakpoint related commands
#
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.bhb bhb", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.bht bht", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.bpt bpt", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.bpn bpn", res)
# disable a breakpoint or all
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.bpd bpd", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.bpda bpda", res)
# clear a breakpoint or all
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.bpc bpc", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command alias bpca breakpoint delete", res)
# enable a breakpoint or all
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.bpe bpe", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.bpea bpea", res)
# commands to set temporary int3 patches and restore original bytes
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.int3 int3", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.rint3 rint3", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.listint3 listint3", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.nop nop", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.null null", res)
# change eflags commands
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.cfa cfa", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.cfc cfc", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.cfd cfd", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.cfi cfi", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.cfo cfo", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.cfp cfp", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.cfs cfs", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.cft cft", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.cfz cfz", res)
# skip/step current instruction commands
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.skip skip", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.stepo stepo", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.si si", res)
# load breakpoints from file
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.LoadBreakPoints lb", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.LoadBreakPointsRva lbrva", res)
# cracking friends
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.crack crack", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.crackcmd crackcmd", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.crackcmd_noret crackcmd_noret", res)
# alias for existing breakpoint commands
# list all breakpoints
lldb.debugger.GetCommandInterpreter().HandleCommand("command alias bpl breakpoint list", res)
# alias "bp" command that exists in gdbinit - lldb also has alias for "b"
lldb.debugger.GetCommandInterpreter().HandleCommand("command alias bp _regexp-break", res)
# to set breakpoint commands - I hate typing too much
lldb.debugger.GetCommandInterpreter().HandleCommand("command alias bcmd breakpoint command add", res)
# launch process and stop at entrypoint (not exactly as gdb command that just inserts breakpoint)
# usually it will be inside dyld and not the target main()
lldb.debugger.GetCommandInterpreter().HandleCommand("command alias break_entrypoint process launch --stop-at-entry", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.show_loadcmds show_loadcmds", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.show_header show_header", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.tester tester", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.datawin datawin", res)
# shortcut command to modify registers content
if CONFIG_ENABLE_REGISTER_SHORTCUTS == 1:
# x64
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.rip rip", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.rax rax", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.rbx rbx", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.rbp rbp", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.rsp rsp", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.rdi rdi", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.rsi rsi", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.rdx rdx", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.rcx rcx", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.r8 r8", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.r9 r9", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.r10 r10", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.r11 r11", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.r12 r12", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.r13 r13", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.r14 r14", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.r15 r15", res)
# x86
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.eip eip", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.eax eax", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.ebx ebx", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.ebp ebp", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.esp esp", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.edi edi", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.esi esi", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.edx edx", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.ecx ecx", res)
if CONFIG_KEYSTONE_AVAILABLE == 1:
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.asm32 asm32", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.asm64 asm64", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.arm32 arm32", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.arm64 arm64", res)
lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.armthumb armthumb", res)
# add the hook - we don't need to wait for a target to be loaded
lldb.debugger.GetCommandInterpreter().HandleCommand("target stop-hook add -o \"HandleHookStopOnTarget\"", res)
return
def lldbinitcmds(debugger, command, result, dict):
'''Display all available lldbinit commands.'''
help_table = [
[ "lldbinitcmds", "this command" ],
[ "enable", "configure lldb and lldbinit options" ],
[ "disable", "configure lldb and lldbinit options" ],
[ "contextcodesize", "set number of instruction lines in code window" ],
[ "b", "breakpoint address" ],
[ "bpt", "set a temporary software breakpoint" ],
[ "bpc", "clear breakpoint" ],
[ "bpca", "clear all breakpoints" ],
[ "bpd", "disable breakpoint" ],
[ "bpda", "disable all breakpoints" ],
[ "bpe", "enable a breakpoint" ],
[ "bpea", "enable all breakpoints" ],
[ "bcmd", "alias to breakpoint command add"],
[ "bpl", "list all breakpoints"],
[ "bpn", "temporarly breakpoint next instruction" ],
[ "break_entrypoint", "launch target and stop at entrypoint" ],
[ "skip", "skip current instruction" ],
[ "int3", "patch memory address with INT3" ],
[ "rint3", "restore original byte at address patched with INT3" ],
[ "listint3", "list all INT3 patched addresses" ],
[ "nop", "patch memory address with NOP" ],
[ "null", "patch memory address with NULL" ],
[ "stepo", "step over calls and loop instructions" ],
[ "lb", "load breakpoints from file and apply them (currently only func names are applied)" ],
[ "lbrva", "load breakpoints from file and apply to main executable, only RVA in this case" ],
[ "db/dw/dd/dq", "memory hex dump in different formats" ],
[ "findmem", "search memory" ],
[ "cfa/cfc/cfd/cfi/cfo/cfp/cfs/cft/cfz", "change CPU flags" ],
[ "u", "dump instructions" ],
[ "iphone", "connect to debugserver running on iPhone" ],
[ "ctx/context", "show current instruction pointer CPU context" ],
[ "show_loadcmds", "show otool output of Mach-O load commands" ],
[ "show_header", "show otool output of Mach-O header" ],
[ "enablesolib/disablesolib", "enable/disable the stop on library load events" ],
[ "enableaslr/disableaslr", "enable/disable process ASLR" ],
[ "crack", "return from current function" ],
[ "crackcmd", "set a breakpoint and return from that function" ],
[ "crackcmd_noret", "set a breakpoint and set a register value. doesn't return from function" ],
[ "datawin", "set start address to display on data window" ],
[ "rip/rax/rbx/etc", "shortcuts to modify x64 registers" ],
[ "eip/eax/ebx/etc", "shortcuts to modify x86 register" ],
[ "asm32/asm64", "x86/x64 assembler using keystone" ],
[ "arm32/arm64/armthumb", "ARM assembler using keystone" ]
]
print "lldbinit available commands:"
for row in help_table:
print(" {: <20} - {: <30}".format(*row))
print "\nUse \'cmdname help\' for extended command help."
# placeholder to make tests
def tester(debugger, command, result, dict):
print "test"
#frame = get_frame()
# the SBValue to ReturnFromFrame must be eValueTypeRegister type
# if we do a lldb.SBValue() we can't set to that type
# so we need to make a copy
# can we use FindRegister() from frame?
#return_value = frame.reg["rax"]
#return_value.value = "1"
#thread.ReturnFromFrame(frame, return_value)
#
# Settings related commands
#
def enable(debugger, command, result, dict):
'''Enable certain lldb and lldbinit options. Use \'enable help\' for more information.'''
help = """
Enable certain lldb and lldbinit configuration options.
Syntax: enable <setting>
Available settings:
color: enable color mode.
solib: enable stop on library events trick.
aslr: enable process aslr.
stackwin: enable stack window in context display.
datawin: enable data window in context display, configure address with datawin.
flow: call targets and objective-c class/methods.
"""
global CONFIG_ENABLE_COLOR
global CONFIG_DISPLAY_STACK_WINDOW
global CONFIG_DISPLAY_FLOW_WINDOW
global CONFIG_DISPLAY_DATA_WINDOW
cmd = command.split()
if len(cmd) == 0:
print "[-] error: command requires arguments."
print ""
print help
return
if cmd[0] == "color":
CONFIG_ENABLE_COLOR = 1
print "[+] Enabled color mode."
elif cmd[0] == "solib":
debugger.HandleCommand("settings set target.process.stop-on-sharedlibrary-events true")
print "[+] Enabled stop on library events trick."
elif cmd[0] == "aslr:":
debugger.HandleCommand("settings 10BC8 set target.disable-aslr false")
print "[+] Enabled ASLR."
elif cmd[0] == "stackwin":
CONFIG_DISPLAY_STACK_WINDOW = 1
print "[+] Enabled stack window in context display."
elif cmd[0] == "flow":
CONFIG_DISPLAY_FLOW_WINDOW = 1
print "[+] Enabled indirect control flow window in context display."
elif cmd[0] == "datawin":
CONFIG_DISPLAY_DATA_WINDOW = 1
print "[+] Enabled data window in context display. Configure address with \'datawin\' cmd."
elif cmd[0] == "help":
print help
else:
print "[-] error: unrecognized command."
print help
return
def disable(debugger, command, result, dict):
'''Disable certain lldb and lldbinit options. Use \'disable help\' for more information.'''
help = """
Disable certain lldb and lldbinit configuration options.
Syntax: disable <setting>
Available settings:
color: disable color mode.
solib: disable stop on library events trick.
aslr: disable process aslr.
stackwin: disable stack window in context display.
datawin: enable data window in context display.
flow: call targets and objective-c class/methods.
"""
global CONFIG_ENABLE_COLOR
global CONFIG_DISPLAY_STACK_WINDOW
global CONFIG_DISPLAY_FLOW_WINDOW
global CONFIG_DISPLAY_DATA_WINDOW
cmd = command.split()
if len(cmd) == 0:
print "[-] error: command requires arguments."
print ""
print help
return
if cmd[0] == "color":
CONFIG_ENABLE_COLOR = 0
print "[+] Disabled color mode."
elif cmd[0] == "solib":
debugger.HandleCommand("settings set target.process.stop-on-sharedlibrary-events false")
print "[+] Disabled stop on library events trick."
elif cmd[0] == "aslr":
debugger.HandleCommand("settings set target.disable-aslr true")
print "[+] Disabled ASLR."
elif cmd[0] == "stackwin":
CONFIG_DISPLAY_STACK_WINDOW = 0
print "[+] Disabled stack window in context display."
elif cmd[0] == "flow":
CONFIG_DISPLAY_FLOW_WINDOW = 0
print "[+] Disabled indirect control flow window in context display."
elif cmd[0] == "datawin":
CONFIG_DISPLAY_DATA_WINDOW = 0
print "[+] Disabled data window in context display."
elif cmd[0] == "help":
print help
else:
print "[-] error: unrecognized command."
print help
return
def contextcodesize(debugger, command, result, dict):
'''Set the number of disassembly lines in code window. Use \'contextcodesize help\' for more information.'''
help = """
Configures the number of disassembly lines displayed in code window.
Syntax: contextcodesize <line_count>
Note: expressions supported, do not use spaces between operators.
"""
global CONFIG_DISASSEMBLY_LINE_COUNT
cmd = command.split()
if len(cmd) != 1:
print "[-] error: please insert the number of disassembly lines to display."
print ""
print help
return
if cmd[0] == "help":
print help
print "\nCurrent configuration value is: %d" % CONFIG_DISASSEMBLY_LINE_COUNT
return
value = evaluate(cmd[0])
if value == None:
print "[-] error: invalid input value."
print ""
print help
return
CONFIG_DISASSEMBLY_LINE_COUNT = value
return
#
# End Settings related commands
#
#
# Color and output related commands
#
def color_reset():
output("\033[0m")
def color_bold():
if CONFIG_ENABLE_COLOR == 0:
output("")
return
output("\033[1m")
def color_underline():
if CONFIG_ENABLE_COLOR == 0:
output("")
return
output("\033[4m")
def color(x):
out_col = ""
if CONFIG_ENABLE_COLOR == 0:
output(out_col)
return
if x == BLACK:
out_col = "\033[30m"
elif x == RED:
out_col = "\033[31m"
elif x == GREEN:
out_col = "\033[32m"
elif x == YELLOW:
out_col = "\033[33m"
elif x == BLUE:
out_col = "\033[34m"
elif x == MAGENTA:
out_col = "\033[35m"
elif x == CYAN:
out_col = "\033[36m"
elif x == WHITE:
out_col = "\033[37m"
output(out_col)
# append data to the output that we display at the end of the hook-stop
def output(x):
global GlobalListOutput
GlobalListOutput.append(x)
#
# End Color related commands
#
#
# Breakpoint related commands
#
# temporary software breakpoint
def bpt(debugger, command, result, dict):
'''Set a temporary software breakpoint. Use \'bpt help\' for more information.'''
help = """
Set a temporary software breakpoint.
Syntax: bpt <address>
Note: expressions supported, do not use spaces between operators.
"""
cmd = command.split()
if len(cmd) != 1:
print "[-] error: please insert a breakpoint address."
print ""
print help
return
if cmd[0] == "help":
print help
return
value = evaluate(cmd[0])
if value == None:
print "[-] error: invalid input value."
print ""
print help
return
target = get_target()
breakpoint = target.BreakpointCreateByAddress(value)
breakpoint.SetOneShot(True)
breakpoint.SetThreadID(get_frame().GetThread().GetThreadID())
print "[+] Set temporary breakpoint at 0x{:x}".format(value)
# hardware breakpoint
def bhb(debugger, command, result, dict):
'''Set a hardware breakpoint'''
print "[-] error: lldb has no x86/x64 hardware breakpoints implementation."
return
# temporary hardware breakpoint
def bht(debugger, command, result, dict):
'''Set a temporary hardware breakpoint'''
print "[-] error: lldb has no x86/x64 hardware breakpoints implementation."
return
# clear breakpoint number
def bpc(debugger, command, result, dict):
'''Clear a breakpoint. Use \'bpc help\' for more information.'''
help = """
Clear a breakpoint.
Syntax: bpc <breakpoint_number>
Note: only breakpoint numbers are valid, not addresses. Use \'bpl\' to list breakpoints.
Note: expressions supported, do not use spaces between operators.
"""
cmd = command.split()
if len(cmd) != 1:
print "[-] error: please insert a breakpoint number."
print ""
print help
return
if cmd[0] == "help":
print help
return
# breakpoint disable only accepts breakpoint numbers not addresses
value = evaluate(cmd[0])
if value == None:
print "[-] error: invalid input value - only a breakpoint number is valid."
print ""
print help
return
target = get_target()
for bpt in target.breakpoint_iter():
if bpt.id == value:
if target.BreakpointDelete(bpt.id) == False:
print "[-] error: failed to delete breakpoint #{:d}".format(value)
return
print "[+] Deleted breakpoint #{:d}".format(value)
return
print "[-] error: breakpoint #{:d} not found".format(value)
return
# disable breakpoint number
# XXX: we could support addresses, not sure it's worth the trouble
def bpd(debugger, command, result, dict):
'''Disable a breakpoint. Use \'bpd help\' for more information.'''
help = """
Disable a breakpoint.
Syntax: bpd <breakpoint_number>
Note: only breakpoint numbers are valid, not addresses. Use \'bpl\' to list breakpoints.
Note: expressions supported, do not use spaces between operators.
"""
cmd = command.split()
if len(cmd) != 1:
print "[-] error: please insert a breakpoint number."
print ""
print help
return
if cmd[0] == "help":
print help
return
# breakpoint disable only accepts breakpoint numbers not addresses
value = evaluate(cmd[0])
if value == None:
print "[-] error: invalid input value - only a breakpoint number is valid."
print ""
print help
return
target = get_target()
for bpt in target.breakpoint_iter():
if bpt.id == value and bpt.IsEnabled() == True:
bpt.SetEnabled(False)
print "[+] Disabled breakpoint #{:d}".format(value)
# disable all breakpoints
def bpda(debugger, command, result, dict):
'''Disable all breakpoints. Use \'bpda help\' for more information.'''
help = """
Disable all breakpoints.
Syntax: bpda
"""
cmd = command.split()
if len(cmd) != 0:
if cmd[0] == "help":
print help
return
print "[-] error: command doesn't take any arguments."
print ""
print help
return
target = get_target()
if target.DisableAllBreakpoints() == False:
print "[-] error: failed to disable all breakpoints."
print "[+] Disabled all breakpoints."
# enable breakpoint number
def bpe(debugger, command, result, dict):
'''Enable a breakpoint. Use \'bpe help\' for more information.'''
help = """
Enable a breakpoint.
Syntax: bpe <breakpoint_number>
Note: only breakpoint numbers are valid, not addresses. Use \'bpl\' to list breakpoints.
Note: expressions supported, do not use spaces between operators.
"""
cmd = command.split()
if len(cmd) != 1:
print "[-] error: please insert a breakpoint number."
print ""
print help
return
if cmd[0] == "help":
print help
return
# breakpoint enable only accepts breakpoint numbers not addresses
value = evaluate(cmd[0])
if value == None:
print "[-] error: invalid input value - only a breakpoint number is valid."
print ""
print help
return
target = get_target()
for bpt in target.breakpoint_iter():
if bpt.id == value and bpt.IsEnabled() == False:
bpt.SetEnabled(True)
print "[+] Enabled breakpoint #{:d}".format(value)
# enable all breakpoints
def bpea(debugger, command, result, dict):
'''Enable all breakpoints. Use \'bpea help\' for more information.'''
help = """
Enable all breakpoints.
Syntax: bpea
"""
cmd = command.split()
if len(cmd) != 0:
if cmd[0] == "help":
print help
return
print "[-] error: command doesn't take any arguments."
print ""
print help
return
target = get_target()
if target.EnableAllBreakpoints() == False:
print "[-] error: failed to enable all breakpoints."
print "[+] Enabled all breakpoints."
# skip current instruction - just advances PC to next instruction but doesn't execute it
def skip(debugger, command, result, dict):
'''Advance PC to instruction at next address. Use \'skip help\' for more information.'''
help = """
Advance current instruction pointer to next instruction.
Syntax: skip
Note: control flow is not respected, it advances to next instruction in memory.
"""
cmd = command.split()
if len(cmd) != 0:
if cmd[0] == "help":
print help
return
print "[-] error: command doesn't take any arguments."
print ""
print help
return
start_addr = get_current_pc()
next_addr = start_addr + get_inst_size(start_addr)
if is_x64():
get_frame().reg["rip"].value = format(next_addr, '#x')
elif is_i386():
get_frame().reg["eip"].value = format(next_addr, '#x')
# show the updated context
lldb.debugger.HandleCommand("context")
# XXX: ARM breakpoint
def int3(debugger, command, result, dict):
'''Patch byte at address to an INT3 (0xCC) instruction. Use \'int3 help\' for more information.'''
help = """
Patch process memory with an INT3 byte at given address.
Syntax: int3 [<address>]
Note: useful in cases where the debugger breakpoints aren't respected but an INT3 will always trigger the debugger.
Note: ARM not yet supported.
Note: expressions supported, do not use spaces between operators.
"""
global Int3Dictionary
error = lldb.SBError()
target = get_target()
cmd = command.split()
# if empty insert a int3 at current PC
if len(cmd) == 0:
int3_addr = get_current_pc()
if int3_addr == 0:
print "[-] error: invalid current address."
return
elif len(cmd) == 1:
if cmd[0] == "help":
print help
return
int3_addr = evaluate(cmd[0])
if int3_addr == None:
print "[-] error: invalid input address value."
print ""
print help
return
else:
print "[-] error: please insert a breakpoint address."
print ""
print help
return
bytes_string = target.GetProcess().ReadMemory(int3_addr, 1, error)
if error.Success() == False:
print "[-] error: Failed to read memory at 0x%x." % int3_addr
return
bytes_read = bytearray(bytes_string)
patch_bytes = str('\xCC')
result = target.GetProcess().WriteMemory(int3_addr, patch_bytes, error)
if error.Success() == False:
print "[-] error: Failed to write memory at 0x%x." % int3_addr
return
# save original bytes for later restore
Int3Dictionary[str(int3_addr)] = bytes_read[0]
print "[+] Patched INT3 at 0x%x" % int3_addr
return
def rint3(debugger, command, result, dict):
'''Restore byte at address from a previously patched INT3 (0xCC) instruction. Use \'rint3 help\' for more information.'''
help = """
Restore the original byte at a previously patched address using \'int3\' command.
Syntax: rint3 [<address>]
Note: expressions supported, do not use spaces between operators.
"""
global Int3Dictionary
error = lldb.SBError()
target = get_target()
cmd = command.split()
# if empty insert a int3 at current PC
if len(cmd) == 0:
int3_addr = get_current_pc()
if int3_addr == 0:
print "[-] error: invalid current address."
return
elif len(cmd) == 1:
if cmd[0] == "help":
print help
return
int3_addr = evaluate(cmd[0])
if int3_addr == None:
print "[-] error: invalid input address value."
print ""
print help
return
else:
print "[-] error: please insert a INT3 patched address."
print ""
print help
return
if len(Int3Dictionary) == 0:
print "[-] error: No INT3 patched addresses to restore available."
return
bytes_string = target.GetProcess().ReadMemory(int3_addr, 1, error)
if error.Success() == False:
print "[-] error: Failed to read memory at 0x%x." % int3_addr
return
bytes_read = bytearray(bytes_string)
if bytes_read[0] == 0xCC:
#print "Found byte patched byte at 0x%x" % int3_addr
try:
original_byte = Int3Dictionary[str(int3_addr)]
except:
print "[-] error: Original byte for address 0x%x not found." % int3_addr
return
patch_bytes = chr(original_byte)
result = target.GetProcess().WriteMemory(int3_addr, patch_bytes, error)
if error.Success() == False:
0