Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
zachriggle committed Feb 22, 2015
1 parent be8fdab commit ca801c0
Show file tree
Hide file tree
Showing 30 changed files with 886 additions and 93 deletions.
1 change: 0 additions & 1 deletion gdbinit.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@

import gef

gef.main()
33 changes: 31 additions & 2 deletions gef/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import gdb
import gef.arch
import gef.vmmap
import gef.dt
Expand All @@ -6,6 +7,34 @@
import gef.proc
import gef.regs
import gef.stack
import gef.commands
import gef.commands.hexdump
import gef.commands.context
import gef.commands.telescope
import gef.commands.vmmap
import gef.commands.dt

def main():
pass

pre_commands = """
set confirm off
set verbose off
set output-radix 0x10
set prompt geef>
set height 0
set history expansion on
set history save on
set disassembly-flavor intel
set follow-fork-mode child
set backtrace past-main on
set step-mode on
set print pretty on
set width 0
set print elements 15
set input-radix 16
handle SIGALRM print nopass
handle SIGSEGV stop print nopass
""".strip()

for line in pre_commands.splitlines():
if line:
gdb.execute(line)
33 changes: 29 additions & 4 deletions gef/arch.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
import struct
import sys
import gdb
import gef.memoize
import gef.events
import gef.types

current = None
ptrmask = 0xfffffffff
endian = 'little'
ptrsize = gef.types.ptrsize
fmt = '=i'

@gef.events.stop
def update():
global current
global ptrmask
current = gdb.selected_frame().architecture().name()
ptrmask = (1 << 8*gef.types.ptrsize)-1
m = sys.modules[__name__]

m.current = gdb.selected_frame().architecture().name()
m.ptrsize = gef.types.ptrsize
m.ptrmask = (1 << 8*gef.types.ptrsize)-1

if 'little' in gdb.execute('show endian', to_string=True):
m.endian = 'little'
else:
m.endian = 'big'

m.fmt = {
(4, 'little'): '<I',
(4, 'big'): '>I',
(8, 'little'): '<Q',
(8, 'big'): '>Q',
}.get((m.ptrsize, m.endian))


def pack(integer):
return struct.pack(fmt, integer & ptrmask)

def unpack(data):
return struct.unpack(fmt, data)[0]
4 changes: 4 additions & 0 deletions gef/auxv.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ def use_info_auxv():
def walk_stack():
sp = gef.regs.sp

print("BAD SP")

if not sp:
return None

Expand Down Expand Up @@ -167,6 +169,8 @@ def walk_stack():

# Scan them into our structure
auxv = AUXV()
print("STARTING AT %s" % p)
print("STOPPING AT %s" % AT_NULL)
while p < AT_NULL:
const, value = p.dereference(), (p+1).dereference()
const = int(const)
Expand Down
34 changes: 20 additions & 14 deletions gef/chain.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import gdb
import gef.types
import gef.color
import gef.enhance
import gef.memory
import gef.types
import gef.vmmap


def get(address, limit=5):
Expand All @@ -10,21 +13,24 @@ def get(address, limit=5):
Returns:
A list containing ``address``, followed by up to ``limit`` valid pointers.
"""
result = [int(address)]
result = []
for i in range(limit):
result.append(address)
try:
# Convert the current address to a void**
address = gef.memory.poi(gef.types.ppvoid, address)

# Ensure that it's a valid pointer by dereferencing it
# *AND* attempting to get the resulting value.
#
# GDB will let you .dereference() anything, the int() throws
# the gdb.MemoryError.
int(address.dereference())

# Save it off
result.append(int(address))
address = int(gef.memory.poi(gef.types.ppvoid, address))
except gdb.MemoryError:
break

return result


def format(value):
chain = get(value)

# Enhance the last entry
end = [gef.enhance.enhance(chain[-1])]

# Colorize the rest
rest = list(map(gef.color.get, chain[:-1]))

return ' --> '.join(rest + end)
32 changes: 26 additions & 6 deletions gef/color.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,23 @@
BLUE = "\x1b[34m"
PURPLE = "\x1b[35m"
CYAN = "\x1b[36m"
GREY = GRAY = "\x1b[37m"
GREY = GRAY = "\x1b[90m"
BOLD = "\x1b[1m"
UNDERLINE = "\x1b[4m"

STACK = BLUE
HEAP = BLUE + BOLD
STACK = YELLOW
HEAP = BLUE
CODE = RED
RWX = RED + BOLD
DATA = YELLOW
RWX = RED + BOLD + UNDERLINE
DATA = PURPLE

def normal(x): return NORMAL + x
def bold(x): return BOLD + x + NORMAL
def red(x): return RED + x + NORMAL
def blue(x): return BLUE + x + NORMAL
def gray(x): return GRAY + x + NORMAL
def green(x): return GREEN + x + NORMAL
def yellow(x): return YELLOW + x + NORMAL

def get(address, text = None):
"""
Expand All @@ -33,14 +41,26 @@ def get(address, text = None):
if page is None: color = NORMAL
elif '[stack' in page.objfile: color = STACK
elif '[heap' in page.objfile: color = HEAP
elif page.rwx: color = RWX
elif page.execute: color = CODE
elif page.rw: color = DATA
else: color = NORMAL

