Initial Upload

This commit is contained in:
Maddie Stone
2017-06-18 11:08:28 -04:00
committed by GitHub
parent f29cbaca2d
commit 8880a668cf
7 changed files with 582 additions and 0 deletions

121
data_offset_calc.py Normal file
View File

@@ -0,0 +1,121 @@
##############################################################################################
# Copyright 2017 The Johns Hopkins University Applied Physics Laboratory LLC
# All rights reserved.
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.
##############################################################################################
# data_offset_calc.py
# Resolves the references to indirect offsets of a variable, register, or memory location
# whose value is known. Changes the display of the operand in the instruction (OpAlt function),
# creates a data cross references (add_dref), and creates a comment of the resolved address
# (MakeComment). User nees to define the following:
# offset_var_string: The string representation of the variable, register, or memory
# location to be replaced by the resolved value
# offset_var_value: The value of the variable defined in offset_var_string
# reg_ex_indirect: A regular expression of how indirect offset accesses to the variable
# reg_ex_immediate: A regular expression of how the immediate offset value is represented
# new_opnd_display: A string representation of how the calculated and resolved
# value should be displayed as the operand in the instruction
#
# Inputs: start_addr: Start address for segment to define as data
# end_addr: End address for segment to define as data
#
##############################################################################################
import re
################### USER DEFINED VALUES ###################
# String of the variable/register/location used as the indirect variable
offset_var_str = "fp"
# The defined offset_var_str's value
offset_var_value = 0x808000
# Regular expression for out offset_var_str is referenced indirectly in the IDA Disassembly
# @(-0x(1-8 hex chars), fp )
reg_ex_indirect = re.compile(r"@\(-?0x[0-9A-Fa-f]{1,8}, "+ offset_var_str +"\)")
# Regular expression for how immediate values are shown in the indirect reference
# For this example, it's 0x1044, but some architectures would show that as 1044h
regex_immediate = re.compile(r"0x[0-9A-Fa-f]{1,8}")
# String expression for how the newly calculated instruction should be displayed within the instruction
new_opnd_display = '@[0x%x]'
# OPTIONAL ---- EXAMPLE FOR ADDING OTHER INSTRUCTIONS TO THE PROCESSING
# If you'd like to add other instructions to be processed for resolving indirect offset accesses,
# update the regular expression here and use it as shown in the "else" block below
reg_ex_add3 = re.compile(r"add3 \w\w, fp, #-?0x[0-9A-Fa-f]{1,8}")
#############################################################
start_addr = AskAddr(MinEA(), "Please enter the starting address for the data to be analyzed.")
end_addr = AskAddr(MaxEA(), "Please enter the ending address for the data to be analyzed.")
if ((start_addr is not None and end_addr is not None) and (start_addr != BADADDR and end_addr != BADADDR) and start_addr < end_addr):
print "[data_offset_calc.py] STARTING. Looking for indirect accesses across 0x%x to 0x%x" % (start_addr, end_addr)
curr_addr = start_addr;
while curr_addr < end_addr:
operand = GetOpnd(curr_addr, 1) # Operand = 2nd Operand in the Instruction at curr_addr
if reg_ex_indirect.match(operand):
print ('[data_offset_calc.py] 0x%x Operand: ' % curr_addr) + operand
# This checks if there are any immediate values also in the 2nd operand with the variable. For example, mov R3, @(0x10, fp)
offset = re.findall(regex_immediate, operand)
if (offset):
print "[data_offset_calc.py] 0x%x Offset: 0x%x" % (curr_addr, int(offset[0],16))
# Check if Immediate Operand is Neg or Pos
if '-' in operand :
new_opnd = offset_var_value - int(offset[0], 16)
else:
new_opnd = offset_var_value + int(offset[0], 16)
print ("[data_offset_calc.py] 0x%x: Offset + " + offset_var_str + " = 0x%0x") % (curr_addr, new_opnd)
OpAlt(curr_addr, 1, new_opnd_display % new_opnd) # Changes Display of Instruction
result = add_dref(curr_addr, new_opnd, dr_T) # Create Data Ref -- Using dref_T because not checking if read or write
print ("[data_offset_calc.py] Creating dref from 0x%x to 0x%x: " % (curr_addr, new_opnd)) + str(result)
# Using dr_O (O as in Offset, not 0) because we are not check if this a "write" or "read"
else:
print "[data_offset_calc.py] 0x%x: No immediate offset identified." % curr_addr
#####################################################################################
# This block is optional but shows how to add additional regular expressions for other instructions
# you'd like to match besides the general indirect offset acceses. For M32R we are also matching
# the add3 instruction that take the form "add3 Reg, fp, 0xNUM"
else:
instruct = GetDisasm(curr_addr)
if reg_ex_add3.match(instruct):
print ('[data_offset_calc.py] 0x%08x Instruct: ' % curr_addr) + instruct
immed_opnd = GetOpnd(curr_addr, 2) # Getting the 3rd Operand Based on the reg_ex_add3 defined above
offset = re.findall(regex_immediate, immed_opnd);
if offset:
if '-' in immed_opnd:
new_opnd = offset_var_value - int(offset[0], 16)
else:
new_opnd = offset_var_value + int(offset[0], 16)
print '[data_offset_calc.py] 0x%x: Offset + fp = 0x%08x' % (curr_addr, new_opnd)
MakeComm(curr_addr, '0x%08x' % new_opnd) # Add comment with new operand instead of overwriting instruction as done above
result = add_dref(curr_addr, new_opnd, dr_T) # Creates Data XREF from Instruct to Calculated Val
print ("[data_offset_calc.py] Creating dref from 0x%x to 0x%x: " % (curr_addr, new_opnd)) + str(result)
else:
print "[data_offset_calc.py] 0x%x: No immediate offset identified." % curr_addr
########################################################################################
prev = curr_addr
curr_addr = NextHead(curr_addr, 0xFFFFF)
if (curr_addr == BADADDR):
print "[data_offset_calc.py] EXITING."
break
else:
print "[data_offset_calc.py] QUITTING. Invalid values entered for starting and ending addresses."

