Merge.
authorNicholas Hastings <skamonkey@gmail.com>
Fri Aug 10 21:54:03 2012 -0400 (2012-08-10)
changeset 3603d3fd010be8fe
parent 3602 1b0eeb2823ad
parent 3601 d3a2fb7b3a1e
child 3604 f29093434099
Merge.
     1.1 --- a/configs/core.cfg	Fri Aug 10 21:49:40 2012 -0400
     1.2 +++ b/configs/core.cfg	Fri Aug 10 21:54:03 2012 -0400
     1.3 @@ -115,4 +115,14 @@
     1.4  	 * In general, this option should be set to "yes" to increase the security of your server.
     1.5  	 */
     1.6  	"SteamAuthstringValidation"	"yes"
     1.7 +	
     1.8 +	/**
     1.9 +	 * Enables or disables whether SourceMod blocks known or potentially malicious plugins from loading.
    1.10 +	 * It is STRONGLY advised that this is left enabled, there have been cases in the past with plugins that
    1.11 +	 * allow anyone to delete files on the server, gain full rcon control, etc.
    1.12 +	 *
    1.13 +	 * "yes"	- Block malware or illegal plugins from loading (default)
    1.14 +	 * "no"		- Warn about malware or illegal plugins loading
    1.15 +	 */
    1.16 +	"BlockBadPlugins"	"yes"
    1.17  }
     2.1 --- a/core/PluginSys.cpp	Fri Aug 10 21:49:40 2012 -0400
     2.2 +++ b/core/PluginSys.cpp	Fri Aug 10 21:54:03 2012 -0400
     2.3 @@ -789,6 +789,8 @@
     2.4  	m_AllPluginsLoaded = false;
     2.5  	m_MyIdent = NULL;
     2.6  	m_LoadingLocked = false;
     2.7 +	
     2.8 +	m_bBlockBadPlugins = true;
     2.9  }
    2.10  
    2.11  CPluginManager::~CPluginManager()
    2.12 @@ -1030,6 +1032,41 @@
    2.13  			}
    2.14  		}
    2.15  	}
    2.16 +	
    2.17 +	if (pPlugin->GetStatus() == Plugin_Created)
    2.18 +	{
    2.19 +		unsigned char *pCodeHash = pPlugin->m_pRuntime->GetCodeHash();
    2.20 +		
    2.21 +		char codeHashBuf[40];
    2.22 +		UTIL_Format(codeHashBuf, 40, "plugin_");
    2.23 +		for (int i = 0; i < 16; i++)
    2.24 +			UTIL_Format(codeHashBuf + 7 + (i * 2), 3, "%02x", pCodeHash[i]);
    2.25 +		
    2.26 +		const char *bulletinUrl = g_pGameConf->GetKeyValue(codeHashBuf);
    2.27 +		if (bulletinUrl != NULL)
    2.28 +		{
    2.29 +			if (m_bBlockBadPlugins)
    2.30 +			{
    2.31 +				if (error)
    2.32 +				{
    2.33 +					if (bulletinUrl[0] != '\0')
    2.34 +					{
    2.35 +						UTIL_Format(error, maxlength, "Known malware detected and blocked. See %s for more info", bulletinUrl);
    2.36 +					} else {
    2.37 +						UTIL_Format(error, maxlength, "Possible malware or illegal plugin detected and blocked");
    2.38 +					}
    2.39 +				}
    2.40 +				pPlugin->m_status = Plugin_BadLoad;
    2.41 +			} else {
    2.42 +				if (bulletinUrl[0] != '\0')
    2.43 +				{
    2.44 +					g_Logger.LogMessage("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl);
    2.45 +				} else {
    2.46 +					g_Logger.LogMessage("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename());
    2.47 +				}
    2.48 +			}
    2.49 +		}
    2.50 +	}
    2.51  
    2.52  	LoadRes loadFailure = LoadRes_Failure;
    2.53  	/* Get the status */
    2.54 @@ -1129,7 +1166,7 @@
    2.55  
    2.56  	if ((res=_LoadPlugin(&pl, plugin, false, PluginType_MapUpdated, error, sizeof(error))) == LoadRes_Failure)
    2.57  	{
    2.58 -		g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s", plugin, error);
    2.59 +		g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error);
    2.60  		pl->SetErrorState(
    2.61  			pl->GetStatus() <= Plugin_Created ? Plugin_BadLoad : pl->GetStatus(), 
    2.62  			"%s",
    2.63 @@ -1889,6 +1926,27 @@
    2.64  	g_ShareSys.DestroyIdentity(m_MyIdent);
    2.65  }
    2.66  
    2.67 +ConfigResult CPluginManager::OnSourceModConfigChanged(const char *key, 
    2.68 +												 const char *value, 
    2.69 +												 ConfigSource source, 
    2.70 +												 char *error, 
    2.71 +												 size_t maxlength)
    2.72 +{
    2.73 +	if (strcmp(key, "BlockBadPlugins") == 0) {
    2.74 +		if (strcasecmp(value, "yes") == 0)
    2.75 +		{
    2.76 +			m_bBlockBadPlugins = true;
    2.77 +		} else if (strcasecmp(value, "no") == 0) {
    2.78 +			m_bBlockBadPlugins = false;
    2.79 +		} else {
    2.80 +			UTIL_Format(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
    2.81 +			return ConfigResult_Reject;
    2.82 +		}
    2.83 +		return ConfigResult_Accept;
    2.84 +	}
    2.85 +	return ConfigResult_Ignore;
    2.86 +}
    2.87 +
    2.88  void CPluginManager::OnHandleDestroy(HandleType_t type, void *object)
    2.89  {
    2.90  	/* We don't care about the internal object, actually */
    2.91 @@ -2269,6 +2327,15 @@
    2.92  				{
    2.93  					g_RootMenu.ConsolePrint("  Timestamp: %s", pl->m_DateTime);
    2.94  				}
    2.95 +				
    2.96 +				unsigned char *pCodeHash = pl->m_pRuntime->GetCodeHash();
    2.97 +				unsigned char *pDataHash = pl->m_pRuntime->GetDataHash();
    2.98 +				
    2.99 +				char combinedHash[33];
   2.100 +				for (int i = 0; i < 16; i++)
   2.101 +					UTIL_Format(combinedHash + (i * 2), 3, "%02x", pCodeHash[i] ^ pDataHash[i]);
   2.102 +				
   2.103 +				g_RootMenu.ConsolePrint("  Hash: %s", combinedHash);
   2.104  			}
   2.105  			else
   2.106  			{
     3.1 --- a/core/PluginSys.h	Fri Aug 10 21:49:40 2012 -0400
     3.2 +++ b/core/PluginSys.h	Fri Aug 10 21:54:03 2012 -0400
     3.3 @@ -57,6 +57,7 @@
     3.4  #include "convar_sm.h"
     3.5  #endif
     3.6  #include "ITranslator.h"
     3.7 +#include "IGameConfigs.h"
     3.8  #include "NativeOwner.h"
     3.9  #include "ShareSys.h"
    3.10  
    3.11 @@ -326,6 +327,7 @@
    3.12  public: //SMGlobalClass
    3.13  	void OnSourceModAllInitialized();
    3.14  	void OnSourceModShutdown();
    3.15 +	ConfigResult OnSourceModConfigChanged(const char *key, const char *value, ConfigSource source, char *error, size_t maxlength);
    3.16  	void OnSourceModMaxPlayersChanged(int newvalue);
    3.17  public: //IHandleTypeDispatch
    3.18  	void OnHandleDestroy(HandleType_t type, void *object);
    3.19 @@ -470,6 +472,9 @@
    3.20  	List<FakeNative *> m_Natives;
    3.21  
    3.22  	bool m_LoadingLocked;
    3.23 +	
    3.24 +	// Config
    3.25 +	bool m_bBlockBadPlugins;
    3.26  };
    3.27  
    3.28  extern CPluginManager g_PluginSys;
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/gamedata/core.games/blacklist.plugins.txt	Fri Aug 10 21:54:03 2012 -0400
     4.3 @@ -0,0 +1,16 @@
     4.4 +/**
     4.5 + * Do not edit this file.  Any changes will be overwritten by the gamedata
     4.6 + * updater or by upgrading your SourceMod install.
     4.7 + *
     4.8 + * For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(SourceMod)
     4.9 + */
    4.10 +
    4.11 +"Games"
    4.12 +{
    4.13 +	"#default"
    4.14 +	{
    4.15 +		"Keys"
    4.16 +		{
    4.17 +		}
    4.18 +	}
    4.19 +}
     5.1 --- a/gamedata/core.games/master.games.txt	Fri Aug 10 21:49:40 2012 -0400
     5.2 +++ b/gamedata/core.games/master.games.txt	Fri Aug 10 21:54:03 2012 -0400
     5.3 @@ -65,4 +65,7 @@
     5.4  		"engine"	"csgo"
     5.5  	}
     5.6  
     5.7 +	"blacklist.plugins.txt"
     5.8 +	{
     5.9 +	}
    5.10  }
     6.1 --- a/plugins/include/tf2_stocks.inc	Fri Aug 10 21:49:40 2012 -0400
     6.2 +++ b/plugins/include/tf2_stocks.inc	Fri Aug 10 21:54:03 2012 -0400
     6.3 @@ -231,7 +231,7 @@
     6.4  	TF_WEAPON_GRENADE_CLEAVER,
     6.5  };
     6.6  
     6.7 -// TF2 Weapon Slots for GetPlayerWeaponSlot
     6.8 +// TF2 Weapon Loadout Slots
     6.9  enum
    6.10  {
    6.11  	TFWeaponSlot_Primary,
     7.1 --- a/public/sourcepawn/sp_vm_api.h	Fri Aug 10 21:49:40 2012 -0400
     7.2 +++ b/public/sourcepawn/sp_vm_api.h	Fri Aug 10 21:54:03 2012 -0400
     7.3 @@ -40,7 +40,7 @@
     7.4  
     7.5  /** SourcePawn Engine API Version */
     7.6  #define SOURCEPAWN_ENGINE_API_VERSION	4
     7.7 -#define SOURCEPAWN_ENGINE2_API_VERSION	3
     7.8 +#define SOURCEPAWN_ENGINE2_API_VERSION	4
     7.9  
    7.10  #if !defined SOURCEMOD_BUILD
    7.11  #define SOURCEMOD_BUILD
    7.12 @@ -479,6 +479,20 @@
    7.13  		 * @return				Memory usage, in bytes.
    7.14  		 */
    7.15  		virtual size_t GetMemUsage() =0;
    7.16 +
    7.17 +		/**
    7.18 +		 * @brief Returns the MD5 hash of the plugin's P-Code.
    7.19 +		 *
    7.20 +		 * @return				16-byte buffer with MD5 hash of the plugin's P-Code.
    7.21 +		 */
    7.22 +		virtual unsigned char *GetCodeHash() =0;
    7.23 +		
    7.24 +		/**
    7.25 +		 * @brief Returns the MD5 hash of the plugin's Data.
    7.26 +		 *
    7.27 +		 * @return				16-byte buffer with MD5 hash of the plugin's Data.
    7.28 +		 */
    7.29 +		virtual unsigned char *GetDataHash() =0;
    7.30  	};
    7.31  
    7.32  	/**
     8.1 --- a/sourcepawn/jit/AMBuilder	Fri Aug 10 21:49:40 2012 -0400
     8.2 +++ b/sourcepawn/jit/AMBuilder	Fri Aug 10 21:54:03 2012 -0400
     8.3 @@ -36,6 +36,7 @@
     8.4  	'zlib/trees.c',
     8.5  	'zlib/uncompr.c',
     8.6  	'zlib/zutil.c',
     8.7 +	'md5/md5.cpp',
     8.8  	'../../knight/shared/KeCodeAllocator.cpp'
     8.9  	])
    8.10  SM.AutoVersion('sourcepawn/jit', binary)
     9.1 --- a/sourcepawn/jit/BaseRuntime.cpp	Fri Aug 10 21:49:40 2012 -0400
     9.2 +++ b/sourcepawn/jit/BaseRuntime.cpp	Fri Aug 10 21:54:03 2012 -0400
     9.3 @@ -8,6 +8,8 @@
     9.4  #include "sp_vm_basecontext.h"
     9.5  #include "engine2.h"
     9.6  
     9.7 +#include "md5/md5.h"
     9.8 +
     9.9  using namespace SourcePawn;
    9.10  
    9.11  BaseRuntime::BaseRuntime() : m_Debug(&m_plugin), m_pPlugin(&m_plugin), m_pCtx(NULL), 
    9.12 @@ -18,6 +20,9 @@
    9.13  	m_FuncCache = NULL;
    9.14  	m_MaxFuncs = 0;
    9.15  	m_NumFuncs = 0;
    9.16 +	
    9.17 +	memset(m_CodeHash, 0, sizeof(m_CodeHash));
    9.18 +	memset(m_DataHash, 0, sizeof(m_DataHash));
    9.19  }
    9.20  
    9.21  BaseRuntime::~BaseRuntime()
    9.22 @@ -227,6 +232,16 @@
    9.23  		memset(m_PubJitFuncs, 0, sizeof(JitFunction *) * m_pPlugin->num_publics);
    9.24  	}
    9.25  
    9.26 +	MD5 md5_pcode;
    9.27 +	md5_pcode.update(plugin->pcode, plugin->pcode_size);
    9.28 +	md5_pcode.finalize();
    9.29 +	md5_pcode.raw_digest(m_CodeHash);
    9.30 +	
    9.31 +	MD5 md5_data;
    9.32 +	md5_data.update(plugin->data, plugin->data_size);
    9.33 +	md5_data.finalize();
    9.34 +	md5_data.raw_digest(m_DataHash);
    9.35 +
    9.36  	m_pPlugin->profiler = g_engine2.GetProfiler();
    9.37  	m_pCtx = new BaseContext(this);
    9.38  	m_pCo = g_Jit.StartCompilation(this);
    9.39 @@ -483,6 +498,16 @@
    9.40  	return mem;
    9.41  }
    9.42  
    9.43 +unsigned char *BaseRuntime::GetCodeHash()
    9.44 +{
    9.45 +	return m_CodeHash;
    9.46 +}
    9.47 +
    9.48 +unsigned char *BaseRuntime::GetDataHash()
    9.49 +{
    9.50 +	return m_DataHash;
    9.51 +}
    9.52 +
    9.53  BaseContext *BaseRuntime::GetBaseContext()
    9.54  {
    9.55  	return m_pCtx;
    10.1 --- a/sourcepawn/jit/BaseRuntime.h	Fri Aug 10 21:49:40 2012 -0400
    10.2 +++ b/sourcepawn/jit/BaseRuntime.h	Fri Aug 10 21:54:03 2012 -0400
    10.3 @@ -48,6 +48,8 @@
    10.4  	virtual void SetPauseState(bool paused);
    10.5  	virtual bool IsPaused();
    10.6  	virtual size_t GetMemUsage();
    10.7 +	virtual unsigned char *GetCodeHash();
    10.8 +	virtual unsigned char *GetDataHash();
    10.9  	JitFunction *GetJittedFunction(uint32_t idx);
   10.10  	uint32_t AddJittedFunction(JitFunction *fn);
   10.11  public:
   10.12 @@ -65,6 +67,9 @@
   10.13  	JitFunction **m_PubJitFuncs;
   10.14  	ICompilation *m_pCo;
   10.15  	unsigned int m_CompSerial;
   10.16 +	
   10.17 +	unsigned char m_CodeHash[16];
   10.18 +	unsigned char m_DataHash[16];
   10.19  };
   10.20  
   10.21  #endif //_INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/sourcepawn/jit/md5/md5.cpp	Fri Aug 10 21:54:03 2012 -0400
    11.3 @@ -0,0 +1,476 @@
    11.4 +// MD5.CC - source code for the C++/object oriented translation and 
    11.5 +//          modification of MD5.
    11.6 +
    11.7 +// Translation and modification (c) 1995 by Mordechai T. Abzug 
    11.8 +
    11.9 +// This translation/ modification is provided "as is," without express or 
   11.10 +// implied warranty of any kind.
   11.11 +
   11.12 +// The translator/ modifier does not claim (1) that MD5 will do what you think 
   11.13 +// it does; (2) that this translation/ modification is accurate; or (3) that 
   11.14 +// this software is "merchantible."  (Language for this disclaimer partially 
   11.15 +// copied from the disclaimer below).
   11.16 +
   11.17 +/* based on:
   11.18 +
   11.19 +   MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
   11.20 +   MDDRIVER.C - test driver for MD2, MD4 and MD5
   11.21 +
   11.22 +
   11.23 +   Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
   11.24 +rights reserved.
   11.25 +
   11.26 +License to copy and use this software is granted provided that it
   11.27 +is identified as the "RSA Data Security, Inc. MD5 Message-Digest
   11.28 +Algorithm" in all material mentioning or referencing this software
   11.29 +or this function.
   11.30 +
   11.31 +License is also granted to make and use derivative works provided
   11.32 +that such works are identified as "derived from the RSA Data
   11.33 +Security, Inc. MD5 Message-Digest Algorithm" in all material
   11.34 +mentioning or referencing the derived work.
   11.35 +
   11.36 +RSA Data Security, Inc. makes no representations concerning either
   11.37 +the merchantability of this software or the suitability of this
   11.38 +software for any particular purpose. It is provided "as is"
   11.39 +without express or implied warranty of any kind.
   11.40 +
   11.41 +These notices must be retained in any copies of any part of this
   11.42 +documentation and/or software.
   11.43 +
   11.44 + */
   11.45 +
   11.46 +#include "md5.h"
   11.47 +
   11.48 +#include <assert.h>
   11.49 +#include <string.h>
   11.50 +
   11.51 +// MD5 simple initialization method
   11.52 +
   11.53 +MD5::MD5(){
   11.54 +
   11.55 +  init();
   11.56 +
   11.57 +}
   11.58 +
   11.59 +
   11.60 +// MD5 block update operation. Continues an MD5 message-digest
   11.61 +// operation, processing another message block, and updating the
   11.62 +// context.
   11.63 +
   11.64 +void MD5::update (uint1 *input, uint4 input_length) {
   11.65 +
   11.66 +  uint4 input_index, buffer_index;
   11.67 +  uint4 buffer_space;                // how much space is left in buffer
   11.68 +
   11.69 +  if (finalized){  // so we can't update!
   11.70 +    /*cerr << "MD5::update:  Can't update a finalized digest!" << endl;*/
   11.71 +    return;
   11.72 +  }
   11.73 +
   11.74 +  // Compute number of bytes mod 64
   11.75 +  buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
   11.76 +
   11.77 +  // Update number of bits
   11.78 +  if (  (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
   11.79 +    count[1]++;
   11.80 +
   11.81 +  count[1] += ((uint4)input_length >> 29);
   11.82 +
   11.83 +
   11.84 +  buffer_space = 64 - buffer_index;  // how much space is left in buffer
   11.85 +
   11.86 +  // Transform as many times as possible.
   11.87 +  if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
   11.88 +    // fill the rest of the buffer and transform
   11.89 +    memcpy (buffer + buffer_index, input, buffer_space);
   11.90 +    transform (buffer);
   11.91 +
   11.92 +    // now, transform each 64-byte piece of the input, bypassing the buffer
   11.93 +    for (input_index = buffer_space; input_index + 63 < input_length; 
   11.94 +	 input_index += 64)
   11.95 +      transform (input+input_index);
   11.96 +
   11.97 +    buffer_index = 0;  // so we can buffer remaining
   11.98 +  }
   11.99 +  else
  11.100 +    input_index=0;     // so we can buffer the whole input
  11.101 +
  11.102 +
  11.103 +  // and here we do the buffering:
  11.104 +  memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
  11.105 +}
  11.106 +
  11.107 +
  11.108 +
  11.109 +// MD5 update for files.
  11.110 +// Like above, except that it works on files (and uses above as a primitive.)
  11.111 +
  11.112 +void MD5::update(FILE *file){
  11.113 +
  11.114 +  unsigned char buffer[1024];
  11.115 +  int len;
  11.116 +
  11.117 +  while ((len=fread(buffer, 1, 1024, file)))
  11.118 +    update(buffer, len);
  11.119 +
  11.120 +  fclose (file);
  11.121 +
  11.122 +}
  11.123 +
  11.124 +
  11.125 +// MD5 finalization. Ends an MD5 message-digest operation, writing the
  11.126 +// the message digest and zeroizing the context.
  11.127 +
  11.128 +
  11.129 +void MD5::finalize (){
  11.130 +
  11.131 +  unsigned char bits[8];
  11.132 +  unsigned int index, padLen;
  11.133 +  static uint1 PADDING[64]={
  11.134 +    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  11.135 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  11.136 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  11.137 +    };
  11.138 +
  11.139 +  if (finalized){
  11.140 +   /* cerr << "MD5::finalize:  Already finalized this digest!" << endl;*/
  11.141 +    return;
  11.142 +  }
  11.143 +
  11.144 +  // Save number of bits
  11.145 +  encode (bits, count, 8);
  11.146 +
  11.147 +  // Pad out to 56 mod 64.
  11.148 +  index = (uint4) ((count[0] >> 3) & 0x3f);
  11.149 +  padLen = (index < 56) ? (56 - index) : (120 - index);
  11.150 +  update (PADDING, padLen);
  11.151 +
  11.152 +  // Append length (before padding)
  11.153 +  update (bits, 8);
  11.154 +
  11.155 +  // Store state in digest
  11.156 +  encode (digest, state, 16);
  11.157 +
  11.158 +  // Zeroize sensitive information
  11.159 +  memset (buffer, 0, sizeof(*buffer));
  11.160 +
  11.161 +  finalized=1;
  11.162 +
  11.163 +}
  11.164 +
  11.165 +
  11.166 +
  11.167 +
  11.168 +MD5::MD5(FILE *file){
  11.169 +
  11.170 +  init();  // must be called be all constructors
  11.171 +  update(file);
  11.172 +  finalize ();
  11.173 +}
  11.174 +
  11.175 +unsigned char *MD5::raw_digest(){
  11.176 +
  11.177 +  uint1 *s = new uint1[16];
  11.178 +
  11.179 +  if (!finalized){
  11.180 +/*    cerr << "MD5::raw_digest:  Can't get digest if you haven't "<<
  11.181 +      "finalized the digest!" <<endl;*/
  11.182 +    return ( (unsigned char*) "");
  11.183 +  }
  11.184 +
  11.185 +  memcpy(s, digest, 16);
  11.186 +  return s;
  11.187 +}
  11.188 +
  11.189 +unsigned char *MD5::raw_digest(unsigned char buffer[16])
  11.190 +{
  11.191 +	if (!finalized)
  11.192 +	{
  11.193 +		return ( (unsigned char*) "");
  11.194 +	}
  11.195 +
  11.196 +	 memcpy(buffer, digest, 16);
  11.197 +	 return buffer;
  11.198 +}
  11.199 +
  11.200 +
  11.201 +
  11.202 +char *MD5::hex_digest(){
  11.203 +
  11.204 +  int i;
  11.205 +  char *s= new char[33];
  11.206 +
  11.207 +  assert(finalized);
  11.208 +
  11.209 +  for (i=0; i<16; i++)
  11.210 +    sprintf(s+i*2, "%02x", digest[i]);
  11.211 +
  11.212 +  s[32]='\0';
  11.213 +
  11.214 +  return s;
  11.215 +}
  11.216 +
  11.217 +
  11.218 +char *MD5::hex_digest(char buffer[33]){
  11.219 +
  11.220 +  int i;
  11.221 +
  11.222 +  assert(finalized);
  11.223 +
  11.224 +  for (i=0; i<16; i++)
  11.225 +    sprintf(buffer+i*2, "%02x", digest[i]);
  11.226 +
  11.227 +  buffer[32]='\0';
  11.228 +
  11.229 +  return buffer;
  11.230 +}
  11.231 +
  11.232 +
  11.233 +// PRIVATE METHODS:
  11.234 +
  11.235 +
  11.236 +
  11.237 +void MD5::init(){
  11.238 +  finalized=0;  // we just started!
  11.239 +
  11.240 +  // Nothing counted, so count=0
  11.241 +  count[0] = 0;
  11.242 +  count[1] = 0;
  11.243 +
  11.244 +  // Load magic initialization constants.
  11.245 +  state[0] = 0x67452301;
  11.246 +  state[1] = 0xefcdab89;
  11.247 +  state[2] = 0x98badcfe;
  11.248 +  state[3] = 0x10325476;
  11.249 +}
  11.250 +
  11.251 +
  11.252 +
  11.253 +// Constants for MD5Transform routine.
  11.254 +// Although we could use C++ style constants, defines are actually better,
  11.255 +// since they let us easily evade scope clashes.
  11.256 +
  11.257 +#define S11 7
  11.258 +#define S12 12
  11.259 +#define S13 17
  11.260 +#define S14 22
  11.261 +#define S21 5
  11.262 +#define S22 9
  11.263 +#define S23 14
  11.264 +#define S24 20
  11.265 +#define S31 4
  11.266 +#define S32 11
  11.267 +#define S33 16
  11.268 +#define S34 23
  11.269 +#define S41 6
  11.270 +#define S42 10
  11.271 +#define S43 15
  11.272 +#define S44 21
  11.273 +
  11.274 +
  11.275 +
  11.276 +
  11.277 +// MD5 basic transformation. Transforms state based on block.
  11.278 +void MD5::transform (uint1 block[64]){
  11.279 +
  11.280 +  uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
  11.281 +
  11.282 +  decode (x, block, 64);
  11.283 +
  11.284 +  assert(!finalized);  // not just a user error, since the method is private
  11.285 +
  11.286 +  /* Round 1 */
  11.287 +  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
  11.288 +  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
  11.289 +  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
  11.290 +  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
  11.291 +  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
  11.292 +  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
  11.293 +  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
  11.294 +  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
  11.295 +  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
  11.296 +  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
  11.297 +  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
  11.298 +  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
  11.299 +  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
  11.300 +  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
  11.301 +  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
  11.302 +  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
  11.303 +
  11.304 + /* Round 2 */
  11.305 +  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
  11.306 +  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
  11.307 +  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
  11.308 +  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
  11.309 +  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
  11.310 +  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
  11.311 +  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
  11.312 +  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
  11.313 +  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
  11.314 +  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
  11.315 +  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
  11.316 +  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
  11.317 +  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
  11.318 +  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
  11.319 +  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
  11.320 +  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
  11.321 +
  11.322 +  /* Round 3 */
  11.323 +  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
  11.324 +  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
  11.325 +  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
  11.326 +  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
  11.327 +  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
  11.328 +  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
  11.329 +  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
  11.330 +  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
  11.331 +  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
  11.332 +  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
  11.333 +  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
  11.334 +  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
  11.335 +  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
  11.336 +  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
  11.337 +  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
  11.338 +  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
  11.339 +
  11.340 +  /* Round 4 */
  11.341 +  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
  11.342 +  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
  11.343 +  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
  11.344 +  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
  11.345 +  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
  11.346 +  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
  11.347 +  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
  11.348 +  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
  11.349 +  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
  11.350 +  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
  11.351 +  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
  11.352 +  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
  11.353 +  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
  11.354 +  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
  11.355 +  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
  11.356 +  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
  11.357 +
  11.358 +  state[0] += a;
  11.359 +  state[1] += b;
  11.360 +  state[2] += c;
  11.361 +  state[3] += d;
  11.362 +
  11.363 +  // Zeroize sensitive information.
  11.364 +  memset ( (uint1 *) x, 0, sizeof(x));
  11.365 +
  11.366 +}
  11.367 +
  11.368 +
  11.369 +
  11.370 +// Encodes input (UINT4) into output (unsigned char). Assumes len is
  11.371 +// a multiple of 4.
  11.372 +void MD5::encode (uint1 *output, uint4 *input, uint4 len) {
  11.373 +
  11.374 +  unsigned int i, j;
  11.375 +
  11.376 +  for (i = 0, j = 0; j < len; i++, j += 4) {
  11.377 +    output[j]   = (uint1)  (input[i] & 0xff);
  11.378 +    output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
  11.379 +    output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
  11.380 +    output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
  11.381 +  }
  11.382 +}
  11.383 +
  11.384 +
  11.385 +
  11.386 +
  11.387 +// Decodes input (unsigned char) into output (UINT4). Assumes len is
  11.388 +// a multiple of 4.
  11.389 +void MD5::decode (uint4 *output, uint1 *input, uint4 len){
  11.390 +
  11.391 +  unsigned int i, j;
  11.392 +
  11.393 +  for (i = 0, j = 0; j < len; i++, j += 4)
  11.394 +    output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
  11.395 +      (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
  11.396 +}
  11.397 +
  11.398 +
  11.399 +
  11.400 +
  11.401 +
  11.402 +// Note: Replace "for loop" with standard memcpy if possible.
  11.403 +void MD5::memcpy (uint1 *output, uint1 *input, uint4 len){
  11.404 +
  11.405 +  unsigned int i;
  11.406 +
  11.407 +  for (i = 0; i < len; i++)
  11.408 +    output[i] = input[i];
  11.409 +}
  11.410 +
  11.411 +
  11.412 +
  11.413 +// Note: Replace "for loop" with standard memset if possible.
  11.414 +void MD5::memset (uint1 *output, uint1 value, uint4 len){
  11.415 +
  11.416 +  unsigned int i;
  11.417 +
  11.418 +  for (i = 0; i < len; i++)
  11.419 +    output[i] = value;
  11.420 +}
  11.421 +
  11.422 +
  11.423 +
  11.424 +// ROTATE_LEFT rotates x left n bits.
  11.425 +
  11.426 +inline unsigned int MD5::rotate_left  (uint4 x, uint4 n){
  11.427 +  return (x << n) | (x >> (32-n))  ;
  11.428 +}
  11.429 +
  11.430 +
  11.431 +
  11.432 +
  11.433 +// F, G, H and I are basic MD5 functions.
  11.434 +
  11.435 +inline unsigned int MD5::F            (uint4 x, uint4 y, uint4 z){
  11.436 +  return (x & y) | (~x & z);
  11.437 +}
  11.438 +
  11.439 +inline unsigned int MD5::G            (uint4 x, uint4 y, uint4 z){
  11.440 +  return (x & z) | (y & ~z);
  11.441 +}
  11.442 +
  11.443 +inline unsigned int MD5::H            (uint4 x, uint4 y, uint4 z){
  11.444 +  return x ^ y ^ z;
  11.445 +}
  11.446 +
  11.447 +inline unsigned int MD5::I            (uint4 x, uint4 y, uint4 z){
  11.448 +  return y ^ (x | ~z);
  11.449 +}
  11.450 +
  11.451 +
  11.452 +
  11.453 +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
  11.454 +// Rotation is separate from addition to prevent recomputation.
  11.455 +
  11.456 +
  11.457 +inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
  11.458 +		    uint4  s, uint4 ac){
  11.459 + a += F(b, c, d) + x + ac;
  11.460 + a = rotate_left (a, s) +b;
  11.461 +}
  11.462 +
  11.463 +inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
  11.464 +		    uint4 s, uint4 ac){
  11.465 + a += G(b, c, d) + x + ac;
  11.466 + a = rotate_left (a, s) +b;
  11.467 +}
  11.468 +
  11.469 +inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
  11.470 +		    uint4 s, uint4 ac){
  11.471 + a += H(b, c, d) + x + ac;
  11.472 + a = rotate_left (a, s) +b;
  11.473 +}
  11.474 +
  11.475 +inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
  11.476 +			     uint4 s, uint4 ac){
  11.477 + a += I(b, c, d) + x + ac;
  11.478 + a = rotate_left (a, s) +b;
  11.479 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/sourcepawn/jit/md5/md5.h	Fri Aug 10 21:54:03 2012 -0400
    12.3 @@ -0,0 +1,106 @@
    12.4 +// MD5.CC - source code for the C++/object oriented translation and 
    12.5 +//          modification of MD5.
    12.6 +
    12.7 +// Translation and modification (c) 1995 by Mordechai T. Abzug 
    12.8 +
    12.9 +// This translation/ modification is provided "as is," without express or 
   12.10 +// implied warranty of any kind.
   12.11 +
   12.12 +// The translator/ modifier does not claim (1) that MD5 will do what you think 
   12.13 +// it does; (2) that this translation/ modification is accurate; or (3) that 
   12.14 +// this software is "merchantible."  (Language for this disclaimer partially 
   12.15 +// copied from the disclaimer below).
   12.16 +
   12.17 +/* based on:
   12.18 +
   12.19 +   MD5.H - header file for MD5C.C
   12.20 +   MDDRIVER.C - test driver for MD2, MD4 and MD5
   12.21 +
   12.22 +   Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
   12.23 +rights reserved.
   12.24 +
   12.25 +License to copy and use this software is granted provided that it
   12.26 +is identified as the "RSA Data Security, Inc. MD5 Message-Digest
   12.27 +Algorithm" in all material mentioning or referencing this software
   12.28 +or this function.
   12.29 +
   12.30 +License is also granted to make and use derivative works provided
   12.31 +that such works are identified as "derived from the RSA Data
   12.32 +Security, Inc. MD5 Message-Digest Algorithm" in all material
   12.33 +mentioning or referencing the derived work.
   12.34 +
   12.35 +RSA Data Security, Inc. makes no representations concerning either
   12.36 +the merchantability of this software or the suitability of this
   12.37 +software for any particular purpose. It is provided "as is"
   12.38 +without express or implied warranty of any kind.
   12.39 +
   12.40 +These notices must be retained in any copies of any part of this
   12.41 +documentation and/or software.
   12.42 +
   12.43 +*/
   12.44 +
   12.45 +#include <stdio.h>
   12.46 +//#include <fstream.h>
   12.47 +//#include <iostream.h>
   12.48 +
   12.49 +class MD5 {
   12.50 +
   12.51 +public:
   12.52 +// methods for controlled operation:
   12.53 +  MD5              ();  // simple initializer
   12.54 +  void  update     (unsigned char *input, unsigned int input_length);
   12.55 +  void  update     (FILE *file);
   12.56 +  void  finalize   ();
   12.57 +
   12.58 +// constructors for special circumstances.  All these constructors finalize
   12.59 +// the MD5 context.
   12.60 +  MD5              (unsigned char *string); // digest string, finalize
   12.61 +  MD5              (FILE *file);            // digest file, close, finalize
   12.62 +
   12.63 +// methods to acquire finalized result
   12.64 +  unsigned char    *raw_digest ();  // digest as a 16-byte binary array
   12.65 +  unsigned char		*raw_digest(unsigned char buffer[16]);
   12.66 +  char *            hex_digest ();  // digest as a 33-byte ascii-hex string
   12.67 +  char *			hex_digest (char buffer[33]); //same as above, passing buffer
   12.68 +
   12.69 +
   12.70 +
   12.71 +private:
   12.72 +
   12.73 +// first, some types:
   12.74 +  typedef unsigned       int uint4; // assumes integer is 4 words long
   12.75 +  typedef unsigned short int uint2; // assumes short integer is 2 words long
   12.76 +  typedef unsigned      char uint1; // assumes char is 1 word long
   12.77 +
   12.78 +// next, the private data:
   12.79 +  uint4 state[4];
   12.80 +  uint4 count[2];     // number of *bits*, mod 2^64
   12.81 +  uint1 buffer[64];   // input buffer
   12.82 +  uint1 digest[16];
   12.83 +  uint1 finalized;
   12.84 +
   12.85 +// last, the private methods, mostly static:
   12.86 +  void init             ();               // called by all constructors
   12.87 +  void transform        (uint1 *buffer);  // does the real update work.  Note 
   12.88 +                                          // that length is implied to be 64.
   12.89 +
   12.90 +  static void encode    (uint1 *dest, uint4 *src, uint4 length);
   12.91 +  static void decode    (uint4 *dest, uint1 *src, uint4 length);
   12.92 +  static void memcpy    (uint1 *dest, uint1 *src, uint4 length);
   12.93 +  static void memset    (uint1 *start, uint1 val, uint4 length);
   12.94 +
   12.95 +  static inline uint4  rotate_left (uint4 x, uint4 n);
   12.96 +  static inline uint4  F           (uint4 x, uint4 y, uint4 z);
   12.97 +  static inline uint4  G           (uint4 x, uint4 y, uint4 z);
   12.98 +  static inline uint4  H           (uint4 x, uint4 y, uint4 z);
   12.99 +  static inline uint4  I           (uint4 x, uint4 y, uint4 z);
  12.100 +  static inline void   FF  (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
  12.101 +			    uint4 s, uint4 ac);
  12.102 +  static inline void   GG  (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
  12.103 +			    uint4 s, uint4 ac);
  12.104 +  static inline void   HH  (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
  12.105 +			    uint4 s, uint4 ac);
  12.106 +  static inline void   II  (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
  12.107 +			    uint4 s, uint4 ac);
  12.108 +
  12.109 +};
    13.1 --- a/tools/ida_scripts/vtable_dump.py	Fri Aug 10 21:49:40 2012 -0400
    13.2 +++ b/tools/ida_scripts/vtable_dump.py	Fri Aug 10 21:54:03 2012 -0400
    13.3 @@ -18,6 +18,79 @@
    13.4  
    13.5  import re
    13.6  
    13.7 +"""
    13.8 +Output Format:"
    13.9 +    VTable for <1>: (<2>, <3>)
   13.10 +    Lin    Win Function
   13.11 +    <4><5> <6> <7>
   13.12 +    <4><5> <6> <7>
   13.13 +    ...
   13.14 +    <4><5> <6> <7>
   13.15 +
   13.16 +1: Classname
   13.17 +2: VTable Offset
   13.18 +3: Linux This Pointer Offset
   13.19 +4: "T" if the function is a MI thunk
   13.20 +5: Linux VTable Index
   13.21 +6: Windows VTable Index
   13.22 +7: Function Signature
   13.23 +"""
   13.24 +
   13.25 +catchclass = False
   13.26 +innerclass = ""
   13.27 +
   13.28 +classname = None
   13.29 +offsetdata = {}
   13.30 +
   13.31 +def ExtractTypeInfo(ea, level = 0):
   13.32 +	global catchclass
   13.33 +	global innerclass
   13.34 +	global classname
   13.35 +	global offsetdata
   13.36 +	
   13.37 +	# Param needed to support old IDAPython versions
   13.38 +	end = NextHead(ea, 4294967295)
   13.39 +	
   13.40 +	# Skip vtable
   13.41 +	ea += 4
   13.42 +	
   13.43 +	# Get type name
   13.44 +	name = Demangle("_Z" + GetString(Dword(ea)), GetLongPrm(INF_LONG_DN))
   13.45 +	ea += 4
   13.46 +	
   13.47 +	if classname is None and level == 0:
   13.48 +		classname = name
   13.49 +	
   13.50 +	if catchclass:
   13.51 +		innerclass = name
   13.52 +		catchclass = False
   13.53 +	
   13.54 +	print "%*s%s" % (level, "", name)
   13.55 +	
   13.56 +	if not ea < end: # Base Type
   13.57 +		pass
   13.58 +	elif isData(GetFlags(Dword(ea))): # Single Inheritance
   13.59 +		ExtractTypeInfo(Dword(ea), level + 1)
   13.60 +		ea += 4
   13.61 +	else: # Multiple Inheritance
   13.62 +		ea += 8
   13.63 +		while ea < end:
   13.64 +			catchclass = True
   13.65 +			ExtractTypeInfo(Dword(ea), level + 1)
   13.66 +			ea += 4
   13.67 +			offset = Dword(ea)
   13.68 +			ea += 4
   13.69 +			#print "%*s Offset: 0x%06X" % (level, "", offset >> 8)
   13.70 +			if (offset >> 8) != 0:
   13.71 +				offsetdata[offset >> 8] = innerclass
   13.72 +
   13.73 +# Source: http://stackoverflow.com/a/9147327
   13.74 +def twos_comp(val, bits):
   13.75 +	"""compute the 2's compliment of int value val"""
   13.76 +	if (val & (1 << (bits - 1))) != 0:
   13.77 +		val = val - (1 << bits)
   13.78 +	return val
   13.79 +
   13.80  def Analyze():
   13.81  	SetStatus(IDA_STATUS_WORK)
   13.82  	
   13.83 @@ -29,7 +102,8 @@
   13.84  	ea = ScreenEA()
   13.85  	
   13.86  	if not isHead(GetFlags(ea)):
   13.87 -		ea = PrevHead(ea)
   13.88 +		# Param needed to support old IDAPython versions
   13.89 +		ea = PrevHead(ea, 0)
   13.90  	
   13.91  	# Param needed to support old IDAPython versions
   13.92  	end = NextHead(ea, 4294967295)
   13.93 @@ -43,18 +117,23 @@
   13.94  	linux_vtable = []
   13.95  	temp_windows_vtable = []
   13.96  	
   13.97 +	other_linux_vtables = {}
   13.98 +	other_thunk_linux_vtables = {}
   13.99 +	temp_other_windows_vtables = {}
  13.100 +	
  13.101  	# Extract vtable
  13.102  	while ea < end:
  13.103 -		offset = Dword(ea)
  13.104 +		# Read thisoffs
  13.105 +		offset = -twos_comp(Dword(ea), 32)
  13.106 +		ea += 4
  13.107  		
  13.108 -		# A vtable starts with some metadata, if it's missing...
  13.109 -		if isCode(GetFlags(offset)):
  13.110 -			Warning("Something went wrong!")
  13.111 -			SetStatus(IDA_STATUS_READY)
  13.112 -			return
  13.113 +		# Read typeinfo address
  13.114 +		typeinfo = Dword(ea)
  13.115 +		ea += 4
  13.116  		
  13.117 -		# Skip thisoffs and typeinfo address
  13.118 -		ea += 8
  13.119 +		if offset == 0: # We only need to read this once
  13.120 +			print "Inheritance Tree:"
  13.121 +			ExtractTypeInfo(typeinfo)
  13.122  		
  13.123  		while ea < end and isCode(GetFlags(Dword(ea))):
  13.124  			name = Demangle(Name(Dword(ea)), GetLongPrm(INF_LONG_DN))
  13.125 @@ -63,9 +142,22 @@
  13.126  				linux_vtable.append(name)
  13.127  				temp_windows_vtable.append(name)
  13.128  			else:
  13.129 +				if offset not in other_linux_vtables:
  13.130 +					other_linux_vtables[offset] = []
  13.131 +					temp_other_windows_vtables[offset] = []
  13.132 +					other_thunk_linux_vtables[offset] = []
  13.133 +				
  13.134 +				if "`non-virtual thunk to'" in name:
  13.135 +					other_linux_vtables[offset].append(name[22:])
  13.136 +					other_thunk_linux_vtables[offset].append(name[22:])
  13.137 +					temp_other_windows_vtables[offset].append(name[22:])
  13.138 +				else:
  13.139 +					other_linux_vtables[offset].append(name)
  13.140 +					temp_other_windows_vtables[offset].append(name)
  13.141 +				
  13.142  				# MI entry, strip "`non-virtual thunk to'" and remove from list
  13.143  				#     But not if it's a dtor... what the hell is this.
  13.144 -				if (name.find("`non-virtual thunk to'") != -1) and name.find("::~") == -1:
  13.145 +				if "`non-virtual thunk to'" in name and "::~" not in name:
  13.146  					name = name[22:]
  13.147  					#print "Stripping '%s' from windows vtable." % (name)
  13.148  					temp_windows_vtable.remove(name)
  13.149 @@ -73,7 +165,7 @@
  13.150  			ea += 4
  13.151  	
  13.152  	for i, v in enumerate(temp_windows_vtable):
  13.153 -		if v.find("::~") != -1:
  13.154 +		if "::~" in v:
  13.155  			#print "Found destructor at index %d: %s" % (i, v)
  13.156  			del temp_windows_vtable[i]
  13.157  			break
  13.158 @@ -96,16 +188,19 @@
  13.159  			overload_stack.append(v)
  13.160  		else:
  13.161  			# If we've moved onto something new, dump the stack first
  13.162 -			if len(overload_stack) > 0:
  13.163 -				#print overload_stack
  13.164 -				while len(overload_stack) > 0:
  13.165 -					windows_vtable.append(overload_stack.pop())
  13.166 +			while len(overload_stack) > 0:
  13.167 +				windows_vtable.append(overload_stack.pop())
  13.168  			
  13.169  			windows_vtable.append(v)
  13.170  		
  13.171  		prev_function = function
  13.172  		prev_symbol = v
  13.173  	
  13.174 +	# If there is anything left in the stack, dump it
  13.175 +	while len(overload_stack) > 0:
  13.176 +		windows_vtable.append(overload_stack.pop())
  13.177 +	
  13.178 +	print "\nVTable for %s: (0, 0)" % (classname)
  13.179  	print "Lin Win Function"
  13.180  	for i, v in enumerate(linux_vtable):
  13.181  		winindex = windows_vtable.index(v) if v in windows_vtable else None
  13.182 @@ -114,7 +209,45 @@
  13.183  		else:
  13.184  			print "%3d     %s" % (i, v)
  13.185  	
  13.186 +	for k in temp_other_windows_vtables:
  13.187 +		for i, v in enumerate(temp_other_windows_vtables[k]):
  13.188 +			if v.find("::~") != -1:
  13.189 +				#print "Found destructor at index %d: %s" % (i, v)
  13.190 +				del temp_other_windows_vtables[k][i]
  13.191 +				break
  13.192 +	
  13.193 +	other_windows_vtables = {}
  13.194 +	for k in temp_other_windows_vtables:
  13.195 +		other_windows_vtables[k] = []
  13.196 +		overload_stack = []
  13.197 +		prev_function = ""
  13.198 +		prev_symbol = ""
  13.199 +		for v in temp_other_windows_vtables[k]:
  13.200 +			function = v.split("(", 1)[0]
  13.201 +			if function == prev_function:
  13.202 +				if len(overload_stack) == 0:
  13.203 +					other_windows_vtables[k].pop()
  13.204 +					overload_stack.append(prev_symbol)
  13.205 +				overload_stack.append(v)
  13.206 +			else:
  13.207 +				if len(overload_stack) > 0:
  13.208 +					while len(overload_stack) > 0:
  13.209 +						other_windows_vtables[k].append(overload_stack.pop())
  13.210 +				other_windows_vtables[k].append(v)
  13.211 +			prev_function = function
  13.212 +			prev_symbol = v
  13.213 +	
  13.214 +	for k in other_linux_vtables:
  13.215 +		print "\nVTable for %s: (%d, %d)" % (offsetdata[k], offsetdata.keys().index(k) + 1, k)
  13.216 +		print "Lin Win Function"
  13.217 +		for i, v in enumerate(other_linux_vtables[k]):
  13.218 +			winindex = other_windows_vtables[k].index(v)
  13.219 +			if v not in other_thunk_linux_vtables[k]:
  13.220 +				print "%3d %3d %s" % (i, winindex, v)
  13.221 +			else:
  13.222 +				print "T%2d %3d %s" % (i, winindex, v)
  13.223 +	
  13.224  	SetStatus(IDA_STATUS_READY)
  13.225  
  13.226  if __name__ == '__main__':
  13.227 -	Analyze()
  13.228 \ No newline at end of file
  13.229 +	Analyze()