-
Notifications
You must be signed in to change notification settings - Fork 1
/
pimped_out_cli.py
executable file
·219 lines (175 loc) · 8.53 KB
/
pimped_out_cli.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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = "Sebastian 'topo' Muniz"
__copyright__ = "Copyright 2017"
__credits__ = []
__license__ = "GPL"
__version__ = "0.1"
__maintainer__ = "Sebastian Muniz"
__email__ = "[email protected]"
__description__ = "Pimped out multi-architecture CPU emulator"
from sys import argv, exit, stdout
from argparse import ArgumentParser
from traceback import print_exc
import logging
from time import sleep
try:
from pimp_my_ride import *
from target.board import Board
from target.emulated_target import EmulatedTargetX86_64
from target.emulated_target_aarch64 import EmulatedTargetAArch64
from target.emulated_target_arm import EmulatedTargetARM
from target.emulated_target_mips import EmulatedTargetMips
from gdbserver.gdb_server import GDBServer
except ImportError, err:
print "Import Error : %s" % err
exit(1)
try:
from elftools.elf.elffile import ELFFile
from elftools.elf.descriptions import (
describe_ei_class, describe_ei_data, describe_ei_version,
describe_ei_osabi, describe_e_type, describe_e_machine,
describe_e_version_numeric, describe_p_type, describe_p_flags,
describe_sh_type, describe_sh_flags,
describe_symbol_type, describe_symbol_bind, describe_symbol_visibility,
describe_symbol_shndx, describe_reloc_type, describe_dyn_tag,
describe_ver_flags, describe_note
)
except ImportError, err:
print "Missing 'pyelftools' module."
exit(1)
def autodetect_architecture(image):
"""Detect the current architecture in use by the disassembler being
used.
"""
architecture = image.get_machine_arch()
bits = image.elfclass
is_little_endian = image.little_endian
return (architecture, bits, is_little_endian)
def get_gdb_server_settings(args):
"""Set GDB server settings."""
return {
#'break_at_hardfault' : args.break_at_hardfault,
#'step_into_interrupt' : args.step_into_interrupt,
#'break_on_reset' : args.break_on_reset,
'persist' : args.persist,
'soft_bkpt_as_hard' : True,#args.soft_bkpt_as_hard, # FIXME
#'chip_erase': get_chip_erase(args),
#'hide_programming_progress' : args.hide_progress,
#'fast_program' : args.fast_program,
'port_urlWSS' : args.port_number,
'log_level' : LOG_LEVELS.get(args.log_level),
}
def logo(a=1):
from pimped_art import pimp_my_ride_art
for line in pimp_my_ride_art.split("\n"):
sleep(0.1)
stdout.write(line + "\n")
stdout.flush()
def main():
log_levels = LOG_LEVELS.keys()
parser = ArgumentParser(description=__description__)
parser.add_argument('--version', action='version', version=__version__)
parser.add_argument('--logo', type=logo, action='store')
parser.add_argument("-p", "--port", dest = "port_number", type=int, default = 3333, help = "Port number that GDB server will listen.")
#parser.add_argument("-c", "--cmd-port", dest = "cmd_port", default = 4444, help = "Command port number. pyOCD doesn't open command port, but it's required to be compatible with OpenOCD and Eclipse.")
#parser.add_argument("-b", "--board", dest = "board_id", default = None, help="Connect to board by board id. Use -l to list all connected boards.")
#parser.add_argument("-l", "--list", action = "store_true", dest = "list_all", default = False, help = "List all connected boards.")
parser.add_argument("-l", "--log-level", dest = "log_level", choices = log_levels, default = 'info', help = "Set the level of system logging output. Supported choices are: "+", ".join(log_levels), metavar="LEVEL")
#parser.add_argument("-n", "--nobreak", dest = "break_at_hardfault", default = True, action="store_false", help = "Disable halt at hardfault handler." )
#parser.add_argument("-r", "--reset-break", dest = "break_on_reset", default = False, action="store_true", help = "Halt the target when reset." )
#parser.add_argument("-s", "--step-int", dest = "step_into_interrupt", default = False, action="store_true", help = "Allow single stepping to step into interrupts." )
#parser.add_argument("-f", "--frequency", dest = "frequency", default = 1000000, type=int, help = "Set the SWD clock frequency in Hz." )
parser.add_argument("-o", "--persist", dest = "persist", default = False, action="store_true", help = "Keep GDB server running even after remote has detached.")
parser.add_argument("-t", "--target", dest = "target", default = None, help = "Target filename to emulate.", metavar="TARGET", required=True)
#parser.add_argument("-bh", "--soft-bkpt-as-hard", dest = "soft_bkpt_as_hard", default = False, action = "store_true", help = "Replace software breakpoints with hardware breakpoints.")
#group = parser.add_mutually_exclusive_group()
#group.add_argument("-ce", "--chip_erase", action="store_true",help="Use chip erase when programming.")
#group.add_argument("-se", "--sector_erase", action="store_true",help="Use sector erase when programming.")
## -Currently "--unlock" does nothing since kinetis parts will automatically get unlocked
#parser.add_argument("-u", "--unlock", action="store_true", default=False, help="Unlock the device.")
## reserved: "-a", "--address"
## reserved: "-s", "--skip"
#parser.add_argument("-hp", "--hide_progress", action="store_true", help = "Don't display programming progress." )
#parser.add_argument("-fp", "--fast_program", action="store_true", help = "Use only the CRC of each page to determine if it already has the same data.")
args = parser.parse_args()
# Setup logging facility and GDB server settings.
#setup_logging(args)
gdb_server_settings = get_gdb_server_settings(args)
try:
fd = open(args.target, 'rb')
except IOError, err:
print "Error : Invalid filename (%s) specified." % args.target
return
image = ELFFile(fd)
#
# Obtain the memory ranges where we're going to operate.
#
#start_address = 0x004007e8 #image.header.e_entry # MIPS
#start_address = 0x4004F4 # X86-64
#start_address = 0x40058C # AArch64
start_address = 0x1043C # ARM
#ret_address = 0x0400814 #0x400502 # MIPS
#ret_address = 0x400504 # X86-64
#ret_address = 0x40059D # AArch64
ret_address = 0x10450 # ARM
#
# Read the code to emulate
#
dot_text = image.get_section_by_name(".text")
addr = dot_text.header.sh_addr
code = dot_text.data()
if not code or len(code) is 0:
print "[-] Unable to obtain codes to emulate. Quitting..."
return
emu = None
gdb = None
try:
# Set architecture specific types for the current binary being
# analyzed.
architecture, bits, is_little_endian = autodetect_architecture(image)
# Initialize the emulator and set the operational parameters.
print "[+] Configuring emulator..."
stack=0x1000
stack_size = 5
emu = PimpMyRide(architecture, bits, is_little_endian,
log_level=LOG_LEVELS.get(args.log_level), stack=stack,
stack_size=stack_size)
emu.add_memory_area(addr, len(code) + 0x100)
emu.add_memory_content(addr, code)
emu.start_address = start_address
emu.return_address = ret_address
# AArch64 & ARM
emu.init_register("pc", start_address)
emu.init_register("sp", stack * stack_size)
# X86-64
#emu.init_register("rip", start_address)
#emu.init_register("rsp", stack * stack_size)
# MIPS
#emu.init_register("pc", start_address) # MIPS
#emu.init_register("sp", stack * stack_size)
# Set tracing all instructions with internal callback.
emu.trace_instructions()
board = Board(EmulatedTargetARM(emu))
#board = Board(EmulatedTargetAArch64(emu))
#board = Board(EmulatedTargetX86_64(emu))
#board = Board(EmulatedTargetMips(emu))
print "[+] Initializing GDB server..."
gdb = GDBServer(board, gdb_server_settings)
#emu.add_breakpoint_callback(gdb.target.breakpoint_callback)
while gdb.isAlive():
gdb.join(timeout=0.5)
except PimpMyRideException, err:
print "[-] Error : %s" % err
return
except KeyboardInterrupt:
print "\n[+] Termination requested..."
except Exception as e:
print "[-] Uncaught exception : %s" % e
print_exc()
finally:
if gdb is not None:
gdb.stop()
if __name__ == "__main__":
print "%s v%s\n" % (__description__, __version__)
main()