summaryrefslogtreecommitdiffstats
path: root/sploit/rev/r2.py
blob: 306e02612629651dc703d805c3d91d3441129b8a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
from sploit.mem import Symtbl
from sploit.arch import arch

import re
from subprocess import run
from collections import namedtuple as nt

def run_cmd(binary,cmd):
    return run(['r2','-q','-c',cmd,'-e','scr.color=false',binary],capture_output=True).stdout.decode('utf-8').split('\n')[:-1]

def get_elf_symbols(elf):
    out = {}

    cmd_syms = 'is~ FUNC '
    out_syms = run_cmd(elf,cmd_syms)
    out_syms = [re.split(r'\s+',sym) for sym in out_syms]
    out_syms = {sym[6]:int(sym[2],0) for sym in out_syms if sym[6].find('.')<0}
    out.update(out_syms)

    cmd_syms = 'is~ LOOS '
    out_syms = run_cmd(elf,cmd_syms)
    out_syms = [re.split(r'\s+',sym) for sym in out_syms]
    out_syms = {sym[6]:int(sym[2],0) for sym in out_syms if sym[6].find('.')<0}
    out.update(out_syms)

    cmd_syms = 'is~ TLS '
    out_syms = run_cmd(elf,cmd_syms)
    out_syms = [re.split(r'\s+',sym) for sym in out_syms]
    out_syms = {sym[6]:int(sym[2],0) for sym in out_syms if sym[6].find('.')<0}
    out.update(out_syms)

    cmd_syms = 'ii~ FUNC '
    out_syms = run_cmd(elf,cmd_syms)
    out_syms = [re.split(r'\s+',sym) for sym in out_syms]
    out_syms = {"_PLT_"+sym[4]:int(sym[1],0) for sym in out_syms}
    out.update(out_syms)

    cmd_syms = 'fs relocs;f'
    out_syms = run_cmd(elf,cmd_syms)
    out_syms = [re.split(r'\s+',sym) for sym in out_syms]
    out_syms = {"_GOT_"+sym[2][sym[2].rfind('.')+1:]:int(sym[0],0) for sym in out_syms}
    out.update(out_syms)

    cmd_strs = 'fs strings;f'
    out_strs = run_cmd(elf,cmd_strs)
    out_strs = [re.split(r'\s+',sym) for sym in out_strs]
    out_strs = {sym[2][sym[2].rfind('.')+1:]:int(sym[0],0) for sym in out_strs}
    out.update(out_strs)

    return Symtbl(**out)

def get_locals(binary,func):
    addr = hex(func)
    cmd_locals = f's {func};af;aafr;aaft;afvf'
    out = run_cmd(binary,cmd_locals)
    out = [re.split(r':?\s+',var) for var in out]
    out = {var[1]:-(int(var[0],0)-arch.wordsize) for var in out}
    return Symtbl(**out)

def ret_gadget(binary):
    cmd_ret = '/R/ ret~ret'
    out = run_cmd(binary,cmd_ret)
    out = out[0]
    out = re.split(r'\s+',out)
    out = out[1]
    return int(out,0)

def rop_gadget(binary,gad):
    cmd_gad = f'"/R/q {gad}"'
    out = run_cmd(binary,cmd_gad)
    Gad = nt("Gad", "addr asm")
    out = [Gad(int(gad[:gad.find(':')],0),gad[gad.find(':')+2:]) for gad in out]
    return out

def rop_gadget_exact(binary,gad):
    gads = rop_gadget(gad,elf)
    for g in gads:
        if g.asm[:-1].replace('; ',';') == gad:
            return g

def get_call_returns(binary,xref_from,xref_to):
    cmd_xrefs = f's {hex(xref_from)};af;axq'
    xrefs = run_cmd(binary,cmd_xrefs)
    xrefs = [re.split(r'\s+',x) for x in xrefs]
    xrefs = [x for x in xrefs if int(x[2],0)==xref_to]
    rets = []
    CallRet = nt("CallRet", "xref_from xref_to call_addr ret_addr")
    for x in xrefs:
        cmd_ret = f's {x[0]};so;s'
        ret = run_cmd(binary,cmd_ret)
        rets.append(CallRet(xref_from,xref_to,int(x[0],0),int(ret[0],0)))
    return rets