if page.rwx:
color = color + UNDERLINE

if text is None and isinstance(address, int) and address > 255:
text = hex(address)
if text is None:
text = address

return "%s%s%s" % (color, text, NORMAL)

def legend():
return 'LEGEND: ' + ' | '.join((
STACK + 'STACK' + NORMAL,
HEAP + 'HEAP' + NORMAL,
CODE + 'CODE' + NORMAL,
DATA + 'DATA' + NORMAL,
UNDERLINE + 'RWX' + NORMAL,
'RODATA'
))
67 changes: 66 additions & 1 deletion gef/commands/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,67 @@
import traceback
import gdb

class Command(gdb.Command):
import gef.regs
import gef.memory
import gef.hexdump
import gef.color
import gef.chain
import gef.enhance
import gef.symbol
import gef.ui
import gef.proc

debug = True

class ParsedCommand(gdb.Command):
def __init__(self, function):
super(ParsedCommand, self).__init__(function.__name__, gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION)
self.function = function

def invoke(self, argument, from_tty):
argv = gdb.string_to_argv(argument)

for i,arg in enumerate(argv):
try:
argv[i] = gdb.parse_and_eval(arg)
continue
except Exception:
pass

try:
arg = gef.regs.fix(arg)
argv[i] = gdb.parse_and_eval(arg)
except Exception:
pass

try:
self.function(*argv)
except TypeError:
if debug: print(traceback.format_exc())
pass

def __call__(self, *args):
self.function(*args)

def OnlyWhenRunning(func):
def wrapper(*a):
func.__doc__
if not gef.proc.alive:
pass
else:
func(*a)
wrapper.__name__ = func.__name__
wrapper.__module__ = func.__module__
return wrapper


@ParsedCommand
@OnlyWhenRunning
def searchmem(searchfor):

if isinstance(searchfor, gdb.Value):
try:
searchfor = gef.memory.read(searchfor.address, searchfor.sizeof)
except:
searchfor = 0
print(searchfor)
86 changes: 86 additions & 0 deletions gef/commands/context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import gdb
import gef.commands
import gef.color
import gef.vmmap
import gef.symbol
import gef.regs
import gef.ui
import gef.disasm
import gef.chain
import gef.commands.telescope
import gef.events


@gef.commands.ParsedCommand
@gef.commands.OnlyWhenRunning
@gef.events.stop
def context(*args):
if len(args) == 0:
args = ['reg','code','stack','backtrace']

args = [a[0] for a in args]

print(gef.color.legend())
if 'r' in args: context_regs()
if 'c' in args: context_code()
if 's' in args: context_stack()
if 'b' in args: context_backtrace()

def context_regs():
print(gef.color.blue(gef.ui.banner("registers")))
for reg in gef.regs.gpr + (gef.regs.frame, gef.regs.stack, '$pc'):
if reg is None:
continue

value = gef.regs[reg]

# Make the register stand out
regname = gef.color.bold(reg.ljust(4).upper())

print("%s %s" % (regname, gef.chain.format(value)))

def context_code():
print(gef.color.blue(gef.ui.banner("code")))
pc = gef.regs.pc
instructions = gef.disasm.near(gef.regs.pc, 5)

# In case $pc is in a new map we don't know about,
# this will trigger an exploratory search.
gef.vmmap.find(pc)

# Ensure screen data is always at the same spot
for i in range(11 - len(instructions)):
print()

# Find all of the symbols for the addresses
symbols = []
for i in instructions:
symbol = gef.symbol.get(i.address)
if symbol:
symbol = '<%s> ' % symbol
symbols.append(symbol)

# Find the longest symbol name so we can adjust
longest_sym = max(map(len, symbols))

# Pad them all out
for i,s in enumerate(symbols):
symbols[i] = s.ljust(longest_sym)

# Print out each instruction
for i,s in zip(instructions, symbols):
asm = gef.disasm.color(i)
prefix = ' =>' if i.address == pc else ' '
print(prefix, s + hex(i.address), asm)

def context_stack():
print(gef.color.blue(gef.ui.banner("stack")))
gef.commands.telescope.telescope(gef.regs.sp)

def context_backtrace():
print(gef.color.blue(gef.ui.banner("backtrace")))
frame = gdb.selected_frame()
for i in range(0,10):
if frame:
print(gef.ui.addrsz(frame.pc()), frame.name() or '???')
frame = frame.older()
10 changes: 10 additions & 0 deletions gef/commands/dt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import gdb
import gef.vmmap
import gef.commands
import gef.color
import gef.dt

@gef.commands.ParsedCommand
@gef.commands.OnlyWhenRunning
def dt(typename, address=None):
print(gef.dt.dt(typename, addr=address))
Loading

0 comments on commit ca801c0

Please sign in to comment.