WIPWIPWIP

pull/14/head
Zach Riggle 11 years ago
parent add3acba15
commit c6347c6bd6

@ -1,6 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import gdb
import pwndbg.disasm
import pwndbg.arch
import pwndbg.arguments
import pwndbg.vmmap

@ -1,17 +1,23 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import collections
import struct
import sys
import gdb
import pwndbg.events
import pwndbg.memoize
import pwndbg.memory
import pwndbg.regs
import pwndbg.typeinfo
from capstone import *
current = 'i386'
ptrmask = 0xfffffffff
endian = 'little'
ptrsize = pwndbg.typeinfo.ptrsize
fmt = '=i'
disasm = lambda: None
def fix_arch(arch):
arches = ['x86-64', 'i386', 'mips', 'powerpc', 'sparc', 'arm', 'aarch64', arch]
@ -37,11 +43,15 @@ def update():
(8, 'big'): '>Q',
}.get((m.ptrsize, m.endian))
m.disasm = gdb.selected_frame().architecture().disassemble
def pack(integer):
return struct.pack(fmt, integer & ptrmask)
def unpack(data):
return struct.unpack(fmt, data)[0]
def signed(integer):
return unpack(pack(integer), signed=True)
def unsigned(integer):
return unpack(pack(integer))

@ -0,0 +1,9 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Stepping until an event occurs
"""
@pwndbg.commands.Command
@pwndbg.commands.OnlyWhenRunning
def nextcall(*args):

@ -8,12 +8,13 @@ import collections
import gdb
import pwndbg.arch
import pwndbg.disasm.mips
import pwndbg.disasm.arch
import pwndbg.disasm.arm
import pwndbg.disasm.ppc
import pwndbg.disasm.x86
import pwndbg.disasm.jump
import pwndbg.disasm.mips
import pwndbg.disasm.ppc
import pwndbg.disasm.sparc
import pwndbg.disasm.x86
import pwndbg.ida
import pwndbg.memory
import pwndbg.symbol
@ -55,6 +56,23 @@ VariableInstructionSizeMax = {
backward_cache = {}
def get_assistant():
return {
'i386': pwndbg.disasm.x86.assistant,
'x86-64': pwndbg.disasm.x86.assistant,
'arm': pwndbg.disasm.arm.assistant
}.get(pwndbg.arch.current, lambda *a: None)(instruction)
def get_operands(instruction):
"""
IFF instruction is the next instruction to be executed,
return an OrderedDict which maps the operand names to
their current values.
Otherwise, returns an empty dict.
"""
if instruction.address != pwndbg.regs.pc:
return {}
def get_target(instruction):
"""

@ -0,0 +1,89 @@
groups = {v:k for k,v in globals().items() if k.startswith('CS_GRP_')}
ops = {v:k for k,v in globals().items() if k.startswith('CS_OP_')}
access = {v:k for k,v in globals().items() if k.startswith('CS_AC_')}
for value1, name1 in access.items():
for value2, name2 in access.items():
access.setdefault(value1 | value2, '%s | %s' % (name1, name2))
class DisassemblyAssistant(object):
def __init__(self):
self.op_handlers = {
CS_OP_IMM: self.immediate,
CS_OP_REG: self.register,
CS_OP_MEM: self.memory
}
self.op_names = {
CS_OP_IMM: self.immediate_sz,
CS_OP_REG: self.register_sz,
CS_OP_MEM: self.memory_sz
}
def operands(self, instruction):
current = (instruction.address == pwndbg.regs.pc)
rv = collections.OrderedDict()
for i, op in enumerate(instruction.operands):
T = op.type
if not current or T not in op_handlers:
rv['op%i' % i] = None
continue
result = self.op_handlers[T](instruction, op)
if result is not None:
rv[self.op_names[T]] = result
return rv
def immediate(self, instruction, operand):
return operand.value.imm
def immediate_sz(self, instruction, operand):
return "%#x" % self.immediate(instruction, operand)
def register(self, instruction, operand):
# Don't care about registers which are only overwritten
if operand.access & CS_AC_READ == 0:
return None
reg = operand.value.reg
name = instruction.reg_name(reg)
return pwndbg.regsisters[name]
def register_sz(self, instruction, operand):
reg = operand.value.reg
return instruction.reg_name(reg).lower()
def memory(self, instruction, operand):
return None
def memory_sz(self, instruction, operand):
raise NotImplementedError
def dump(self, instruction):
ins = instruction
rv = []
rv.append('%s %s' % (ins.mnemonic,ins.op_str))
for i, group in enumerate(ins.groups):
rv.append(' groups[%i] = %s' % (i, groups[group]))
ops = self.operands(instruction)
for i, ((name, value), op) in enumerate(zip(ops.items(), ins.operands)):
rv.append(' operands[%i] = %s' % (i, ops[op.type]))
rv.append(' access = %s' % (get_access(op.access)))
if None not in (name, value):
rv.append(' %s = %#x' % (name, value))
return '\n'.join(rv)
assistant = DisassemblyAssistant()

