-
Notifications
You must be signed in to change notification settings - Fork 14
/
rop_arm.py
156 lines (109 loc) · 3.79 KB
/
rop_arm.py
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/usr/bin/python
from lib.darm import darm
import os
import sys
import elf
import colors
import re
import struct
import binascii
def match_disas(disas, match):
for (offset, size, instruction, hexdump) in disas:
if instruction.find(match) != -1:
return True
return False
def ok_disas(disas):
for (offset, size, instruction, hexdump) in disas:
if instruction.find("DB ") != -1:
return False
if instruction.find("CALL") != -1:
return False
return True
def findstr(section, matchstring):
ropmatches = []
matchstring = matchstring.replace("?", ".")
p = re.compile(matchstring)
for m in p.finditer(section.encode("hex")):
if (m.start() % 4) != 0:
continue
ropmatches.append([ m.start() / 2, m.group() ])
return ropmatches
def assemble_str(code):
code = code.replace(";","\n")
code = "_start:\n" + code + "\n"
f = open("tmp.s", 'w')
f.write(code)
f.close()
ret = os.system("arm-none-eabi-gcc -s -o tmp.elf tmp.s -nostartfiles -nodefaultlibs 2>/dev/null")
if ret != 0:
print ">> Assemble fail :("
#os.system("rm -rf tmp.s tmp.elf tmp.bin")
exit()
os.system("arm-none-eabi-objcopy -O binary -j .text tmp.elf tmp.bin")
pattern = binascii.hexlify(open("tmp.bin").read())
os.system("rm -rf tmp.s tmp.elf tmp.bin")
return pattern
def disas_str(addr, data, thumb_mode):
out_insn = []
if thumb_mode == True:
insns = struct.unpack("H"*(len(data)/2), data)
for insn in insns:
out_insn.append(str(darm.disasm_thumb(insn)))
else:
insns = struct.unpack("I"*(len(data)/4), data)
for insn in insns:
out_insn.append(str(darm.disasm_armv7(insn)))
return out_insn
def do_ropfind(file, match_string):
gadgets = []
myelf = elf.fromfile(file)
if myelf.data[0:4] != "\x7F"+"ELF":
print "[!] '%s' is not a valid ELF file :(" % (file)
sys.exit(-1)
# figure out parameter
if re.search("^[0-9a-f\?]+$", match_string) != None:
pattern = match_string
else:
pattern = assemble_str(match_string)
print "[!] pattern: '%s'" % pattern
for section_name in myelf.strtable:
if section_name == "":
continue
section = myelf.section(section_name)
# check for PROGBITS type
if section['type'] != 1:
continue
matches = findstr(section['data'], pattern)
if len(matches) == 0:
continue
pstr = colors.fg('cyan') + ">> section '" + colors.bold() + section_name + colors.end()
pstr += colors.fg('cyan') + "' [" + colors.bold() + str(len(matches)) + colors.end()
pstr += colors.fg('cyan') + " hits]"
m = 0
for match in matches:
if match[1] in gadgets:
continue
if m == 0:
print pstr
m = 1
disas = disas_str(section['addr'] + match[0], binascii.unhexlify(match[1]), True)
fstr = colors.fg('cyan') + " \_ " + colors.fg('green') + "%08x [" + colors.bold() + match[1] + colors.end()
fstr += colors.fg('green') + "] "+ colors.bold() + "-> " + colors.end()
fstr += colors.fg('red') + "("+colors.bold()+"Thumb"+colors.end()+colors.fg('red')+") " + ' ; '.join(disas).lower() + colors.end()
print fstr % (section['addr'] + match[0] + 1)
gadgets.append(match[1])
if (len(binascii.unhexlify(match[1])) % 4) == 0:
disas = disas_str(section['addr'] + match[0], binascii.unhexlify(match[1]), False)
fstr = colors.fg('cyan') + " \_ " + colors.fg('green') + "%08x [" + colors.bold() + match[1] + colors.end()
fstr += colors.fg('green') + "] "+ colors.bold() + "-> " + colors.end()
fstr += colors.fg('red') + "("+colors.bold()+"ARM"+colors.end()+colors.fg('red')+" ) " + ' ; '.join(disas).lower() + colors.end()
if not (len(disas) == 1 and (disas[0] == "" or disas[0] == "None")):
print fstr % (section['addr'] + match[0])
gadgets.append(match[1])
if m == 1:
print ""
def main(args):
if len(args) < 2:
print "usage: moneyshot rop-arm <binary> <pattern/code>"
else:
do_ropfind(args[0], " ".join(args[1:]))