92
define_code_functions.py Normal file
View File

@@ -0,0 +1,92 @@
##############################################################################################
# Copyright 2017 The Johns Hopkins University Applied Physics Laboratory LLC
# All rights reserved.
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.
##############################################################################################
# define_code_functions.py
# Attempts to define the bytes in the user-entered address range as code and then as functions
# based on the user-define smart_prolog and smart_epilog regular expressions for that architecture.
#
# Inputs: start_addr: Start address for segment to define as data
# end_addr: End address for segment to define as data
# data_type: Type of data to set segment to (dependent on architecture)
#
##############################################################################################
import re
################### USER DEFINED VALUES ###################
# Enter a regular expression for how this architecture usually begins and ends functions.
# If the architecture does not dictate how to start or end a function use r".*" to allow
# for any instruction
# 8051 Architecture Prologue and Epilogue
smart_prolog = re.compile(r".*")
smart_epilog = re.compile(r"reti{0,1}")
# PIC18 Architecture Prologue and Epilogue
#smart_prolog = re.compile(r".*")
#smart_epilog = re.compile(r"return 0")
# Mitsubishi M32R Architecutre Prologue and Epilogue
#smart_prolog = re.compile(r"push +lr")
#smart_epilog = re.compile(r"jmp +lr.*")
# Texas Instruments TMS320C28x
#smart_prolog = re.compile(r".*")
#smart_epilog = re.compile(r"lretr")
# AVR
#smart_prolog = re.compile(r"push +r")
#smart_epilog = re.compile(r"reti{0,1}")
############################################################
start_addr = AskAddr(MinEA(), "Please enter the starting address for the data to be defined.")
end_addr = AskAddr(MaxEA(), "Please enter the ending address for the data to be defined.")
if ((start_addr is not None and end_addr is not None) and (start_addr != BADADDR and end_addr != BADADDR)):
do_make_unk = AskYN(0, "Do you want to make all of the code block UNKNOWN first?")
if (do_make_unk == 1):
curr_addr = start_addr
while (curr_addr < end_addr):
MakeUnkn(curr_addr,idc.DOUNK_SIMPLE)
curr_addr += 1
if (do_make_unk != -1):
curr_addr = start_addr
print "[make_code_functions.py] Running script to define code and functions on 0x%x to 0x%x" % (start_addr, end_addr)
while (curr_addr < end_addr):
next_unexplored = FindUnexplored(curr_addr, idaapi.BIN_SEARCH_FORWARD)
MakeCode(next_unexplored) # We don't care whether it succeeds or fails so not storing retval
curr_addr = next_unexplored
# Finished attempting to make all unexplored bytes into code
# Now, attempt to create functions of all code not currently in a function
print "[make_code_functions.py] Completed attempting to define bytes as code. Now trying to define functions."
curr_addr = start_addr
while (curr_addr != BADADDR and curr_addr < end_addr):
if (isCode(GetFlags(curr_addr)) and GetFunctionAttr(curr_addr, FUNCATTR_START) == BADADDR):
#print "Function Stuffs 0x%0x" % curr_addr
if(smart_prolog.match(GetDisasm(curr_addr)) or smart_epilog.match(GetDisasm(PrevHead(curr_addr)))):
#print "Smart Prolog match"
if (MakeFunction(curr_addr) != 0):
# MakeFunction(curr_addr) was successful so set curr_addr to next addr after the new function
curr_addr = GetFunctionAttr(curr_addr, FUNCATTR_END) # Returns first address AFTER the end of the function
continue
curr_addr = NextHead(curr_addr)
else:
print "[make_code_functions.py] Quitting. Entered address values are not valid."

