299 lines · python
1#!/usr/bin/env python2 3# ----------------------------------------------------------------------4# Be sure to add the python path that points to the LLDB shared library.5#6# # To use this in the embedded python interpreter using "lldb" just7# import it with the full path using the "command script import"8# command9# (lldb) command script import /path/to/cmdtemplate.py10# ----------------------------------------------------------------------11 12import platform13import os14import re15import sys16import subprocess17 18try:19 # Just try for LLDB in case PYTHONPATH is already correctly setup20 import lldb21except ImportError:22 lldb_python_dirs = list()23 # lldb is not in the PYTHONPATH, try some defaults for the current platform24 platform_system = platform.system()25 if platform_system == "Darwin":26 # On Darwin, try the currently selected Xcode directory27 xcode_dir = subprocess.check_output("xcode-select --print-path", shell=True)28 if xcode_dir:29 lldb_python_dirs.append(30 os.path.realpath(31 xcode_dir + "/../SharedFrameworks/LLDB.framework/Resources/Python"32 )33 )34 lldb_python_dirs.append(35 xcode_dir + "/Library/PrivateFrameworks/LLDB.framework/Resources/Python"36 )37 lldb_python_dirs.append(38 "/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python"39 )40 success = False41 for lldb_python_dir in lldb_python_dirs:42 if os.path.exists(lldb_python_dir):43 if not (sys.path.__contains__(lldb_python_dir)):44 sys.path.append(lldb_python_dir)45 try:46 import lldb47 except ImportError:48 pass49 else:50 print('imported lldb from: "%s"' % (lldb_python_dir))51 success = True52 break53 if not success:54 print(55 "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"56 )57 sys.exit(1)58 59import optparse60import shlex61import string62import struct63import time64 65 66def append_data_callback(option, opt_str, value, parser):67 if opt_str == "--uint8":68 int8 = int(value, 0)69 parser.values.data += struct.pack("1B", int8)70 if opt_str == "--uint16":71 int16 = int(value, 0)72 parser.values.data += struct.pack("1H", int16)73 if opt_str == "--uint32":74 int32 = int(value, 0)75 parser.values.data += struct.pack("1I", int32)76 if opt_str == "--uint64":77 int64 = int(value, 0)78 parser.values.data += struct.pack("1Q", int64)79 if opt_str == "--int8":80 int8 = int(value, 0)81 parser.values.data += struct.pack("1b", int8)82 if opt_str == "--int16":83 int16 = int(value, 0)84 parser.values.data += struct.pack("1h", int16)85 if opt_str == "--int32":86 int32 = int(value, 0)87 parser.values.data += struct.pack("1i", int32)88 if opt_str == "--int64":89 int64 = int(value, 0)90 parser.values.data += struct.pack("1q", int64)91 92 93def create_memfind_options():94 usage = "usage: %prog [options] STARTADDR [ENDADDR]"95 description = """This command can find data in a specified address range.96Options are used to specify the data that is to be looked for and the options97can be specified multiple times to look for longer streams of data.98"""99 parser = optparse.OptionParser(description=description, prog="memfind", usage=usage)100 parser.add_option(101 "-s",102 "--size",103 type="int",104 metavar="BYTESIZE",105 dest="size",106 help="Specify the byte size to search.",107 default=0,108 )109 parser.add_option(110 "--int8",111 action="callback",112 callback=append_data_callback,113 type="string",114 metavar="INT",115 dest="data",116 help="Specify a 8 bit signed integer value to search for in memory.",117 default="",118 )119 parser.add_option(120 "--int16",121 action="callback",122 callback=append_data_callback,123 type="string",124 metavar="INT",125 dest="data",126 help="Specify a 16 bit signed integer value to search for in memory.",127 default="",128 )129 parser.add_option(130 "--int32",131 action="callback",132 callback=append_data_callback,133 type="string",134 metavar="INT",135 dest="data",136 help="Specify a 32 bit signed integer value to search for in memory.",137 default="",138 )139 parser.add_option(140 "--int64",141 action="callback",142 callback=append_data_callback,143 type="string",144 metavar="INT",145 dest="data",146 help="Specify a 64 bit signed integer value to search for in memory.",147 default="",148 )149 parser.add_option(150 "--uint8",151 action="callback",152 callback=append_data_callback,153 type="string",154 metavar="INT",155 dest="data",156 help="Specify a 8 bit unsigned integer value to search for in memory.",157 default="",158 )159 parser.add_option(160 "--uint16",161 action="callback",162 callback=append_data_callback,163 type="string",164 metavar="INT",165 dest="data",166 help="Specify a 16 bit unsigned integer value to search for in memory.",167 default="",168 )169 parser.add_option(170 "--uint32",171 action="callback",172 callback=append_data_callback,173 type="string",174 metavar="INT",175 dest="data",176 help="Specify a 32 bit unsigned integer value to search for in memory.",177 default="",178 )179 parser.add_option(180 "--uint64",181 action="callback",182 callback=append_data_callback,183 type="string",184 metavar="INT",185 dest="data",186 help="Specify a 64 bit unsigned integer value to search for in memory.",187 default="",188 )189 return parser190 191 192def memfind_command(debugger, command, result, dict):193 # Use the Shell Lexer to properly parse up command options just like a194 # shell would195 command_args = shlex.split(command)196 parser = create_memfind_options()197 (options, args) = parser.parse_args(command_args)198 # try:199 # (options, args) = parser.parse_args(command_args)200 # except:201 # # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit202 # # (courtesy of OptParse dealing with argument errors by throwing SystemExit)203 # result.SetStatus (lldb.eReturnStatusFailed)204 # print >>result, "error: option parsing failed" # returning a string is the same as returning an error whose description is the string205 # return206 memfind(debugger.GetSelectedTarget(), options, args, result)207 208 209def print_error(str, show_usage, result):210 print(str, file=result)211 if show_usage:212 print(create_memfind_options().format_help(), file=result)213 214 215def memfind(target, options, args, result):216 num_args = len(args)217 start_addr = 0218 if num_args == 1:219 if options.size > 0:220 print_error(221 "error: --size must be specified if there is no ENDADDR argument",222 True,223 result,224 )225 return226 start_addr = int(args[0], 0)227 elif num_args == 2:228 if options.size != 0:229 print_error(230 "error: --size can't be specified with an ENDADDR argument",231 True,232 result,233 )234 return235 start_addr = int(args[0], 0)236 end_addr = int(args[1], 0)237 if start_addr >= end_addr:238 print_error(239 "error: inavlid memory range [%#x - %#x)" % (start_addr, end_addr),240 True,241 result,242 )243 return244 options.size = end_addr - start_addr245 else:246 print_error("error: memfind takes 1 or 2 arguments", True, result)247 return248 249 if not options.data:250 print("error: no data specified to search for", file=result)251 return252 253 if not target:254 print("error: invalid target", file=result)255 return256 process = target.process257 if not process:258 print("error: invalid process", file=result)259 return260 261 error = lldb.SBError()262 bytes = process.ReadMemory(start_addr, options.size, error)263 if error.Success():264 num_matches = 0265 print(266 "Searching memory range [%#x - %#x) for" % (start_addr, end_addr),267 end=" ",268 file=result,269 )270 for byte in options.data:271 print("%2.2x" % ord(byte), end=" ", file=result)272 print(file=result)273 274 match_index = string.find(bytes, options.data)275 while match_index != -1:276 num_matches = num_matches + 1277 print(278 "%#x: %#x + %u" % (start_addr + match_index, start_addr, match_index),279 file=result,280 )281 match_index = string.find(bytes, options.data, match_index + 1)282 283 if num_matches == 0:284 print("error: no matches found", file=result)285 else:286 print("error: %s" % (error.GetCString()), file=result)287 288 289if __name__ == "__main__":290 print(291 "error: this script is designed to be used within the embedded script interpreter in LLDB"292 )293 294 295def __lldb_init_module(debugger, internal_dict):296 memfind_command.__doc__ = create_memfind_options().format_help()297 debugger.HandleCommand("command script add -o -f memory.memfind_command memfind")298 print('"memfind" command installed, use the "--help" option for detailed help')299