├── LoadMap ├── LoadMap.plw ├── LoadMap.vcxproj.user ├── stdafx.cpp ├── ReadMe.txt ├── LoadMap.lnt ├── LoadMap.sln ├── LoadMap.vcxproj.filters ├── stdafx.h ├── LoadMap.vcxproj └── LoadMap.cpp ├── idb2sig ├── idb2sig.plw ├── idb2sig.vcxproj.user ├── stdafx.cpp ├── idb2sig.lnt ├── stdafx.h ├── idb2sig.sln ├── idb2sig.vcxproj.filters ├── idb2sig.h ├── ReadMe.txt ├── idb2sig.vcxproj └── idb2sig.cpp └── README.md /LoadMap/LoadMap.plw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihilus/Fast_IDB2Sig_and_LoadMap_IDA_plugins/HEAD/LoadMap/LoadMap.plw -------------------------------------------------------------------------------- /idb2sig/idb2sig.plw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihilus/Fast_IDB2Sig_and_LoadMap_IDA_plugins/HEAD/idb2sig/idb2sig.plw -------------------------------------------------------------------------------- /LoadMap/LoadMap.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /idb2sig/idb2sig.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /LoadMap/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // LoadMap.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /idb2sig/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // idb2sig.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /LoadMap/ReadMe.txt: -------------------------------------------------------------------------------- 1 | LoadMap: An IDA plugin, which loads a VC/Borland/Dede map file into IDA 4.5 2 | Written by TQN - truong_quoc_ngan@yahoo.com 3 | Base on the idea of loadmap plugin of Toshiyuki Tega 4 | Ver: 1.0 - 09/11/2004 - Initial release 5 | 6 | a) Copy the LoadMap.plw and LoadMap.ini into IDA's plugins directory. 7 | b) Press Shift key when click the plugin in Edit/Plugins menu of IDA will show 8 | the Options dialog. All options will be saved to INI file and will be reloaded 9 | when plugin loaded. Take sometime to play with them. 10 | c) Default shortcut key is: Ctrl-M 11 | -------------------------------------------------------------------------------- /idb2sig/idb2sig.lnt: -------------------------------------------------------------------------------- 1 | /* -dConfiguration= ... none provided */ 2 | -D_WINDLL // 15: ConfigurationType = "2" 3 | -D_MBCS // 18: CharacterSet = "2" 4 | -i..\..\include // 22: AdditionalIncludeDirectories = "..\..\include" 5 | -DNDEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL 6 | // 23: PreprocessorDefinitions = "_DEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL" 7 | -D_MT;NDEBUG;_DLL // 25: RuntimeLibrary = "3" 8 | idb2sig.cpp // 157: RelativePath = "idb2sig.cpp" 9 | -------------------------------------------------------------------------------- /LoadMap/LoadMap.lnt: -------------------------------------------------------------------------------- 1 | /* -dConfiguration= ... none provided */ 2 | -D_WINDLL // 21: ConfigurationType = "2" 3 | -D_MBCS // 22: CharacterSet = "2" 4 | -i..\..\include // 26: AdditionalIncludeDirectories = "..\..\include" 5 | -DWIN32;NDEBUG;__NT__;__IDP__;MAXSTR=1024;_WINDOWS;_USRDLL;LOADMAP_EXPORTS 6 | // 27: PreprocessorDefinitions = "WIN32;NDEBUG;__NT__;__IDP__;MAXSTR=1024;_WINDOWS;_USRDLL;LOADMAP_EXPORTS" 7 | -DNDEBUG // 30: RuntimeLibrary = "5" 8 | .\LoadMap.cpp // 125: RelativePath = ".\LoadMap.cpp" 9 | .\stdafx.cpp // 128: RelativePath = ".\stdafx.cpp" 10 | -------------------------------------------------------------------------------- /idb2sig/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 9 | 10 | // Windows Header Files: 11 | #include 12 | 13 | // CRTL Debugging support header file 14 | #include 15 | 16 | // Shell Lightweight API Header File 17 | #include 18 | #pragma comment(lib, "shlwapi.lib") 19 | 20 | // IDA SDK Header Files 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | // STL Header Files 30 | #pragma warning(disable: 4702) 31 | 32 | #include 33 | #include 34 | -------------------------------------------------------------------------------- /LoadMap/LoadMap.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 11.00 2 | # Visual Studio 2010 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LoadMap", "LoadMap.vcxproj", "{7C447846-1C43-4270-8A0E-DCE3C8EB183D}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Win32 = Debug|Win32 8 | Release|Win32 = Release|Win32 9 | EndGlobalSection 10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 11 | {7C447846-1C43-4270-8A0E-DCE3C8EB183D}.Debug|Win32.ActiveCfg = Debug|Win32 12 | {7C447846-1C43-4270-8A0E-DCE3C8EB183D}.Debug|Win32.Build.0 = Debug|Win32 13 | {7C447846-1C43-4270-8A0E-DCE3C8EB183D}.Release|Win32.ActiveCfg = Release|Win32 14 | {7C447846-1C43-4270-8A0E-DCE3C8EB183D}.Release|Win32.Build.0 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /idb2sig/idb2sig.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 11.00 2 | # Visual Studio 2010 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "idb2sig", "idb2sig.vcxproj", "{7C447846-1C43-4270-8A0E-DCE3C8EB183D}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Win32 = Debug|Win32 8 | Release|Win32 = Release|Win32 9 | EndGlobalSection 10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 11 | {7C447846-1C43-4270-8A0E-DCE3C8EB183D}.Debug|Win32.ActiveCfg = Debug|Win32 12 | {7C447846-1C43-4270-8A0E-DCE3C8EB183D}.Debug|Win32.Build.0 = Debug|Win32 13 | {7C447846-1C43-4270-8A0E-DCE3C8EB183D}.Release|Win32.ActiveCfg = Release|Win32 14 | {7C447846-1C43-4270-8A0E-DCE3C8EB183D}.Release|Win32.Build.0 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /LoadMap/LoadMap.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | Source Files 19 | 20 | 21 | 22 | 23 | Header Files 24 | 25 | 26 | -------------------------------------------------------------------------------- /LoadMap/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 9 | #include 10 | 11 | // C RTL Debug Support Header Files 12 | #include 13 | 14 | // Shell Lightweight API 15 | #include 16 | #pragma comment(lib, "shlwapi.lib") 17 | 18 | // IDA SDK Header Files 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef _DEBUG 28 | #define _VERIFY(x) _ASSERTE(x) 29 | 30 | #define WIN32CHECK(x) { \ 31 | DWORD __dwErr__ = GetLastError(); \ 32 | _ASSERTE(x); \ 33 | SetLastError(__dwErr__); \ 34 | }; 35 | #else 36 | #define _VERIFY(x) (x) 37 | #define WIN32CHECK(x) (x) 38 | #endif 39 | 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Fast_IDB2Sig_and_LoadMap_IDA_plugins 2 | ==================================== 3 | http://www.woodmann.com/collaborative/tools/index.php/Fast_IDB2Sig_and_LoadMap_IDA_plugins 4 | 5 | It took me two weeks to write two IDA plugins, a renew, fast IDB2Sig plugin and a new, very fast LoadMap plugin. 6 | The IDB2SIG plugin I rewrote base on the orginal source code and idea of: 7 | - Quine (quine@blacksun.res.cmu.edu) 8 | - Darko 9 | - IDB2PAT of J.C. Roberts 10 | Thanks all of you very much. I think all of you will allow me to public the new source code. 11 | The LoadMap plugin I wrote base on the idea of Toshiyuki Tega. It will supports loading and parsing VC++, Borland (Delphi/BC++/CBuilder) and DeDe map files. 12 | And with two plugins, I need only two days to create two signature file for Delphi 6/7. Very fast and convenience. Hereafter, we can use two above plugins to create signature files, load map symbols... 13 | 14 | Source is included, and plugins are precompiled for IDA 4.5 and 5.2. 15 | 16 | ---- UPDATED by Swine 17 | 06.10.2011 Fixed behavior for 64-bit disassemblies 18 | -------------------------------------------------------------------------------- /idb2sig/idb2sig.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | Source Files 19 | 20 | 21 | 22 | 23 | Header Files 24 | 25 | 26 | Header Files 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /idb2sig/idb2sig.h: -------------------------------------------------------------------------------- 1 | #ifndef __IDB2SIG_H__ 2 | #define __IDB2SIG_H__ 3 | 4 | #pragma once 5 | 6 | #define DOT 0x2E 7 | #define SPACE 0x20 8 | #define ONE_MB (1024 * 1024) 9 | 10 | #define countof(x) (sizeof(x) / sizeof((x)[0])) 11 | 12 | #define DEF_REVERSE_SIZE 10 13 | #define DEF_MIN_FUNC_LENGTH 6 14 | 15 | #ifdef _DEBUG 16 | #define _VERIFY(x) _ASSERTE(x) 17 | #else 18 | #define _VERIFY(x) (x) 19 | #endif 20 | 21 | typedef enum tagFUNCTION_MODE { 22 | FUNCTION_MODE_MIN = 0, 23 | NON_AUTO_FUNCTIONS = FUNCTION_MODE_MIN, // non auto-generated functions 24 | LIBRARY_FUNCTIONS, // library functions 25 | PUBLIC_FUNCTIONS, // public functions 26 | ENTRY_POINT_FUNCTIONS, // entry point function 27 | ALL_FUNCTIONS, // all functions 28 | USER_SELECT_FUNCTION, // any current or user selects function 29 | FUNCTION_MODE_MAX = USER_SELECT_FUNCTION 30 | } FUNCTION_MODE; 31 | 32 | struct PLUGIN_OPTIONS 33 | { 34 | FUNCTION_MODE funcMode; 35 | bool bPatAppend; 36 | bool bConfirm; 37 | ulong ulMinFuncLen; 38 | ulong ulReverseSize; 39 | 40 | PLUGIN_OPTIONS() 41 | { 42 | funcMode = FUNCTION_MODE_MIN; 43 | bPatAppend = false; 44 | bConfirm = true; 45 | ulMinFuncLen = NON_AUTO_FUNCTIONS; 46 | ulReverseSize = DEF_REVERSE_SIZE; 47 | } 48 | }; 49 | 50 | #endif // __IDB2SIG_H__ 51 | -------------------------------------------------------------------------------- /idb2sig/ReadMe.txt: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | IDB2SIG plugin 3 | Rewrite and add some abilyties by TQN (truong_quoc_ngan@yahoo.com) 4 | Reuse some code from IDB2PAT of J.C. Roberts 5 | 6 | Original written by Quine (quine@blacksun.res.cmu.edu) and Darko 7 | Visit Quine's IDA Page at http://surf.to/quine_ida 8 | 9 | Contribute to ExeTools and Woodmann forum and community 10 | ************************************************************************** 11 | Revision History : 12 | Version Author Date Description 13 | V1.0 Quine ?????????? creation. 14 | V1.1 Darko 04.10.2002 modification for IDA Pro v4.3 and SDK 4.3. 15 | V1.2 Darko 05.10.2002 pat file opened in appending mode. 16 | V1.3 Darko 21.12.2002 bug fix for reference bad address. 17 | V1.4 TQN 30.08.2004 bug fix for reference bad address. 18 | some code optimize. 19 | add options dialog. 20 | add save and restore options to and from INI file. 21 | Compile for IDA Pro v4.5. 22 | *************************************************************************/ 23 | 24 | DEFAULT idb2sig.plw IN THIS PACKAGE IS FOR IDA 4.5! 25 | If you want to use it with some other version of IDA you have to recompile it. 26 | 27 | a) Copy idb2sig.plw and idb2sig.ini into IDA's plugin directory. 28 | b) Press Shift key when click the plugin in Edit/Plugins menu of IDA will show 29 | the Options dialog. All options will be saved to INI file and will be reloaded 30 | when plugin loaded. All options have mouse hint. Take sometime to play with them. 31 | c) Default shortcut key is: Ctrl-F7 32 | -------------------------------------------------------------------------------- /idb2sig/idb2sig.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {7C447846-1C43-4270-8A0E-DCE3C8EB183D} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Win32Proj 24 | 25 | 26 | 27 | DynamicLibrary 28 | MultiByte 29 | true 30 | 31 | 32 | DynamicLibrary 33 | MultiByte 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | <_ProjectFileVersion>10.0.40219.1 47 | Debug\ 48 | Debug\ 49 | true 50 | Release\ 51 | Release\ 52 | AllRules.ruleset 53 | 54 | 55 | AllRules.ruleset 56 | 57 | 58 | 59 | 60 | 61 | Disabled 62 | ..\..\..\include;%(AdditionalIncludeDirectories) 63 | USE_DANGEROUS_FUNCTIONS;_CRT_SECURE_NO_DEPRECATE;WIN32;_DEBUG;__NT__;__IDP__;MAXSTR=1024;_WINDOWS;_USRDLL;IDB2SIG_EXPORTS;%(PreprocessorDefinitions) 64 | true 65 | EnableFastChecks 66 | MultiThreadedDebug 67 | Use 68 | Level4 69 | EditAndContinue 70 | StdCall 71 | 72 | 73 | /export:PLUGIN %(AdditionalOptions) 74 | ida.lib;%(AdditionalDependencies) 75 | idb2sig.plw 76 | ..\..\..\lib\x86_win_vc_32;%(AdditionalLibraryDirectories) 77 | true 78 | $(OutDir)idb2sig.pdb 79 | 80 | 81 | 82 | 83 | Size 84 | true 85 | ..\..\..\include;%(AdditionalIncludeDirectories) 86 | USE_DANGEROUS_FUNCTIONS;_CRT_SECURE_NO_DEPRECATE;WIN32;NDEBUG;_WINDOWS;_USRDLL;__NT__;__IDP__;MAXSTR=1024;IDB2SIG_EXPORTS;%(PreprocessorDefinitions) 87 | Use 88 | Level4 89 | StdCall 90 | 91 | 92 | /export:PLUGIN %(AdditionalOptions) 93 | ida.lib;%(AdditionalDependencies) 94 | idb2sig.plw 95 | ..\..\..\lib\x86_win_vc_32;%(AdditionalLibraryDirectories) 96 | true 97 | true 98 | 99 | 100 | 101 | 102 | 103 | Create 104 | Create 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /LoadMap/LoadMap.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {7C447846-1C43-4270-8A0E-DCE3C8EB183D} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Win32Proj 24 | 25 | 26 | 27 | DynamicLibrary 28 | MultiByte 29 | true 30 | 31 | 32 | DynamicLibrary 33 | MultiByte 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | <_ProjectFileVersion>10.0.40219.1 47 | Debug\ 48 | Debug\ 49 | true 50 | Release\ 51 | Release\ 52 | AllRules.ruleset 53 | 54 | 55 | AllRules.ruleset 56 | 57 | 58 | 59 | 60 | 61 | Disabled 62 | ..\..\..\include;%(AdditionalIncludeDirectories) 63 | USE_DANGEROUS_FUNCTIONS;_CRT_SECURE_NO_DEPRECATE;WIN32;_DEBUG;__NT__;__IDP__;MAXSTR=1024;_WINDOWS;_USRDLL;LOADMAP_EXPORTS;%(PreprocessorDefinitions) 64 | true 65 | EnableFastChecks 66 | MultiThreadedDebug 67 | Use 68 | Level4 69 | EditAndContinue 70 | StdCall 71 | 72 | 73 | /export:PLUGIN %(AdditionalOptions) 74 | ida.lib;%(AdditionalDependencies) 75 | LoadMap.plw 76 | ..\..\..\lib\x86_win_vc_32;%(AdditionalLibraryDirectories) 77 | true 78 | $(OutDir)LoadMap.pdb 79 | 80 | 81 | 82 | 83 | AnySuitable 84 | Size 85 | true 86 | ..\..\..\include;%(AdditionalIncludeDirectories) 87 | USE_DANGEROUS_FUNCTIONS;_CRT_SECURE_NO_DEPRECATE;WIN32;NDEBUG;_WINDOWS;_USRDLL;__NT__;__IDP__;MAXSTR=1024;LOADMAP_EXPORTS;%(PreprocessorDefinitions) 88 | false 89 | Use 90 | Level4 91 | StdCall 92 | 93 | 94 | /export:PLUGIN %(AdditionalOptions) 95 | ida.lib;%(AdditionalDependencies) 96 | LoadMap.plw 97 | ..\..\..\lib\x86_win_vc_32;%(AdditionalLibraryDirectories) 98 | true 99 | true 100 | 101 | 102 | 103 | 104 | 105 | Create 106 | Create 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /LoadMap/LoadMap.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * @file LoadMap.cpp 4 | * The main implementation file 5 | * @author TQN (truong_quoc_ngan@yahoo.com) 6 | * @date 09/11/2004 7 | * An IDA plugin, which loads a VC/Borland/Dede map file into IDA 4.5 8 | * Base on the idea of loadmap plugin of Toshiyuki Tega 9 | * Ver: 1.0 - 09/11/2004 - Initial release 10 | */ 11 | //////////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "stdafx.h" 14 | 15 | typedef struct _tagPLUGIN_OPTIONS { 16 | bool bNameApply; // true - apply to name, false - apply to comment 17 | bool bReplace; // replace the existing name or comment 18 | bool bVerbose; // show detail messages 19 | } PLUGIN_OPTIONS; 20 | 21 | typedef enum _tagMAP_OPEN_ERROR { 22 | OPEN_NO_ERROR = 0, 23 | WIN32_ERROR, 24 | FILE_EMPTY_ERROR, 25 | FILE_BINARY_ERROR 26 | } MAP_OPEN_ERROR; 27 | 28 | // This is where the symbol table starts, do not edit. 29 | const char VC_HDR_START[] = "Address Publics by Value Rva+Base Lib:Object"; 30 | const char BL_HDR_NAME_START[] = "Address Publics by Name"; 31 | const char BL_HDR_VALUE_START[] = "Address Publics by Value"; 32 | 33 | const size_t g_minLineLen = 14; // For a "xxxx:xxxxxxxx " line 34 | 35 | static HINSTANCE g_hinstPlugin = NULL; 36 | static char g_szIniPath[MAX_PATH] = { 0 }; 37 | 38 | /* Global variable for options of plugin */ 39 | static PLUGIN_OPTIONS g_options = { 0 }; 40 | 41 | /* Ini Section and Key names */ 42 | static char g_szLoadMapSection[] = "LoadMap"; 43 | static char g_szOptionsKey[] = "Options"; 44 | 45 | //////////////////////////////////////////////////////////////////////////////// 46 | /// global inline static SkipSpaces 47 | /// @brief Seek to non space character at the beginning of a memory buffer 48 | /// @param lpStart LPSTR Pointer to start of buffer 49 | /// @param lpEnd LPSTR Pointer to end of buffer 50 | /// @return LPSTR Pointer to first non space character at the beginning of buffer 51 | /// @author TQN 52 | /// @date 09/11/2004 53 | //////////////////////////////////////////////////////////////////////////////// 54 | static inline LPSTR SkipSpaces(LPCSTR pStart, LPCSTR pEnd) 55 | { 56 | _ASSERTE(pStart != NULL); 57 | _ASSERTE(pEnd != NULL); 58 | _ASSERTE(pStart <= pEnd); 59 | 60 | LPCSTR p = pStart; 61 | while ((p < pEnd) && isspace(*p)) 62 | { 63 | p++; 64 | } 65 | 66 | return (LPSTR) p; 67 | } 68 | 69 | //////////////////////////////////////////////////////////////////////////////// 70 | /// global inline static FindEOLChar 71 | /// @brief Find the EOL character '\r' or '\n' in a memory buffer 72 | /// @param lpStart LPSTR Pointer to start of buffer 73 | /// @param lpEnd LPSTR Pointer to end of buffer 74 | /// @return LPSTR Pointer to first EOL character in the buffer 75 | /// @author TQN 76 | /// @date 09/12/2004 77 | //////////////////////////////////////////////////////////////////////////////// 78 | static inline LPSTR FindEOL(LPCSTR pStart, LPCSTR pEnd) 79 | { 80 | _ASSERTE(pStart != NULL); 81 | _ASSERTE(pEnd != NULL); 82 | _ASSERTE(pStart <= pEnd); 83 | 84 | LPCSTR p = pStart; 85 | while ((p < pEnd) && ('\r' != *p) && ('\n' != *p)) 86 | { 87 | p++; 88 | } 89 | 90 | return (LPSTR) p; 91 | } 92 | 93 | //////////////////////////////////////////////////////////////////////////////// 94 | /// global static ShowMsg 95 | /// @brief Output a formatted string to messages window [analog of printf()] 96 | /// only when the verbose flag of plugin's options is true 97 | /// @param format const char * printf() style message string. 98 | /// @return void 99 | /// @author TQN 100 | /// @date 09/11/2004 101 | //////////////////////////////////////////////////////////////////////////////// 102 | static void ShowMsg(const char *format, ...) 103 | { 104 | if (g_options.bVerbose) 105 | { 106 | va_list va; 107 | va_start(va, format); 108 | (void) vmsg(format, va); 109 | va_end(va); 110 | } 111 | } 112 | 113 | //////////////////////////////////////////////////////////////////////////////// 114 | /** 115 | * @brief Open a map file and map the file content to virtual memory 116 | * @param lpszFileName Path name of file to open. 117 | * @param dwSize Out variable to receive size of file. 118 | * @param lpMapAddr The pointer to memory address of mapped file 119 | * @return enum value of OPEN_FILE_ERROR 120 | * @author TQN 121 | * @date 09/12/2004 122 | */ 123 | //////////////////////////////////////////////////////////////////////////////// 124 | static MAP_OPEN_ERROR MapFileOpen(IN LPCSTR lpszFileName, 125 | OUT LPSTR &lpMapAddr, 126 | OUT DWORD &dwSize) 127 | { 128 | // Set default values for output parameters 129 | lpMapAddr = NULL; 130 | dwSize = INVALID_FILE_SIZE; 131 | 132 | // Validate all input pointer parameters 133 | _ASSERTE(NULL != lpszFileName); 134 | _ASSERTE(FALSE == IsBadStringPtr(lpszFileName, (UINT_PTR) -1)); 135 | if ((NULL == lpszFileName) || IsBadStringPtr(lpszFileName, (UINT_PTR) -1)) 136 | { 137 | SetLastError(ERROR_INVALID_PARAMETER); 138 | return WIN32_ERROR; 139 | } 140 | 141 | // Open the file 142 | HANDLE hFile = CreateFile(lpszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, 143 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 144 | if (INVALID_HANDLE_VALUE == hFile) 145 | { 146 | return WIN32_ERROR; 147 | } 148 | 149 | dwSize = GetFileSize(hFile, NULL); 150 | if ((INVALID_FILE_SIZE == dwSize) || (0 == dwSize)) 151 | { 152 | // File too large or empty 153 | WIN32CHECK(CloseHandle(hFile)); 154 | return ((0 == dwSize) ? FILE_EMPTY_ERROR : WIN32_ERROR); 155 | } 156 | 157 | HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); 158 | if (NULL == hMap) 159 | { 160 | WIN32CHECK(CloseHandle(hFile)); 161 | return WIN32_ERROR; 162 | } 163 | 164 | // Mapping creation successful, do not need file handle anymore 165 | WIN32CHECK(CloseHandle(hFile)); 166 | 167 | lpMapAddr = (LPSTR) MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, dwSize); 168 | if (NULL == lpMapAddr) 169 | { 170 | WIN32CHECK(CloseHandle(hMap)); 171 | return WIN32_ERROR; 172 | } 173 | 174 | // Map View successful, do not need the map handle anymore 175 | WIN32CHECK(CloseHandle(hMap)); 176 | 177 | if (NULL != memchr(lpMapAddr, 0, dwSize)) 178 | { 179 | // File is binary or Unicode file 180 | WIN32CHECK(UnmapViewOfFile(lpMapAddr)); 181 | lpMapAddr = NULL; 182 | return FILE_BINARY_ERROR; 183 | } 184 | 185 | return OPEN_NO_ERROR; 186 | } 187 | 188 | //////////////////////////////////////////////////////////////////////////////// 189 | /** 190 | * @brief Close memory map file which opened by MemMapFileOpen function. 191 | * @param lpAddr: Pointer to memory return by MemMapFileOpen. 192 | * @author TQN 193 | * @date 09/12/2004 194 | */ 195 | //////////////////////////////////////////////////////////////////////////////// 196 | static void MapFileClose(IN LPCVOID lpAddr) 197 | { 198 | WIN32CHECK(UnmapViewOfFile(lpAddr)); 199 | } 200 | 201 | /* The DLL entry point of plugin */ 202 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID) 203 | { 204 | if (DLL_PROCESS_ATTACH == fdwReason) 205 | { 206 | WIN32CHECK(DisableThreadLibraryCalls(g_hinstPlugin = hinstDLL)); 207 | } 208 | 209 | return TRUE; 210 | } 211 | 212 | //////////////////////////////////////////////////////////////////////////////// 213 | /// global static ShowOptionsDlg 214 | /// Show options dialog for getting user desired options 215 | /// @return void 216 | /// @author TQN 217 | /// @date 09/11/2004 218 | //////////////////////////////////////////////////////////////////////////////// 219 | static void ShowOptionsDlg(void) 220 | { 221 | // Build the format string constant used to create the dialog 222 | const char format[] = 223 | "STARTITEM 0\n" // TabStop 224 | "LoadMap Options\n" // Title 225 | "\n" // Radio Button 0 226 | ">\n" // Radio Button 1 227 | ">\n" // Checkbox Button 228 | ">\n\n"; // Checkbox Button 229 | 230 | // Create the option dialog. 231 | short name = (g_options.bNameApply ? 0 : 1); 232 | short replace = (g_options.bReplace ? 1 : 0); 233 | short verbose = (g_options.bVerbose ? 1 : 0); 234 | if (AskUsingForm_c(format, &name, &replace, &verbose)) 235 | { 236 | g_options.bNameApply = (0 == name); 237 | g_options.bReplace = (1 == replace); 238 | g_options.bVerbose = (1 == verbose); 239 | } 240 | } 241 | 242 | //////////////////////////////////////////////////////////////////////////////// 243 | /** 244 | * global static init 245 | * @brief Plugin initialize function 246 | * @return PLUGIN_KEEP always 247 | * @author TQN 248 | * @date 09/11/2004 249 | */ 250 | //////////////////////////////////////////////////////////////////////////////// 251 | static int idaapi init(void) 252 | { 253 | msg("\nLoadMap: Plugin init.\n\n"); 254 | 255 | // Get the full path of plugin 256 | WIN32CHECK(GetModuleFileName(g_hinstPlugin, g_szIniPath, sizeof(g_szIniPath))); 257 | g_szIniPath[sizeof(g_szIniPath) - 1] = '\0'; 258 | 259 | // Change the extension of plugin to '.ini' 260 | _VERIFY(PathRenameExtension(g_szIniPath, ".ini")); 261 | 262 | // Get options saved in ini file 263 | _VERIFY(GetPrivateProfileStruct(g_szLoadMapSection, g_szOptionsKey, 264 | &g_options, sizeof(g_options), g_szIniPath)); 265 | 266 | return PLUGIN_KEEP; 267 | } 268 | 269 | //////////////////////////////////////////////////////////////////////////////// 270 | /** 271 | * global static run 272 | * @brief Plugin run function 273 | * @param int Don't used 274 | * @return void 275 | * @author TQN 276 | * @date 09/11/2004 277 | */ 278 | //////////////////////////////////////////////////////////////////////////////// 279 | static void idaapi run(int /* arg */) 280 | { 281 | static char mapFileName[_MAX_PATH] = { 0 }; 282 | 283 | // If user press shift key, show options dialog 284 | if (GetAsyncKeyState(VK_SHIFT) & 0x8000) 285 | { 286 | ShowOptionsDlg(); 287 | } 288 | 289 | ulong numOfSegs = (ulong) get_segm_qty(); 290 | if (0 == numOfSegs) 291 | { 292 | warning("Not found any segments"); 293 | return; 294 | } 295 | 296 | if ('\0' == mapFileName[0]) 297 | { 298 | // First run (after all, mapFileName is static) 299 | get_input_file_path(mapFileName, sizeof(mapFileName)); 300 | WIN32CHECK(PathRenameExtension(mapFileName, ".map")); 301 | } 302 | 303 | // Show open map file dialog 304 | char *fname = askfile_c(0, mapFileName, "Open MAP file"); 305 | if (NULL == fname) 306 | { 307 | msg("LoadMap: User cancel\n"); 308 | return; 309 | } 310 | 311 | // Open the map file 312 | LPSTR pMapStart = NULL; 313 | DWORD mapSize = INVALID_FILE_SIZE; 314 | MAP_OPEN_ERROR eRet = MapFileOpen(fname, pMapStart, mapSize); 315 | switch (eRet) 316 | { 317 | case WIN32_ERROR: 318 | warning("Could not open file '%s'.\nWin32 Error Code = 0x%08X", 319 | fname, GetLastError()); 320 | return; 321 | 322 | case FILE_EMPTY_ERROR: 323 | warning("File '%s' is empty, zero size", fname); 324 | return; 325 | 326 | case FILE_BINARY_ERROR: 327 | warning("File '%s' seem to be a binary or Unicode file", fname); 328 | return; 329 | 330 | case OPEN_NO_ERROR: 331 | default: 332 | break; 333 | } 334 | 335 | bool foundHdr = false; 336 | ulong validSyms = 0; 337 | ulong invalidSyms = 0; 338 | 339 | // The mark pointer to the end of memory map file 340 | // all below code must not read or write at and over it 341 | LPSTR pMapEnd = pMapStart + mapSize; 342 | 343 | show_wait_box("Parsing and applying symbols from the Map file '%s'", fname); 344 | 345 | __try 346 | { 347 | LPSTR pLine = pMapStart; 348 | LPSTR pEOL = pMapStart; 349 | while (pLine < pMapEnd) 350 | { 351 | // Skip the spaces, '\r', '\n' characters, blank lines, seek to the 352 | // non space character at the beginning of a non blank line 353 | pLine = SkipSpaces(pEOL, pMapEnd); 354 | 355 | // Find the EOL '\r' or '\n' characters 356 | pEOL = FindEOL(pLine, pMapEnd); 357 | 358 | size_t lineLen = (size_t) (pEOL - pLine); 359 | if (lineLen < g_minLineLen) 360 | { 361 | continue; 362 | } 363 | 364 | if (!foundHdr) 365 | { 366 | if ((0 == strnicmp(pLine, VC_HDR_START , lineLen)) || 367 | (0 == strnicmp(pLine, BL_HDR_NAME_START , lineLen)) || 368 | (0 == strnicmp(pLine, BL_HDR_VALUE_START, lineLen))) 369 | { 370 | foundHdr = true; 371 | } 372 | } 373 | else 374 | { 375 | ulong seg = SREG_NUM; 376 | ulong addr = BADADDR; 377 | char name[MAXNAMELEN + 1]; 378 | char fmt[80]; 379 | 380 | name[0] = '\0'; 381 | fmt[0] = '\0'; 382 | 383 | // Get segment number, address, name, by pass spaces at beginning, 384 | // between ':' character, between address and name 385 | int ret = _snscanf(pLine, min(lineLen, MAXNAMELEN + g_minLineLen), 386 | " %04X : %08X %s", &seg, &addr, name); 387 | if (3 != ret) 388 | { 389 | // we have parsed to end of value/name symbols table or reached EOF 390 | _snprintf(fmt, sizeof(fmt), "Parsing finished at line: '%%.%ds'.\n", lineLen); 391 | ShowMsg(fmt, pLine); 392 | break; 393 | } 394 | else if ((0 == seg) || (--seg >= numOfSegs) || 395 | (BADADDR == addr) || ('\0' == name[0])) 396 | { 397 | sprintf(fmt, "Invalid map line: %%.%ds.\n", lineLen); 398 | ShowMsg(fmt, pLine); 399 | 400 | invalidSyms++; 401 | } 402 | else 403 | { 404 | // Ensure name is NULL terminated 405 | name[MAXNAMELEN] = '\0'; 406 | 407 | // Determine the DeDe map file 408 | bool bNameApply = g_options.bNameApply; 409 | char *pname = name; 410 | if (('<' == pname[0]) && ('-' == pname[1])) 411 | { 412 | // Functions indicator symbol of DeDe map 413 | pname += 2; 414 | bNameApply = true; 415 | } 416 | else if ('*' == pname[0]) 417 | { 418 | // VCL controls indicator symbol of DeDe map 419 | pname++; 420 | bNameApply = false; 421 | } 422 | else if (('-' == pname[0]) && ('>' == pname[1])) 423 | { 424 | // VCL methods indicator symbol of DeDe map 425 | pname += 2; 426 | bNameApply = false; 427 | } 428 | 429 | ulong la = addr + getnseg((int) seg)->startEA; 430 | flags_t f = getFlags(la); 431 | 432 | if (bNameApply) // Apply symbols for name 433 | { 434 | // Add name if there's no meaningful name assigned. 435 | if (g_options.bReplace || 436 | (!has_name(f) || has_dummy_name(f) || has_auto_name(f))) 437 | { 438 | if (set_name(la, pname, SN_NOWARN)) 439 | { 440 | ShowMsg("%04X:%08X - Change name to '%s' successed\n", 441 | seg, la, pname); 442 | validSyms++; 443 | } 444 | else 445 | { 446 | ShowMsg("%04X:%08X - Change name to '%s' failed\n", 447 | seg, la, pname); 448 | invalidSyms++; 449 | } 450 | } 451 | } 452 | else if (g_options.bReplace || !has_cmt(f)) 453 | { 454 | // Apply symbols for comment 455 | if (set_cmt(la, pname, false)) 456 | { 457 | ShowMsg("%04X:%08X - Change comment to '%s' successed\n", 458 | seg, la, pname); 459 | validSyms++; 460 | } 461 | else 462 | { 463 | ShowMsg("%04X:%08X - Change comment to '%s' failed\n", 464 | seg, la, pname); 465 | invalidSyms++; 466 | } 467 | } 468 | } 469 | } 470 | } 471 | } 472 | __finally 473 | { 474 | MapFileClose(pMapStart); 475 | hide_wait_box(); 476 | } 477 | 478 | if (!foundHdr) 479 | { 480 | warning("File '%s' is not a valid Map file", fname); 481 | } 482 | else 483 | { 484 | // Save file name for next askfile_c dialog 485 | strncpy(mapFileName, fname, sizeof(mapFileName)); 486 | 487 | // Show the result 488 | msg("Result of loading and parsing the Map file '%s'\n" 489 | " Number of Symbols applied: %d\n" 490 | " Number of Invalid Symbols: %d\n\n", 491 | fname, validSyms, invalidSyms); 492 | } 493 | } 494 | 495 | //////////////////////////////////////////////////////////////////////////////// 496 | /** 497 | * global static term 498 | * @brief Plugin terminate function 499 | * @return void 500 | * @author TQN 501 | * @date 09/11/2004 502 | */ 503 | //////////////////////////////////////////////////////////////////////////////// 504 | static void idaapi term(void) 505 | { 506 | msg("LoadMap: Plugin terminate.\n"); 507 | 508 | // Write the plugin's options to ini file 509 | _VERIFY(WritePrivateProfileStruct(g_szLoadMapSection, g_szOptionsKey, &g_options, 510 | sizeof(g_options), g_szIniPath)); 511 | } 512 | 513 | //-------------------------------------------------------------------------- 514 | // Plugin information. 515 | //-------------------------------------------------------------------------- 516 | static char wanted_name[] = "LoadMap - Load Symbols From Map File"; 517 | static char wanted_hotkey[] = "Ctrl-M"; 518 | static char comment[] = "LoadMap loads symbols from a VC/Borland/Dede map file."; 519 | static char help[] = "LoadMap, VC/Borland/Dede map file import plugin." 520 | "This module reads an accompanying map file,\n" 521 | "and loads symbols into IDA database."; 522 | 523 | //-------------------------------------------------------------------------- 524 | // Plugin description block. 525 | //-------------------------------------------------------------------------- 526 | extern "C" { 527 | plugin_t PLUGIN = { 528 | IDP_INTERFACE_VERSION, 529 | 0, // Plugin flags (not used). 530 | init, // Initialize. 531 | term, // Terminate (not used). 532 | run, // Main function. 533 | comment, 534 | help, 535 | wanted_name, 536 | wanted_hotkey 537 | }; 538 | } 539 | -------------------------------------------------------------------------------- /idb2sig/idb2sig.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | IDB2SIG plugin 3 | Rewrite and add some abilyties by TQN (truong_quoc_ngan@yahoo.com) 4 | Reuse some code from IDB2PAT of J.C. Roberts 5 | 6 | Original written by Quine (quine@blacksun.res.cmu.edu) and Darko 7 | Visit Quine's IDA Page at http://surf.to/quine_ida 8 | 9 | Contribute to ExeTools and Woodmann forum and community 10 | ************************************************************************** 11 | Revision History : 12 | Version Author Date Description 13 | V1.0 Quine ?????????? creation. 14 | V1.1 Darko 04.10.2002 modification for IDA Pro v4.3 and SDK 4.3. 15 | V1.2 Darko 05.10.2002 pat file opened in appending mode. 16 | V1.3 Darko 21.12.2002 bug fix for reference bad address. 17 | V1.4 TQN 30.08.2004 bug fix for reference bad address. 18 | some code optimize. 19 | add options dialog. 20 | add save and restore options to and from INI file. 21 | Compile for IDA Pro v4.5. 22 | V1.5 Swine 06.10.2011 Fixed behavior for 64-bit disassemblies 23 | Compile for IDA Pro v6.1 24 | 25 | *************************************************************************/ 26 | 27 | #include "stdafx.h" 28 | #include "idb2sig.h" 29 | 30 | using namespace std; 31 | 32 | static HINSTANCE g_hinstPlugin = NULL; 33 | static char g_szIniPath[MAX_PATH] = { 0 }; 34 | static char g_szPatFile[MAX_PATH] = { 0 }; 35 | 36 | /* Global variable for options */ 37 | static PLUGIN_OPTIONS g_options; 38 | 39 | /* Ini Section and Key names */ 40 | static char g_szIDB2SIGSection[] = "IDB2SIG"; 41 | static char g_szOptionsKey[] = "Options"; 42 | 43 | /* CRC_CCITT table and poly */ 44 | #define POLY 0x8408 45 | static uint CRC_CCITT_TABLE[256]; 46 | 47 | typedef map > ref_map; 48 | 49 | /********************************************************************** 50 | * Function: PageFaultExceptionFilter 51 | * Description: 52 | * SEH exception filter to commit pages from the reserved region. 53 | * Whenever a page fault exception occurs, this function is executed. 54 | * If it can allocate another page, the execution continues at the 55 | * point where the exception occurred. Otherwise, the exception handler 56 | * is executed. 57 | * Returns: Exception code 58 | **********************************************************************/ 59 | static int PageFaultExceptionFilter(IN DWORD dwCode, IN OUT LPSTR *lppNextPage) 60 | { 61 | LPVOID lpvResult = NULL; 62 | 63 | _ASSERTE(lppNextPage != NULL); 64 | 65 | // If the exception is not a page fault, exit. 66 | if (EXCEPTION_ACCESS_VIOLATION != dwCode) 67 | { 68 | (void) msg("IDB2SIG: Exception occurred. Exception code = 0x%08X.\n", dwCode); 69 | return EXCEPTION_EXECUTE_HANDLER; 70 | } 71 | 72 | // Otherwise, commit another 1MB of virtual memory. 73 | lpvResult = VirtualAlloc(*lppNextPage, // next page address to commit 74 | ONE_MB, 75 | MEM_COMMIT, // allocate committed pages 76 | PAGE_READWRITE); // read/write access 77 | if (NULL == lpvResult) 78 | { 79 | (void) msg("IDB2SIG: Call VirtualAlloc to commit memory failed." 80 | " Run out of reversing virtual memory." 81 | "\tPlease increase the size of reversing virtual memory.\n"); 82 | return EXCEPTION_EXECUTE_HANDLER; 83 | } 84 | 85 | // Advance pNextPage to the next reserve page. 86 | *lppNextPage += ONE_MB; 87 | 88 | // Continue execution where the page fault occurred. 89 | return EXCEPTION_CONTINUE_EXECUTION; 90 | } 91 | 92 | /********************************************************************** 93 | * Function: GetLine 94 | * Description: 95 | * Reads a line from file f, up to the size of the buffer. The line in the 96 | * buffer will NOT include line termination, although any of (CR, LF, CRLF) 97 | * is accepted on input. The return value is < 0 on error, 0 if the line 98 | * was terminated abnormally (EOF, error, or out of buffer space), and 99 | * length (of the line) if the line was terminated normally. 100 | * 101 | * Passing in a buffer less than 2 characters long is not a terribly bright 102 | * idea. 103 | * Parameters: char *szBuf 104 | * uint maxLen 105 | * FILE *fp 106 | * Returns: int - buffer length or error code if < 0 107 | **********************************************************************/ 108 | static int GetLine(char *szBuf, uint maxLen, FILE *fp) 109 | { 110 | _ASSERTE(fp != NULL); 111 | _ASSERTE(szBuf != NULL); 112 | _ASSERTE(maxLen > 0); 113 | if ((NULL == szBuf) || (NULL == fp) || (0 == maxLen)) 114 | { 115 | (void) msg("IDB2SIG - %s(%d) : Incorrect function input arguments.\n", 116 | __FILE__, __LINE__); 117 | return -1; 118 | } 119 | 120 | memset(szBuf, 0, maxLen); 121 | char *pStr = szBuf; 122 | int state = 0; 123 | for (;;) 124 | { 125 | int ch = qfgetc(fp); 126 | 127 | if ('\n' == ch) 128 | { 129 | *pStr = 0; 130 | return (int) strlen(szBuf); /* Line terminated with \n or \r\n */ 131 | } 132 | 133 | if (state != 0) 134 | { 135 | *pStr = 0; 136 | (void) qfseek(fp, -1L, SEEK_CUR); 137 | return (int) strlen(szBuf); /* Line terminated with \r */ 138 | } 139 | 140 | if (feof(fp)) 141 | { 142 | *pStr = 0; 143 | clearerr(fp); 144 | return (pStr == szBuf) ? -1 : -2; /* Error */ 145 | } 146 | 147 | if (ferror(fp)) 148 | { 149 | *pStr = 0; 150 | clearerr(fp); 151 | return -3; /* Error */ 152 | } 153 | 154 | if ('\r' == ch) 155 | { 156 | state = 1; 157 | } 158 | else 159 | { 160 | if (--maxLen > 0) 161 | { 162 | *pStr++ = (char) ch; 163 | } 164 | else 165 | { 166 | *pStr = 0; 167 | (void) qfseek(fp, -1L, SEEK_CUR); 168 | return -4; /* Out of buffer space */ 169 | } 170 | } 171 | } 172 | } /* end of getLine */ 173 | 174 | /********************************************************************** 175 | * Function: SkipBackward 176 | * Description: scrolls a number of lines backward from current position in file 177 | * IT IS A NASTY ONE!! 178 | * Parameters: FILE *fp 179 | * int numOfRows 180 | * Returns: int 181 | **********************************************************************/ 182 | static int SkipBackward(FILE *fp, int numOfRows) 183 | { 184 | int c = 0; 185 | 186 | _ASSERTE(fp != NULL); 187 | _ASSERTE(numOfRows > 0); 188 | if ((NULL == fp) || (numOfRows <= 0)) 189 | { 190 | (void) msg("IDB2SIG - %s(%d) : Incorrect function input arguments.\n", 191 | __FILE__, __LINE__); 192 | return 1; 193 | } 194 | 195 | while (numOfRows > 0) 196 | { 197 | if (qftell(fp) >= 2) 198 | { 199 | if (qfseek(fp, -2L, SEEK_CUR)) 200 | { 201 | clearerr(fp); 202 | (void) qfseek(fp, 0L, SEEK_SET); 203 | return 1; 204 | } 205 | } 206 | else 207 | { 208 | (void) qfseek(fp, 0L, SEEK_SET); 209 | } 210 | 211 | c = qfgetc(fp); 212 | 213 | if (feof(fp)) 214 | { 215 | clearerr(fp); 216 | return 1; 217 | } 218 | 219 | if ('\n' == c) 220 | { 221 | numOfRows--; 222 | } 223 | 224 | if (1 == qftell(fp)) 225 | { 226 | (void) qfseek(fp, 0L, SEEK_SET); 227 | return 0; 228 | } 229 | } 230 | 231 | return 0; 232 | } /* end of SkipBackward */ 233 | 234 | /* Init the table lookup for CRC_CCITT 16 calculation */ 235 | static void InitCRCTable(void) 236 | { 237 | for (uint i = 0; i < 256; i++) 238 | { 239 | uint crc = i; 240 | for (int j = 0; j < 8; j++) 241 | { 242 | if (crc & 1) 243 | crc = (crc >> 1) ^ POLY; 244 | else 245 | crc >>= 1; 246 | } 247 | CRC_CCITT_TABLE[i] = crc; 248 | } 249 | } 250 | 251 | /********************************************************************** 252 | * Function: crc16 253 | * Description: 254 | * crc16 is ripped straight out the c file that comes with the 255 | * FLAIR package 256 | * 16 12 5 257 | * this is the CCITT CRC 16 polynomial X + X + X + 1. 258 | * This works out to be 0x1021, but the way the algorithm works 259 | * lets us use 0x8408 (the reverse of the bit pattern). The high 260 | * bit is always assumed to be set, thus we only use 16 bits to 261 | * represent the 17 bit value. 262 | * Parameters: uchar *pdata - pointer to data 263 | * uint16 len - data length 264 | * Returns: CRC 265 | * Optimize by TQN, run faster about 12 times 266 | **********************************************************************/ 267 | static uint16 crc16(const uchar *pdata, uint16 len) 268 | { 269 | _ASSERTE(pdata != NULL); 270 | if (NULL == pdata) 271 | { 272 | (void) msg("IDB2SIG - %s(%d) : Incorrect function input arguments.\n", 273 | __FILE__, __LINE__); 274 | return 0; 275 | } 276 | 277 | if (0 == len) 278 | { 279 | return 0; 280 | } 281 | 282 | uint data; 283 | uint crc = 0xFFFF; 284 | do 285 | { 286 | data = *pdata++; 287 | crc = (crc >> 8) ^ CRC_CCITT_TABLE[(crc ^ data) & 0xFF]; 288 | } while (--len); 289 | 290 | crc = ~crc; 291 | data = crc; 292 | crc = (crc << 8) | ((data >> 8) & 0xFF); 293 | 294 | return (uint16) crc; 295 | } 296 | 297 | /********************************************************************** 298 | * Function: Num2HexStr 299 | * Description: Convert a number to a hex string 300 | * Parameters: pBuf: Pointer to buffer to store the result hex string. 301 | * The caller must ensure buffer have enough space to store 302 | * len of hex characters and a NULL character. 303 | * len: number of hex character required. The buffer will be 304 | * add 0 to the left to ensure have have len hex characters 305 | * num: number will be converted 306 | * Returns: The pointer to the next last written character to pBuf 307 | **********************************************************************/ 308 | static inline char* Num2HexStr(char *pBuf, uint len, uint num) 309 | { 310 | static const char HEXSTR[] = "0123456789ABCDEF"; 311 | 312 | _ASSERTE(pBuf != NULL); 313 | if (NULL == pBuf) 314 | { 315 | (void) msg("IDB2SIG - %s(%d) : Invalid function input arguments.\n", 316 | __FILE__, __LINE__); 317 | return pBuf; 318 | } 319 | 320 | char *p = pBuf + len; 321 | *p-- = '\0'; 322 | while (p >= pBuf) 323 | { 324 | int digit = num & 0x0F; 325 | num >>= 4; 326 | *p-- = HEXSTR[digit]; 327 | } 328 | 329 | return (pBuf + len); 330 | } 331 | 332 | /********************************************************************** 333 | * Function: find_ref_loc 334 | * Description: 335 | * this function finds the location of a reference within an instruction 336 | * or a data item 337 | * eg: 00401000 E8 FB 0F 00 00 call sub_402000 338 | * find_ref_loc(0x401000, 0x402000) would return 0x401001 339 | * it works for both segment relative and self-relative offsets 340 | * all references are assumed to be 4 bytes long 341 | * Parameters: ea_t item 342 | * ea_t _ref 343 | * Returns: ea_t 344 | *ref_len : length of reference in bytes 345 | **********************************************************************/ 346 | static ea_t find_ref_loc(ea_t item, ea_t _ref, uint *ref_len) 347 | { 348 | ea_t ref_orig = _ref; 349 | _ASSERTE(item != BADADDR); 350 | _ASSERTE(_ref != BADADDR); 351 | if ((BADADDR == item) || (BADADDR == _ref)) 352 | { 353 | (void) msg("IDB2SIG - %s(%d) : Incorrect function input arguments.\n", 354 | __FILE__, __LINE__); 355 | return BADADDR; 356 | } 357 | 358 | /* 359 | // Swine 06/10/2011: removed as more sophisticated analysis is required to manage offset displacement in a deterministic manner; 360 | // Swine 06/10/2011: cheap and effective solution is just to check for any of displaced or absolute offset 361 | 362 | if (isCode(getFlags(item))) 363 | { 364 | (void) ua_ana0(item); 365 | if (cmd.Operands[0].type == o_near) 366 | { 367 | // we have got a self-relative reference 368 | _ref = _ref - get_item_end(item); 369 | } 370 | } 371 | */ 372 | 373 | ea_t item_end = get_item_end(item); 374 | 375 | #ifdef __EA64__ 376 | for (ea_t i = item; i <= get_item_end(item) - 8; i++) 377 | { 378 | uint64 v; 379 | v = get_qword(i); 380 | if (v == _ref || v == _ref - item_end) 381 | { 382 | *ref_len = 8; 383 | return i; 384 | } 385 | } 386 | #endif 387 | 388 | 389 | for (ea_t i = item; i <= get_item_end(item) - 4; i++) 390 | { 391 | uint32 v; 392 | v = get_long(i); 393 | if (v == (uint32)_ref || (int32)(_ref - item_end) == (int64)(_ref - item_end) && v == (uint32)(_ref - item_end) ) 394 | { 395 | *ref_len = 4; 396 | return i; 397 | } 398 | } 399 | 400 | 401 | msg("WARNING: Could not find ref loc (ea=%a, ref_orig=%a, ref=%a)\n", item, ref_orig, _ref); 402 | return BADADDR; 403 | } 404 | 405 | /********************************************************************** 406 | * Function: set_v_bytes 407 | * Description: marks off a string of bytes as variable 408 | * Parameters: bool_vec& bv 409 | * int pos 410 | * int len 411 | * Returns: none 412 | **********************************************************************/ 413 | static inline void set_v_bytes(vector &bv, uint pos, uint len) 414 | { 415 | _ASSERTE(pos + len <= bv.size()); 416 | if (pos + len > bv.size()) 417 | { 418 | (void) msg("IDB2SIG - %s(%d) : Incorrect function input arguments.\n", 419 | __FILE__, __LINE__); 420 | return; 421 | } 422 | else 423 | { 424 | for (uint i = 0; i < len; i++) 425 | { 426 | bv[pos + i] = true; 427 | } 428 | } 429 | } 430 | 431 | /********************************************************************** 432 | * Function: make_func_sig 433 | * Description: 434 | * this is what does the real work 435 | * given a starting address, a length, and a FILE pointer, it 436 | * writes a pattern line to the file 437 | * Parameters: ea_t start_ea 438 | * ulong len 439 | * FILE* f 440 | * Returns: none 441 | **********************************************************************/ 442 | static size_t make_func_sig(ea_t start_ea, ulong len, char *pSigBuf) 443 | { 444 | ea_t ea, ref, ref_loc; 445 | uint ref_len; 446 | 447 | uint first_string = 0, alen = 0; 448 | uint i = 0; 449 | uchar crc_data[256] = { 0 }; 450 | uint16 crc = 0; 451 | flags_t flags = 0; 452 | char szName[MAXNAMELEN + 1] = { 0 }; 453 | const char *pName = szName; 454 | vector v_bytes(len); 455 | vector v_publics; 456 | ref_map refs; 457 | 458 | _ASSERTE(start_ea != BADADDR); 459 | if (BADADDR == start_ea) 460 | { 461 | (void) msg("IDB2SIG - %s(%d) : Incorrect function input arguments.\n", 462 | __FILE__, __LINE__); 463 | return 0; 464 | } 465 | 466 | if (len < g_options.ulMinFuncLen) 467 | { 468 | char buf[512]; 469 | get_segm_name(start_ea, buf, sizeof buf); 470 | (void) msg("%s:%08X - Function length is %d and less than %d\n", 471 | buf, start_ea, len, g_options.ulMinFuncLen); 472 | return 0; 473 | } 474 | 475 | ea = start_ea; 476 | while ((ea != BADADDR) && (ea - start_ea < len)) 477 | { 478 | flags = getFlags(ea); 479 | if (has_name(flags) || ((ALL_FUNCTIONS == g_options.funcMode) && has_any_name(flags))) 480 | { 481 | v_publics.push_back(ea); 482 | } 483 | 484 | ref = get_first_dref_from(ea); 485 | if (BADADDR != ref) 486 | { 487 | // a data location is referenced 488 | ref_loc = find_ref_loc(ea, ref, &ref_len); 489 | if (BADADDR != ref_loc) 490 | { 491 | set_v_bytes(v_bytes, (uint)(ref_loc - start_ea), ref_len); 492 | refs[ref_loc] = ref; 493 | } 494 | 495 | // check if there is a second data location ref'd 496 | ref = get_next_dref_from(ea, ref); 497 | if (BADADDR != ref) 498 | { 499 | ref_loc = find_ref_loc(ea, ref, &ref_len); 500 | if (BADADDR != ref_loc) 501 | { 502 | set_v_bytes(v_bytes, (uint)(ref_loc - start_ea), ref_len); 503 | refs[ref_loc] = ref; 504 | } 505 | } 506 | } 507 | else 508 | { 509 | // do we have a code ref? 510 | ref = get_first_fcref_from(ea); 511 | if (BADADDR != ref) 512 | { 513 | // if so, make sure it is outside of function 514 | if ((ref < start_ea) || (ref >= start_ea + len)) 515 | { 516 | ref_loc = find_ref_loc(ea, ref, &ref_len); 517 | if (BADADDR != ref_loc) 518 | { 519 | set_v_bytes(v_bytes, (uint)(ref_loc - start_ea), ref_len); 520 | refs[ref_loc] = ref; 521 | } 522 | } 523 | } 524 | } 525 | 526 | ea = next_not_tail(ea); 527 | } 528 | 529 | char *pc = pSigBuf; // The increment pointer 530 | 531 | // write out the first string of bytes, making sure not to go past 532 | // the end of the function 533 | first_string = (len < 32 ? len : 32); 534 | for (i = 0; i < first_string; i++) 535 | { 536 | if (v_bytes[i]) 537 | { 538 | *pc++ = DOT; 539 | *pc++ = DOT; 540 | } 541 | else 542 | { 543 | pc = Num2HexStr(pc, 2, get_byte(start_ea + i)); 544 | } 545 | } 546 | 547 | // fill in anything less than 32 548 | for (i = 0; i < 32 - first_string; i++) 549 | { 550 | *pc++ = DOT; 551 | *pc++ = DOT; 552 | } 553 | 554 | // put together the crc data 555 | uint pos = 32; 556 | while ((pos < len) && !v_bytes[pos] && (pos < 255 + 32)) 557 | { 558 | crc_data[pos - 32] = get_byte(start_ea + pos); 559 | pos++; 560 | } 561 | 562 | // alen is length of the crc data 563 | alen = pos - 32; 564 | crc = crc16(crc_data, (uint16) alen); 565 | 566 | // Format alen, crc and len to " %02X %04X %04X" format 567 | *pc++ = SPACE; 568 | pc = Num2HexStr(pc, 2, alen); 569 | *pc++ = SPACE; 570 | pc = Num2HexStr(pc, 4, crc); 571 | *pc++ = SPACE; 572 | pc = Num2HexStr(pc, 4, len); 573 | 574 | // write the publics 575 | for (vector::const_iterator p = v_publics.begin(); p != v_publics.end(); p++) 576 | { 577 | pName = get_true_name(BADADDR , *p, szName, sizeof(szName)); 578 | 579 | // Make sure we have a name when all functions mode specified or 580 | // it is a user-specified name (valid name & !dummy prefix) 581 | if ((NULL != pName) && (is_uname(pName) || (ALL_FUNCTIONS == g_options.funcMode))) 582 | { 583 | // Format pSigBuf with " :%04X " or " :-%04X " format 584 | // Check for negative offset and adjust output 585 | *pc++ = SPACE; 586 | *pc++ = ':'; 587 | if (*p >= start_ea) 588 | { 589 | pc = Num2HexStr(pc, 4, (uint)(*p - start_ea)); 590 | *pc++ = SPACE; 591 | } 592 | else 593 | { 594 | *pc++ = '-'; 595 | pc = Num2HexStr(pc, 4, (long)(start_ea - *p)); 596 | *pc ++ = SPACE; 597 | } 598 | 599 | while (*pName != '\0') 600 | { 601 | *pc++= *pName++; 602 | } 603 | } 604 | } 605 | 606 | // write the references 607 | for (ref_map::const_iterator r = refs.begin(); r != refs.end(); r++) 608 | { 609 | pName = get_true_name(BADADDR, (*r).second, szName, sizeof(szName)); 610 | flags = getFlags((*r).second); 611 | 612 | // Make sure we have a name when all functions mode specified or 613 | // it is a user-specified name 614 | if ((NULL != pName) && (has_user_name(flags) || (ALL_FUNCTIONS == g_options.funcMode))) 615 | { 616 | // Format pSigBuf with " ^%04X " or " ^-%04X " format 617 | // Check for negative offset and adjust output 618 | *pc++ = SPACE; 619 | *pc++ = '^'; 620 | if ((*r).first >= start_ea) 621 | { 622 | pc = Num2HexStr(pc, 4, (uint)((*r).first - start_ea)); 623 | *pc++ = SPACE; 624 | } 625 | else 626 | { 627 | *pc++ = '-'; 628 | pc = Num2HexStr(pc, 4, (uint)(start_ea - (*r).first)); 629 | *pc++ = SPACE; 630 | } 631 | 632 | while (*pName != '\0') 633 | { 634 | *pc++= *pName++; 635 | } 636 | } 637 | } 638 | 639 | // and finally write out the last string with the rest of the function 640 | *pc++ = SPACE; 641 | for (i = pos; i < len; i++) 642 | { 643 | if (v_bytes[i]) 644 | { 645 | *pc++ = DOT; 646 | *pc++ = DOT; 647 | } 648 | else 649 | { 650 | pc = Num2HexStr(pc, 2, get_byte(start_ea + i)); 651 | } 652 | } 653 | 654 | *pc++ = '\r'; 655 | *pc++ = '\n'; 656 | 657 | return (size_t) (pc - pSigBuf); 658 | } 659 | 660 | /********************************************************************** 661 | * Function: get_pat_file 662 | * Description: open and prepare output file for write 663 | * Parameters: none 664 | * Returns: FILE* 665 | **********************************************************************/ 666 | static FILE* get_pat_file(void) 667 | { 668 | int i = 0; 669 | long pos = 0; 670 | FILE *fp = NULL; 671 | char szLine[50] = { 0 }; 672 | char *filename = NULL; 673 | 674 | if ('\0' == g_szPatFile[0]) 675 | { 676 | /* First run */ 677 | char buf[512]; 678 | get_input_file_path(buf, sizeof buf); 679 | strncpy(g_szPatFile, buf, countof(g_szPatFile)); 680 | _VERIFY(PathRenameExtension(g_szPatFile, ".pat")); 681 | } 682 | 683 | AskFile: 684 | filename = askfile_c(1, g_szPatFile, "Enter the name of the pattern file:"); 685 | if (NULL == filename) 686 | { 687 | (void) msg("IDB2SIG: User chose cancel.\n"); 688 | return NULL; 689 | } 690 | 691 | if (g_options.bPatAppend) 692 | { 693 | /* Open existing PAT file for read and write */ 694 | fp = qfopen(filename, "r+b"); 695 | } 696 | else 697 | { 698 | /* In overwrite mode */ 699 | if (g_options.bConfirm && PathFileExists(filename)) 700 | { 701 | /* Confirm is true, confirm overwrite the existing file */ 702 | int ret = askyn_c(-1, "Do you want to overwrite the existing file %s", filename); 703 | if (-1 == ret) 704 | { 705 | /* User chose cancel */ 706 | return NULL; 707 | } 708 | else if (0 == ret) 709 | { 710 | /* User chose no button, select another file */ 711 | goto AskFile; 712 | } 713 | } 714 | } 715 | 716 | if (NULL == fp) 717 | { 718 | /* 719 | * In appending mode, if the file did not exist, create it 720 | * In overwrite mode, creating a new or overwrite an existing file 721 | */ 722 | fp = qfopen(filename, "w+b"); 723 | } 724 | 725 | if (NULL == fp) 726 | { 727 | warning("Could not create or open file %s.\n", filename); 728 | return NULL; 729 | } 730 | 731 | /* Save file name for next askfile_c dialog */ 732 | strncpy(g_szPatFile, filename, countof(g_szPatFile)); 733 | g_szPatFile[countof(g_szPatFile) - 1] = '\0'; 734 | 735 | /* 736 | * This section tests if pat file exists and overwrite '---' at the end 737 | * in the file append mode 738 | */ 739 | if (g_options.bPatAppend) 740 | { 741 | (void) qfseek(fp, 0L, SEEK_END); /* go to end_of_file */ 742 | pos = qftell(fp); 743 | if (pos != 0) 744 | { 745 | /* pat file is not empty */ 746 | do 747 | { 748 | (void) SkipBackward(fp, 1); /* one line back */ 749 | pos = qftell(fp); 750 | i = GetLine(szLine, sizeof(szLine), fp); 751 | if (i == 0) /* skip empty lines at the end of file */ 752 | { 753 | (void) SkipBackward(fp, 1); /* one more line back */ 754 | } 755 | } while (i == 0); /* skip empty lines at the end of file */ 756 | 757 | if (i < 0) 758 | { 759 | warning("Something is wrong with %s or '---' is missing!\n", filename); 760 | (void) qfclose(fp); 761 | return NULL; /* abandon ship */ 762 | } 763 | 764 | if (i > 0) 765 | { 766 | if (strcmp(szLine, "---")) 767 | { 768 | warning("%s is not a valid PAT file!\n", filename); 769 | (void) qfclose(fp); 770 | return NULL; /* abandon ship */ 771 | } 772 | } 773 | 774 | (void) qfseek(fp, pos, SEEK_SET); /* overwrite '---' */ 775 | } 776 | } 777 | 778 | return fp; 779 | } 780 | 781 | /* The DLL entry point of plugin */ 782 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID) 783 | { 784 | if (DLL_PROCESS_ATTACH == fdwReason) 785 | { 786 | _VERIFY(DisableThreadLibraryCalls(g_hinstPlugin = hinstDLL)); 787 | } 788 | 789 | return TRUE; 790 | } 791 | 792 | /********************************************************************** 793 | * Function: ShowOptionsDlg 794 | * Description: Show options dialog for getting user desired options 795 | * Parameters: none 796 | * Returns: none 797 | **********************************************************************/ 798 | static void ShowOptionsDlg(void) 799 | { 800 | // Build the format string constant used to create the dialog 801 | const char format[] = 802 | "STARTITEM 0\n" // TabStop 803 | "IDB2SIG Options\n\n" // Title 804 | "Choose the method for selecting functions:\n" // MsgText 805 | 806 | // Radio Button 0x0000 - NON_AUTO_FUNCTIONS 807 | "<#Create patterns for all functions with user created names.\n" // hint0 808 | "This excludes all library functions and auto-generated names.#" // hint0 809 | "Non-Auto Named Functions:R>\n" // text0 810 | 811 | // Radio Button 0x0001 - LIBRARY_FUNCTIONS 812 | "<#Create patterns for functions maked as libraries.\n" // hint1 813 | "This excludes all auto-generated names.#" // hint1 814 | "Library Functions Only:R>\n" // text1 815 | 816 | // Radio Button 0x0002 - PUBLIC_FUNCTIONS 817 | "<#Create patterns for functions marked as public.\n" // hint2 818 | "This excludes all auto-generated names.#" // hint2 819 | "Public Functions Only:R>\n" // text2 820 | 821 | // Radio Button 0x0003 - ENTRY_POINT_FUNCTIONS 822 | "<#Create patterns for functions marked as entry point.\n" // hint3 823 | "This excludes all auto-generated names.#" // hint3 824 | "Entry Point Functions Only:R>\n" // text3 825 | 826 | // Radio Button 0x0004 - ALL_FUNCTIONS 827 | "<#Create Patterns For Everything.\n" 828 | "CAUTION -This will make a real mess of names in any\n" // hint4 829 | "disassembly where the resulting signature is applied.#" // hint4 830 | "All Functions:R>\n" // text4 831 | 832 | // Radio Button 0x0005 - USER_SELECT_FUNCTION 833 | "<#Select a function from a dialog with a list of functions.#" // hint5 834 | "User Selected Function:R>>\n\n" // text5 835 | 836 | // Checkbox Button - Append PAT file 837 | "<#Append or overwrite the existing PAT file.#" // hint6 838 | "Append To Existing PAT file:C>\n" // text6 839 | 840 | // Checkbox Button - Confirm overwrite 841 | "<#Display a message box to confirm overwriting an existing file#" // hint7 842 | "Confirm Overwrite:C>>\n\n" // text7 843 | 844 | // Editbox - Minimum function length 845 | "<#The minimum function length (in bytes).\n" // hint8 846 | "The signature will not be created for any\n" 847 | "functions less than this specified length.\n" 848 | "Default and minimum is 6.#" 849 | "Minimum Function Length :D:8:::>\n\n" // text8 850 | 851 | // Editbox - The size of reversing virtual memory size 852 | "<#The size (in MB) of virtual memory will be reversed.\n" // hint9 853 | "To improve speed, this plugin will reverse with this size and\n" 854 | "dynamic commit 1 MB of virtual memory to create all signature\n" 855 | "lines in memory before writing to disk. Default and minimum is 10 MB.\n" 856 | "If an exception occur, please increase this size. Otherwise,\n" 857 | "if and an out of memory occur, please decrease this size.#" 858 | "Size Of Virtual Memory Reversing (in MB) :D:8:::>\n\n"; // text9 859 | 860 | // Create the option dialog. 861 | short mode = (short) g_options.funcMode; 862 | short chkMask = 0; 863 | if (g_options.bPatAppend) 864 | { 865 | chkMask |= 1; 866 | } 867 | if (g_options.bConfirm) 868 | { 869 | chkMask |= 2; 870 | } 871 | long len = (long) g_options.ulMinFuncLen; 872 | long size = (long) g_options.ulReverseSize; 873 | if (AskUsingForm_c(format, &mode, &chkMask, &len, &size)) 874 | { 875 | g_options.funcMode = (FUNCTION_MODE) mode; 876 | g_options.bPatAppend = ((chkMask & 1) != 0); 877 | g_options.bConfirm = ((chkMask & 2) != 0); 878 | 879 | if (len < DEF_MIN_FUNC_LENGTH) 880 | { 881 | (void) msg("Value inputted for minimum function length is invalid." 882 | " Get default value is %d.\n", DEF_MIN_FUNC_LENGTH); 883 | } 884 | g_options.ulMinFuncLen = (ulong) max(len, DEF_MIN_FUNC_LENGTH); 885 | 886 | if (size < DEF_REVERSE_SIZE) 887 | { 888 | (void) msg("Value inputted for size of virtual memory reversing is invalid." 889 | " Get default value is %d MB.\n", DEF_REVERSE_SIZE); 890 | } 891 | g_options.ulReverseSize = (ulong) max(size, DEF_REVERSE_SIZE); 892 | } 893 | } 894 | 895 | /********************************************************************** 896 | * Function: init 897 | * Description: Plugin init 898 | * Parameters: none 899 | * Returns: PLUGIN_OK 900 | **********************************************************************/ 901 | static int idaapi init(void) 902 | { 903 | (void) msg("IDB2SIG: Plugin init.\n"); 904 | 905 | InitCRCTable(); 906 | 907 | /* Get the full path of plugin */ 908 | _VERIFY(GetModuleFileName(g_hinstPlugin, g_szIniPath, countof(g_szIniPath))); 909 | g_szIniPath[countof(g_szIniPath) - 1] = '\0'; 910 | 911 | /* Change the extension of plugin to '.ini'. */ 912 | _VERIFY(PathRenameExtension(g_szIniPath, ".ini")); 913 | 914 | /* Get options saved in ini file */ 915 | _VERIFY(GetPrivateProfileStruct(g_szIDB2SIGSection, g_szOptionsKey, &g_options, 916 | sizeof(g_options), g_szIniPath)); 917 | 918 | /* Check and validate all members in global options */ 919 | g_options.funcMode = min(FUNCTION_MODE_MAX, max(FUNCTION_MODE_MIN, g_options.funcMode)); 920 | g_options.ulMinFuncLen = max(DEF_MIN_FUNC_LENGTH, g_options.ulMinFuncLen); 921 | g_options.ulReverseSize = max(DEF_REVERSE_SIZE, g_options.ulReverseSize); 922 | 923 | return PLUGIN_KEEP; 924 | } 925 | 926 | /********************************************************************** 927 | * Function: term 928 | * Description: Plugin terminate 929 | * Parameters: none 930 | * Returns: none 931 | **********************************************************************/ 932 | static void idaapi term(void) 933 | { 934 | (void) msg("IDB2SIG: Plugin terminate.\n"); 935 | 936 | /* Write options to ini file */ 937 | _VERIFY(WritePrivateProfileStruct(g_szIDB2SIGSection, g_szOptionsKey, &g_options, 938 | sizeof(g_options), g_szIniPath)); 939 | } 940 | 941 | /********************************************************************** 942 | * Function: run 943 | * Description: entry function of the plugin 944 | * Parameters: int arg 945 | * Returns: none 946 | **********************************************************************/ 947 | static void idaapi run(int /*arg*/) 948 | { 949 | func_t* pFunc = NULL; 950 | LPSTR pSigBuf = NULL; 951 | LPSTR pNextPage = NULL; 952 | 953 | // If user press shift key, show options dialog 954 | if (GetAsyncKeyState(VK_SHIFT) & 0x8000) 955 | { 956 | ShowOptionsDlg(); 957 | } 958 | 959 | int numOfFuncs = get_func_qty(); 960 | if (numOfFuncs <= 0) 961 | { 962 | (void) msg("IDB2SIG: Not found any functions\n"); 963 | return; 964 | } 965 | 966 | // Preprocess for user select function mode 967 | if (USER_SELECT_FUNCTION == g_options.funcMode) 968 | { 969 | pFunc = choose_func("Choose Function:", ea_t(-1)); 970 | if (NULL == pFunc) 971 | { 972 | (void) msg("IDB2SIG: User not select any function!\n"); 973 | return; 974 | } 975 | 976 | // Move the cursor to selected function 977 | jumpto(pFunc->startEA); 978 | 979 | if (!has_any_name(getFlags(pFunc->startEA))) 980 | { 981 | (void) msg("IDB2SIG: The current function does not have any name.\n"); 982 | return; 983 | } 984 | } 985 | 986 | // Reserve a large block of virtual memory. 987 | pSigBuf = pNextPage = (LPSTR) VirtualAlloc(NULL, 988 | g_options.ulReverseSize * ONE_MB, 989 | MEM_RESERVE, 990 | PAGE_NOACCESS); 991 | if (NULL == pSigBuf) 992 | { 993 | (void) msg("IDB2SIG: Call VirtualAlloc to reserve %d MB of virtual memory failed.\n" 994 | "\tPlease decrease the size of reversing virtual memory.\n", 995 | g_options.ulReverseSize); 996 | return; 997 | } 998 | 999 | FILE *fp = get_pat_file(); 1000 | if (NULL == fp) 1001 | { 1002 | // Release the block of memory pages 1003 | _VERIFY(VirtualFree(pSigBuf, 0, MEM_RELEASE)); 1004 | return; 1005 | } 1006 | 1007 | show_wait_box("Creating FLAIR PAT file %s.", g_szPatFile); 1008 | 1009 | __try 1010 | { 1011 | __try 1012 | { 1013 | int i = 0; 1014 | size_t len = 0; 1015 | switch (g_options.funcMode) 1016 | { 1017 | case NON_AUTO_FUNCTIONS: // write all non auto-generated name functions 1018 | for (i = 0; i < numOfFuncs; i++) 1019 | { 1020 | pFunc = getn_func(i); 1021 | if ((NULL != pFunc) && has_name(getFlags(pFunc->startEA)) && 1022 | !(pFunc->flags & FUNC_LIB)) 1023 | { 1024 | len += make_func_sig(pFunc->startEA, 1025 | (ulong)(pFunc->endEA - pFunc->startEA), 1026 | &pSigBuf[len]); 1027 | } 1028 | } 1029 | break; 1030 | 1031 | case LIBRARY_FUNCTIONS: // write all library functions 1032 | for (i = 0; i < numOfFuncs; i++) 1033 | { 1034 | pFunc = getn_func(i); 1035 | if ((NULL != pFunc) && (pFunc->flags & FUNC_LIB)) 1036 | { 1037 | len += make_func_sig(pFunc->startEA, 1038 | (ulong)(pFunc->endEA - pFunc->startEA), 1039 | &pSigBuf[len]); 1040 | } 1041 | } 1042 | break; 1043 | 1044 | case PUBLIC_FUNCTIONS: // write all public function 1045 | for (i = 0; i < numOfFuncs; i++) 1046 | { 1047 | pFunc = getn_func(i); 1048 | if ((NULL != pFunc) && is_public_name(pFunc->startEA)) 1049 | { 1050 | len += make_func_sig(pFunc->startEA, 1051 | (ulong)(pFunc->endEA - pFunc->startEA), 1052 | &pSigBuf[len]); 1053 | } 1054 | } 1055 | break; 1056 | 1057 | case ENTRY_POINT_FUNCTIONS: // write all entry point functions 1058 | for (i = 0; i < numOfFuncs; i++) 1059 | { 1060 | pFunc = get_func(get_entry(get_entry_ordinal((ulong) i))); 1061 | if (NULL != pFunc) 1062 | { 1063 | len += make_func_sig(pFunc->startEA, 1064 | (ulong)(pFunc->endEA - pFunc->startEA), 1065 | &pSigBuf[len]); 1066 | } 1067 | } 1068 | break; 1069 | 1070 | case ALL_FUNCTIONS: 1071 | for (i = 0; i < numOfFuncs; i++) 1072 | { 1073 | pFunc = getn_func(i); 1074 | if (NULL != pFunc) 1075 | { 1076 | len += make_func_sig(pFunc->startEA, 1077 | (ulong)(pFunc->endEA - pFunc->startEA), 1078 | &pSigBuf[len]); 1079 | } 1080 | } 1081 | break; 1082 | 1083 | case USER_SELECT_FUNCTION: 1084 | // Write the current function or user select function 1085 | _ASSERTE(pFunc != NULL); 1086 | if (NULL != pFunc) 1087 | { 1088 | len = make_func_sig(pFunc->startEA, 1089 | (ulong)(pFunc->endEA - pFunc->startEA), 1090 | pSigBuf); 1091 | } 1092 | break; 1093 | 1094 | default: 1095 | __assume(0); 1096 | break; 1097 | } 1098 | 1099 | if (len > 0) 1100 | { 1101 | // Append the terminate signature of pat file 1102 | strcpy(&pSigBuf[len], "---\r\n"); 1103 | len += 5; 1104 | 1105 | if (len != (size_t) qfwrite(fp, pSigBuf, len)) 1106 | { 1107 | (void) msg("IDB2SIG: Write all signature lines to PAT file %s failed.n", 1108 | g_szPatFile); 1109 | } 1110 | else 1111 | { 1112 | (void) msg("IDB2SIG: Creating PAT file %s successed.\n", 1113 | g_szPatFile); 1114 | } 1115 | } 1116 | else 1117 | { 1118 | (void) msg("Did not create any signature lines.\n"); 1119 | } 1120 | } 1121 | __except (PageFaultExceptionFilter(GetExceptionCode(), &pNextPage)) 1122 | { 1123 | (void) msg("Creating PAT file %s failed.\n", g_szPatFile); 1124 | } 1125 | } 1126 | __finally 1127 | { 1128 | hide_wait_box(); 1129 | 1130 | (void) qfclose(fp); 1131 | 1132 | // Release the block of memory pages 1133 | _VERIFY(VirtualFree(pSigBuf, 0, MEM_RELEASE)); 1134 | } 1135 | } 1136 | 1137 | //-------------------------------------------------------------------------- 1138 | char help[] = "This plugin converts a function or set of functions to a FLAIR PAT file"; 1139 | char comment[] = "Convert a function or functions to a FLAIR PAT file"; 1140 | char wanted_name[] = "IDB2SIG - Create FLAIR PAT file"; 1141 | char wanted_hotkey[] = "Ctrl-F7"; 1142 | 1143 | //-------------------------------------------------------------------------- 1144 | // 1145 | // PLUGIN DESCRIPTION BLOCK 1146 | // 1147 | //-------------------------------------------------------------------------- 1148 | 1149 | extern "C" { 1150 | plugin_t PLUGIN = { 1151 | IDP_INTERFACE_VERSION, 1152 | 0, // plugin flags 1153 | init, // initialize 1154 | term, // terminate. this pointer may be NULL. 1155 | run, // invoke plugin 1156 | comment, // long comment about the plugin 1157 | // it could appear in the status line 1158 | // or as a hint 1159 | help, // multiline help about the plugin 1160 | wanted_name, // the preferred short name of the plugin 1161 | wanted_hotkey // the preferred hotkey to run the plugin 1162 | }; 1163 | } 1164 | --------------------------------------------------------------------------------