I've written a small IDAPython script that searches for a string in the bytes preceding MmGetSystemRoutineAddress
calls and then marks that call with the function being imported. It worked on the x64 and x86 drivers I had to hand but I've left my commented out debug prints in just in case.
There's definitely improvements that could be made:
- Make sure that the
MmGetSystemRoutineAddress
xref is an actual call - The function pointer result is often put into a global pointer (i.e.
mov dword_444E0, eax
), having this pointer automatically named would be very useful. - The other common use case is seeing it being called straight after (i.e.
call eax
) so having this call marked would be nice.
I'll have a look at making these improvements and updating when I can.
#Using Sark would have made the line iteration a bit nicer but I wanted
#something I could use anywhere without any external dependencies
import idc
import idautils
import idaapi
print "Trying to find MmGetSystemRoutineAddress..."
getsys_addr = idc.LocByName("MmGetSystemRoutineAddress")
print "Found MmGetSystemRoutineAddress @ %08X" % getsys_addr
num_xrefs = sum(1 for i in idautils.CodeRefsTo(getsys_addr, 0))
print "Found %d xrefs to MmGetSystemRoutineAddress" % num_xrefs
#Get the strings so we can see what might have been passed in
sc = idautils.Strings(default_setup = False)
# we want C & Unicode strings, and *only* existing strings.
sc.setup(strtypes=Strings.STR_C | Strings.STR_UNICODE, ignore_instructions = True, display_only_existing_strings = True)
#Make a list of all string locations
string_locs = []
for s in sc:
string_locs.append((s.ea, str(s)))
#print "%x: len=%d type=%d -> '%s'" % (s.ea, s.length, s.type, str(s))
#Make a dict of all places strings are Xrefs
string_xrefs = {}
for loc in string_locs:
#print "%08X %s" % (loc[0], loc[1])
for xref in idautils.XrefsTo(loc[0]):
#print "Xref @ %08X" % xref.frm
string_xrefs[xref.frm] = loc
#Iterate through each Xref to MmGetSystemRoutineAddress and see if a string is used in the preceding instructions...
for getsys_ref in idautils.CodeRefsTo(getsys_addr, 0):
print "\nMmGetSystemRoutineAddress called @ %08X" % getsys_ref
#Start at line above MmGetSystemRoutineAddress call
new_ea = idaapi.get_item_head(getsys_ref - 1)
#Continue until we've gone back 50 bytes or found a string
while new_ea > getsys_ref - 50:
print " %08X %s" % (new_ea, idc.GetDisasm(new_ea))
#Go to the line above
new_ea = idaapi.get_item_head(new_ea-1)
if new_ea in string_xrefs:
print " Found an Xref to a string in preceding 50 bytes! Mark it up"
print " %08X %s" % (new_ea, idc.GetDisasm(new_ea))
idc.MakeComm(getsys_ref, string_xrefs[new_ea][1] + " - auto added")
break