@ -0,0 +1,73 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import collections
import pwndbg.arch
import pwndbg.disasm.arch
import pwndbg.memory
import pwndbg.regs
from capstone import *
from capstone.arm import *
import pwndbg.disasm.arch
import pdb
pdb.set_trace()
class DisassemblyAssistant(pwndbg.disasm.arch.DisassemblyAssistant):
def memory_sz(self, instruction, operand):
segment = ''
parts = []
if op.mem.base != 0:
parts.append(instruction.reg_name(op.mem.base))
if op.mem.disp != 0:
parts.append("%#x" % op.value.mem.disp)
if op.mem.index != 0:
index = pwndbg.regs[instruction.reg_name(op.mem.index)]
scale = op.mem.scale
parts.append("%s*%#x" % (index, scale))
return "[%s]" % (segment, ', '.join(parts))
def immediate_sz(self, instruction, operand):
imm = self.immediate(instruction, operand)
imm = self.arch.signed(imm)
if abs(imm) < 0x10:
return '#%i' % imm
return '#%#x' % imm
assistant = DisassemblyAssistant()
def is_jump_taken(instruction):
cpsr = pwndbg.regs.cpsr
N = cpsr & (1<<31)
Z = cpsr & (1<<30)
C = cpsr & (1<<29)
V = cpsr & (1<<28)
return {
ARM_CC_EQ: Z,
ARM_CC_NE: not Z,
ARM_CC_HS: C,
ARM_CC_LO: not C,
ARM_CC_MI: N,
ARM_CC_PL: not N,
ARM_CC_VS: V,
ARM_CC_VC: not V,
ARM_CC_HI: C and not Z,
ARM_CC_LS: Z or not C,
ARM_CC_GE: N == V,
ARM_CC_LT: N != V,
ARM_CC_GT: not Z and (N==V),
ARM_CC_LE: Z or (N != V),
# ARM_CC_AL: 1,
}.get(instruction.id, None)
is_condition_true = is_jump_taken