63
define_data_as_types.py Normal file
View File

@@ -0,0 +1,63 @@
##############################################################################################
# Copyright 2017 The Johns Hopkins University Applied Physics Laboratory LLC
# All rights reserved.
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.
##############################################################################################
# define_data_as_types.py
# Defines a segment of addresses as the user-specified data type (byte, word, or double word).
# The byte length for each of these types is architecture dependent, but generally:
# 1 byte = Byte
# 2 bytes = Word
# 4 bytes = Double Word
# This script with undefine all bytes in the range first which means if you previously had
# code or strings defined in the area, they will be overwritten as data.
#
# Inputs: start_addr: Start address for segment to define as data
# end_addr: End address for segment to define as data
# data_type: Type of data to set segment to (dependent on architecture)
#
##############################################################################################
def define_as_data_by_size_for_block(start_addr, end_addr, data_size):
curr_addr = start_addr;
while (curr_addr < end_addr):
if (data_size == 1):
MakeByte(curr_addr)
elif (data_size == 2):
MakeWord(curr_addr)
elif (data_size == 4):
MakeDword(curr_addr)
else:
Warning("Invalid data_size. Breaking.")
break;
curr_addr += data_size
start_addr = AskAddr(MinEA(), "Please enter the starting address for the data to be defined.")
end_addr = AskAddr(MaxEA(), "Please enter the ending address for the data to be defined.")
if ((start_addr is not None and end_addr is not None) and (start_addr != BADADDR and end_addr != BADADDR) and start_addr < end_addr):
data_size = AskLong(1, "Enter the size of each data item to be defined in the address block.\nExample: '1' for byte, '2' for word, '4' for dword\nNote the exact implementation will be dependent on architecture.")
if (data_size == 1 or data_size == 2 or data_size == 4):
print ("[define_data_as_types.py] STARTING. start_addr: 0x%X, end_addr: 0x%X, data_size: %d" % (start_addr, end_addr, data_size))
MakeUnknown(start_addr, (end_addr - start_addr), DOUNK_SIMPLE)
print "[define_data_as_types.py] Undefined all data between 0x%X and 0x%0X" % (start_addr, end_addr)
print "[define_data_as_types.py] Defining all data as size " + str(data_size)
define_as_data_by_size_for_block(start_addr, end_addr, data_size)
print "[define_data_as_types.py] FINISHED."
else:
Warning("[define_data_as_types.py] You entered a size of %d bytes. Please enter 1 (byte), 2 (short/word), 4(long, dword)");
else:
print "[define_data_as_types.py] ERROR. Please enter valid address values."

