diff --git a/SigMaker.sln b/SigMaker.sln new file mode 100644 index 0000000..0f27fe4 --- /dev/null +++ b/SigMaker.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2002 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SigMaker", "SigMaker\SigMaker.vcxproj", "{60916877-60AB-4565-93BC-2D6097976D86}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Debug64|Win32 = Debug64|Win32 + Debug64|x64 = Debug64|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Release64|Win32 = Release64|Win32 + Release64|x64 = Release64|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {60916877-60AB-4565-93BC-2D6097976D86}.Debug|Win32.ActiveCfg = Debug|Win32 + {60916877-60AB-4565-93BC-2D6097976D86}.Debug|Win32.Build.0 = Debug|Win32 + {60916877-60AB-4565-93BC-2D6097976D86}.Debug|x64.ActiveCfg = Debug|x64 + {60916877-60AB-4565-93BC-2D6097976D86}.Debug|x64.Build.0 = Debug|x64 + {60916877-60AB-4565-93BC-2D6097976D86}.Debug64|Win32.ActiveCfg = Debug64|Win32 + {60916877-60AB-4565-93BC-2D6097976D86}.Debug64|Win32.Build.0 = Debug64|Win32 + {60916877-60AB-4565-93BC-2D6097976D86}.Debug64|x64.ActiveCfg = Debug64|x64 + {60916877-60AB-4565-93BC-2D6097976D86}.Debug64|x64.Build.0 = Debug64|x64 + {60916877-60AB-4565-93BC-2D6097976D86}.Release|Win32.ActiveCfg = Release|Win32 + {60916877-60AB-4565-93BC-2D6097976D86}.Release|Win32.Build.0 = Release|Win32 + {60916877-60AB-4565-93BC-2D6097976D86}.Release|x64.ActiveCfg = Release|x64 + {60916877-60AB-4565-93BC-2D6097976D86}.Release|x64.Build.0 = Release|x64 + {60916877-60AB-4565-93BC-2D6097976D86}.Release64|Win32.ActiveCfg = Release64|Win32 + {60916877-60AB-4565-93BC-2D6097976D86}.Release64|Win32.Build.0 = Release64|Win32 + {60916877-60AB-4565-93BC-2D6097976D86}.Release64|x64.ActiveCfg = Release64|x64 + {60916877-60AB-4565-93BC-2D6097976D86}.Release64|x64.Build.0 = Release64|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {802A9F2E-7038-472F-B090-4154959F470D} + EndGlobalSection +EndGlobal diff --git a/SigMaker/Converter.cpp b/SigMaker/Converter.cpp new file mode 100644 index 0000000..6cecb56 --- /dev/null +++ b/SigMaker/Converter.cpp @@ -0,0 +1,243 @@ +#include "Includes.h" +#include "Misc.h" + +void ShowSigConverter( void ) +{ + static const char szForm[] = + "Sig Converter\n" + "\n" + "\n" + " \n" + " \n" + "\n" + " <##Code to IDA:R>\n" // 0 + " <##Code to CRC:R>\n" // 1 + " <##IDA to CRC:R>\n" // 2 + " <##IDA to Code:R>\n" // 3 + " <##IDA to Olly:R>\n" // 4 + " <##Olly to IDA:R>>\n" // 5 + "\n" + "\n"; + + char szSigIn[MAXSTR] = { 0 }; + char szMaskIn[MAXSTR] = { 0 }; + + ushort usCheckBox = 0; + + qstring strTemp; + + if (ask_form( szForm, szSigIn, szMaskIn, &usCheckBox ) > 0) + { + strTemp = szSigIn; + qstring strSigIn = szSigIn; + qstring strMaskIn = szMaskIn; + ea_t dwCRC = 0, dwMask = 0; + + switch (usCheckBox) + { + case 0: + CodeToIDA( strTemp, strSigIn, strMaskIn ); + break; + case 1: + CodeToCRC( strSigIn, strMaskIn, dwCRC, dwMask ); + strTemp.sprnt( "0x%x, 0x%x", dwCRC, dwMask ); + break; + case 2: + IDAToCRC( strSigIn, dwCRC, dwMask ); + strTemp.sprnt( "0x%x, 0x%x", dwCRC, dwMask ); + break; + case 3: + IDAToCode( strTemp, strSigIn, szMaskIn ); + strTemp.sprnt( "%s, %s", szSigIn, szMaskIn ); + break; + case 4: + strTemp.replace( " ? ", " ?? " ); + break; + case 5: + strTemp.replace( " ?? ", " ? " ); + break; + } + if (TextToClipboard( strTemp.c_str( ) ) == false) + { + if (Settings.iLogLevel >= 1) + { + msg( "Converted: %s\n", strTemp.c_str( ) ); + } + } + } +} + +bool GetNextByte( char** pszString, unsigned char& rByte, bool& isWhiteSpace ) +{ + do + { + if (*(*pszString) == '?') + { + rByte = 0; + isWhiteSpace = true; + *(*pszString)++; + + if (*(*pszString) == '?') + *(*pszString)++; + + return true; + } + else if (qisxdigit( **pszString )) + { + isWhiteSpace = false; + rByte = (unsigned char)(strtoul( *pszString, pszString, 16 ) & 0xFF); + return true; + } + } while (*(*pszString)++); + + return false; +} + +int Text2Hex( const char* pszString, unsigned char* pbArray, char* pszMask = NULL ) +{ + int Count = 0; + bool isWhiteSpace = false; + + if (pszMask) + *pszMask = 0; + + if (GetNextByte( const_cast(&pszString), pbArray[Count], isWhiteSpace )) + { + do + { + Count++; + + if (pszMask) + qstrncat( pszMask, (isWhiteSpace) ? "?" : "x", MAXSTR ); + + } while (GetNextByte( const_cast(&pszString), pbArray[Count], isWhiteSpace )); + } + + return Count; +} + +int CodeStyleToByte( const char* pszSignature, unsigned char* pbArray, char* pszMask ) +{ + char szBuffer[MAXSTR] = { 0 }; + char szTemp[2] = { 0 }; + + size_t iLength = strlen( pszSignature ); + + for (size_t i = 0; i < iLength; i++) + { + if (pszSignature[i] == '\\') + { + continue; + } + else if (pszSignature[i] == 'x') + { + qstrncat( szBuffer, " ", sizeof( szBuffer ) ); + } + else + { + szTemp[0] = pszSignature[i]; + qstrncat( szBuffer, szTemp, sizeof( szBuffer ) ); + } + } + + return Text2Hex( szBuffer, pbArray, pszMask ); +} + +// To Code conversion +void IDAToCode( const qstring& strSig, qstring& strByteSig, char* pszMask ) +{ + unsigned char ucByteArray[MAXSTR]; + int iCount = Text2Hex( strSig.c_str( ), ucByteArray, pszMask ); + strByteSig.clear( ); + + for (int i = 0; i < iCount; i++) + strByteSig.cat_sprnt( "\\x%02X", ucByteArray[i] ); +} + +// to crc conversion +void IDAToCRC( const qstring& strSig, ea_t& dwCRC32, ea_t& dwMask ) +{ + unsigned char ucByteArray[MAXSTR]; + char szMask[MAXSTR]; + int iCount = Text2Hex( strSig.c_str( ), ucByteArray, szMask ); + + for (int i = 0; i < 32; i++) + { + if (i <= iCount && szMask[i] == 'x') + { + dwMask |= (1 << i); + } + else + { + dwMask &= ~(1 << i); + } + } + + dwCRC32 = calc_crc32( 0, ucByteArray, 32 ); +} + +void CodeToCRC( const qstring& strByteSig, const qstring& strMask, ea_t& dwCRC32, ea_t& dwMask ) +{ + unsigned char ucByteArray[MAXSTR]; + char szMask[MAXSTR]; + int iCount = Text2Hex( strByteSig.c_str( ), ucByteArray, szMask ); + + for (int i = 0; i < 32; i++) + { + if (i <= iCount && szMask[i] == 'x') + { + dwMask |= 1 << i; + } + else + { + dwMask &= ~(1 << i); + } + } + + dwCRC32 = calc_crc32( 0, ucByteArray, 32 ); +} + +// to ida conversation +void CodeToIDA( qstring& strSig, const qstring& strByteSig, const qstring& strMask ) +{ + unsigned char ucByteArray[MAXSTR] = { 0 }; + + int iCount = Text2Hex( strByteSig.c_str( ), ucByteArray, NULL ); + + size_t nLength = strMask.length( ); + strSig.clear( ); + + for (size_t i = 0; i < nLength; i++) + { + if (strMask[i] == 'x' || strMask[i] == 'X') + { + strSig.cat_sprnt( "0x%02X ", ucByteArray[i] ); + } + else + { + strSig += "? "; + } + } +} + +void CodeToIDAC( qstring& strSig, const char* strByteSig, const char* strMask ) +{ + unsigned char ucByteArray[MAXSTR] = { 0 }; + + int iCount = Text2Hex( strByteSig, ucByteArray, NULL ); + + size_t nLength = qstrlen( strMask ); + strSig.clear( ); + + for (size_t i = 0; i < nLength; i++) + { + if (strMask[i] == 'x' || strMask[i] == 'X') + { + strSig.cat_sprnt( "%02X ", ucByteArray[i] ); + } + else + { + strSig += "? "; + } + } +} \ No newline at end of file diff --git a/SigMaker/Generate.cpp b/SigMaker/Generate.cpp new file mode 100644 index 0000000..07d0590 --- /dev/null +++ b/SigMaker/Generate.cpp @@ -0,0 +1,438 @@ +#include "Misc.h" + +void AddBytesToSig( qstring& strSig, ea_t dwAddress, ea_t dwSize ) +{ + for (ea_t i = 0; i < dwSize; i++) + strSig.cat_sprnt( "%02X ", get_byte( dwAddress + i ) ); +} + +void AddWhiteSpacesToSig( qstring& strSig, ea_t dwSize ) +{ + for (ea_t i = 0; i < dwSize; i++) + strSig.cat_sprnt( "? " ); +} + +unsigned int getCurrentOpcodeSize( insn_t *cmd, unsigned int& uiCount ) +{ + for (unsigned int i = 0; i < UA_MAXOP; i++) + { + uiCount = i; + if (cmd->ops[i].type == o_void) + return 0; + if (cmd->ops[i].offb != 0) + return cmd->ops[i].offb; + } + return 0; +} + +bool MatchOperands( insn_t *cmd, unsigned int uiOperand, unsigned int uiSize ) // this is where all the options kick in +{ + //if ( cmd.Operands[ uiOperand ].type == o_mem || cmd.Operands[ uiOperand ].type == o_far) + // return false; + + if (get_first_dref_from( cmd->ea ) != BADADDR) // data reference + return false; + + if (Settings.iKeepUnsafeData != 0) + { + if (get_first_fcref_from( cmd->ea ) != BADADDR) // code reference + return false; + } + else + { + if (get_first_cref_from( cmd->ea ) != BADADDR) // code reference + return false; + } + + return true; +} + +void AddInsToSig( insn_t *cmd, qstring& strSig ) +{ + unsigned int uiCount = 0; + unsigned int uiSize = getCurrentOpcodeSize( cmd, uiCount ); + if (uiSize == 0) + { + AddBytesToSig( strSig, cmd->ea, cmd->size ); + return; + } + else + { + AddBytesToSig( strSig, cmd->ea, uiSize ); + } + + if (MatchOperands( cmd, 0, uiSize )) + { + AddBytesToSig( strSig, cmd->ea + uiSize, cmd->size - uiSize ); + } + else + { + AddWhiteSpacesToSig( strSig, cmd->size - uiSize ); + } +} + +bool AddOneInstructionToSig( qstring& strSig, ea_t& dwCurentAddress ) +{ + insn_t cmd; + + if (decode_insn( &cmd, dwCurentAddress ) == 0) + return false; + + if (cmd.size == 0) // prevent an infinite loop + return false; + + if (cmd.size < 5) + AddBytesToSig( strSig, dwCurentAddress, cmd.size ); + else + AddInsToSig( &cmd, strSig ); + + dwCurentAddress += cmd.size; + return true; +} + +bool AutoGenerate( qSigVector& refvecSig, ea_t dwAddress ) +{ + qSigVector vecSig; // remove previous entries + + show_wait_box( "Please Wait..." ); + + unsigned int nTotalCount = 0; + + refvecSig.clear( ); + + if (get_func_num( dwAddress ) != -1) // this just a check to see if the function is valid code + { + sAutoSig_t TargetLocation; + TargetLocation.dwStartAddress = TargetLocation.dwCurrentAddress = dwAddress; + TargetLocation.iOpCount = 0; + TargetLocation.eType = PT_DIRECT; + vecSig.push_back( TargetLocation ); + nTotalCount++; + if (Settings.iLogLevel >= 3) + { + msg( "A direct signature is available for the current address.\n" ); + } + } + + msg( "adding references\n" ); + + // got references? + for (ea_t dwCurrent = get_first_cref_to( dwAddress ); + dwCurrent != BADADDR; + dwCurrent = get_next_cref_to( dwAddress, dwCurrent )) + { + if (dwCurrent == dwAddress) + continue; + + sAutoSig_t TargetLocation; + TargetLocation.dwStartAddress = TargetLocation.dwCurrentAddress = dwCurrent; + TargetLocation.iOpCount = 0; + TargetLocation.eType = PT_REFERENCE; + vecSig.push_back( TargetLocation ); + + nTotalCount++; + + if (Settings.iMaxRefCount > 0) + { + if (nTotalCount >= Settings.iMaxRefCount) + break; + } + } + + if (Settings.iLogLevel >= 3 && nTotalCount > 1) + { + msg( "Added %i references to the selected address.\n", nTotalCount - 1 ); + } + + if (nTotalCount < 5) // we are pointing at data + { + func_t* pFunc = get_func( dwAddress ); + + if (Settings.iLogLevel >= 3) + { + msg( "Not enough references were found (%i so far), trying the function.\n", nTotalCount ); + } + + if (pFunc && pFunc->start_ea != dwAddress) + { + if (Settings.iLogLevel >= 3) + { + msg( "the function seems valid scanning...\n" ); + } + for (ea_t dwCurrent = get_first_cref_to( pFunc->start_ea ); + dwCurrent != BADADDR; + dwCurrent = get_next_cref_to( pFunc->start_ea, dwCurrent )) + { + if (dwCurrent == dwAddress) + continue; + + sAutoSig_t TargetLocation; + + TargetLocation.dwStartAddress = pFunc->start_ea; + TargetLocation.dwCurrentAddress = dwCurrent; + TargetLocation.iOpCount = 0; + TargetLocation.eType = PT_FUNCTION; + vecSig.push_back( TargetLocation ); + + nTotalCount++; + + if (Settings.iMaxRefCount > 0) + if (nTotalCount >= Settings.iMaxRefCount) + break; + } + } + else + { + if (Settings.iLogLevel >= 2) + { + msg( "the function was invalid...\n" ); + } + } + } + + if (Settings.iLogLevel >= 2) + { + msg( "added a total of %i references.\n", nTotalCount ); + } + + int iCount = 0; + + do + { + if (nTotalCount < 1) // vecSig.size() + { + hide_wait_box( ); + + if (Settings.iLogLevel >= 2) + { + msg( "automated signature generation failed. Unable to proceed.\n" ); + } + + return false; + } + + for (qSigVector::iterator i = vecSig.begin( ); i != vecSig.end( ); i++) + { + if (AddOneInstructionToSig( (*i).strSig, (*i).dwCurrentAddress ) == false) + { + if (Settings.iLogLevel >= 2) + { + msg( "dropped a sig due to decompilation failure.\n" ); + } + + if (vecSig.size( ) < 1) + { + hide_wait_box( ); + msg( "not enough candidates to proceed. aborting...\n" ); + return false; + } + vecSig.erase( i ); + continue; + } + (*i).iOpCount++; + (*i).iHitCount = ((*i).strSig.length( ) > 5) ? GetOccurenceCount( (*i).strSig, true ) : 0; + } + } while (HasOneHitSig( vecSig ) == false); + + refvecSig.clear( ); + + + for (qSigVector::iterator i = vecSig.begin( ); i != vecSig.end( ); i++) + { + + if ((*i).iHitCount == 1) + { + if (Settings.iLogLevel >= 3) + { + msg( "[%x] Signature %s is viable candidate for final evaluation.", (*i).dwStartAddress, (*i).strSig.c_str( ) ); + } + refvecSig.push_back( (*i) ); + } + } + hide_wait_box( ); + vecSig.clear( ); + return (refvecSig.size( ) != 0); +} + + +void CreateSig( SigType eType ) +{ + qstring strSig; + ea_t dwStart, dwEnd; + + if (read_range_selection( get_current_viewer( ), &dwStart, &dwEnd )) + { + if (dwEnd - dwStart < 5) + { + msg( "Your selection is too short!\n" ); + return; + } + + insn_t cmd; + + func_item_iterator_t fIterator; + bool isWithinRange = fIterator.set_range( dwStart, dwEnd ); + + for (ea_t dwCurrentInstruction = fIterator.current( ); + decode_insn( &cmd, dwCurrentInstruction ) != 0; + dwCurrentInstruction = fIterator.current( )) + { + if (cmd.size < 5) + AddBytesToSig( strSig, dwCurrentInstruction, cmd.size ); + else + AddInsToSig( &cmd, strSig ); + + if (fIterator.next_not_tail( ) == false) + break; + } + + if (Settings.iLogLevel >= 2) + { + msg( "Sig %s\n", strSig.c_str( ) ); + } + } + else + { + if (Settings.iLogLevel >= 1) + { + msg( "no code selected.\n" ); + } + return; + } + + qstring strTmp; + char szMask[MAXSTR]; + + switch (eType) + { + case SIG_IDA: + break; + case SIG_CODE: + IDAToCode( strSig, strTmp, szMask ); + strSig.sprnt( "%s, %s", strTmp.c_str( ), szMask ); + break; + case SIG_CRC: + IDAToCRC( strSig, dwStart, dwEnd ); + strSig.sprnt( "0x%X, 0x%X", dwStart, dwEnd ); + break; + } + + TextToClipboard( strSig.c_str( ) ); + + if (Settings.iLogLevel >= 1) + { + msg( "Sig: %s\n", strSig.c_str( ) ); + } +} + +unsigned int GetCharCount( const char* pszString, char chSign, bool bCaseInsenstive = false ) +{ + unsigned int nLength = 0; + + do + { + if (bCaseInsenstive) + { + if (qtolower( *pszString ) == qtolower( chSign )) + nLength++; + } + else + { + if (*pszString == chSign) + nLength++; + } + } while (*pszString++); + + return nLength; +} + +void GenerateSig( SigType eType ) +{ + qSigVector vecSig; + qSigVector::iterator SigIterator; + size_t uiLength = 9999; + + ea_t dwAddress = get_screen_ea( ); + + if (dwAddress == BADADDR) + { + if (Settings.iLogLevel >= 2) + { + msg( "You must select an address.\n" ); + } + return; + } + + if (AutoGenerate( vecSig, dwAddress )) + { + for (qSigVector::iterator i = vecSig.begin( ); i != vecSig.end( ); i++) + { + if (Settings.iSelectionType == 0) + { + size_t nLength = (*i).strSig.length( ); + if (uiLength > nLength || ((*i).eType == PT_DIRECT && uiLength == nLength)) + { + uiLength = nLength; + SigIterator = i; + } + } + else + { + if (Settings.iSelectionType == 1) + { + if (uiLength > (*i).iOpCount || ((*i).eType == PT_DIRECT && uiLength == (*i).iOpCount)) + { + uiLength = (*i).iOpCount; + SigIterator = i; + } + } + else + { + unsigned int nLength = GetCharCount( (*i).strSig.c_str( ), '?' ); + + if (uiLength > nLength || ((*i).eType == PT_DIRECT && uiLength == nLength)) + { + uiLength = nLength; + SigIterator = i; + } + } + } + } + } + + qstring strSig = (*SigIterator).strSig, strTmp; + char szMask[MAXSTR]; + ea_t dwStart, dwEnd; + + switch (eType) + { + case SIG_IDA: + break; + case SIG_CODE: + IDAToCode( strSig, strTmp, szMask ); + strSig.sprnt( "%s, %s", strTmp.c_str( ), szMask ); + break; + case SIG_CRC: + IDAToCRC( strSig, dwStart, dwEnd ); + strSig.sprnt( "0x%X, 0x%X", dwStart, dwEnd ); + break; + } + + TextToClipboard( strSig.c_str( ) ); + + if (Settings.iLogLevel >= 1) + { + switch ((*SigIterator).eType) + { + case PT_DIRECT: + msg( "sig: %s\n", strSig.c_str( ) ); + break; + case PT_FUNCTION: + msg( "sig to containing function: (+0x%X) %s\n", dwAddress - (*SigIterator).dwStartAddress, strSig.c_str( ) ); + break; + case PT_REFERENCE: + msg( "direct reference: [actual address in first opcode] %s\n", strSig.c_str( ) ); + break; + } + } +} \ No newline at end of file diff --git a/SigMaker/Includes.h b/SigMaker/Includes.h new file mode 100644 index 0000000..1b8e2f4 --- /dev/null +++ b/SigMaker/Includes.h @@ -0,0 +1,31 @@ +#pragma once + +#define _CRT_SECURE_NO_WARNINGS 1 +#define __IDP__ 1 +#define __NT__ 1 +#define __X64__ 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // find_binary +#include +#include +#include + +#pragma comment(lib, "ida.lib") +#pragma comment(lib, "pro.lib") \ No newline at end of file diff --git a/SigMaker/Main.cpp b/SigMaker/Main.cpp new file mode 100644 index 0000000..56bbeda --- /dev/null +++ b/SigMaker/Main.cpp @@ -0,0 +1,107 @@ +#include "Includes.h" +#include "Misc.h" + +void ShowOptions( void ) +{ + char szBuffer[MAXSTR]; + qsnprintf( szBuffer, MAXSTR - 1, "%i", Settings.iMaxRefCount ); + + int iResult = ask_form( + "Options\n" + "<##choose the best sig from total length:R>\n" // 0 + "<##choose the best sig from the amount of opcodes:R>\n" // 1 + "<##choose the best sig by the smallest amount of wildcards:R>>\n\n" // 2 + "\n" + "<##add only relilable data to sigs(choose if unsure):R>\n" // 0 + "<##include unsafe data in sigs(may produce better results):R>>\n\n" // 1 + "<##disable logging:R>\n" // 0 + "<##log results:R>\n" // 1 + "<##log errors and results:R>\n" // 2 + "<##log errors, results and interim steps of all proceedures:R>>\n\n" // 3 + , &Settings.iSelectionType, szBuffer, &Settings.iKeepUnsafeData, &Settings.iLogLevel ); + + qsscanf( szBuffer, "%i", &Settings.iMaxRefCount ); + + Settings.Save( "sigmaker.ini" ); +} + +bool idaapi run( size_t /*arg*/ ) +{ + int iAction = 0; + int iResult = ask_form( + "What do you want to do?\n" + "<##create ida pattern from selection:R>\n" // 0 + "<##create code pattern from selection:R>\n" // 1 + "<##create crc32 pattern from selection:R>\n" // 2 + "<##auto create ida pattern:R>\n" // 3 + "<##auto create code pattern:R>\n" // 4 + "<##auto create crc32 pattern:R>\n" // 5 + "<##test ida pattern:R>\n" // 6 + "<##test code pattern:R>\n" // 7 + "<##convert a sig:R>\n" // 8 + "<##configure the plugin:R>>\n\n", // 9 + &iAction ); + + if (iResult > 0) + { + switch (iAction) + { + case 0: + CreateSig( SIG_IDA ); + break; + case 1: + CreateSig( SIG_CODE ); + break; + case 2: + CreateSig( SIG_CRC ); + break; + case 3: + GenerateSig( SIG_IDA ); + break; + case 4: + GenerateSig( SIG_CODE ); + break; + case 5: + GenerateSig( SIG_CRC ); + break; + case 6: + ShowSearchWindow( ); + break; + case 7: + ShowSearchDialog( ); + break; + case 8: + ShowSigConverter( ); + break; + case 9: + ShowOptions( ); + break; + } + } + + return true; +} + +int __stdcall init( void ) +{ + if (inf.filetype != f_PE) + return PLUGIN_SKIP; + + Settings.Init( ); + Settings.Load( "sigmaker.ini" ); + + return PLUGIN_OK; +} + +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + PLUGIN_KEEP, + init, + NULL, + run, + "creates a sigs", + "SigMaker plugin\n", + "SigMaker", + "Ctrl-Alt-S"// Alt-F11 +}; \ No newline at end of file diff --git a/SigMaker/Misc.cpp b/SigMaker/Misc.cpp new file mode 100644 index 0000000..0d19c7a --- /dev/null +++ b/SigMaker/Misc.cpp @@ -0,0 +1,53 @@ +#include "Misc.h" + +Settings_t Settings; + +void Settings_t::Init( void ) +{ + memset( this, 0, sizeof( Settings_t ) ); + Settings.iLogLevel = 1; +} + +void Settings_t::Save( const char* pszFileName ) +{ + char szLocation[MAXSTR]; + + qsnprintf( szLocation, MAXSTR - 1, "%s\\%s", get_user_idadir( ), pszFileName ); + + if (Settings.iLogLevel >= 3) + { + msg( "saving settings to %s\n", szLocation ); + } + + FILE* pFile = qfopen( szLocation, "wb" ); + + if (pFile) + { + qfwrite( pFile, this, sizeof( Settings_t ) ); + qfclose( pFile ); + } +} + +void Settings_t::Load( const char* pszFileName ) +{ + char szLocation[MAXSTR]; + + qsnprintf( szLocation, MAXSTR - 1, "%s\\%s", get_user_idadir( ), pszFileName ); + + if (Settings.iLogLevel >= 3) + { + msg( "loading settings from %s\n", szLocation ); + } + + FILE* pFile = qfopen( szLocation, "rb" ); + if (pFile) + { + qfread( pFile, this, sizeof( Settings_t ) ); + qfclose( pFile ); + } + else + { + if (Settings.iLogLevel >= 2) + msg( "couldn't open settings file using either default or current settings\n" ); + } +} \ No newline at end of file diff --git a/SigMaker/Misc.h b/SigMaker/Misc.h new file mode 100644 index 0000000..44b9c06 --- /dev/null +++ b/SigMaker/Misc.h @@ -0,0 +1,72 @@ +#pragma once + +#include "Includes.h" + +#define IsValidEA( x ) x != 0 && x != BADADDR + +enum ePatternType { + PT_DIRECT, + PT_FUNCTION, + PT_REFERENCE +}; + +typedef struct { + qstring strSig; + ea_t dwStartAddress; + ea_t dwCurrentAddress; + int iHitCount; + unsigned int iOpCount; + ePatternType eType; +} sAutoSig_t; + +typedef qvector qSigVector; + + +typedef enum { + SIG_IDA, + SIG_CODE, + SIG_CRC, +} SigType; + +typedef struct { + int iSelectionType; + unsigned int iMaxRefCount; + int iKeepUnsafeData; + int iLogLevel; + + void Init( void ); + void Save( const char* pszFileName ); + void Load( const char* pszFileName ); +} Settings_t; + +extern Settings_t Settings; + +// search.cpp +void ShowSearchDialog( void ); +void ShowSearchWindow( void ); +bool HasOneHitSig( qSigVector& vecSig ); +int GetOccurenceCount( const qstring& strSig, bool bSkipOut ); +void SearchForSigs( const qstring& strSig ); +void ShowSearchDialog( const char* pszSignature, const char* pszMask ); + +// generate.cpp +void CreateSig( SigType eType ); +void GenerateSig( SigType eType ); +bool AutoGenerate( qSigVector& vecSig, ea_t dwAddress ); +bool AddOneInstructionToSig( qstring& strSig, ea_t& dwCurentAddress ); +void AddInsToSig( insn_t *cmd, qstring& strSig ); +bool MatchOperands( insn_t *cmd, unsigned int uiOperand, unsigned int uiSize ); +unsigned int getCurrentOpcodeSize( insn_t *cmd, unsigned int& uiCount ); +void AddBytesToSig( qstring& strSig, ea_t dwAddress, ea_t dwSize ); +void AddWhiteSpacesToSig( qstring& strSig, ea_t dwSize ); + +// converter.cpp +void IDAToCode( const qstring& strSig, qstring& pszByteSig, char* pszMask ); +void CodeToIDA( qstring& strSig, const qstring& strByteSig, const qstring& strMask ); +void IDAToCRC( const qstring& strSig, ea_t& dwCRC32, ea_t& dwMask ); +void CodeToCRC( const qstring& strByteSig, const qstring& strMask, ea_t& dwCRC32, ea_t& dwMask ); +void CodeToIDAC( qstring& strSig, const char* strByteSig, const char* strMask ); +void ShowSigConverter( void ); + +// platform.cpp +bool TextToClipboard( const char* pszText ); diff --git a/SigMaker/Platform.cpp b/SigMaker/Platform.cpp new file mode 100644 index 0000000..39368a0 --- /dev/null +++ b/SigMaker/Platform.cpp @@ -0,0 +1,54 @@ +// this file shall be used to implement platform dependant features + +// NT Platform +#define __NT__ + +#ifdef __NT__ +#include + +#pragma comment(lib, "Kernel32.lib") +#pragma comment(lib, "ida.lib") +#pragma comment(lib, "pro.lib") + +bool TextToClipboard( const char* pszText ) +{ + bool bResult = false; + + if (OpenClipboard( NULL )) + { + if (EmptyClipboard( )) + { + size_t iDataSize = (strlen( pszText ) + 1); + if (iDataSize > 1) + { + HGLOBAL hTextMem = GlobalAlloc( GMEM_MOVEABLE, iDataSize ); + if (hTextMem) + { + char* pTextMem = (char*)GlobalLock( hTextMem ); + if (pTextMem) + { + memcpy( pTextMem, pszText, iDataSize ); + GlobalUnlock( hTextMem ); + bResult = (SetClipboardData( CF_TEXT, hTextMem ) != NULL); + } + } + } + } + // no freeing needed windows now owns our memory + CloseClipboard( ); + } + + return bResult; +} + +int __stdcall DllMain( HMODULE hModule, DWORD dwReason, LPVOID lpReserved ) +{ + return 1; +} + +#else +bool TextToClipboard( const char* pszText ) +{ + return false; // got a mac or linux? +} +#endif // __NT__*/ \ No newline at end of file diff --git a/SigMaker/Search.cpp b/SigMaker/Search.cpp new file mode 100644 index 0000000..83ffc60 --- /dev/null +++ b/SigMaker/Search.cpp @@ -0,0 +1,203 @@ +#include "Misc.h" + +bool HasOneHitSig( qSigVector& vecSig ) +{ + for (qSigVector::iterator i = vecSig.begin( ); i != vecSig.end( ); i++) + if ((*i).iHitCount == 1) + return true; + + return false; +} + +int GetOccurenceCount( const qstring& strSig, bool bSkipOut = false ) +{ + int iCount = 0; + ea_t dwAddress = find_binary( inf.min_ea, inf.max_ea, strSig.c_str( ), 16, SEARCH_DOWN ); + + if (IsValidEA( dwAddress )) + { + do + { + if (bSkipOut == true && iCount >= 2) + return iCount; + + iCount++; + dwAddress = find_binary( dwAddress + 1, inf.max_ea, strSig.c_str( ), 16, SEARCH_DOWN ); + } while (IsValidEA( dwAddress )); + } + else + { + dwAddress = find_binary( inf.omin_ea, inf.omax_ea, strSig.c_str( ), 16, SEARCH_DOWN ); + if (IsValidEA( dwAddress )) + { + do + { + if (bSkipOut == true && iCount >= 2) + return iCount; + iCount++; + dwAddress = find_binary( dwAddress + 1, inf.omax_ea, strSig.c_str( ), 16, SEARCH_DOWN ); + } while (IsValidEA( dwAddress )); + } + } + + return iCount; +} + +void SearchForSigs( const qstring& strSig ) +{ + ea_t dwAddress = find_binary( inf.min_ea, inf.max_ea, strSig.c_str( ), 16, SEARCH_DOWN ); + + const char* pszMessage = "===========================\n"; + + msg( pszMessage ); + + if (IsValidEA( dwAddress )) + { + do + { + msg( "sig found at %x\n", dwAddress ); + dwAddress = find_binary( dwAddress + 1, inf.max_ea, strSig.c_str( ), 16, SEARCH_DOWN ); + } while (IsValidEA( dwAddress )); + } + else + { + dwAddress = find_binary( inf.omin_ea, inf.omax_ea, strSig.c_str( ), 16, SEARCH_DOWN ); + + if (IsValidEA( dwAddress )) + { + do + { + msg( "sig found at %x\n", dwAddress ); + dwAddress = find_binary( dwAddress + 1, inf.omax_ea, strSig.c_str( ), 16, SEARCH_DOWN ); + } while (IsValidEA( dwAddress )); + } + } + msg( pszMessage ); +} + +void ShowSearchDialog( const char* pszSignature, const char* pszMask ) +{ + static const char szForm[] = + "Test Sig\n" + "\n" + "\n" + " \n" + " \n" + "\n"; + + char szSignature[MAXSTR] = { 0 }, szMask[MAXSTR] = { 0 }; + qstring strSig = ""; + + if (pszSignature) + qstrncpy( szSignature, pszSignature, sizeof( szSignature ) ); + + if (pszMask) + qstrncpy( szMask, pszMask, sizeof( szMask ) ); + + if (ask_form( szForm, szSignature, szMask ) > 0) + { + show_wait_box( "please wait..." ); + + //msg( "%s %s\n", szSignature, szMask ); + + CodeToIDAC( strSig, szSignature, szMask ); + + if (Settings.iLogLevel >= 3) + msg( "%s = %s %s\n", strSig.c_str( ), szSignature, szMask ); + + SearchForSigs( strSig ); //*/ + + hide_wait_box( ); + } +} + +void ShowSearchDialog( void ) +{ + char szSignature[MAXSTR] = { 0 }, szMask[MAXSTR] = { 0 }; + + qstring strSig, strSigCode; + ea_t dwStart, dwEnd; + + if (read_range_selection( get_current_viewer( ), &dwStart, &dwEnd )) + { + if (dwEnd - dwStart > 5) + { + insn_t cmd; + + func_item_iterator_t fIterator; + bool isWithinRange = fIterator.set_range( dwStart, dwEnd ); + + for (ea_t dwCurrentInstruction = fIterator.current( ); + decode_insn( &cmd, dwCurrentInstruction ) != 0; + dwCurrentInstruction = fIterator.current( )) + { + if (cmd.size < 5) + AddBytesToSig( strSig, dwCurrentInstruction, cmd.size ); + else + AddInsToSig( &cmd, strSig ); + + if (fIterator.next_not_tail( ) == false) + break; + } + } + } + + if (strSig.length( ) < 3) + return; + + IDAToCode( strSig, strSigCode, szMask ); + + qstrncpy( szSignature, strSigCode.c_str( ), sizeof( szSignature ) ); + + ShowSearchDialog( szSignature, szMask ); +} + +void ShowSearchWindow( void ) +{ + static const char szForm[] = + "Test Sig\n" + "\n" + "\n" + " \n" + "\n"; + + qstring strSig; + ea_t dwStart, dwEnd; + + if (read_range_selection( get_current_viewer( ), &dwStart, &dwEnd )) + { + if (dwEnd - dwStart > 5) + { + insn_t cmd; + + func_item_iterator_t fIterator; + bool isWithinRange = fIterator.set_range( dwStart, dwEnd ); + + for (ea_t dwCurrentInstruction = fIterator.current( ); + decode_insn( &cmd, dwCurrentInstruction ) != 0; + dwCurrentInstruction = fIterator.current( )) + { + if (cmd.size < 5) + AddBytesToSig( strSig, dwCurrentInstruction, cmd.size ); + else + AddInsToSig( &cmd, strSig ); + + if (fIterator.next_not_tail( ) == false) + break; + } + } + } + + char szSignature[MAXSTR] = { 0 }; + + if (strSig.length( ) > 3) + qstrncpy( szSignature, strSig.c_str( ), sizeof( szSignature ) ); + + if (ask_form( szForm, szSignature ) > 0) + { + show_wait_box( "please wait..." ); + qstring strSig = szSignature; + SearchForSigs( strSig ); + hide_wait_box( ); + } +} \ No newline at end of file diff --git a/SigMaker/SigMaker.vcxproj b/SigMaker/SigMaker.vcxproj new file mode 100644 index 0000000..bde6bf9 --- /dev/null +++ b/SigMaker/SigMaker.vcxproj @@ -0,0 +1,391 @@ + + + + + Debug64 + Win32 + + + Debug64 + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release64 + Win32 + + + Release64 + x64 + + + Release + Win32 + + + Release + x64 + + + + {60916877-60AB-4565-93BC-2D6097976D86} + Win32Proj + SigMaker + 10.0.16299.0 + + + + DynamicLibrary + true + Unicode + v141 + + + DynamicLibrary + true + Unicode + v141 + + + DynamicLibrary + true + Unicode + v141 + + + DynamicLibrary + true + Unicode + v141 + + + DynamicLibrary + false + true + Unicode + v141 + + + DynamicLibrary + false + true + Unicode + v141 + + + DynamicLibrary + false + true + Unicode + v141 + + + DynamicLibrary + false + true + Unicode + v141 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + true + $(ProjectName)64 + + + false + false + false + + + false + false + false + + + false + false + false + + + false + false + false + $(ProjectName)64 + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;SIGMAKER_EXPORTS;%(PreprocessorDefinitions) + $(IDADIR)\idasdk\include;%(AdditionalIncludeDirectories) + + + Windows + true + C:\Program Files (x86)\IDA\plugins\SigMaker_IDA.plw + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;SIGMAKER_EXPORTS;%(PreprocessorDefinitions) + $(IDADIR)\idasdk\include;%(AdditionalIncludeDirectories) + + + Windows + true + C:\Program Files (x86)\IDA\plugins\SigMaker_IDA.plw + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;SIGMAKER_EXPORTS;%(PreprocessorDefinitions) + $(IDADIR)\idasdk\include;%(AdditionalIncludeDirectories) + + + Windows + true + $(IDADIR)\plugins\sigmaker.dll + $(IDADIR)\idasdk\lib\x64_win_vc_32;%(AdditionalLibraryDirectories) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;__X64__;__EA64__;SIGMAKER_EXPORTS;%(PreprocessorDefinitions) + $(IDADIR)\idasdk\include;%(AdditionalIncludeDirectories) + + + Windows + true + $(IDADIR)\plugins\sigmaker64.dll + $(IDADIR)\idasdk\lib\x64_win_vc_64;%(AdditionalLibraryDirectories) + + + + + Level3 + + + Full + false + false + WIN32;NDEBUG;_WINDOWS;_USRDLL;SIGMAKER_EXPORTS;%(PreprocessorDefinitions) + Size + false + MultiThreaded + true + false + AnySuitable + false + false + + + Console + false + true + true + C:\Program Files (x86)\IDA\plugins\SigMaker_IDA.plw + + + false + false + ida.lib;pro.lib;%(AdditionalDependencies) + /EXPORT:PLUGIN %(AdditionalOptions) + false + true + false + + + false + + + + + Level3 + + + Full + false + false + WIN32;NDEBUG;_WINDOWS;_USRDLL;SIGMAKER_EXPORTS;%(PreprocessorDefinitions) + Size + false + MultiThreaded + true + false + AnySuitable + false + false + + + Console + false + true + true + C:\Program Files (x86)\IDA\plugins\SigMaker_IDA.plw + + + false + false + ida.lib;pro.lib;%(AdditionalDependencies) + /EXPORT:PLUGIN %(AdditionalOptions) + false + true + false + + + false + + + + + Level3 + + + Full + false + false + WIN32;NDEBUG;_WINDOWS;_USRDLL;SIGMAKER_EXPORTS;%(PreprocessorDefinitions) + Size + false + MultiThreaded + true + Sync + AnySuitable + false + false + $(IDADIR)\idasdk\include;%(AdditionalIncludeDirectories) + + + Console + false + true + true + $(IDADIR)\plugins\sigmaker.dll + + + false + false + ida.lib;pro.lib;%(AdditionalDependencies) + /EXPORT:PLUGIN %(AdditionalOptions) + false + true + false + $(IDADIR)\idasdk\lib\x64_win_vc_64;%(AdditionalLibraryDirectories) + + + false + + + + + Level3 + + + Full + false + false + WIN32;NDEBUG;_WINDOWS;_USRDLL;__X64__;__EA64__;SIGMAKER_EXPORTS;%(PreprocessorDefinitions) + Size + false + MultiThreaded + true + Sync + AnySuitable + false + false + $(IDADIR)\idasdk\include;%(AdditionalIncludeDirectories) + + + Console + false + true + true + $(IDADIR)\plugins\sigmaker64.dll + + + false + false + ida.lib;pro.lib;%(AdditionalDependencies) + /EXPORT:PLUGIN %(AdditionalOptions) + false + true + false + $(IDADIR)\idasdk\lib\x64_win_vc_64;%(AdditionalLibraryDirectories) + + + false + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SigMaker/SigMaker.vcxproj.filters b/SigMaker/SigMaker.vcxproj.filters new file mode 100644 index 0000000..604b010 --- /dev/null +++ b/SigMaker/SigMaker.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Resource Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file