@ -1,5 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import collections
import pwndbg.arch
import pwndbg.memory
import pwndbg.regs
@ -12,6 +14,30 @@ ops = {v:k for k,v in globals().items() if k.startswith('X86_OP_')}
regs = {v:k for k,v in globals().items() if k.startswith('X86_REG_')}
access = {v:k for k,v in globals().items() if k.startswith('CS_AC_')}
class DisassemblyAssistant(pwndbg.disasm.arch.DisassemblyAssistant):
def memory_sz(self, instruction, operand):
segment = ''
parts = []
if op.mem.segment != 0:
segment = '%s:' % instructions.reg_name(op.mem.segment)
if op.mem.base != 0:
parts.append(instruction.reg_name(op.mem.base))
if op.mem.disp != 0:
parts.append("%#x" % op.value.mem.disp)
if op.mem.index != 0:
index = pwndbg.regs[instruction.reg_name(op.mem.index)]
scale = op.mem.scale
parts.append("%s*%#x" % (index, scale))
return "%s[%s]" % (segment, ' + '.join(parts))
assistant = DisassemblyAssistant()
def is_memory_op(op):
return op.type == X86_OP_MEM
@ -21,16 +47,16 @@ def get_access(ac):
if ac & k: rv.append(v)
return ' | '.join(rv)
def dump(instruction):
ins = instruction
rv = []
rv.append('%s %s' % (ins.mnemonic,ins.op_str))
for i, group in enumerate(ins.groups):
rv.append(' groups[%i] = %s' % (i, groups[group]))
for i, op in enumerate(ins.operands):
rv.append(' operands[%i] = %s' % (i, ops[op.type]))
rv.append(' access = %s' % (get_access(op.access)))
return '\n'.join(rv)
def dump(self, instruction):
ins = instruction
rv = []
rv.append('%s %s' % (ins.mnemonic,ins.op_str))
for i, group in enumerate(ins.groups):
rv.append(' groups[%i] = %s' % (i, groups[group]))
for i, op in enumerate(ins.operands):
rv.append(' operands[%i] = %s' % (i, ops[op.type]))
rv.append(' access = %s' % (get_access(op.access)))
return '\n'.join(rv)
def resolve(instruction):
ops = list(instruction.operands)
@ -61,6 +87,52 @@ def resolve(instruction):
print("Weird number of operands!!!!!")
print(dump(instruction))
def register(i, op):
assert CS_OP_REG == op.type
regname = instruction.reg_name(op.value.reg)
return pwndbg.regs[regname]
def immediate(i, op):
assert CS_OP_IMM == op.type
return op.value.imm
def memory():
current = (instruction.address == pwndbg.regs.pc)
constant = bool(op.mem.base == 0 and op.mem.index == 0)
if not current and not constant:
return (None, False)
if op.mem.segment != 0:
return (None, False)
if op.mem.base != 0:
regname = instruction.reg_name(op.mem.base)
target += pwndbg.regs[regname]
if op.mem.disp != 0:
target += op.value.mem.disp
if op.mem.index != 0:
scale = op.mem.scale
index = pwndbg.regs[instruction.reg_name(op.mem.index)]
target += (scale * index)
# for source operands, resolve
if op.access == CS_AC_READ:
try:
target = pwndbg.memory.u(target, op.size * 8)
except:
return (None, False)
return (target, constant)
resolvers = {
CS_OP_REG: register,
CS_OP_IMM: immediate,
CS_OP_MEM: memory
}
def get_operand_target(instruction, op):
current = (instruction.address == pwndbg.regs.pc)