88
find_mem_accesses.py Normal file
View File

@@ -0,0 +1,88 @@
##############################################################################################
# Copyright 2017 The Johns Hopkins University Applied Physics Laboratory LLC
# All rights reserved.
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.
##############################################################################################
# find_mem_accesses.py
#
# Identifies the memory accesses used in the code. When a memory access is identified based
# on the user contributed regular expression, this script completes three different actions
# to help with the static analysis:
# 1. A cross reference is created between the instruction and the memory address. This
# will fail if the address doesn't currently exist because the segment was not created.
# 2. The value at the memory address is retrieved and added as a comment to the
# referencing instruction.
# 3. A dictionary of all of the memory addresses accessed and the referencing instructions'
# addresses are printed and saved to a file.
# ** NOTE:If you are using a Harvard architecture, ensure you can distinguish between memory
# spaces or comment out the cross-reference and value parts of this script.
#
# Inputs: start_addr: Start address for segment to define as data
# end_addr: End address for segment to define as data
# file_name: File to write the accesses to
#
##############################################################################################
import re
################### USER DEFINED VALUES ###################
# Enter a regular expression for the memory access instructions you'd like to identify.
# Also enter the index of the operand in the instruction so that it can be retrieved via
# the GetOperandValue() function.
#
# 8051 (movx DPTR, #addr)
regex_mem_instruct = re.compile(r"mov +DPTR, #")
operand_index = 1
############################################################
start_addr = AskAddr(MinEA(), "Please enter the starting address for the code to be analyzed.")
end_addr = AskAddr(MaxEA(), "Please enter the ending address for the code to be analyzed.")
default_fn = "memory_use_locations.txt"
filename = AskFile(1, default_fn, "Please choose the location to save the memory accesses file.")
accesses_dict = {}
if ((start_addr is not None and end_addr is not None) and (start_addr != BADADDR and end_addr != BADADDR) and start_addr < end_addr):
curr_addr = start_addr
while (curr_addr < end_addr):
if (regex_mem_instruct.match(GetDisasm(curr_addr))):
#mem_addr = regex_mem_addr.match(GetDisasm(curr_addr))
mem_addr = GetOperandValue(curr_addr, operand_index)
print "[find_mem_accesses.py] Instruction Address: 0x%x Operand Address: 0x%0x" % (curr_addr, mem_addr)
# Create Cross-Reference to Address
result = add_dref(curr_addr, mem_addr, dr_T)
if (not result):
print "[find_mem_accesses.py] Could NOT create data cross-references."
else:
# Try to Get Value at Memory Address and Record at Reference
# Defaulting to WORD (2 bytes) can change or add other intelligence here
value = Word(mem_addr)
MakeComm(curr_addr, "@[0x%x] = 0x%x" % (mem_addr, value))
if (mem_addr in accesses_dict):
accesses_dict[mem_addr].append(curr_addr)
else:
accesses_dict[mem_addr] = [curr_addr, ]
curr_addr = NextHead(curr_addr)
print "[find_mem_accesses.py] Finished searching range. Writing to file."
with open(filename, "w") as out_file:
for key in sorted(accesses_dict.keys()):
out_file.write("0x%0x: \n" % key)
for ref in accesses_dict[key]:
out_file.write("\t0x%0x \n" % ref)
else:
print "[find_mem_accesses.py] ERROR. Please enter valid addresses."

View File

