Skip to content

Instantly share code, notes, and snippets.

@handsomematt
Created January 30, 2015 19:41
Show Gist options
  • Save handsomematt/338d8cd96dc5f602c843 to your computer and use it in GitHub Desktop.
Save handsomematt/338d8cd96dc5f602c843 to your computer and use it in GitHub Desktop.
"""
//
// This will take all cross references to strings containing '.cpp', and pre-pend the name of the .cpp file
// to any IDA-recognized subs that xref that string. For example, if sub_b0aafd references a string that
// looks like '..\dev\src\game\client\main\file.cpp', this script will re-name sub_b0aafd to file.cpp_sub_b0aafd.
//
// To use:
// Run this as an idaPython script. I don't know IDA very well, so I usually just copy it, in its entirety, into the
// Python command window.
//
"""
from idautils import *
from idaapi import *
from idc import *
prefixToStringMappings = dict()
stringToPrefixMapping = dict()
prefixToSI = dict()
def contains(s, xdict):
if(xdict.get(s) is not None):
return True
return False
def deconflictPrefix(origPrefix, conflictString):
conflictPrefix = origPrefix
origString = prefixToStringMappings[origPrefix]
origList = origString.split("\\")
conflictList = conflictString.split("\\")
if(len(origList)!=len(conflictList)):
# iterate backwards, because they are likely in totally different paths
origList=reversed(origList)
conflictList = reversed(conflictList)
# iterate through in the chosen directory to find
for x,y in zip(origList, conflictList):
if(x.find('.')>-1): continue
if(y.find('.')>-1): continue
if x != y:
origNewCandidate = x+"_"+origPrefix
conflictNewCandidate = y+"_"+conflictPrefix
if((contains(origNewCandidate, prefixToStringMappings) is False) and (contains(conflictNewCandidate, prefixToStringMappings)) is False ):
# both prefixes are good. Make the change.
# add a new entry for origNewCandidate
prefixToStringMappings[origNewCandidate]=origString
stringToPrefixMapping[origString]=origNewCandidate
# Update the overall SI to prefix/string mapping for originalstring. Remove the original prefix, add the new one.
# DO NOT update the prefixToStringsMapping to remove the original prefix. If there are more than 2 conflicts, we want to make sure we get them all.
tempSI = prefixToSI[origPrefix]
# this will be None if we have previously had a conflict on this prefix
if(tempSI is not None):
prefixToSI[origNewCandidate] = tempSI
del prefixToSI[origPrefix]
return checkPrefix(conflictNewCandidate, conflictString)
# this should NEVER get hit. If it does, there's some major flaw in my logic
filenameLoc = chkstr.rfind("\\")
prevDir = conflictString.rfind("\\", 0, filenameLoc)
prevDir = prevDir+1 #don't include \
prefix = conflictString[prevDir:filenameLoc] +"_"+ prefix
return checkPrefix(prefix, chkstr)
def checkPrefix(prefix, chkstr):
filenameLoc = chkstr.rfind("\\")
# Easy check to see if we've ever seen this prefix before
if(contains(prefix, prefixToStringMappings)):
# If we've seen this prefix before, see if the chkstr is a duplicate
originalPrefix = prefix # save the duplicate prefix so we can go back and fix the other reference
if(prefixToStringMappings[prefix] == chkstr):
return prefix
else:
# Then we need to update the old string, too, since it is probably not descriptive enough
newprefix = deconflictPrefix(originalPrefix, chkstr)
return newprefix
else:
prefixToStringMappings[prefix]=chkstr
stringToPrefixMapping[chkstr]=prefix
return prefix
def makePrefix(chkstr):
filenameLoc = chkstr.rfind("\\")
prefix = chkstr[filenameLoc+1:]
return checkPrefix(prefix, chkstr)
def getStringItemsByContent(filter):
foundStringItems = dict()
s = Strings(False)
s.setup(strtypes=Strings.STR_UNICODE | Strings.STR_C)
for si in s:
chkstr = GetString(si.ea, si.length, si.type)
if chkstr != None:
if ((chkstr.find(filter) > -1) and (chkstr.find('\\') > -1)):
foundPrefix = makePrefix(chkstr)
prefixToSI[foundPrefix]=si
return foundStringItems
def renameXrefFuncs(si, prefix):
if (prefix is None): return;
flag = 1
sourceAddr = si.ea
length = len(prefix);
lastChar = prefix[length-1:length];
if(lastChar!="_"):
newPrefix = prefix + "_"
xrefs = XrefsTo(sourceAddr, 0)
for xref in xrefs:
ea = xref.frm
if(xref.to is not None):
originalName = GetFunctionName(ea);
if(originalName is not None):
functionOffset = GetFunctionAttr(ea,FUNCATTR_START);
contains = originalName.find(newPrefix);
if(contains <= -1):
newName = newPrefix + originalName;
MakeNameEx(functionOffset,newName,SN_NOCHECK);
else:
i = 1+1
def renameXrefFunc():
renameXrefFuncs(get_screen_ea());
print "Starting..."
string = getStringItemsByContent('.cpp')
for prefix in prefixToSI:
si = prefixToSI[prefix]
path = GetString(si.ea, si.length, si.type)
print "Pre-pending "+prefix+" to all subs that xref "+path+"."
renameXrefFuncs(si, prefix)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment