-
Notifications
You must be signed in to change notification settings - Fork 69
/
radare2-listing.py
189 lines (159 loc) · 5.13 KB
/
radare2-listing.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#!/usr/bin/env python
__description__ = "Program to add information to radare2 listing"
__author__ = 'Didier Stevens'
__version__ = '0.0.1'
__date__ = '2016/11/01'
"""
Source code put in public domain by Didier Stevens, no Copyright
https://DidierStevens.com
Use at your own risk
History:
2016/09/15: start
2016/09/21: continue
2016/09/28: all text on one line
2016/11/01: added option -c
Todo:
"""
import optparse
import glob
import collections
import re
import sys
import textwrap
import binascii
def PrintManual():
manual = '''
Manual:
'''
for line in manual.split('\n'):
print(textwrap.fill(line))
def File2Strings(filename):
try:
f = open(filename, 'r')
except:
return None
try:
return map(lambda line:line.rstrip('\n'), f.readlines())
except:
return None
finally:
f.close()
def ProcessAt(argument):
if argument.startswith('@'):
strings = File2Strings(argument[1:])
if strings == None:
raise Exception('Error reading %s' % argument)
else:
return strings
else:
return [argument]
# CIC: Call If Callable
def CIC(expression):
if callable(expression):
return expression()
else:
return expression
# IFF: IF Function
def IFF(expression, valueTrue, valueFalse):
if expression:
return CIC(valueTrue)
else:
return CIC(valueFalse)
class cOutput():
def __init__(self, filename=None):
self.filename = filename
if self.filename and self.filename != '':
self.f = open(self.filename, 'w')
else:
self.f = None
def Line(self, line):
if self.f:
self.f.write(line + '\n')
else:
print(line)
def Close(self):
if self.f:
self.f.close()
self.f = None
def ExpandFilenameArguments(filenames):
return list(collections.OrderedDict.fromkeys(sum(map(glob.glob, sum(map(ProcessAt, filenames), [])), [])))
class cOutputResult():
def __init__(self, options):
if options.output:
self.oOutput = cOutput(options.output)
else:
self.oOutput = cOutput()
self.options = options
def Line(self, line):
self.oOutput.Line(line)
def Close(self):
self.oOutput.Close()
def ProcessFile(fIn, fullread):
if fullread:
yield fIn.read()
else:
for line in fIn:
yield line.strip('\n')
def Radare2ListingSingle(filenames, oOutput, options):
oRE = re.compile('0x[0-9a-fA-F]{4,}')
for filename in filenames:
if filename == '':
fIn = sys.stdin
else:
fIn = open(filename, 'r')
comment = ''
lines = []
for line in [line.strip('\r\n\a') for line in ProcessFile(fIn, False)] + ['']:
if line[12:14] == '0x':
code = line[42:]
position = code.find(';')
if position != -1:
code = code[:position]
oMatch = oRE.search(code)
if oMatch != None and len(oMatch.group(0)[2:]) % 2 == 0:
# comment = " ; '%s'" % ''.join([IFF(b < chr(32) or b > chr(127), '.', b) for b in binascii.a2b_hex(oMatch.group(0)[2:])[::-1]])
comment += ''.join([IFF(b < chr(32) or b > chr(127), '.', b) for b in binascii.a2b_hex(oMatch.group(0)[2:])[::-1]])
lines.append(line)
else:
if comment == '':
if not options.comment:
oOutput.Line(line)
else:
oOutput.Line(lines[0] + " ; '%s'" % comment)
if not options.comment:
for line1 in lines[1:]:
oOutput.Line(line1)
comment = ''
lines = []
else:
oOutput.Line(line)
if fIn != sys.stdin:
fIn.close()
def Radare2Listing(filenames, options):
oOutput = cOutputResult(options)
Radare2ListingSingle(filenames, oOutput, options)
oOutput.Close()
def Main():
global dLibrary
moredesc = '''
Arguments:
@file: process each file listed in the text file specified
wildcards are supported
Source code put in the public domain by Didier Stevens, no Copyright
Use at your own risk
https://DidierStevens.com'''
oParser = optparse.OptionParser(usage='usage: %prog [options] [expression [[@]file ...]]\n' + __description__ + moredesc, version='%prog ' + __version__)
oParser.add_option('-m', '--man', action='store_true', default=False, help='Print manual')
oParser.add_option('-c', '--comment', action='store_true', default=False, help='Only list lines with added comments')
oParser.add_option('-o', '--output', type=str, default='', help='Output to file')
(options, args) = oParser.parse_args()
if options.man:
oParser.print_help()
PrintManual()
return
if len(args) == 0:
Radare2Listing([''], options)
else:
Radare2Listing(ExpandFilenameArguments(args), options)
if __name__ == '__main__':
Main()