@ -1,100 +0,0 @@
# Table stolen from
# http://ps-2.kev009.com/wisclibrary/aix52/usr/share/man/info/en_US/a_doc_lib/aixassem/alangref/branch_mnem.htm
powerpc = """
bc+ bc- bca+ bca-
bcctr+ bcctr- bcctrl+ bcctrl-
bcl+ bcl- bcla+ bcla-
bclr+ bclr- bclrl+ bclrl-
bdneq+ bdneq- bdnge+ bdnge-
bdngt+ bdngt- bdnle+ bdnle-
bdnlt+ bdnlt- bdnne+ bdnne-
bdnns+ bdnns- bdnso+ bdnso-
bdnz+ bdnz- bdnza+ bdnza-
bdnzf+ bdnzf- bdnzfa+ bdnzfa-
bdnzfl+ bdnzfl- bdnzfla+ bdnzfla-
bdnzflr+ bdnzflr- bdnzflrl+ bdnzflrl-
bdnzl+ bdnzl- bdnzla+ bdnzla-
bdnzlr+ bdnzlr- bdnzlrl+ bdnzlrl-
bdnzt+ bdnzt- bdnzta+ bdnzta-
bdnztl+ bdnztl- bdnztla+ bdnztla-
bdnztlr+ bdnztlr- bdnztlrl+ bdnztlrl-
bdz+ bdz- bdza+ bdza-
bdzeq+ bdzeq- bdzf+ bdzf-
bdzfa+ bdzfa- bdzfl+ bdzfl-
bdzfla+ bdzfla- bdzflr+ bdzflr-
bdzflrl+ bdzflrl- bdzge+ bdzge-
bdzgt+ bdzgt- bdzl+ bdzl-
bdzla+ bdzla- bdzle+ bdzle-
bdzlr+ bdzlr- bdzlrl+ bdzlrl-
bdzlt+ bdzlt- bdzne+ bdzne-
bdzns+ bdzns- bdzso+ bdzso-
bdzt+ bdzt- bdzta+ bdzta-
bdztl+ bdztl- bdztla+ bdztla-
bdztlr+ bdztlr- bdztlrl+ bdztlrl-
beq+ beq- beqa+ beqa-
beqctr+ beqctr- beqctrl+ beqctrl-
beql+ beql- beqla+ beqla-
beqlr+ beqlr- beqlrl+ beqlrl-
bf+ bf- bfa+ bfa-
bfctr+ bfctr- bfctrl+ bfctrl-
bfl+ bfl- bfla+ bfla-
bflr+ bflr- bflrl+ bflrl-
bge+ bge- bgea+ bgea-
bgectr+ bgectr- bgectrl+ bgectrl-
bgel+ bgel- bgela+ bgela-
bgelr+ bgelr- bgelrl+ bgelrl-
bgt+ bgt- bgta+ bgta-
bgtctr+ bgtctr- bgtctrl+ bgtctrl-
bgtl+ bgtl- bgtla+ bgtla-
bgtlr+ bgtlr- bgtlrl+ bgtlrl-
ble+ ble- blea+ blea-
blectr+ blectr- blectrl+ blectrl-
blel+ blel- blela+ blela-
blelr+ blelr- blelrl+ blelrl-
blt+ blt- blta+ blta-
bltctr+ bltctr- bltctrl+ bltctrl-
bltl+ bltl- bltla+ bltla-
bltlr+ bltlr- bltlrl+ bltlrl-
bne+ bne- bnea+ bnea-
bnectr+ bnectr- bnectrl+ bnectrl-
bnel+ bnel- bnela+ bnela-
bnelr+ bnelr- bnelrl+ bnelrl-
bng+ bng- bnga+ bnga-
bngctr+ bngctr- bngctrl+ bngctrl-
bngl+ bngl- bngla+ bngla-
bnglr+ bnglr- bnglrl+ bnglrl-
bnl+ bnl- bnla+ bnla-
bnlctr+ bnlctr- bnlctrl+ bnlctrl-
bnll+ bnll- bnlla+ bnlla-
bnllr+ bnllr- bnllrl+ bnllrl-
bns+ bns- bnsa+ bnsa-
bnsctr+ bnsctr- bnsctrl+ bnsctrl-
bnsl+ bnsl- bnsla+ bnsla-
bnslr+ bnslr- bnslrl+ bnslrl-
bnu+ bnu- bnua+ bnua-
bnuctr+ bnuctr- bnuctrl+ bnuctrl-
bnul+ bnul- bnula+ bnula-
bnulr+ bnulr- bnulrl+ bnulrl-
bnz+ bnz- bnza+ bnza-
bnzctr+ bnzctr- bnzctrl+ bnzctrl-
bnzl+ bnzl- bnzla+ bnzla-
bnzlr+ bnzlr- bnzlrl+ bnzlrl-
bso+ bso- bsoa+ bsoa-
bsoctr+ bsoctr- bsoctrl+ bsoctrl-
bsol+ bsol- bsola+ bsola-
bsolr+ bsolr- bsolrl+ bsolrl-
bt+ bt- bta+ bta-
btctr+ btctr- btctrl+ btctrl-
btl+ btl- btla+ btla-
btlr+ btlr- btlrl+ btlrl-
bun+ bun- buna+ buna-
bunctr+ bunctr- bunctrl+ bunctrl-
bunl+ bunl- bunla+ bunla-
bunlr+ bunlr- bunlrl+ bunlrl-
bz+ bz- bza+ bza-
bzctr+ bzctr- bzctrl+ bzctrl-
bzl+ bzl- bzla+ bzla-
bzlr+ bzlr- bzlrl+ bzlrl-
""".strip().split()
branches = set(map(lambda x: x.rstrip('+-'), powerpc))