@@ -0,0 +1,73 @@
##############################################################################################
# Copyright 2017 The Johns Hopkins University Applied Physics Laboratory LLC
# All rights reserved.
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.
##############################################################################################
# identify_ port_use_locations.py
# Identifies all code using the CPU's ports and records the address and instruction
# in the identified file.
#
# User-Defined Input:
# ** Before use, edit the regex_pinref regular expression to match how the ports are displayed
# in instructions for your architecture.
#
##############################################################################################
################### USER DEFINED VALUES ###################
# PIC18F8722
regex_pinref = re.compile(r" PORT[A-H]")
# 87C52 (8051) - Ports referenced as FSR_80 (P0)...FSR_B0 (P3)
#regex_pinref = re.compile(r" FSR_[8-9A-Ba-b]0.?[0-7]?")
# C515 (8051) - Ports referened as P1 or P1_8
#regex_pinref = re.compile(r" P\d+\_?\d+")
# M32R
#regex_pinref = re.compile(r"
############################################################
start_addr = AskAddr(MinEA(), "Please enter the starting address for the code to be analyzed.")
end_addr = AskAddr(MaxEA(), "Please enter the ending address for the code to be analyzed.")
default_fn = "port_use_locations.txt"
filename = AskFile(1, default_fn, "Please choose the location to save the port use locations file.")
change_func_nm = AskYN(0, "Would you like to append a prefix to the names of funcs using ports?")
curr_addr = start_addr
func_name_out = False
with open(filename, "w") as out_file:
while curr_addr < end_addr:
if (isCode(GetFlags(curr_addr))):
instruct = GetDisasm(curr_addr);
#print ("0x%08x: " % curr_addr) + instruct
if regex_pinref.search(instruct):
out_file.write(("0x%08x: " % curr_addr) + instruct);
print ("0x%08x: " % curr_addr) + instruct
if (change_func_nm == 1):
func_start_addr = GetFunctionAttr(curr_addr, FUNCATTR_START)
if (func_start_addr != BADADDR):
curr_name = GetFunctionName(curr_addr)
if (curr_name != "" and not curr_name.startswith("pin")):
port_nums = regex_pinref.findall(instruct)
name = "pin" + port_nums[0] + "Used_" + curr_name
MakeName(func_start_addr, name)
curr_addr = NextHead(curr_addr)

View File

@@ -0,0 +1,78 @@
##############################################################################################
# Copyright 2017 The Johns Hopkins University Applied Physics Laboratory LLC
# All rights reserved.
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.
##############################################################################################
# label_funcs_with_no_xrefs.py
# This script checks each defined function in the address range entered for cross-references.
# If there are no cross-references to the function, the prefix "noXrefs_" is added to the
# function's name. It then iterates through all functions in the code range again to identify
# all functions who's only code references are functions that have no cross-references. This
# is to detected functions called only by other functions who have no code references.
# This script helps to detect "dead code" that is never called.
#
# Inputs: start_addr: Start address for segment to define as data
# end_addr: End address for segment to define as data
#
##############################################################################################
################### USER DEFINED VALUES ###################
# None needed.
###########################################################
def addPrefixToFunctionName(prefix, functionAddr):
name = GetFunctionName(curr_addr)
if (name and not name.startswith(prefix)):
name = prefix + name
print ("[label_funcs_with_no_xrefs.py] Function 0x%x Name: " % curr_addr) + name
MakeName(curr_addr, name)
start_addr = AskAddr(MinEA(), "Please enter the starting address for the functions to be examined.")
end_addr = AskAddr(MaxEA(), "Please enter the ending address for the functions to be examined.")
if ((start_addr is not None and end_addr is not None) and (start_addr != BADADDR and end_addr != BADADDR) and start_addr < end_addr):
print "[label_funcs_with_no_xrefs.py] Running on addresses 0x%x to 0x%x" % (start_addr, end_addr)
# If start_addr is in a function, get the starting address of that function. Else, returns -1.
curr_addr = GetFunctionAttr(start_addr, FUNCATTR_START) # Get the function head for the "start" addr
if (curr_addr == BADADDR):
# start_addr is not currently in a function so select the beginning of the next function
curr_addr = NextFunction(start_addr)
# Using this to continually iterate through all functions until no new functions
# having no code reference paths are found.
new_noXrefs_found = False
while (curr_addr != BADADDR and curr_addr < end_addr):
if (not GetFunctionName(curr_addr).startwith("noXrefs_")):
xrefs = XrefsTo(curr_addr)
has_valid_xref = False;
for x in xrefs:
if (not GetFunctionName(x.frm).startswith("noXrefs_")):
# Function has a valid cross-reference and is not "dead code"
has_valid_xref = True;
break;
if (has_valid_xref == False):
# No valid xrefs were found to this function
new_noXrefs_found = True
addPrefixToFunctionName("noXrefs_", curr_addr)
curr_addr = NextFunction(curr_addr)
if ((curr_addr == BADADDR or curr_addr >= end_addr) and new_noXrefs_found):
print "[label_funcs_with_no_xrefs.py] Iterating through range again because new functions with no Xrefs found."
curr_addr = start_addr
new_noXrefs_found = False
print "[label_funcs_with_no_xrefs.py] FINISHED."
else:
print "[label_funcs_with_no_xrefs.py] QUITTING. Invalid address(es) entered."

