Added some useful IDA scripts (NPOTB).
authorAsher Baker <asherkin@gmail.com>
Sun Jul 29 02:51:50 2012 +0100 (2012-07-29)
changeset 35906908e80a69af
parent 3589 3a310379e46c
child 3591 ffbb8efd0b81
Added some useful IDA scripts (NPOTB).
tools/ida_scripts/makesig.idc
tools/ida_scripts/vtable_dump.py
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/ida_scripts/makesig.idc	Sun Jul 29 02:51:50 2012 +0100
     1.3 @@ -0,0 +1,126 @@
     1.4 +#include <idc.idc>
     1.5 +
     1.6 +/* makesig.idc: IDA script to automatically create and wildcard a function signature.
     1.7 + * Copyright 2012, Asher Baker
     1.8 + * 
     1.9 + * This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
    1.10 + * 
    1.11 + * Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
    1.12 + * 
    1.13 + * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
    1.14 + * 
    1.15 + * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
    1.16 + * 
    1.17 + * 3. This notice may not be removed or altered from any source distribution.
    1.18 +*/
    1.19 +
    1.20 +static main()
    1.21 +{
    1.22 +	Wait(); // We won't work until autoanalysis is complete
    1.23 +
    1.24 +	SetStatus(IDA_STATUS_WORK);
    1.25 +	
    1.26 +	auto pAddress = ScreenEA();
    1.27 +	pAddress = GetFunctionAttr(pAddress, FUNCATTR_START);
    1.28 +	if (pAddress == BADADDR)
    1.29 +	{
    1.30 +		Warning("Make sure you are in a function!");							
    1.31 +		SetStatus(IDA_STATUS_READY);
    1.32 +		return;
    1.33 +	}
    1.34 +	
    1.35 +	auto sig;
    1.36 +	auto pFunctionEnd = GetFunctionAttr(pAddress, FUNCATTR_END);
    1.37 +	
    1.38 +	while (pAddress != BADADDR)
    1.39 +	{
    1.40 +		auto pInfo = DecodeInstruction(pAddress);
    1.41 +		if (!pInfo)
    1.42 +		{
    1.43 +			Warning("Something went terribly wrong D:");       
    1.44 +			SetStatus(IDA_STATUS_READY);
    1.45 +			return;
    1.46 +		}
    1.47 +		
    1.48 +		// isCode(GetFlags(pAddress)) == Opcode
    1.49 +		// isTail(GetFlags(pAddress)) == Operand
    1.50 +		// ((GetFlags(pAddress) & MS_CODE) == FF_IMMD) == :iiam:
    1.51 +		
    1.52 +		auto bDone = 0;
    1.53 +		
    1.54 +		if (pInfo.n == 1)
    1.55 +		{
    1.56 +			if (pInfo.Op0.type == o_near || pInfo.Op0.type == o_far)
    1.57 +			{
    1.58 +				sig = sprintf("%s%02X %s", sig, Byte(pAddress), PrintWildcards(GetDTSize(pInfo.Op0.dtyp)));
    1.59 +				bDone = 1;
    1.60 +			}
    1.61 +		}
    1.62 +		
    1.63 +		if (!bDone) { // unknown, just wildcard addresses
    1.64 +			auto i;
    1.65 +			for (i = 0; i < pInfo.size; i++)
    1.66 +			{
    1.67 +				auto pLoc = pAddress + i;
    1.68 +				if (GetFixupTgtType(pLoc) == FIXUP_OFF32)
    1.69 +				{
    1.70 +					sig = sprintf("%s%s", sig, PrintWildcards(4));
    1.71 +					i = i + 3;
    1.72 +				} else {
    1.73 +					sig = sprintf("%s%02X ", sig, Byte(pLoc));
    1.74 +				}
    1.75 +			}
    1.76 +		}
    1.77 +		
    1.78 +		if (IsGoodSig(sig))
    1.79 +			break;
    1.80 +		
    1.81 +		pAddress = NextHead(pAddress, pFunctionEnd);
    1.82 +	}
    1.83 +	
    1.84 +	Message("%s\n", sig);
    1.85 +	
    1.86 +	SetStatus(IDA_STATUS_READY);
    1.87 +	return;
    1.88 +}
    1.89 +
    1.90 +static GetDTSize(dtyp)
    1.91 +{
    1.92 +	if (dtyp == dt_byte)
    1.93 +	{
    1.94 +		return 1;
    1.95 +	} else if (dtyp == dt_word) {
    1.96 +		return 2;
    1.97 +	} else if (dtyp == dt_dword) {
    1.98 +		return 4;
    1.99 +	} else if (dtyp == dt_float) {
   1.100 +		return 4;
   1.101 +	} else if (dtyp == dt_double) {
   1.102 +		return 8;
   1.103 +	} else {
   1.104 +		Warning("Unknown type size (%d)", dtyp);
   1.105 +		return -1;
   1.106 +	}
   1.107 +}
   1.108 +
   1.109 +static PrintWildcards(count)
   1.110 +{
   1.111 +	auto i, string;
   1.112 +	for (i = 0; i < count; i++)
   1.113 +	{
   1.114 +		string = sprintf("%s? ", string);
   1.115 +	}
   1.116 +	return string;
   1.117 +}
   1.118 +
   1.119 +static IsGoodSig(sig)
   1.120 +{
   1.121 +	auto count, addr;
   1.122 +	addr = FindBinary(addr, SEARCH_DOWN|SEARCH_NEXT, sig);
   1.123 +	while (addr != BADADDR)
   1.124 +	{
   1.125 +		count = count + 1;
   1.126 +		addr = FindBinary(addr, SEARCH_DOWN|SEARCH_NEXT, sig);
   1.127 +	}
   1.128 +	return (count == 1);
   1.129 +}
   1.130 \ No newline at end of file
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/ida_scripts/vtable_dump.py	Sun Jul 29 02:51:50 2012 +0100
     2.3 @@ -0,0 +1,120 @@
     2.4 +"""vtable_dump.py: IDAPython script to dump a linux vtable (and a reconstructed windows one) from a binary."""
     2.5 +
     2.6 +"""
     2.7 +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
     2.8 +
     2.9 +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
    2.10 +
    2.11 +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
    2.12 +
    2.13 +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
    2.14 +
    2.15 +3. This notice may not be removed or altered from any source distribution.
    2.16 +"""
    2.17 +
    2.18 +__author__ = "Asher Baker"
    2.19 +__copyright__ = "Copyright 2012, Asher Baker"
    2.20 +__license__ = "zlib/libpng"
    2.21 +
    2.22 +import re
    2.23 +
    2.24 +def Analyze():
    2.25 +	SetStatus(IDA_STATUS_WORK)
    2.26 +	
    2.27 +	if GetLongPrm(INF_COMPILER).id != COMP_GNU:
    2.28 +		Warning("This script is for binaries compiled with GCC only.")
    2.29 +		SetStatus(IDA_STATUS_READY)
    2.30 +		return
    2.31 +	
    2.32 +	ea = ScreenEA()
    2.33 +	
    2.34 +	if not isHead(GetFlags(ea)):
    2.35 +		ea = PrevHead(ea)
    2.36 +	
    2.37 +	# Param needed to support old IDAPython versions
    2.38 +	end = NextHead(ea, 4294967295)
    2.39 +	
    2.40 +	name = Demangle(Name(ea), GetLongPrm(INF_LONG_DN))
    2.41 +	if ea == BADADDR or name is None or not re.search(r"vf?table(?: |'\{)for", name):
    2.42 +		Warning("No vtable selected!\nSelect vtable block first.")
    2.43 +		SetStatus(IDA_STATUS_READY)
    2.44 +		return
    2.45 +	
    2.46 +	linux_vtable = []
    2.47 +	temp_windows_vtable = []
    2.48 +	
    2.49 +	# Extract vtable
    2.50 +	while ea < end:
    2.51 +		offset = Dword(ea)
    2.52 +		
    2.53 +		# A vtable starts with some metadata, if it's missing...
    2.54 +		if isCode(GetFlags(offset)):
    2.55 +			Warning("Something went wrong!")
    2.56 +			SetStatus(IDA_STATUS_READY)
    2.57 +			return
    2.58 +		
    2.59 +		# Skip thisoffs and typeinfo address
    2.60 +		ea += 8
    2.61 +		
    2.62 +		while ea < end and isCode(GetFlags(Dword(ea))):
    2.63 +			name = Demangle(Name(Dword(ea)), GetLongPrm(INF_LONG_DN))
    2.64 +			
    2.65 +			if offset == 0:
    2.66 +				linux_vtable.append(name)
    2.67 +				temp_windows_vtable.append(name)
    2.68 +			else:
    2.69 +				# MI entry, strip "`non-virtual thunk to'" and remove from list
    2.70 +				#     But not if it's a dtor... what the hell is this.
    2.71 +				if (name.find("`non-virtual thunk to'") != -1) and name.find("::~") == -1:
    2.72 +					name = name[22:]
    2.73 +					#print "Stripping '%s' from windows vtable." % (name)
    2.74 +					temp_windows_vtable.remove(name)
    2.75 +			
    2.76 +			ea += 4
    2.77 +	
    2.78 +	for i, v in enumerate(temp_windows_vtable):
    2.79 +		if v.find("::~") != -1:
    2.80 +			#print "Found destructor at index %d: %s" % (i, v)
    2.81 +			del temp_windows_vtable[i]
    2.82 +			break
    2.83 +	
    2.84 +	windows_vtable = []
    2.85 +	overload_stack = []
    2.86 +	prev_function = ""
    2.87 +	prev_symbol = ""
    2.88 +	for v in temp_windows_vtable:
    2.89 +		function = v.split("(", 1)[0]
    2.90 +		
    2.91 +		if function == prev_function:
    2.92 +			# If we don't have a stack, we need to push the last function on first
    2.93 +			if len(overload_stack) == 0:
    2.94 +				# We will have added this in the previous run, remove it again...
    2.95 +				windows_vtable.pop()
    2.96 +				#print "Storing '%s' (!)" % (prev_symbol)
    2.97 +				overload_stack.append(prev_symbol)
    2.98 +			#print "Storing '%s'" % (v)
    2.99 +			overload_stack.append(v)
   2.100 +		else:
   2.101 +			# If we've moved onto something new, dump the stack first
   2.102 +			if len(overload_stack) > 0:
   2.103 +				#print overload_stack
   2.104 +				while len(overload_stack) > 0:
   2.105 +					windows_vtable.append(overload_stack.pop())
   2.106 +			
   2.107 +			windows_vtable.append(v)
   2.108 +		
   2.109 +		prev_function = function
   2.110 +		prev_symbol = v
   2.111 +	
   2.112 +	print "Lin Win Function"
   2.113 +	for i, v in enumerate(linux_vtable):
   2.114 +		winindex = windows_vtable.index(v) if v in windows_vtable else None
   2.115 +		if winindex is not None:
   2.116 +			print "%3d %3d %s" % (i, winindex, v)
   2.117 +		else:
   2.118 +			print "%3d     %s" % (i, v)
   2.119 +	
   2.120 +	SetStatus(IDA_STATUS_READY)
   2.121 +
   2.122 +if __name__ == '__main__':
   2.123 +	Analyze()
   2.124 \ No newline at end of file