@ -106,6 +106,17 @@ class reset_on_start(memoize):
for obj in reset_on_start.caches:
obj.clear()
class reset_on_cont(memoize):
caches = []
kind = 'cont'
@staticmethod
@pwndbg.events.cont
def __reset():
for obj in reset_on_cont.caches:
obj.clear()
class while_running(memoize):
caches = []
kind = 'running'

@ -16,19 +16,61 @@ import pwndbg.memoize
class RegisterSet(object):
def __init__(self, pc, stack, frame, retaddr, flags, gpr, misc, args, retval):
self.pc = pc
#: Program counter register
pc = None
#: Stack pointer register
stack = None
#: Frame pointer register
frame = None
#: Return address register
retaddr = None
#: Flags register (eflags, cpsr)
flags = None
#: List of native-size generalp-purpose registers
gpr = None
#: List of miscellaneous, valid registers
misc = None
#: Register-based arguments for most common ABI
regs = None
#: Return value register
retval = None
#: Common registers which should be displayed in the register context
common = None
#: All valid registers
all = None
def __init__(self,
pc='pc',
stack='sp',
frame=None,
retaddr=tuple(),
flags=tuple(),
gpr=tuple(),
misc=tuple(),
args=tuple(),
retval=None):
self.pc = pc
self.stack = stack
self.frame = frame
self.retaddr = retaddr
self.flags = flags
self.gpr = gpr
self.misc = misc
self.args = args
self.flags = flags
self.gpr = gpr
self.misc = misc
self.args = args
self.retval = retval
self.common = set(i for i in gpr + (frame, stack, pc) if i)
self.all = set(i for i in misc or tuple()) | set(flags or tuple()) | self.common
self.all = set(i for i in misc) | set(flags) | self.common
self.common -= {None}
self.all -= {None}
@ -37,54 +79,50 @@ class RegisterSet(object):
for r in self.all:
yield r
arm = RegisterSet( 'pc',
'sp',
None,
('lr',),
('cpsr',),
('r0','r1','r2','r3','r4','r5','r6','r7','r8','r9','r10','r11','r12'),
tuple(),
('r0','r1','r2','r3'),
'r0')
aarch64 = RegisterSet('pc',
'sp',
None,
('lr',),
('cpsr',),
('x0','x1','x2','x3','x4','x5','x6','x7','x8','x9','x10','x11','x12'),
tuple(),
('x0','x1','x2','x3'),
'x0')
amd64 = RegisterSet('rip',
'rsp',
'rbp',
tuple(),
('eflags',),
('rax','rbx','rcx','rdx','rdi','rsi',
'r8', 'r9', 'r10','r11','r12',
'r13','r14','r15'),
('cs','ss','ds','es','fs','gs'),
('rdi','rsi','rdx','rcx','r8','r9'),
'rax')
i386 = RegisterSet('eip',
'esp',
'ebp',
tuple(),
('eflags',),
('eax','ebx','ecx','edx','edi','esi'),
('cs','ss','ds','es','fs','gs'),
('*((void**)$sp+0)',
'*((void**)$sp+1)',
'*((void**)$sp+2)',
'*((void**)$sp+3)',
'*((void**)$sp+4)',
'*((void**)$sp+5)',
'*((void**)$sp+6)',),
'eax')
arm = RegisterSet( retaddr = ('lr',),
flags = ('cpsr',),
gpr = tuple('r%i' % i for i in range(13)),
args = ('r0','r1','r2','r3'),
retval = 'r0')
aarch64 = RegisterSet( retaddr = ('lr',),
flags = ('cpsr',),
gpr = tuple('x%i' % i for i in range(32)),
misc = tuple('w%i' % i for i in range(32)),
args = ('x0','x1','x2','x3'),
retval = 'x0')
amd64 = RegisterSet(pc = 'rip',
stack = 'rsp',
frame = 'rbp',
flags = ('eflags',),
gpr = ('rax','rbx','rcx','rdx','rdi','rsi',
'r8', 'r9', 'r10','r11','r12',
'r13','r14','r15'),
misc = ('cs','ss','ds','es','fs','gs',
'ax','ah','al',
'bx','bh','bl',
'cx','ch','cl',
'dx','dh','dl',
'dil','sil','spl','bpl',
'di','si','bp','sp','ip'),
args = ('rdi','rsi','rdx','rcx','r8','r9'),
retval = 'rax')
i386 = RegisterSet( pc = 'eip',
stack = 'esp',
frame = 'ebp',
flags = ('eflags',),
gpr = ('eax','ebx','ecx','edx','edi','esi'),
misc = ('cs','ss','ds','es','fs','gs',
'ax','ah','al',
'bx','bh','bl',
'cx','ch','cl',
'dx','dh','dl',
'dil','sil','spl','bpl',
'di','si','bp','sp','ip'),
retval = 'eax')
# http://math-atlas.sourceforge.net/devel/assembly/elfspec_ppc.pdf
@ -97,15 +135,12 @@ i386 = RegisterSet('eip',
# r13 Small data area pointer register (points to TLS)
# r14-r30 Registers used for local variables
# r31 Used for local variables or "environment pointers"
powerpc = RegisterSet('pc',
'sp',
None,
('lr','r0'),
('msr','xer'),
tuple('r%i' % i for i in range(3,32)),
('cr','lr','r2'),
tuple(),
'r3')
powerpc = RegisterSet( retaddr = ('lr','r0'),
flags = ('msr','xer'),
gpr = tuple('r%i' % i for i in range(3,32)),
misc = ('cr','lr','r2'),
args = tuple('r%i' for i in range(3,11)),
retval = 'r3')
# http://people.cs.clemson.edu/~mark/sparc/sparc_arch_desc.txt
# http://people.cs.clemson.edu/~mark/subroutines/sparc.html
@ -137,15 +172,13 @@ sparc_gp = tuple(['g%i' % i for i in range(1,8)]
+['o%i' % i for i in range(0,6)]
+['l%i' % i for i in range(0,8)]
+['i%i' % i for i in range(0,6)])
sparc = RegisterSet('pc',
'o6',
'i6',
('o7',),
('psr',),
sparc_gp,
tuple(),
('i0','i1','i2','i3','i4','i5'),
'o0')
sparc = RegisterSet(stack = 'o6',
frame = 'i6',
retaddr = ('o7',),
flags = ('psr',),
gpr = sparc_gp,
args = ('i0','i1','i2','i3','i4','i5'),
retval = 'o0')
# http://logos.cs.uic.edu/366/notes/mips%20quick%20tutorial.htm
@ -161,17 +194,13 @@ sparc = RegisterSet('pc',
# r29 => stack pointer
# r30 => frame pointer
# r31 => return address
mips = RegisterSet( 'pc',
'sp',
'fp',
('ra',),
tuple(),
('v0','v1','a0','a1','a2','a3') \
+ tuple('t%i' % i for i in range(10)) \
+ tuple('s%i' % i for i in range(9)),
tuple(),
('a0','a1','a2','a3'),
'v0')
mips = RegisterSet( frame = 'fp',
retaddr = ('ra',),
gpr = ('v0','v1','a0','a1','a2','a3') \
+ tuple('t%i' % i for i in range(10)) \
+ tuple('s%i' % i for i in range(9)),
args = ('a0','a1','a2','a3'),
retval = 'v0')
arch_to_regs = {
'i386': i386,
@ -188,6 +217,7 @@ arch_to_regs = {
class module(ModuleType):
last = {}
@pwndbg.memoize.reset_on_stop
def __getattr__(self, attr):
try:
value = gdb.parse_and_eval('$' + attr.lstrip('$'))
@ -201,6 +231,7 @@ class module(ModuleType):
except gdb.error:
return None
@pwndbg.memoize.reset_on_stop
def __getitem__(self, item):
if isinstance(item, int):
return arch_to_regs[pwndbg.arch.current][item]

Loading…
Cancel
Save