67
make_strings.py Normal file
View File

@@ -0,0 +1,67 @@
##############################################################################################
# Copyright 2017 The Johns Hopkins University Applied Physics Laboratory LLC
# All rights reserved.
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.
##############################################################################################
# make_strings.py
# Searches the user entered address range for a series of ASCII bytes to define as strings.
# If the continuous series of ASCII bytes has a length greater or equal to minimum_length and
# ends with a character in string_end, the scripts undefines the bytes in the series
# and attempts to define it as a string.
#
# Input: start_addr: Start address for range to search for strings
# end_addr: End address for range to search for strings
#
##############################################################################################
################### USER DEFINED VALUES ###################
min_length = 5 # Minimum number of characters needed to define a string
string_end = [0x00] # Possible "ending characters" for strings. A string will not be
# defined if it does not end with one of these characters
###########################################################
start_addr = AskAddr(MinEA(), "Please enter the starting address for the data to be analyzed.")
end_addr = AskAddr(MaxEA(), "Please enter the ending address for the data to be analyzed.")
if ((start_addr is not None and end_addr is not None) and (start_addr != BADADDR and end_addr != BADADDR) and start_addr < end_addr):
string_start = start_addr
print "[make_strings.py] STARTING. Attempting to make strings with a minimum length of %d on data in range 0x%x to 0x%x" % (min_length, start_addr, end_addr)
num_strings = 0;
while string_start < end_addr:
num_chars = 0
curr_addr = string_start
while curr_addr < end_addr:
byte = Byte(curr_addr)
if ((byte < 0x7F and byte > 0x1F) or byte in (0x9, 0xD, 0xA)): # Determine if a byte is a "character" based on this ASCII range
num_chars += 1
curr_addr += 1
else:
if ((byte in string_end) and (num_chars >= min_length)):
MakeUnknown(string_start, curr_addr - string_start, DOUNK_SIMPLE)
if (MakeStr(string_start, curr_addr) == 1):
print "[make_strings.py] String created at 0x%x to 0x%x" % (string_start, curr_addr)
num_strings += 1
string_start = curr_addr
break
else:
print "[make_strings.py] String create FAILED at 0x%x to 0x%x" % (string_start, curr_addr)
break
else:
# String does not end with one of the defined "ending characters", does not meet the minimum string length, or is not an ASCII character
break
string_start += 1
print "[make_strings.py] FINISHED. Created %d strings in range 0x%x to 0x%x" % (num_strings, start_addr, end_addr)
else:
print "[make_strings.py] QUITTING. Entered address values not valid."