-
Notifications
You must be signed in to change notification settings - Fork 464
/
Copy pathrender-r2-import-script.py
106 lines (86 loc) · 4.06 KB
/
render-r2-import-script.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
#!/usr/bin/env python3
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
render-r2-import-script.py
Translate a floss result document into an radare2 script
that marks up the current workspace.
Usage:
$ floss suspicious.exe -j > floss-results.json
$ python render-r2-import-script.py floss-results.json > apply_floss.py
# now run `apply_floss.py` in radare2
"""
import sys
import base64
import logging
import argparse
from pathlib import Path
from floss.results import AddressType, ResultDocument
logger = logging.getLogger("floss.render-r2-import-script")
def render_r2_script(result_document: ResultDocument) -> str:
"""
Create r2script contents for r2 session annotations.
"""
main_commands = []
fvas = []
for ds in result_document.strings.decoded_strings:
if ds.string != "":
sanitized_string = base64.b64encode(
b'"FLOSS: %s (floss_%x)"' % (ds.string.encode("utf-8"), ds.address)
).decode("ascii")
if ds.address_type == AddressType.GLOBAL:
main_commands.append("CCu base64:%s @ %d" % (sanitized_string, ds.address))
if ds.decoding_routine not in fvas:
main_commands.append("af @ %d" % (ds.decoding_routine))
main_commands.append("afn floss_%x @ %d" % (ds.decoding_routine, ds.decoding_routine))
fvas.append(ds.decoding_routine)
else:
main_commands.append("CCu base64:%s @ %d" % (sanitized_string, ds.decoded_at))
if ds.decoding_routine not in fvas:
main_commands.append("af @ %d" % (ds.decoding_routine))
main_commands.append("afn floss_%x @ %d" % (ds.decoding_routine, ds.decoding_routine))
fvas.append(ds.decoding_routine)
for ss in result_document.strings.stack_strings:
if ss.string != "":
sanitized_string = base64.b64encode(b'"FLOSS: %s"' % ss.string.encode("utf-8")).decode("ascii")
main_commands.append("Ca -0x%x base64:%s @ %d" % (ss.frame_offset, sanitized_string, ss.function))
for ts in result_document.strings.tight_strings:
if ts.string != "":
sanitized_string = base64.b64encode(b'"FLOSS: %s"' % ts.string.encode("utf-8")).decode("ascii")
main_commands.append("Ca -0x%x base64:%s @ %d" % (ts.frame_offset, sanitized_string, ts.function))
return "\n".join(main_commands)
def main():
parser = argparse.ArgumentParser(description="Generate an radare2 script to apply FLOSS results.")
parser.add_argument("/path/to/report.json", help="path to JSON document from `floss --json`")
logging_group = parser.add_argument_group("logging arguments")
logging_group.add_argument("-d", "--debug", action="store_true", help="enable debugging output on STDERR")
logging_group.add_argument(
"-q", "--quiet", action="store_true", help="disable all status output except fatal errors"
)
args = parser.parse_args()
args.report_path = getattr(args, "/path/to/report.json")
if args.quiet:
logging.basicConfig(level=logging.WARNING)
logging.getLogger().setLevel(logging.WARNING)
elif args.debug:
logging.basicConfig(level=logging.DEBUG)
logging.getLogger().setLevel(logging.DEBUG)
else:
logging.basicConfig(level=logging.INFO)
logging.getLogger().setLevel(logging.INFO)
result_document = ResultDocument.parse_file(Path(args.report_path))
print(render_r2_script(result_document))
return 0
if __name__ == "__main__":
sys.exit(main())