├── README.md ├── analyzeidawll ├── LICENSE ├── README └── analyze_idawll.idc ├── dbgext ├── NOTEPAD.EXE.vcg ├── callgraph.idc ├── dbgcmds.idc ├── lm.idc └── readme ├── epf ├── readme ├── src │ └── epf.cpp └── tutorial │ ├── 01.png │ ├── 02.png │ ├── 03.png │ ├── 04.png │ └── 05.png ├── gotoseh └── gotoseh.cpp ├── graphtest └── layout.cpp ├── graphtest2 ├── flowgraph,cpp └── pegraph.cpp ├── segdump ├── readme ├── screenshot │ └── screenshot.png └── src │ ├── segdump.cpp │ └── segdump.hpp ├── snapshot ├── readme └── src │ └── snapshot.cpp └── vscp └── vscp.cpp /README.md: -------------------------------------------------------------------------------- 1 | # idaplugins 2 | Dump of some of my old plugins for IDA Pro 3 | -------------------------------------------------------------------------------- /analyzeidawll/LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | * ---------------------------------------------------------------------------- 3 | * "THE BEER-WARE LICENSE" (Revision 42): 4 | * wrote this file. As long as you retain this notice you 5 | * can do whatever you want with this stuff. If we meet some day, and you think 6 | * this stuff is worth it, you can buy me a beer in return 7 | * ---------------------------------------------------------------------------- 8 | */ -------------------------------------------------------------------------------- /analyzeidawll/README: -------------------------------------------------------------------------------- 1 | IDA Pro ida.wll analysis script 2 | tested on Windows build of IDA Pro 6.0 and 6.1 3 | 4 | usage: 5 | load ida.wll into IDA, run this script 6 | 7 | history: 8 | 9 | 2011-04-13 10 | ---------- 11 | script parses "Funcset" and "Extfun" tables, 12 | renames and comments its elements for better 13 | readability. This will reveal (most of the) 14 | IDC functions that wrap SDK functions and 15 | some undocumented ones like _peek(), _lpoke(), 16 | _poke(), _time(), _call(), DecodeInstruction(), 17 | ____(), and others. 18 | If invoked at run-time (i.e. ida.wll during 19 | a debugging session), the script will also 20 | reveal IDC functions that have dynamically 21 | been added using the SDK's set_idc_func() 22 | functions. 23 | 24 | (c) Dennis Elser -------------------------------------------------------------------------------- /analyzeidawll/analyze_idawll.idc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static GetExtfunFlags (flags) 4 | { 5 | auto s = 0; 6 | 7 | if ((flags & 1) == 1) 8 | s = "EXTFUN_BASE"; 9 | if ((flags & 2) == 2) 10 | { 11 | if (s) 12 | s = s + ", EXTFUN_NORET"; 13 | else 14 | s = "EXTFUN_NORET"; 15 | } 16 | return s; 17 | } 18 | 19 | static GetIDCFuncFlags (ea) 20 | { 21 | auto flags = 0; 22 | if (ea) 23 | flags = Dword (ea); 24 | return GetExtfunFlags (flags); 25 | } 26 | 27 | static GetVT (vt) 28 | { 29 | auto t = 0; 30 | if (vt == 1) 31 | t = "VT_STR"; 32 | else if (vt == 2) 33 | t = "VT_LONG"; 34 | else if (vt == 3) 35 | t = "VT_FLOAT"; 36 | else if (vt == 4) 37 | t = "VT_WILD"; 38 | else if (vt == 5) 39 | t = "VT_OBJ"; 40 | else if (vt == 6) 41 | t = "VT_FUNC"; 42 | else if (vt == 7) 43 | t = "VT_STR2"; 44 | else if (vt == 8) 45 | t = "VT_PVOID"; 46 | else if (vt == 9) 47 | t = "VT_INT64"; 48 | else if (vt == 10) 49 | t = "VT_REF"; 50 | 51 | return t; 52 | } 53 | 54 | static GetIDCFuncArgs (ea) 55 | { 56 | auto args = ""; 57 | auto b, t, _ea; 58 | _ea = ea; 59 | if (_ea) 60 | { 61 | while ((b=Byte (_ea)) != 0) 62 | { 63 | _ea = _ea + 1; 64 | t = GetVT (b); 65 | args = args + t; 66 | if (Byte (_ea) != 0) 67 | args = args+ ", "; 68 | } 69 | } 70 | return args; 71 | } 72 | 73 | static ParseExtfunTable (ea, count) 74 | { 75 | auto _ea = ea; 76 | auto i; 77 | auto ExtfunAddr, ExtfunName, ExtfunArgs, ExtfunFlags; 78 | 79 | if (ea && count) 80 | { 81 | auto extfun = object (); 82 | for (_ea; _ea < ea+count*4*4; _ea = _ea + 4*4) 83 | { 84 | for (i=0; i<4; i++) 85 | MakeDword (_ea+i*4); 86 | extfun.name = GetString (Dword(_ea), -1, GetStringType (Dword (_ea))); 87 | extfun.fp = Dword (_ea+4); 88 | extfun.args = GetIDCFuncArgs (Dword (_ea+8)); 89 | extfun.flags = GetIDCFuncFlags (_ea+0xC); 90 | 91 | MakeFunction (extfun.fp, BADADDR); 92 | MakeName (extfun.fp, "idcfunc_" + extfun.name); 93 | MakeRptCmt (Dword (_ea+8), extfun.args); 94 | MakeComm (_ea+0xC, extfun.flags); 95 | Message ("%x: %s (%s)\n", extfun.fp, extfun.name, extfun.args); 96 | } 97 | } 98 | } 99 | 100 | static ParseFuncSetTable () 101 | { 102 | auto ea = LocByName ("IDCFuncs"); 103 | if (ea != BADADDR) 104 | { 105 | auto funcSetTable = object(); 106 | 107 | // for now, manually parsing the structure 108 | // is favored over deserializing it (o.retrieve()) 109 | funcSetTable.qnty = Dword (ea); 110 | funcSetTable.extfun_t_ptr = Dword (ea+4); 111 | MakeName (ea+4, "p_Extfuntable"); 112 | funcSetTable.idcengine_startup_ptr = Dword (ea+8); 113 | MakeName (ea+8, "p_idcengine_startup"); 114 | funcSetTable.idcengine_shutdown_ptr = Dword (ea+0xC); 115 | MakeName (ea+0xC, "p_idcengine_shutdown"); 116 | funcSetTable.idcengine_init_ptr = Dword (ea+0x10); 117 | MakeName (ea+0x10, "p_idcengine_init"); 118 | funcSetTable.idcengine_term_ptr = Dword (ea+0x14); 119 | MakeName (ea+0x14, "p_idcengine_term"); 120 | funcSetTable.is_database_open_ptr = Dword (ea+0x18); 121 | MakeName (ea+0x18, "p_is_database_open"); 122 | funcSetTable.ea2str_ptr = Dword (ea+0x1C); 123 | MakeName (ea+0x1C, "p_ea2str"); 124 | funcSetTable.undeclared_variable_ok_ptr = Dword (ea+0x20); 125 | MakeName (ea+0x20, "p_undeclared_variable_ok"); 126 | funcSetTable.get_unkvar_ptr = Dword (ea+0x24); 127 | MakeName (ea+0x24, "p_get_unkvar"); 128 | funcSetTable.set_unkvar_ptr = Dword (ea+0x28); 129 | MakeName (ea+0x28, "p_set_unkvar"); 130 | funcSetTable.exec_resolved_func_ptr = Dword (ea+0x2C); 131 | MakeName (ea+0x2C, "p_exec_resolved_func"); 132 | funcSetTable.calc_sizeof_ptr = Dword (ea+0x30); 133 | MakeName (ea+0x30, "p_calc_sizeof"); 134 | funcSetTable.get_field_ea_ptr = Dword (ea+0x34); 135 | MakeName (ea+0x34, "p_get_field_ea"); 136 | 137 | MakeName (funcSetTable.extfun_t_ptr, "Extfuntable"); 138 | MakeName (funcSetTable.idcengine_startup_ptr, "idcengine_startup"); 139 | MakeName (funcSetTable.idcengine_shutdown_ptr, "idcengine_shutdown"); 140 | MakeName (funcSetTable.idcengine_init_ptr, "idcengine_init"); 141 | MakeName (funcSetTable.idcengine_term_ptr, "idcengine_init"); 142 | MakeName (funcSetTable.is_database_open_ptr, "is_database_open"); 143 | MakeName (funcSetTable.ea2str_ptr, "ea2str"); 144 | MakeName (funcSetTable.undeclared_variable_ok_ptr, "undeclared_variable_ok"); 145 | MakeName (funcSetTable.get_unkvar_ptr, "get_unkvar"); 146 | MakeName (funcSetTable.set_unkvar_ptr, "set_unkvar"); 147 | MakeName (funcSetTable.exec_resolved_func_ptr, "exec_resolved_func"); 148 | MakeName (funcSetTable.calc_sizeof_ptr, "calc_sizeof"); 149 | MakeName (funcSetTable.get_field_ea_ptr, "get_field_ea"); 150 | 151 | Message("%08X: FuncSetTable\n", ea); 152 | ParseExtfunTable (funcSetTable.extfun_t_ptr, funcSetTable.qnty); 153 | } 154 | } 155 | 156 | static main() 157 | { 158 | if (GetInputFile () == "ida.wll") 159 | { 160 | ParseFuncSetTable (); 161 | } 162 | else 163 | Message ("This script can only operate on an ida.wll idb.\n"); 164 | } -------------------------------------------------------------------------------- /dbgext/NOTEPAD.EXE.vcg: -------------------------------------------------------------------------------- 1 | graph: 2 | { 3 | title: "Flow graph of functions called during a debugging session (NOTEPAD.EXE)" 4 | manhattan_edges: yes 5 | layoutalgorithm: maxdepthslow 6 | finetuning: yes 7 | color: lightyellow 8 | xlspace: 30 9 | yspace: 100 10 | 11 | node: { title: "start" label: "start" color: lightblue} 12 | node: { title: "sub_1006CA8" label: "sub_1006CA8" color: lightblue} 13 | edge: { sourcename: "start" targetname: "sub_1006CA8" color: black} 14 | 15 | node: { title: "edi" label: "edi" color: lightblue} 16 | edge: { sourcename: "start" targetname: "edi" color: black} 17 | 18 | node: { title: "ds:__set_app_type" label: "ds:__set_app_type" color: lightblue} 19 | edge: { sourcename: "start" targetname: "ds:__set_app_type" color: black} 20 | 21 | node: { title: "ds:__p__fmode" label: "ds:__p__fmode" color: lightblue} 22 | edge: { sourcename: "start" targetname: "ds:__p__fmode" color: black} 23 | 24 | node: { title: "ds:__p__commode" label: "ds:__p__commode" color: lightblue} 25 | edge: { sourcename: "start" targetname: "ds:__p__commode" color: black} 26 | 27 | node: { title: "sub_1006D10" label: "sub_1006D10" color: lightblue} 28 | edge: { sourcename: "start" targetname: "sub_1006D10" color: black} 29 | 30 | node: { title: "sub_1006CFE" label: "sub_1006CFE" color: lightblue} 31 | edge: { sourcename: "start" targetname: "sub_1006CFE" color: black} 32 | 33 | node: { title: "_controlfp" label: "_controlfp" color: lightblue} 34 | edge: { sourcename: "sub_1006CFE" targetname: "_controlfp" color: black} 35 | 36 | node: { title: "_initterm" label: "_initterm" color: lightblue} 37 | edge: { sourcename: "start" targetname: "_initterm" color: black} 38 | 39 | node: { title: "ds:__getmainargs" label: "ds:__getmainargs" color: lightblue} 40 | edge: { sourcename: "start" targetname: "ds:__getmainargs" color: black} 41 | 42 | node: { title: "ds:GetStartupInfoA" label: "ds:GetStartupInfoA" color: lightblue} 43 | edge: { sourcename: "start" targetname: "ds:GetStartupInfoA" color: black} 44 | 45 | node: { title: "sub_1002801" label: "sub_1002801" color: lightblue} 46 | edge: { sourcename: "start" targetname: "sub_1002801" color: black} 47 | 48 | node: { title: "ds:GetCommandLineW" label: "ds:GetCommandLineW" color: lightblue} 49 | edge: { sourcename: "sub_1002801" targetname: "ds:GetCommandLineW" color: black} 50 | 51 | node: { title: "ds:GetSystemMetrics" label: "ds:GetSystemMetrics" color: lightblue} 52 | edge: { sourcename: "sub_1002801" targetname: "ds:GetSystemMetrics" color: black} 53 | 54 | node: { title: "ds:GetProcAddress" label: "ds:GetProcAddress" color: lightblue} 55 | edge: { sourcename: "sub_1002801" targetname: "ds:GetProcAddress" color: black} 56 | 57 | node: { title: "sub_1001B4A" label: "sub_1001B4A" color: lightblue} 58 | edge: { sourcename: "sub_1002801" targetname: "sub_1001B4A" color: black} 59 | 60 | node: { title: "ds:CharNextW" label: "ds:CharNextW" color: lightblue} 61 | edge: { sourcename: "sub_1001B4A" targetname: "ds:CharNextW" color: black} 62 | 63 | node: { title: "sub_10041CA" label: "sub_10041CA" color: lightblue} 64 | edge: { sourcename: "sub_1002801" targetname: "sub_10041CA" color: black} 65 | 66 | node: { title: "esi" label: "esi" color: lightblue} 67 | edge: { sourcename: "sub_10041CA" targetname: "esi" color: black} 68 | 69 | node: { title: "ds:GetDC" label: "ds:GetDC" color: lightblue} 70 | edge: { sourcename: "sub_10041CA" targetname: "ds:GetDC" color: black} 71 | 72 | node: { title: "sub_1003D57" label: "sub_1003D57" color: lightblue} 73 | edge: { sourcename: "sub_10041CA" targetname: "sub_1003D57" color: black} 74 | 75 | node: { title: "sub_1003CF2" label: "sub_1003CF2" color: lightblue} 76 | edge: { sourcename: "sub_1003D57" targetname: "sub_1003CF2" color: black} 77 | 78 | node: { title: "ds:LocalAlloc" label: "ds:LocalAlloc" color: lightblue} 79 | edge: { sourcename: "sub_1003CF2" targetname: "ds:LocalAlloc" color: black} 80 | 81 | node: { title: "ds:LoadStringW" label: "ds:LoadStringW" color: lightblue} 82 | edge: { sourcename: "sub_1003CF2" targetname: "ds:LoadStringW" color: black} 83 | 84 | node: { title: "ds:LocalFree" label: "ds:LocalFree" color: lightblue} 85 | edge: { sourcename: "sub_1003CF2" targetname: "ds:LocalFree" color: black} 86 | 87 | edge: { sourcename: "sub_1003D57" targetname: "ds:LocalAlloc" color: black} 88 | 89 | node: { title: "ds:LocalSize" label: "ds:LocalSize" color: lightblue} 90 | edge: { sourcename: "sub_1003D57" targetname: "ds:LocalSize" color: black} 91 | 92 | edge: { sourcename: "sub_1003D57" targetname: "ds:LoadStringW" color: black} 93 | 94 | edge: { sourcename: "sub_1003D57" targetname: "esi" color: black} 95 | 96 | edge: { sourcename: "sub_10041CA" targetname: "ds:GetSystemMetrics" color: black} 97 | 98 | edge: { sourcename: "sub_10041CA" targetname: "edi" color: black} 99 | 100 | node: { title: "ds:LoadAcceleratorsW" label: "ds:LoadAcceleratorsW" color: lightblue} 101 | edge: { sourcename: "sub_10041CA" targetname: "ds:LoadAcceleratorsW" color: black} 102 | 103 | node: { title: "sub_1004143" label: "sub_1004143" color: lightblue} 104 | edge: { sourcename: "sub_10041CA" targetname: "sub_1004143" color: black} 105 | 106 | edge: { sourcename: "sub_1004143" targetname: "ds:GetSystemMetrics" color: black} 107 | 108 | node: { title: "ds:LoadCursorW" label: "ds:LoadCursorW" color: lightblue} 109 | edge: { sourcename: "sub_1004143" targetname: "ds:LoadCursorW" color: black} 110 | 111 | node: { title: "ds:LoadIconW" label: "ds:LoadIconW" color: lightblue} 112 | edge: { sourcename: "sub_1004143" targetname: "ds:LoadIconW" color: black} 113 | 114 | node: { title: "ds:LoadImageW" label: "ds:LoadImageW" color: lightblue} 115 | edge: { sourcename: "sub_1004143" targetname: "ds:LoadImageW" color: black} 116 | 117 | node: { title: "ds:RegisterClassExW" label: "ds:RegisterClassExW" color: lightblue} 118 | edge: { sourcename: "sub_1004143" targetname: "ds:RegisterClassExW" color: black} 119 | 120 | node: { title: "sub_10018DF" label: "sub_10018DF" color: lightblue} 121 | edge: { sourcename: "sub_10041CA" targetname: "sub_10018DF" color: black} 122 | 123 | node: { title: "ds:GetLocaleInfoW" label: "ds:GetLocaleInfoW" color: lightblue} 124 | edge: { sourcename: "sub_10018DF" targetname: "ds:GetLocaleInfoW" color: black} 125 | 126 | node: { title: "sub_1003972" label: "sub_1003972" color: lightblue} 127 | edge: { sourcename: "sub_10041CA" targetname: "sub_1003972" color: black} 128 | 129 | node: { title: "ds:GetStockObject" label: "ds:GetStockObject" color: lightblue} 130 | edge: { sourcename: "sub_1003972" targetname: "ds:GetStockObject" color: black} 131 | 132 | node: { title: "ds:GetObjectW" label: "ds:GetObjectW" color: lightblue} 133 | edge: { sourcename: "sub_1003972" targetname: "ds:GetObjectW" color: black} 134 | 135 | node: { title: "ds:RegCreateKeyW" label: "ds:RegCreateKeyW" color: lightblue} 136 | edge: { sourcename: "sub_1003972" targetname: "ds:RegCreateKeyW" color: black} 137 | 138 | node: { title: "sub_1003682" label: "sub_1003682" color: lightblue} 139 | edge: { sourcename: "sub_1003972" targetname: "sub_1003682" color: black} 140 | 141 | node: { title: "ds:RegQueryValueExW" label: "ds:RegQueryValueExW" color: lightblue} 142 | edge: { sourcename: "sub_1003682" targetname: "ds:RegQueryValueExW" color: black} 143 | 144 | node: { title: "sub_10036D0" label: "sub_10036D0" color: lightblue} 145 | edge: { sourcename: "sub_1003972" targetname: "sub_10036D0" color: black} 146 | 147 | edge: { sourcename: "sub_10036D0" targetname: "ds:RegQueryValueExW" color: black} 148 | 149 | node: { title: "ds:RegCloseKey" label: "ds:RegCloseKey" color: lightblue} 150 | edge: { sourcename: "sub_1003972" targetname: "ds:RegCloseKey" color: black} 151 | 152 | node: { title: "ds:CreateWindowExW" label: "ds:CreateWindowExW" color: lightblue} 153 | edge: { sourcename: "sub_10041CA" targetname: "ds:CreateWindowExW" color: black} 154 | 155 | node: { title: "ds:SetWindowPlacement" label: "ds:SetWindowPlacement" color: lightblue} 156 | edge: { sourcename: "sub_10041CA" targetname: "ds:SetWindowPlacement" color: black} 157 | 158 | node: { title: "ds:DragAcceptFiles" label: "ds:DragAcceptFiles" color: lightblue} 159 | edge: { sourcename: "sub_10041CA" targetname: "ds:DragAcceptFiles" color: black} 160 | 161 | node: { title: "ds:CreateStatusWindowW" label: "ds:CreateStatusWindowW" color: lightblue} 162 | edge: { sourcename: "sub_10041CA" targetname: "ds:CreateStatusWindowW" color: black} 163 | 164 | node: { title: "sub_1001B9A" label: "sub_1001B9A" color: lightblue} 165 | edge: { sourcename: "sub_10041CA" targetname: "sub_1001B9A" color: black} 166 | 167 | edge: { sourcename: "sub_1001B9A" targetname: "esi" color: black} 168 | 169 | node: { title: "ds:_snwprintf" label: "ds:_snwprintf" color: lightblue} 170 | edge: { sourcename: "sub_1001B9A" targetname: "ds:_snwprintf" color: black} 171 | 172 | node: { title: "ds:GetMenu" label: "ds:GetMenu" color: lightblue} 173 | edge: { sourcename: "sub_10041CA" targetname: "ds:GetMenu" color: black} 174 | 175 | node: { title: "ds:GetSubMenu" label: "ds:GetSubMenu" color: lightblue} 176 | edge: { sourcename: "sub_10041CA" targetname: "ds:GetSubMenu" color: black} 177 | 178 | node: { title: "ds:EnableMenuItem" label: "ds:EnableMenuItem" color: lightblue} 179 | edge: { sourcename: "sub_10041CA" targetname: "ds:EnableMenuItem" color: black} 180 | 181 | node: { title: "ds:GetDeviceCaps" label: "ds:GetDeviceCaps" color: lightblue} 182 | edge: { sourcename: "sub_10041CA" targetname: "ds:GetDeviceCaps" color: black} 183 | 184 | node: { title: "ds:MulDiv" label: "ds:MulDiv" color: lightblue} 185 | edge: { sourcename: "sub_10041CA" targetname: "ds:MulDiv" color: black} 186 | 187 | node: { title: "ds:CreateFontIndirectW" label: "ds:CreateFontIndirectW" color: lightblue} 188 | edge: { sourcename: "sub_10041CA" targetname: "ds:CreateFontIndirectW" color: black} 189 | 190 | node: { title: "ds:SelectObject" label: "ds:SelectObject" color: lightblue} 191 | edge: { sourcename: "sub_10041CA" targetname: "ds:SelectObject" color: black} 192 | 193 | node: { title: "ds:GetTextFaceW" label: "ds:GetTextFaceW" color: lightblue} 194 | edge: { sourcename: "sub_10041CA" targetname: "ds:GetTextFaceW" color: black} 195 | 196 | node: { title: "ds:lstrcmpiW" label: "ds:lstrcmpiW" color: lightblue} 197 | edge: { sourcename: "sub_10041CA" targetname: "ds:lstrcmpiW" color: black} 198 | 199 | node: { title: "ds:ReleaseDC" label: "ds:ReleaseDC" color: lightblue} 200 | edge: { sourcename: "sub_10041CA" targetname: "ds:ReleaseDC" color: black} 201 | 202 | edge: { sourcename: "sub_10041CA" targetname: "ds:LocalAlloc" color: black} 203 | 204 | node: { title: "ds:PostMessageW" label: "ds:PostMessageW" color: lightblue} 205 | edge: { sourcename: "sub_10041CA" targetname: "ds:PostMessageW" color: black} 206 | 207 | node: { title: "sub_1001C5B" label: "sub_1001C5B" color: lightblue} 208 | edge: { sourcename: "sub_10041CA" targetname: "sub_1001C5B" color: black} 209 | 210 | node: { title: "ds:lstrcmpW" label: "ds:lstrcmpW" color: lightblue} 211 | edge: { sourcename: "sub_1001C5B" targetname: "ds:lstrcmpW" color: black} 212 | 213 | node: { title: "ds:lstrcpyW" label: "ds:lstrcpyW" color: lightblue} 214 | edge: { sourcename: "sub_1001C5B" targetname: "ds:lstrcpyW" color: black} 215 | 216 | edge: { sourcename: "sub_1001C5B" targetname: "ds:_snwprintf" color: black} 217 | 218 | node: { title: "ds:SendMessageW" label: "ds:SendMessageW" color: lightblue} 219 | edge: { sourcename: "sub_1001C5B" targetname: "ds:SendMessageW" color: black} 220 | 221 | node: { title: "ds:lstrcatW" label: "ds:lstrcatW" color: lightblue} 222 | edge: { sourcename: "sub_1001C5B" targetname: "ds:lstrcatW" color: black} 223 | 224 | node: { title: "ds:SetWindowTextW" label: "ds:SetWindowTextW" color: lightblue} 225 | edge: { sourcename: "sub_1001C5B" targetname: "ds:SetWindowTextW" color: black} 226 | 227 | node: { title: "ds:ShowWindow" label: "ds:ShowWindow" color: lightblue} 228 | edge: { sourcename: "sub_10041CA" targetname: "ds:ShowWindow" color: black} 229 | 230 | node: { title: "ds:SetCursor" label: "ds:SetCursor" color: lightblue} 231 | edge: { sourcename: "sub_10041CA" targetname: "ds:SetCursor" color: black} 232 | 233 | node: { title: "sub_1003E0F" label: "sub_1003E0F" color: lightblue} 234 | edge: { sourcename: "sub_10041CA" targetname: "sub_1003E0F" color: black} 235 | 236 | node: { title: "sub_1003C15" label: "sub_1003C15" color: lightblue} 237 | edge: { sourcename: "sub_10041CA" targetname: "sub_1003C15" color: black} 238 | 239 | edge: { sourcename: "sub_1003C15" targetname: "esi" color: black} 240 | 241 | node: { title: "sub_1003E29" label: "sub_1003E29" color: lightblue} 242 | edge: { sourcename: "sub_10041CA" targetname: "sub_1003E29" color: black} 243 | 244 | edge: { sourcename: "sub_1003E29" targetname: "sub_1003C15" color: black} 245 | 246 | node: { title: "sub_1003F7F" label: "sub_1003F7F" color: lightblue} 247 | edge: { sourcename: "sub_10041CA" targetname: "sub_1003F7F" color: black} 248 | 249 | edge: { sourcename: "sub_1003F7F" targetname: "sub_1003C15" color: black} 250 | 251 | node: { title: "sub_10040D7" label: "sub_10040D7" color: lightblue} 252 | edge: { sourcename: "sub_10041CA" targetname: "sub_10040D7" color: black} 253 | 254 | edge: { sourcename: "sub_10040D7" targetname: "esi" color: black} 255 | 256 | edge: { sourcename: "sub_10040D7" targetname: "edi" color: black} 257 | 258 | node: { title: "ds:GetKeyboardLayout" label: "ds:GetKeyboardLayout" color: lightblue} 259 | edge: { sourcename: "sub_10041CA" targetname: "ds:GetKeyboardLayout" color: black} 260 | 261 | node: { title: "ds:GetCurrentProcessId" label: "ds:GetCurrentProcessId" color: lightblue} 262 | edge: { sourcename: "sub_1002801" targetname: "ds:GetCurrentProcessId" color: black} 263 | 264 | node: { title: "ds:SetWinEventHook" label: "ds:SetWinEventHook" color: lightblue} 265 | edge: { sourcename: "sub_1002801" targetname: "ds:SetWinEventHook" color: black} 266 | 267 | edge: { sourcename: "sub_1002801" targetname: "edi" color: black} 268 | 269 | node: { title: "ds:TranslateAcceleratorW" label: "ds:TranslateAcceleratorW" color: lightblue} 270 | edge: { sourcename: "sub_1002801" targetname: "ds:TranslateAcceleratorW" color: black} 271 | 272 | node: { title: "ds:TranslateMessage" label: "ds:TranslateMessage" color: lightblue} 273 | edge: { sourcename: "sub_1002801" targetname: "ds:TranslateMessage" color: black} 274 | 275 | node: { title: "ds:DispatchMessageW" label: "ds:DispatchMessageW" color: lightblue} 276 | edge: { sourcename: "sub_1002801" targetname: "ds:DispatchMessageW" color: black} 277 | 278 | node: { title: "sub_10018B0" label: "sub_10018B0" color: lightblue} 279 | edge: { sourcename: "sub_1002801" targetname: "sub_10018B0" color: black} 280 | 281 | edge: { sourcename: "sub_1002801" targetname: "ds:LocalFree" color: black} 282 | 283 | node: { title: "ds:UnhookWinEvent" label: "ds:UnhookWinEvent" color: lightblue} 284 | edge: { sourcename: "sub_1002801" targetname: "ds:UnhookWinEvent" color: black} 285 | 286 | node: { title: "ds:exit" label: "ds:exit" color: lightblue} 287 | edge: { sourcename: "start" targetname: "ds:exit" color: black} 288 | } -------------------------------------------------------------------------------- /dbgext/callgraph.idc: -------------------------------------------------------------------------------- 1 | /* 2 | Callgraph IDC script v1.0 - written by Dennis Elser 3 | --------------------------------------------------- 4 | This is an IDC script for the 5 | Disassembler IDA Pro by Datarescue. 6 | The script needs IDA Pro v4.6 SP1 7 | or above! 8 | 9 | What does the script do? 10 | ------------------------ 11 | The script creates a callgraph of a process 12 | being debugged/traced by the IDA debugger. 13 | You can create multiple graphs and compare 14 | them using an external comparison tool/parser 15 | in order to find differences in the behaviour 16 | of the process/executable. 17 | 18 | 19 | history: 20 | -------- 21 | 13.04.2004 - initial release 22 | 23 | 24 | usage: 25 | ------ 26 | The script can only be used with the integrated 27 | debugger in IDA 4.60 SP1 and above! 28 | 29 | Usage is as follows: 30 | Load and compile the IDC script (callgraph.idc). 31 | Go to the 'Stop condition' field in the menu 32 | 'Debugger > Tracing > Tracing options..' and 33 | enter: 34 | 35 | call() 36 | 37 | Run the process and stop at a specific location 38 | (for example using a breakpoint or 'run to cursor' 39 | and enable tracing mode). Resume the process. 40 | The plugin will create a .vcg file in your IDA 41 | directory. 42 | 43 | Careful: You need to rename existing VCG files 44 | if you plan to rerun the IDC script ! 45 | 46 | 47 | Commercial usage is strictly prohibited without 48 | asking for permission! 49 | If you plan to use this script commercially, 50 | write an email to dennis(at)backtrace.de 51 | */ 52 | 53 | static call(/*start_ea, end_ea*/) 54 | { 55 | auto filename; 56 | auto eof; 57 | 58 | 59 | //if(Eip < start_ea || Eip > end_ea) return 0; 60 | 61 | eof = 0; 62 | 63 | filename = form("%s\\%s%s",GetIdaDirectory(),GetInputFile(),".vcg"); 64 | 65 | if(!CreateGraph(filename)) 66 | { 67 | RemEofComment(filename); 68 | } 69 | 70 | if(GetMnem(Eip)=="call") 71 | { 72 | Message("%08X: %s is calling %s\n", Eip, GetFunctionName(Eip), GetOpnd(Eip,0)); 73 | 74 | if(IsNewNode(filename,GetFunctionName(Eip))) 75 | { 76 | CreateNode(filename,GetFunctionName(Eip),GetFunctionName(Eip),"color: lightblue"); 77 | eof = 1; 78 | } 79 | if(IsNewNode(filename,GetOpnd(Eip,0))) 80 | { 81 | CreateNode(filename,GetOpnd(Eip,0),GetOpnd(Eip,0),"color: lightblue"); 82 | eof = 1; 83 | } 84 | if(IsNewEdge(filename,GetFunctionName(Eip),GetOpnd(Eip,0))) 85 | { 86 | CreateEdge(filename,GetFunctionName(Eip),GetOpnd(Eip,0),"color: black"); 87 | eof = 1; 88 | } 89 | if(eof) 90 | { 91 | WriteEofComment(filename); 92 | } 93 | } 94 | return 0; 95 | } 96 | 97 | static IsNewNode(filename, node) 98 | { 99 | return !Exists(filename, 100 | form("node: { title: \"%s\"", 101 | node) 102 | ); 103 | } 104 | 105 | static IsNewEdge(filename, src,dst) 106 | { 107 | return !Exists(filename, 108 | form("edge: { sourcename: \"%s\" targetname: \"%s", 109 | src, 110 | dst) 111 | ); 112 | } 113 | 114 | 115 | static Exists(filename, line) 116 | { 117 | auto fhandle; 118 | auto fline; 119 | 120 | fhandle=fopen(filename,"a+"); 121 | while( filelength(fhandle) != ftell(fhandle) ) 122 | { 123 | fline=freadln(fhandle); 124 | if(strstr(fline,line) != -1) 125 | { 126 | fclose(fhandle); 127 | return 1; 128 | } 129 | } 130 | fclose(fhandle); 131 | return 0; 132 | } 133 | 134 | static WriteEofComment(filename) 135 | { 136 | auto fhandle; 137 | fwriteln(filename,"}"); 138 | return; 139 | } 140 | 141 | 142 | static RemEofComment(filename) 143 | { 144 | auto fhandle; 145 | auto fc; 146 | 147 | fhandle=fopen(filename,"r+"); 148 | fseek(fhandle,filelength(fhandle)-1,0); 149 | fc=fgetc(fhandle); 150 | if(fc=='}') 151 | { 152 | fseek(fhandle,filelength(fhandle)-1,0); 153 | fprintf(fhandle,"\n"); 154 | } 155 | fclose(fhandle); 156 | return; 157 | } 158 | 159 | 160 | static CreateGraph(filename) 161 | { 162 | auto fhandle; 163 | auto fline; 164 | auto header; 165 | 166 | header= form("graph:\n" 167 | "{\n" 168 | "title: \"Flow graph of functions called during a debugging session (%s)\"\n" 169 | "manhattan_edges: yes\n" 170 | "layoutalgorithm: maxdepthslow\n" 171 | "finetuning: yes\n" 172 | //"layout_downfactor: 100\n" 173 | //"layout_upfactor: 100\n" 174 | //"layout_nearfactor: 100\n" 175 | "color: lightyellow\n" 176 | "xlspace: 30\n" 177 | "yspace: 100\n\n",GetInputFile()); 178 | 179 | 180 | 181 | fhandle=fopen(filename,"a+"); 182 | fline=freadln(fhandle); 183 | fclose(fhandle); 184 | if(strstr(fline,"graph") != -1) 185 | { 186 | return 0; 187 | } 188 | 189 | fwriteln(filename,header); 190 | return 1; 191 | } 192 | 193 | 194 | static freadln(handle) 195 | { 196 | auto line; 197 | auto c; 198 | 199 | line=""; 200 | while( ((c=fgetc(handle)) != '\n') ) 201 | { 202 | if(c==-1) return line; 203 | line=line+c; 204 | } 205 | return line; 206 | } 207 | 208 | static CreateNode(filename,node,label, color) 209 | { 210 | fwriteln(filename, 211 | form("node: { title: \"%s\" label: \"%s\" %s}\n", 212 | node, 213 | label, 214 | color) 215 | ); 216 | } 217 | 218 | static CreateEdge(filename,src,dst,color) 219 | { 220 | fwriteln(filename, 221 | form("edge: { sourcename: \"%s\" targetname: \"%s\" %s}\n", 222 | src, 223 | dst, 224 | color) 225 | ); 226 | } 227 | 228 | 229 | 230 | static fwriteln(filename,line) 231 | { 232 | auto fhandle; 233 | 234 | fhandle=fopen(filename,"a+"); 235 | fprintf(fhandle,line); 236 | fclose(fhandle); 237 | } 238 | -------------------------------------------------------------------------------- /dbgext/dbgcmds.idc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | dbgcmds IDC script v1.05 - written by Dennis Elser 5 | --------------------------------------------------- 6 | This is an IDC script for the 7 | Disassembler IDA Pro by Datarescue. 8 | 9 | 10 | What does the script do? 11 | ------------------------ 12 | The script extends the IDA debugger by useful commands, 13 | but it can also be used on a regular database (idb). 14 | 15 | See 'supported commands' for detailed usage 16 | and examples. 17 | 18 | history: 19 | -------- 20 | 13.04.2004 - initial release 21 | 16.04.2004 - bugfixes, added dumpseg() and dumpsegs() 22 | 19.04.2004 - saveregs(), loadregs(), fillmem() and help() added 23 | 24 | 25 | usage: 26 | ------ 27 | Load and compile the IDC script (dbgcmds.idc). 28 | Run the debugger and suspend the process. 29 | Select the 'File>IDC command' menu and enter 30 | any command supported by this script. 31 | 32 | 33 | Supported commands: 34 | ------------------- 35 | 36 | dumpmem(filename, address, size) 37 | dumps "size" bytes starting at "address" to "filename" 38 | 39 | patchmem(filename, address) 40 | patches memory starting at "address" with the contents 41 | of "filename" 42 | 43 | dumpseg(filename,segname) 44 | dumps a whole segment named "segname" to "filename" 45 | 46 | dumpsegs(path) 47 | dumps all available segments to "path" 48 | 49 | saveregs(filename) 50 | saves all the standard x86 registers to a file 51 | (including Eflags) 52 | 53 | loadregs(filename) 54 | restores all the standard x86 registers from a file 55 | (including Eflags) 56 | 57 | fillmem(address, count, character) 58 | fills memory starting at "address" with "count" number of 59 | "character"s 60 | 61 | help() 62 | display list of all supported commands 63 | 64 | 65 | Examples: 66 | --------- 67 | dumpmem("c:\\dump.bin",0x401000,0x100); 68 | 69 | This command will dump 0x100 bytes starting at address 0x401000 70 | to the file c:\dump.bin 71 | 72 | patchmem("c:\\dump.bin",0x401000); 73 | 74 | This command will patch memory of a running process starting 75 | at address 0x401000 with the contents of c:\dump.bin 76 | 77 | 78 | */ 79 | 80 | 81 | 82 | static help() 83 | { 84 | Message("\n" 85 | "command: example:\n" 86 | "----------------------------------------------------------------------------------\n" 87 | "dumpmem(filename, address, size) - dumpmem(\"c:\\\\dump.bin\", Esp, 0x10);\n" 88 | "patchmem(filename, address) - patchmem(\"c:\\\\dump.bin\", 0x401000);\n" 89 | "dumpseg(filename,segname) - dumpseg(\"c:\\\\codesegment.bin\", \".text\");\n" 90 | "dumpsegs(path) - dumpsegs(\"c:\\\\\");\n" 91 | "saveregs(filename) - saveregs(\"c:\\\\registers.bin\");\n" 92 | "loadregs(filename) - loadregs(\"c:\\\\registers.bin\");\n" 93 | "fillmem(address, count, character) - fillmem(0x402000, 0x50, \'x\');\n" 94 | "help() - help();\n\n" 95 | ); 96 | 97 | return; 98 | } 99 | 100 | static fillmem(address, count, character) 101 | { 102 | auto ea; 103 | 104 | for(ea=address;ea Tracing > Tracing options..' and 41 | enter: 42 | 43 | lm(userstring,condition) 44 | 45 | where 'userstring' is a string to look for and 46 | 'condition' is either '0' or '1'. 47 | '0' means, the script will let the debugger 48 | continue after each condition met 49 | '1' means, the script will cause the debugger to 50 | pause/halt after each condition met and you'll be able to 51 | examine the code immediately. 52 | 53 | 54 | Example usage: 55 | -------------- 56 | Let's say you are examining an ftpd which you 57 | suspect to contain a buffer overflow vulnerability 58 | in its string-handling routines: 59 | 60 | 1. Load the ftpd into IDA. 61 | 2. Run the process using IDA's integrated 62 | debugger. 63 | 3. Pause the running process. 64 | 4. Specify a stop condition like: 65 | lm("PWD",1). 66 | 5. Enable 'instruction tracing" in IDA. 67 | 6. Resume the process. 68 | 7. Connect to the running ftpd using an 69 | ftp client. 70 | 8. Send "PWD" over the ftp client to the 71 | ftpd. 72 | 9. IDA will pause the running ftpd as soon 73 | as any register is pointing to the "PWD" string. 74 | You'll most probably land in or near a routine that 75 | parses user input (your "PWD" string), ready 76 | to be examined. 77 | 78 | 79 | 80 | Credits go to Greg Hoglund and Gary McGraw 81 | (I picked up your idea of parsing user input 82 | from your book 83 | "Exploiting Software - How to break code") 84 | and to Ilfak Guilfanov for providing help 85 | with the IDC language 86 | -------------------------------------------------------- 87 | 88 | */ 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | //LEVEL = recursion/dereference depth 97 | //the higher the number of levels is, the slower 98 | //the IDA tracer will be. 99 | //LEVEL = 1 should fit all your needs 100 | // *(esp) would be LEVEL 0 101 | //*(*(esp)) would be LEVEL 1 102 | //and so on... 103 | #define LEVEL 1 104 | 105 | 106 | 107 | //******************** 108 | //* 109 | //* MAIN 110 | //* 111 | //******************** 112 | 113 | // lm() is the main function to call 114 | // as explained in the 'usage' section 115 | // of this script 116 | static lm(s,condition) 117 | { 118 | auto triggered; 119 | auto addr; 120 | auto fhandle; 121 | 122 | auto reg_eax; 123 | auto reg_ebx; 124 | auto reg_ecx; 125 | auto reg_edx; 126 | auto reg_esi; 127 | auto reg_edi; 128 | auto reg_ebp; 129 | auto reg_esp; 130 | 131 | 132 | reg_eax=" "; 133 | reg_ebx=" "; 134 | reg_ecx=" "; 135 | reg_edx=" "; 136 | reg_esi=" "; 137 | reg_edi=" "; 138 | reg_ebp=" "; 139 | reg_esp=" "; 140 | 141 | triggered=0; 142 | 143 | if( (addr=IsPointerTo(Eax,s,LEVEL)) != 0 ) 144 | { 145 | reg_eax="eax"; 146 | triggered=1; 147 | //return condition; 148 | } 149 | if( (addr=IsPointerTo(Ebx,s,LEVEL)) != 0 ) 150 | { 151 | reg_ebx="ebx"; 152 | triggered=1; 153 | //return condition; 154 | } 155 | if( (addr=IsPointerTo(Ecx,s,LEVEL)) != 0 ) 156 | { 157 | reg_ecx="ecx"; 158 | triggered=1; 159 | //return condition; 160 | } 161 | if( (addr=IsPointerTo(Edx,s,LEVEL)) != 0 ) 162 | { 163 | reg_edx="edx"; 164 | triggered=1; 165 | //return condition; 166 | } 167 | if( (addr=IsPointerTo(Esi,s,LEVEL)) != 0 ) 168 | { 169 | reg_esi="esi"; 170 | triggered=1; 171 | //return condition; 172 | } 173 | if( (addr=IsPointerTo(Edi,s,LEVEL)) != 0 ) 174 | { 175 | reg_edi="edi"; 176 | triggered=1; 177 | //return condition; 178 | } 179 | if( (addr=IsPointerTo(Ebp,s,LEVEL)) != 0 ) 180 | { 181 | reg_ebp="ebp"; 182 | triggered=1; 183 | //return condition; 184 | } 185 | if( (addr=IsPointerTo(Esp,s,LEVEL)) != 0 ) 186 | { 187 | reg_esp="esp"; 188 | triggered=1; 189 | //return condition; 190 | } 191 | if(triggered) 192 | { 193 | Message("%08X: %s %s %s %s %s %s %s %s -> %s\n", 194 | Eip, 195 | reg_eax, 196 | reg_ebx, 197 | reg_ecx, 198 | reg_edx, 199 | reg_esi, 200 | reg_edi, 201 | reg_ebp, 202 | reg_esp, 203 | GetDisasm(Eip)); 204 | 205 | fhandle=fopen(BuildFilename(),"a+"); 206 | fprintf(fhandle,"%08X: %s %s %s %s %s %s %s %s -> %s\n", 207 | Eip, 208 | reg_eax, 209 | reg_ebx, 210 | reg_ecx, 211 | reg_edx, 212 | reg_esi, 213 | reg_edi, 214 | reg_ebp, 215 | reg_esp, 216 | GetDisasm(Eip)); 217 | fclose(fhandle); 218 | return condition; 219 | } 220 | return 0; 221 | } 222 | 223 | 224 | static BuildFilename() 225 | { 226 | return GetIdaDirectory() + "\\" + GetInputFile() + ".lmf"; 227 | } 228 | 229 | //returns !=0 if 'reg' is a pointer 230 | //to the user supplied string 's' 231 | // returns 0 otherwise 232 | //'level' is the number of indirect 233 | //pointers to scan for in a loop 234 | static IsPointerTo(reg,s,level) 235 | { 236 | auto pStr; 237 | auto i; 238 | 239 | pStr=reg; 240 | for(i=0;i<=level;i++) 241 | { 242 | if( Compare(pStr,s,strlen(s)) ) 243 | return pStr; 244 | pStr=Dword(pStr); 245 | } 246 | return 0; 247 | } 248 | 249 | 250 | //compares strings (both ASCII and UNICODE) 251 | //returns 1 if strings match 252 | // 0 if they mismatch 253 | static Compare(str1,str2,len) 254 | { 255 | if( StrCmp(str1,str2,len) || UniStrCmp(str1,str2,len) ) 256 | { 257 | return 1; 258 | } 259 | return 0; 260 | } 261 | 262 | //ASCII string comparison / bytewise 263 | //returns 0 if strings mismatch 264 | // 1 if strings match 265 | static StrCmp(str1,str2,len) 266 | { 267 | auto i; 268 | auto ascii; 269 | 270 | ascii = GetString(str1,len); 271 | 272 | for(i=0;i 62 | #include 63 | #include 64 | #include 65 | #include 66 | 67 | #define MAX_STR 260 68 | 69 | 70 | //function prototype(s) 71 | ea_t get_reg_val(char *regname); 72 | void toggle_tracer(void); 73 | void set_tracer_internal_state(bool state); 74 | //------------------------------------------------------------- 75 | 76 | 77 | //global constants 78 | const char *onoff[]={"off","on"}; 79 | const char *registers[]={"eax","ebx","ecx","edx","esi","edi","ebp","esp","eip"}; 80 | const short CHKBX_0001 = 0x0001; // First Check Box 81 | /* 82 | const short CHKBX_0002 = 0x0002; // Second Check Box 83 | const short CHKBX_0003 = 0x0004; // Third Check Box 84 | const short CHKBX_0004 = 0x0008; // Fourth Check Box 85 | const short CHKBX_0005 = 0x0010; 86 | */ 87 | 88 | //The dialogs were made with the help of 89 | //J.C.Roberts' excellent examples, thanks you! 90 | const char dlg[] = 91 | "STARTITEM 0\n" 92 | "HELP\n" // Help 93 | "EPF - Entry Point Finder\n\n" 94 | "The plugin's intention is to find the original entry point\n" 95 | "of a packed/crypted PE executable (or any file which can be\n" 96 | "run using IDA's built in debugger).\n\n" 97 | "The plugin comes with full sourcecode.\n" 98 | "Parts (the dialogs) of the code have been adapted\n" 99 | "from J.C.Roberts' excellent examples.\n" 100 | "The author of EPF can be reached at dennis(at)backtrace(dot)de\n" 101 | "ENDHELP\n" 102 | 103 | "Entrypoint Finder\n" // Title 104 | "Entrypoint Finder plugin by Dennis Elser.\n\n" // Dialog Text 105 | 106 | " Please select\n" // Dialog Text 107 | // Group #1 Radio Buttons NOTE: using capital "R" 108 | "<#Choose this option if the target section is unknown.#" // hint radio0 109 | "Trace until EIP reaches a different section:R>" // text radio0 110 | 111 | "<#Choose this option if the target area is known.#" // hint radio1 112 | "Trace until EIP reaches a specific memory area:R>" 113 | 114 | "<#Please enter a mnemonic below.#" // hint radio1 115 | "Trace until EIP reaches a specific mnemonic:R>" 116 | 117 | "<#Please enter a register and value below.#" // hint radio1 118 | "Trace until a register holds a specific value:R>" 119 | 120 | "<#Please enter a value below.#" // hint radio1 121 | "Trace until any register holds a specific value:R>>\n\n\n\n\n\n\n" 122 | 123 | "<#Enter an *exact* mnemonic-string here.#" 124 | "Mnemonic :A:255:32:::>\n" // text radio1 125 | 126 | "<#Enter a register (eax, ebx..) here.#" 127 | "Register :A:255:32:::>\n" // text radio1 128 | 129 | "<#Enter a value here.#" 130 | "Value :A:255:32:::>\n" // text radio1 131 | 132 | "<#Tracking Eip gives a nice visual effect but slows down!#" 133 | "Track Eip :C>>\n\n" 134 | 135 | ; // End Dialog Format String 136 | //------------------------------------------------------------- 137 | 138 | 139 | //global vars 140 | bool b_switch=false; 141 | char seg[MAXSTR]; 142 | int status=0; 143 | ea_t start_address; 144 | ea_t end_address; 145 | 146 | char mnem[MAX_STR]="popa"; 147 | char temp[MAX_STR]; 148 | 149 | char reg[MAX_STR]="eax"; 150 | char value[MAX_STR]="0xDEADBEEF"; 151 | 152 | ea_t reg_val; 153 | bool b_trackEip=false; 154 | 155 | //------------------------------------------------------------- 156 | 157 | 158 | 159 | void toggle_tracer(void) 160 | { 161 | char *segname; 162 | short checkbox; 163 | 164 | if(!b_switch) 165 | { 166 | checkbox = (short)(b_trackEip * CHKBX_0001); 167 | if ( AskUsingForm_c(dlg,&status,&mnem, ®, &value, &checkbox) == 0) 168 | { 169 | msg("-> EPF: aborted.\n"); 170 | return; 171 | } 172 | 173 | b_trackEip = (bool)(checkbox & CHKBX_0001); 174 | 175 | switch(status) 176 | { 177 | case 0: 178 | segname = get_segm_name(get_reg_val("eip")); 179 | if(segname!=NULL) 180 | { 181 | strncpy(seg,segname,MAXSTR-1); 182 | } 183 | break; 184 | case 1: 185 | if (askaddr(&start_address,"Please enter start address:\n") == 0) 186 | { 187 | msg("-> EPF: aborted.\n"); 188 | return; 189 | } 190 | 191 | if (askaddr(&end_address,"Please enter end address [inclusive]:\n") == 0) 192 | { 193 | msg("-> EPF: aborted.\n"); 194 | return; 195 | } 196 | break; 197 | /* case 2: 198 | break;*/ 199 | case 3: 200 | case 4: 201 | if ( !str2ea(value, ®_val, get_screen_ea()) || 202 | !atoea(value, ®_val)) 203 | { 204 | msg("-> EPF: %s is not a valid value (use \"0x\" for HEX values)!\n",value); 205 | return; 206 | } 207 | break; 208 | } 209 | 210 | } 211 | b_switch^=1; 212 | enable_step_trace(b_switch); 213 | msg("-> EPF is now %s\n",onoff[b_switch]); 214 | if( b_switch ) msg ("-> EPF: Please resume the process now!\n"); 215 | } 216 | //------------------------------------------------------------- 217 | 218 | 219 | void set_tracer_internal_state(bool state) 220 | { 221 | b_switch=state; 222 | msg("-> EPF is now %s\n",onoff[b_switch]); 223 | } 224 | //------------------------------------------------------------- 225 | 226 | 227 | //(personal comment) 228 | //dbg.hpp has the following function, which I might use 229 | //in future versions of this plugin 230 | //bool idaapi get_reg_val(const char *regname, regval_t *regval); 231 | ea_t get_reg_val(char *regname) 232 | { 233 | regval_t eip; 234 | get_reg_val(regname,&eip); 235 | return eip.ival; 236 | } 237 | //------------------------------------------------------------- 238 | 239 | 240 | static int idaapi dbg_callback(void * /*user_data*/, int event_id, va_list /*va*/) 241 | { 242 | ea_t eip; 243 | int i; 244 | 245 | if(!b_switch) return 0; 246 | 247 | if(event_id==dbg_trace) 248 | { 249 | eip = get_reg_val("eip"); 250 | if (b_trackEip) jumpto(eip); 251 | showAddr(eip); 252 | switch(status) 253 | { 254 | case 0: 255 | if( strcmp(seg, get_segm_name(get_reg_val("eip"))) != 0 ) 256 | { 257 | msg("-> EPF: EIP is pointing into a different section at: %08X.\n",eip); 258 | suspend_process(); 259 | toggle_tracer(); 260 | } 261 | break; 262 | case 1: 263 | if( eip >= start_address && eip <= end_address) 264 | { 265 | msg("-> EPF: EIP is pointing into given memory area at %08X.\n",eip); 266 | suspend_process(); 267 | toggle_tracer(); 268 | } 269 | break; 270 | case 2: 271 | //(personal comment) 272 | //this can be speed-optimized by converting the mnemonic 273 | //into a cmd.itype state before... (consider it as "to be done") 274 | ua_mnem(eip, temp, MAX_STR); 275 | if( strcmp(temp, mnem) == 0) 276 | { 277 | msg("-> EPF: Mnemonic found at %08X.\n",eip); 278 | suspend_process(); 279 | toggle_tracer(); 280 | } 281 | break; 282 | case 3: 283 | if( reg_val == get_reg_val(reg) ) 284 | { 285 | msg("-> EPF: %s == %08X at %08X.\n",reg, reg_val, eip); 286 | suspend_process(); 287 | toggle_tracer(); 288 | } 289 | break; 290 | case 4: 291 | for(i=0;i<9;i++) 292 | { 293 | if( reg_val == get_reg_val((char *)registers[i]) ) 294 | { 295 | msg("-> EPF: %s == %08X at %08X.\n",registers[i], reg_val, eip); 296 | suspend_process(); 297 | toggle_tracer(); 298 | } 299 | } 300 | break; 301 | } 302 | } 303 | else if(event_id==dbg_process_exit) 304 | { 305 | set_tracer_internal_state(false); 306 | } 307 | return 0; 308 | } 309 | //------------------------------------------------------------- 310 | 311 | 312 | //init, run, term 313 | int idaapi init(void) 314 | { 315 | //(personal comment) 316 | //can/should be changed since the debugger 317 | //can debug more than PE files ;-) 318 | if ( inf.filetype != f_PE ) return PLUGIN_SKIP; 319 | 320 | //register the debugger callback 321 | hook_to_notification_point(HT_DBG, dbg_callback, NULL); 322 | 323 | return PLUGIN_KEEP; 324 | } 325 | 326 | void idaapi term(void) 327 | { 328 | //unregister callback 329 | unhook_from_notification_point(HT_DBG, dbg_callback); 330 | } 331 | 332 | void idaapi run(int arg) 333 | { 334 | //is_debugger_on(void) ? 335 | if(get_process_state() == 0) 336 | { 337 | msg("-> EPF: No process is currently being debugged.\n" 338 | " Please run and suspend the process first!\n"); 339 | return; 340 | } 341 | 342 | toggle_tracer(); 343 | } 344 | 345 | //------------------------------------------------------------- 346 | 347 | char comment[] = "Entry point finder plugin for IDA PRO"; 348 | char help[] = "This plugin can find the entry point of packed executables.\n"; 349 | char wanted_name[] = "Toggle EPF tracer on or off"; 350 | char wanted_hotkey[] = "Alt-7"; 351 | 352 | plugin_t PLUGIN = 353 | { 354 | IDP_INTERFACE_VERSION, 355 | 0, 356 | init, 357 | term, 358 | run, 359 | comment, 360 | help, 361 | wanted_name, 362 | wanted_hotkey 363 | }; 364 | -------------------------------------------------------------------------------- /epf/tutorial/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patois/idaplugins/ef187498036ca7f84b620040c15ba444b968398c/epf/tutorial/01.png -------------------------------------------------------------------------------- /epf/tutorial/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patois/idaplugins/ef187498036ca7f84b620040c15ba444b968398c/epf/tutorial/02.png -------------------------------------------------------------------------------- /epf/tutorial/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patois/idaplugins/ef187498036ca7f84b620040c15ba444b968398c/epf/tutorial/03.png -------------------------------------------------------------------------------- /epf/tutorial/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patois/idaplugins/ef187498036ca7f84b620040c15ba444b968398c/epf/tutorial/04.png -------------------------------------------------------------------------------- /epf/tutorial/05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patois/idaplugins/ef187498036ca7f84b620040c15ba444b968398c/epf/tutorial/05.png -------------------------------------------------------------------------------- /gotoseh/gotoseh.cpp: -------------------------------------------------------------------------------- 1 | // gotoSEH IDA Pro plugin 2 | // 3 | // (c) Dennis Elser 4 | // 5 | // history: 6 | // 7 | // 17.11.2006 - initial release 8 | // 20.02.2007 - public release 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | extern plugin_t PLUGIN; 20 | 21 | 22 | 23 | int idaapi init(void) 24 | { 25 | if ( inf.filetype != f_PE ) return PLUGIN_SKIP; 26 | 27 | return PLUGIN_OK; 28 | } 29 | 30 | void idaapi term(void) 31 | { 32 | } 33 | 34 | 35 | void idaapi run(int arg) 36 | { 37 | thread_id_t tid; 38 | char segname[0x20]; 39 | segment_t *tibseg; 40 | ulong ptr_seh; 41 | ulong seh_handler; 42 | 43 | tid = get_current_thread(); //use "getn_thread(0)" for IDA releases below 5.1 44 | if( tid == PROCESS_NO_THREAD ) 45 | { 46 | warning( "Thread does not exist!" ); 47 | return; 48 | } 49 | 50 | qsnprintf( segname, sizeof( segname ), "TIB[%08X]", tid ); 51 | tibseg = get_segm_by_name( segname ); 52 | 53 | if( tibseg == NULL ) 54 | { 55 | warning( "Could not get segment pointer!" ); 56 | return; 57 | } 58 | 59 | ptr_seh = get_long( tibseg->startEA ); 60 | seh_handler = get_long( ptr_seh + 4 ); 61 | auto_make_proc( seh_handler ); 62 | jumpto( seh_handler ); 63 | } 64 | 65 | //-------------------------------------------------------------------------- 66 | char comment[] = "gotoSEH"; 67 | char help[] = "no help ;)"; 68 | char wanted_name[] = "gotoSEH"; 69 | char wanted_hotkey[] = "0"; 70 | 71 | 72 | //-------------------------------------------------------------------------- 73 | // 74 | // PLUGIN DESCRIPTION BLOCK 75 | // 76 | //-------------------------------------------------------------------------- 77 | plugin_t PLUGIN = 78 | { 79 | IDP_INTERFACE_VERSION, 80 | 0, // plugin flags 81 | init, // initialize 82 | 83 | term, // terminate. this pointer may be NULL. 84 | 85 | run, // invoke plugin 86 | 87 | comment, // long comment about the plugin 88 | // it could appear in the status line 89 | // or as a hint 90 | 91 | help, // multiline help about the plugin 92 | 93 | wanted_name, // the preferred short name of the plugin 94 | wanted_hotkey // the preferred hotkey to run the plugin 95 | }; -------------------------------------------------------------------------------- /graphtest/layout.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * layout.cpp 3 | * ---------- 4 | * This example plugin for IDA 5.0 (and above) 5 | * shows you how to use the new graphing interface 6 | * and some of its new callbacks. 7 | * The plugin adds an item to the graph's popup-menu 8 | * and lets you choose between one of three layout 9 | * algorithms (circle, tree and digraph). 10 | * 11 | * Author: Dennis Elser 12 | * 13 | * Hint: This plugin is an extension to the ugraph 14 | * sample plugin provided with the IDA sdk. 15 | * 16 | * history: 17 | * -------- 18 | * 19 | * 19.03.2006 - initial release 20 | * 21 | */ 22 | 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | //-------------------------------------------------------------------------- 33 | static bool hooked = false; 34 | static bool newmenu = false; 35 | static int layout = layout_digraph; 36 | static TForm *form = NULL; 37 | static graph_viewer_t *gv = NULL; 38 | 39 | 40 | #define MENU_ITEM_CAPTION "Set layout" 41 | 42 | //-------------------------------------------------------------------------- 43 | void doCircleLayout(mutable_graph_t *g, point_t center, int radius) 44 | { 45 | g->current_layout = layout_circle; 46 | g->circle_center = center; 47 | g->circle_radius = radius; 48 | g->create_circle_layout(center, radius); 49 | g->redo_layout(); 50 | return; 51 | } 52 | 53 | 54 | //-------------------------------------------------------------------------- 55 | void doTreeLayout(mutable_graph_t *g) 56 | { 57 | g->current_layout = layout_tree; 58 | g->create_tree_layout(); 59 | g->redo_layout(); 60 | return; 61 | } 62 | 63 | 64 | 65 | //-------------------------------------------------------------------------- 66 | void doDigraphLayout(mutable_graph_t *g) 67 | { 68 | g->current_layout = layout_digraph; 69 | g->create_digraph_layout(); 70 | g->redo_layout(); 71 | return; 72 | } 73 | 74 | 75 | 76 | //-------------------------------------------------------------------------- 77 | // callback function for layout selection 78 | bool idaapi menu_callback(void *ud) 79 | { 80 | mutable_graph_t *g = get_viewer_graph(gv); 81 | if( g == NULL ) 82 | return false; 83 | 84 | int code = askbuttons_c("Circle", "Tree", "Digraph", 1, "Please select layout type"); 85 | 86 | // code is being converted to a globally "useful" variable 87 | switch( code ) 88 | { 89 | case 1: // circle 90 | layout = layout_circle; 91 | // use 200,200 (x/y) as center by default 92 | // 2000 as radius by default 93 | doCircleLayout(g, point_t(200, 200), 2000); 94 | break; 95 | case 0: // tree 96 | layout = layout_tree; 97 | doTreeLayout(g); 98 | break; 99 | case -1: // digraph 100 | layout = layout_digraph; 101 | doDigraphLayout(g); 102 | break; 103 | } 104 | 105 | refresh_viewer(gv); 106 | return true; 107 | } 108 | 109 | 110 | 111 | //-------------------------------------------------------------------------- 112 | // callback for graph 113 | static int idaapi callback(void *, int code, va_list va) 114 | { 115 | int result = 0; 116 | switch ( code ) 117 | { 118 | // gotfocus is used to get global form- and graphview pointers 119 | case grcode_gotfocus: 120 | { 121 | // always get current form and gv 122 | // because "reset desktop" may close 123 | // the current form and thus invalidate 124 | // its old handle. 125 | form = get_current_tform(); 126 | if(form == NULL) 127 | break; 128 | gv = get_graph_viewer(form); 129 | if ( gv != NULL && (!newmenu) ) 130 | { 131 | if(viewer_add_menu_item(gv, MENU_ITEM_CAPTION, menu_callback, gv, 0)) 132 | newmenu = true; 133 | } 134 | break; 135 | } 136 | break; 137 | // user selected a different graph / function 138 | // -> render graph with layout chosen by user 139 | case grcode_changed_graph: 140 | { 141 | if( gv == NULL ) 142 | break; 143 | 144 | mutable_graph_t *g = get_viewer_graph(gv); 145 | 146 | if( g == NULL ) 147 | break; 148 | 149 | switch( layout ) 150 | { 151 | case layout_circle: // circle 152 | doCircleLayout(g, point_t(200, 200), 2000); 153 | break; 154 | case layout_tree: // tree 155 | doTreeLayout(g); 156 | break; 157 | case layout_digraph: // digraph 158 | doDigraphLayout(g); 159 | break; 160 | } 161 | } 162 | break; 163 | } 164 | return result; 165 | } 166 | 167 | 168 | //-------------------------------------------------------------------------- 169 | int idaapi init(void) 170 | { 171 | if ( !hooked ) 172 | hooked = hook_to_notification_point(HT_GRAPH, callback, NULL); 173 | 174 | return ( hooked ) ? PLUGIN_KEEP : PLUGIN_SKIP; 175 | } 176 | 177 | //-------------------------------------------------------------------------- 178 | void idaapi term(void) 179 | { 180 | if ( hooked ) 181 | unhook_from_notification_point(HT_GRAPH, callback); 182 | } 183 | 184 | //-------------------------------------------------------------------------- 185 | void idaapi run(int /*arg*/) 186 | { 187 | msg("Additional graph layouts are %s.\n" 188 | "Right click on a graph and select \"%s\".", 189 | (newmenu) ? "enabled" : "disabled", 190 | MENU_ITEM_CAPTION); 191 | } 192 | 193 | //-------------------------------------------------------------------------- 194 | char comment[] = "This plugin allows you to switch the current graph's layout"; 195 | 196 | char help[] = 197 | "This plugin allows you to switch the current graph's layout"; 198 | 199 | 200 | //-------------------------------------------------------------------------- 201 | // This is the preferred name of the plugin module in the menu system 202 | // The preferred name may be overriden in plugins.cfg file 203 | 204 | char wanted_name[] = "Set graph layout"; 205 | 206 | 207 | // This is the preferred hotkey for the plugin module 208 | // The preferred hotkey may be overriden in plugins.cfg file 209 | // Note: IDA won't tell you if the hotkey is not correct 210 | // It will just disable the hotkey. 211 | 212 | char wanted_hotkey[] = ""; 213 | 214 | 215 | //-------------------------------------------------------------------------- 216 | // 217 | // PLUGIN DESCRIPTION BLOCK 218 | // 219 | //-------------------------------------------------------------------------- 220 | plugin_t PLUGIN = 221 | { 222 | IDP_INTERFACE_VERSION, 223 | 0, // plugin flags 224 | init, // initialize 225 | 226 | term, // terminate. this pointer may be NULL. 227 | 228 | run, // invoke plugin 229 | 230 | comment, // long comment about the plugin 231 | // it could appear in the status line 232 | // or as a hint 233 | 234 | help, // multiline help about the plugin 235 | 236 | wanted_name, // the preferred short name of the plugin 237 | wanted_hotkey // the preferred hotkey to run the plugin 238 | }; 239 | -------------------------------------------------------------------------------- /graphtest2/flowgraph,cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Graphtest 2 - flowgraph 3 | * 4 | * Author: Dennis Elser, 06/2006 5 | * 6 | * This example displays a custom flowgraph of the 7 | * currently "active" function. Each basic block contains 8 | * the following information (instead of disassembly): 9 | * 10 | * 1.) Node number 11 | * 2.) Start Address 12 | * 3.) End Address 13 | * 4.) Number of instructions 14 | * 5.) Indegree (incoming edges) 15 | * 6.) Outdegree (outgoing edges) 16 | * 17 | * The color of a basic block / node indicates the number 18 | * of edges: 19 | * 20 | * blue = node has either incoming or outgoing edges only (single direction) 21 | * white = node has incoming and outgoing edges, but less than five 22 | * yellow = node has incoming and outgoing edges, but more than four 23 | * grey = indegree of node matches outdegree 24 | * 25 | * Feel free to modify! 26 | * 27 | * Released on The IDA Palace (www.backtrace.de). 28 | * 29 | * nb: parts of the code have been taken from Ilfak Guilvanov's Coverage Analyzer "Coverit". 30 | * You can get Coverit at www.hexblog.com 31 | * 32 | */ 33 | 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | 43 | typedef std::map basic_blocks_t; 44 | 45 | //-------------------------------------------------------------------------- 46 | static bool hooked = false; 47 | static std::vector graph_text; 48 | static basic_blocks_t bbs; 49 | static netnode id; 50 | 51 | //-------------------------------------------------------------------------- 52 | static bool gather_basic_blocks(ea_t ea1, ea_t ea2) 53 | { 54 | show_wait_box("Finding basic blocks"); 55 | ea_t start = BADADDR; 56 | bool ok = true; 57 | int cnt = 0; 58 | while ( ea1 != ea2 ) 59 | { 60 | if ( wasBreak() ) 61 | { 62 | ok = false; 63 | break; 64 | } 65 | //if ( ++cnt == 1000 ) 66 | { 67 | showAddr(ea1); 68 | cnt = 0; 69 | } 70 | if ( start == BADADDR ) 71 | { 72 | start = ea1; 73 | ea1 = nextthat(ea1, ea2, f_isCode, NULL); 74 | if ( ea1 >= ea2 ) 75 | break; 76 | //start = ea1; 77 | } 78 | while ( ea1 < ea2 ) 79 | { 80 | if ( !ua_ana0(ea1) ) 81 | break; 82 | ea1 = get_item_end(ea1); 83 | if ( is_basic_block_end(false) ) 84 | break; 85 | } 86 | if ( ea1 != start ) 87 | bbs[start] = ea1 - start; // remember the bb start and size 88 | if ( !isCode(get_flags_novalue(ea1)) ) 89 | start = BADADDR; 90 | else 91 | start = ea1; 92 | } 93 | hide_wait_box(); 94 | return ok; 95 | } 96 | 97 | 98 | //-------------------------------------------------------------------------- 99 | // wrapper for gather_basic_blocks() 100 | static void update_basic_blocks(void) 101 | { 102 | bbs.clear(); 103 | func_t *f = NULL; 104 | 105 | f = get_func(get_screen_ea()); 106 | if( f != NULL ) 107 | { 108 | if( gather_basic_blocks( f->startEA, f->endEA ) ) 109 | { 110 | //msg("List of basic blocks:\n"); 111 | for ( basic_blocks_t::iterator p=bbs.begin(); p != bbs.end(); ++p ) 112 | { 113 | size_t i = p->first;// - base; 114 | //msg("%08X: (end: %08X)\n",i,i+p->second); 115 | } 116 | } 117 | 118 | } 119 | 120 | } 121 | 122 | 123 | //-------------------------------------------------------------------------- 124 | // return number of instructions within two addresses 125 | static size_t get_num_insns(ea_t start, ea_t end) 126 | { 127 | ea_t cur = start; 128 | size_t insns = 0; 129 | 130 | while( cur != BADADDR ) 131 | { 132 | if(isCode(getFlags(cur))) 133 | insns++; 134 | start = cur; 135 | cur=next_head( start, end ); 136 | } 137 | 138 | return insns; 139 | } 140 | 141 | 142 | 143 | //-------------------------------------------------------------------------- 144 | static int idaapi callback(void *, int code, va_list va) 145 | { 146 | int result = 0; 147 | switch ( code ) 148 | { 149 | 150 | case grcode_user_refresh: // refresh user-defined graph nodes and edges 151 | // in: mutable_graph_t *g 152 | // out: success 153 | { 154 | mutable_graph_t *g = va_arg(va, mutable_graph_t *); 155 | msg("%x: refresh\n", g); 156 | 157 | if ( g->empty() ) 158 | g->resize( (int)(bbs.size()) ); 159 | 160 | int j=0; 161 | for ( basic_blocks_t::iterator p=bbs.begin(); p != bbs.end(); ++p ) 162 | { 163 | //size_t i = p->first;// - base; 164 | //msg("%08X: (end: %08X)\n",i,i+p->second); 165 | xrefblk_t xb; 166 | for ( bool ok=xb.first_from(prevthat(p->first+p->second, 0, f_isCode, NULL), XREF_ALL); ok; ok=xb.next_from() ) 167 | { 168 | //xb.to - contains the referenced address 169 | int k=0; 170 | for ( basic_blocks_t::iterator p2=bbs.begin(); p2 != bbs.end(); ++p2 ) 171 | { 172 | if( xb.to == p2->first ) 173 | { 174 | g->add_edge(j, k, NULL); 175 | msg("%08x: -> %08X\n", prevthat(p->first+p->second, 0, f_isCode, NULL), xb.to); 176 | } 177 | k++; 178 | } 179 | } 180 | j++; 181 | } 182 | result = true; 183 | } 184 | break; 185 | 186 | case grcode_user_gentext: // generate text for user-defined graph nodes 187 | // in: mutable_graph_t *g 188 | // out: must return 0 189 | { 190 | mutable_graph_t *g = va_arg(va, mutable_graph_t *); 191 | msg("%x: generate text for graph nodes\n", g); 192 | graph_text.resize(g->size()); 193 | 194 | for ( node_iterator p=g->begin(); p != g->end(); ++p ) 195 | { 196 | int n = *p; 197 | char buf[MAXSTR]; 198 | 199 | qsnprintf(buf,sizeof(buf),"Node %8d\n",n); 200 | graph_text[n] = buf; 201 | 202 | int j=0; 203 | for ( basic_blocks_t::iterator bbi=bbs.begin(); bbi != bbs.end(); ++bbi ) 204 | { 205 | if(n==j) 206 | { 207 | qsnprintf(buf, sizeof(buf), "StartEA %08X\n" 208 | "EndEA %08X\n", 209 | bbi->first, 210 | bbi->first+bbi->second); 211 | graph_text[n] += buf; 212 | qsnprintf(buf,sizeof(buf),"Instr %8d\n",get_num_insns(bbi->first,bbi->first+bbi->second)); 213 | graph_text[n] += buf; 214 | break; 215 | } 216 | j++; 217 | } 218 | 219 | qsnprintf(buf, sizeof(buf),"Indeg %8d\n" 220 | "Outdeg %8d\n", 221 | g->npred(n), 222 | g->nsucc(n) 223 | ); 224 | 225 | 226 | graph_text[n] += buf; 227 | 228 | } 229 | result = true; 230 | } 231 | break; 232 | 233 | case grcode_user_text: // retrieve text for user-defined graph node 234 | // in: mutable_graph_t *g 235 | // int node 236 | // const char **result 237 | // bgcolor_t *bg_color (maybe NULL) 238 | // out: must return 0, result must be filled 239 | // NB: do not use anything calling GDI! 240 | { 241 | mutable_graph_t *g = va_arg(va, mutable_graph_t *); 242 | int node = va_argi(va, int); 243 | const char **text = va_arg(va, const char **); 244 | bgcolor_t *bgcolor = va_arg(va, bgcolor_t *); 245 | 246 | int succ = g->nsucc(node); 247 | int pred = g->npred(node); 248 | 249 | *text = graph_text[node].c_str(); 250 | 251 | if ( bgcolor != NULL ) 252 | { 253 | // same indegree as outdegree and != 0 ? 254 | if(pred == succ && pred != 0) 255 | *bgcolor = RGB(220, 220, 220); 256 | 257 | // a few edges only 258 | else if( succ <= 2 && pred <= 2 ) 259 | { 260 | if( succ == 0 || pred == 0 ) 261 | { 262 | // nodes with no edges at all 263 | if(pred == succ) 264 | *bgcolor = RGB(255, 50, 50); 265 | // nodes with either in- or outdegree edges only 266 | else 267 | *bgcolor = RGB(0, 130, 255); 268 | } 269 | // "normal" node, default color 270 | else 271 | *bgcolor = DEFCOLOR; 272 | } 273 | // in- or outdegree > 2 274 | else 275 | *bgcolor = RGB( 255, 255, 0 ); 276 | } 277 | 278 | result = true; 279 | qnotused(g); 280 | } 281 | break; 282 | 283 | 284 | case grcode_dblclicked: // a graph node has been double clicked 285 | // in: graph_viewer_t *gv 286 | // selection_item_t *current_item 287 | // out: 0-ok, 1-ignore click 288 | { 289 | graph_viewer_t *v = va_arg(va, graph_viewer_t *); 290 | selection_item_t *s = va_arg(va, selection_item_t *); 291 | 292 | if ( s->is_node ) 293 | { 294 | int j=0; 295 | 296 | for ( basic_blocks_t::iterator bbi=bbs.begin(); bbi != bbs.end(); ++bbi ) 297 | { 298 | if(s->node==j) 299 | { 300 | //jump to dblclicked node in disassembly/IDA graph view 301 | jumpto(bbi->first,-1); 302 | break; 303 | } 304 | j++; 305 | } 306 | } 307 | 308 | } 309 | break; 310 | 311 | } 312 | return result; 313 | } 314 | 315 | 316 | //-------------------------------------------------------------------------- 317 | int idaapi init(void) 318 | { 319 | // stay in the memory since we have hooks 320 | return PLUGIN_KEEP; 321 | } 322 | 323 | //-------------------------------------------------------------------------- 324 | void idaapi term(void) 325 | { 326 | if ( hooked ) 327 | unhook_from_notification_point(HT_GRAPH, callback); 328 | } 329 | 330 | 331 | //-------------------------------------------------------------------------- 332 | void idaapi run(int /*arg*/) 333 | { 334 | 335 | HWND hwnd = NULL; 336 | graph_viewer_t *gv = NULL; 337 | TForm *form = NULL; 338 | 339 | update_basic_blocks(); 340 | 341 | form = create_tform("Graphtest 2", &hwnd); 342 | if ( hwnd != NULL ) 343 | { 344 | if ( !hooked ) 345 | { 346 | hooked = true; 347 | hook_to_notification_point(HT_GRAPH, callback, NULL); 348 | } 349 | // get a unique graph id 350 | id.create(); 351 | gv = create_graph_viewer( form, id ); 352 | open_tform( form, FORM_MDI|FORM_TAB|FORM_MENU ); 353 | if ( gv != NULL ) 354 | { 355 | viewer_fit_window( gv ); 356 | } 357 | } 358 | else 359 | { 360 | if( int x = askyn_cv(0,"Close the current graph? Select 'No' to refresh the graph.",0) == 1 ) 361 | close_tform(form, 0); 362 | else if(x == 0) 363 | { 364 | gv = create_graph_viewer( form, id ); 365 | refresh_viewer( gv ); 366 | } 367 | } 368 | } 369 | 370 | //-------------------------------------------------------------------------- 371 | char comment[] = "custom flowgrapher"; 372 | 373 | char help[] = 374 | "Graphtest 2\n" 375 | "\n" 376 | "Shows you how to create custom graphs\n" 377 | "See sourcecode for details ;)"; 378 | 379 | 380 | //-------------------------------------------------------------------------- 381 | // This is the preferred name of the plugin module in the menu system 382 | // The preferred name may be overriden in plugins.cfg file 383 | 384 | char wanted_name[] = "Custom graph"; 385 | 386 | 387 | // This is the preferred hotkey for the plugin module 388 | // The preferred hotkey may be overriden in plugins.cfg file 389 | // Note: IDA won't tell you if the hotkey is not correct 390 | // It will just disable the hotkey. 391 | 392 | char wanted_hotkey[] = "6"; 393 | 394 | 395 | //-------------------------------------------------------------------------- 396 | // 397 | // PLUGIN DESCRIPTION BLOCK 398 | // 399 | //-------------------------------------------------------------------------- 400 | plugin_t PLUGIN = 401 | { 402 | IDP_INTERFACE_VERSION, 403 | 0, // plugin flags 404 | init, // initialize 405 | 406 | term, // terminate. this pointer may be NULL. 407 | 408 | run, // invoke plugin 409 | 410 | comment, // long comment about the plugin 411 | // it could appear in the status line 412 | // or as a hint 413 | 414 | help, // multiline help about the plugin 415 | 416 | wanted_name, // the preferred short name of the plugin 417 | wanted_hotkey // the preferred hotkey to run the plugin 418 | }; 419 | -------------------------------------------------------------------------------- /graphtest2/pegraph.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Graphtest 2 - pegraph 3 | * 4 | * Author: Dennis Elser, 06/2006 5 | * 6 | * This example displays parts of the pe header in a graph. 7 | * Feel free to modify! 8 | * 9 | * Released on The IDA Palace (www.backtrace.de). 10 | * 11 | */ 12 | 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include <../ldr/pe.h> 22 | 23 | //-------------------------------------------------------------------------- 24 | static bool hooked = false; 25 | static std::vector graph_text; 26 | static peheader_t pe; 27 | 28 | 29 | //-------------------------------------------------------------------------- 30 | static int idaapi callback(void *, int code, va_list va) 31 | { 32 | int result = 0; 33 | switch ( code ) 34 | { 35 | 36 | case grcode_user_refresh: // refresh user-defined graph nodes and edges 37 | // in: mutable_graph_t *g 38 | // out: success 39 | { 40 | mutable_graph_t *g = va_arg(va, mutable_graph_t *); 41 | 42 | if ( !g->empty() ) 43 | break; 44 | 45 | for( int i=0; i<=get_segm_qty(); i++ ) 46 | { 47 | g->add_node( NULL ); 48 | } 49 | 50 | 51 | for( int i = 0; icontains(pe.imagebase32 + pe.entry) ) 54 | g->add_edge(0, i+1, NULL); 55 | } 56 | 57 | result = true; 58 | } 59 | break; 60 | 61 | case grcode_user_gentext: // generate text for user-defined graph nodes 62 | // in: mutable_graph_t *g 63 | // out: must return 0 64 | { 65 | mutable_graph_t *g = va_arg(va, mutable_graph_t *); 66 | graph_text.resize(g->size()); 67 | 68 | char buf[MAXSTR]; 69 | char temp[MAXSTR]; 70 | 71 | 72 | qsnprintf( buf, 73 | sizeof(buf), 74 | COLSTR("PE Header\n",SCOLOR_UNAME) 75 | "--------------------\n" 76 | "Imagebase : %08X\n" 77 | "Entrypoint: %08X\n" 78 | "EA : %08X\n", 79 | pe.imagebase32, 80 | pe.entry, 81 | pe.imagebase32 + pe.entry ); 82 | 83 | graph_text[0] = buf; 84 | 85 | 86 | for( int i = 0; istartEA, 97 | getnseg(i)->endEA, 98 | (getnseg(i)->perm & SEGPERM_EXEC) ? COLSTR("yes", SCOLOR_CREFTAIL) : COLSTR("no",SCOLOR_DNUM) ); 99 | graph_text[i+1] = buf; 100 | } 101 | 102 | result = true; 103 | } 104 | break; 105 | 106 | case grcode_user_text: // retrieve text for user-defined graph node 107 | // in: mutable_graph_t *g 108 | // int node 109 | // const char **result 110 | // bgcolor_t *bg_color (maybe NULL) 111 | // out: must return 0, result must be filled 112 | // NB: do not use anything calling GDI! 113 | { 114 | mutable_graph_t *g = va_arg(va, mutable_graph_t *); 115 | int node = va_arg(va, int); 116 | const char **text = va_arg(va, const char **); 117 | bgcolor_t *bgcolor = va_arg(va, bgcolor_t *); 118 | *text = graph_text[node].c_str(); 119 | if ( bgcolor != NULL ) 120 | *bgcolor = DEFCOLOR; 121 | result = true; 122 | qnotused(g); 123 | } 124 | break; 125 | 126 | 127 | } 128 | return result; 129 | } 130 | 131 | 132 | 133 | //-------------------------------------------------------------------------- 134 | int idaapi init(void) 135 | { 136 | if ( inf.filetype != f_PE ) 137 | return PLUGIN_SKIP; 138 | return PLUGIN_KEEP; 139 | } 140 | 141 | //-------------------------------------------------------------------------- 142 | void idaapi term(void) 143 | { 144 | if ( hooked ) 145 | unhook_from_notification_point(HT_GRAPH, callback); 146 | } 147 | 148 | //-------------------------------------------------------------------------- 149 | void idaapi run(int /*arg*/) 150 | { 151 | netnode penode; 152 | 153 | penode.create(PE_NODE); 154 | 155 | if ( penode.valobj(&pe, sizeof(pe)) <= 0 ) 156 | { 157 | msg("Could not get PE Header from IDB!\n"); 158 | return; 159 | } 160 | 161 | HWND hwnd = NULL; 162 | TForm *form = create_tform("pegraph", &hwnd); 163 | if ( hwnd != NULL ) 164 | { 165 | if ( !hooked ) 166 | { 167 | hooked = true; 168 | hook_to_notification_point(HT_GRAPH, callback, NULL); 169 | } 170 | // get a unique graph id 171 | netnode id; 172 | id.create(); 173 | graph_viewer_t *gv = create_graph_viewer(form, id); 174 | open_tform(form, FORM_MDI|FORM_TAB|FORM_MENU); 175 | if ( gv != NULL ) 176 | { 177 | viewer_fit_window(gv); 178 | } 179 | } 180 | else 181 | { 182 | close_tform(form, 0); 183 | } 184 | } 185 | 186 | //-------------------------------------------------------------------------- 187 | char comment[] = "pegraph."; 188 | 189 | char help[] = 190 | "A sample graph plugin module\n" 191 | "\n" 192 | "This module shows you how to create a graph viewer."; 193 | 194 | 195 | //-------------------------------------------------------------------------- 196 | // This is the preferred name of the plugin module in the menu system 197 | // The preferred name may be overriden in plugins.cfg file 198 | 199 | char wanted_name[] = "pegraph"; 200 | 201 | 202 | // This is the preferred hotkey for the plugin module 203 | // The preferred hotkey may be overriden in plugins.cfg file 204 | // Note: IDA won't tell you if the hotkey is not correct 205 | // It will just disable the hotkey. 206 | 207 | char wanted_hotkey[] = "7"; 208 | 209 | 210 | //-------------------------------------------------------------------------- 211 | // 212 | // PLUGIN DESCRIPTION BLOCK 213 | // 214 | //-------------------------------------------------------------------------- 215 | plugin_t PLUGIN = 216 | { 217 | IDP_INTERFACE_VERSION, 218 | 0, // plugin flags 219 | init, // initialize 220 | 221 | term, // terminate. this pointer may be NULL. 222 | 223 | run, // invoke plugin 224 | 225 | comment, // long comment about the plugin 226 | // it could appear in the status line 227 | // or as a hint 228 | 229 | help, // multiline help about the plugin 230 | 231 | wanted_name, // the preferred short name of the plugin 232 | wanted_hotkey // the preferred hotkey to run the plugin 233 | }; 234 | -------------------------------------------------------------------------------- /segdump/readme: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////// 2 | // 3 | // Segdump plugin for IDA PRO 4 | // written by Dennis Elser. 5 | // 6 | // ------------------------------------------- 7 | // 8 | // This plugin can create dumps of (memory) 9 | // segments on your harddisk. 10 | // This can be useful when unpacking packed 11 | // executables. 12 | // 13 | // ------------------------------------------- 14 | // 15 | // history: 16 | // -------- 17 | // - 12.10.2004: 18 | // * initial version 19 | // 20 | // - 13.10.2004 21 | // * fixed a bug in bool dump_seg_to_disk() 22 | // where the filehandle wasn't closed. 23 | // * The dialog now shows start and 24 | // end addresses. 25 | // * commented the code ;-) 26 | // 27 | // (c) 2004, Dennis Elser 28 | // 29 | ////////////////////////////////////////////////// -------------------------------------------------------------------------------- /segdump/screenshot/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patois/idaplugins/ef187498036ca7f84b620040c15ba444b968398c/segdump/screenshot/screenshot.png -------------------------------------------------------------------------------- /segdump/src/segdump.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////// 2 | // 3 | // Segdump plugin for IDA PRO 4 | // written by Dennis Elser. 5 | // 6 | // ------------------------------------------- 7 | // 8 | // This plugin can create dumps of (memory) 9 | // segments on your harddisk. 10 | // This can be useful when unpacking packed 11 | // executables. 12 | // 13 | // 14 | // ------------------------------------------- 15 | // 16 | // history: 17 | // -------- 18 | // - 12.10.2004: 19 | // * initial version 20 | // 21 | // - 13.10.2004 22 | // * fixed a bug in bool dump_seg_to_disk() 23 | // where the filehandle wasn't closed. 24 | // * The dialog now shows start and 25 | // end addresses. 26 | // * commented the code ;-) 27 | // 28 | // (c) 2004, Dennis Elser 29 | // 30 | ////////////////////////////////////////////////// 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "segdump.hpp" 40 | 41 | //headline for the listbox 42 | const char *headline[]={"Name of segment","Start address","End address"}; 43 | //popup menu strings 44 | const char *popupnames[]={"x","y","Dump segment to disk","Refresh"}; 45 | 46 | 47 | //returns the size of a segment in bytes 48 | int getsegsize(segment_t *segment) 49 | { 50 | return (segment->endEA - segment->startEA); 51 | } 52 | 53 | //allocates memory and stores a copy of each 54 | //byte of the given area 55 | uchar *get_segment_data(ea_t s_a, ea_t e_a, ea_t size) 56 | { 57 | uchar *mem; 58 | 59 | mem = (uchar *)malloc(size+1); 60 | 61 | get_many_bytes(s_a,mem,size); 62 | return mem; 63 | } 64 | 65 | 66 | //saves a segment to harddisk 67 | bool dump_seg_to_disk(ulong n) 68 | { 69 | segment_t *curseg; 70 | uchar *segdata; 71 | char *answer; 72 | FILE *file; 73 | 74 | curseg = getnseg(n); 75 | 76 | //show "save file" dialog 77 | answer = askfile_cv(1,get_segm_name(curseg),"Enter a filename for the segment:",0); 78 | if(answer == NULL) 79 | { 80 | return false; 81 | } 82 | 83 | //get copy of segment and save it to disk 84 | segdata = get_segment_data(curseg->startEA, curseg->endEA, getsegsize(curseg)); 85 | file = fopenWB(answer); 86 | ewrite(file, segdata, getsegsize(curseg)); 87 | eclose(file); 88 | free(segdata); 89 | return true; 90 | } 91 | 92 | //callback function for choose2() / popup menu item 93 | void dump_seg(void *obj,ulong n) 94 | { 95 | line *ptr = (line *)obj; 96 | bool dumped; 97 | 98 | msg("Dumping segment %s to disk...", (char *)ptr[n].segname); 99 | //dump 100 | dumped = dump_seg_to_disk(n-1); 101 | 102 | msg("%s\n",dumped?"done":"failed"); 103 | } 104 | 105 | 106 | //build an object for the listbox 107 | //and fill it with appropriate data: 108 | //headline | headline | headline 109 | //name of segment start address end address 110 | //... ... ... 111 | line *build_segm_obj(void) 112 | { 113 | int i; 114 | int seg_qty = get_segm_qty(); 115 | line *obj; 116 | char addrbuf[10]; 117 | segment_t *curseg; 118 | 119 | //allocate seg_qty lines +1 (for the header line) 120 | obj = (line *)malloc(sizeof(line)*(seg_qty+1)); 121 | 122 | //first line will be filled with headline captions 123 | strcpy( (char *)obj[0].segname, headline[0]); 124 | strcpy( (char *)obj[0].startEA,headline[1]); 125 | strcpy( (char *)obj[0].endEA,headline[2]); 126 | 127 | //the following lines will contain name of segment, 128 | //start- and end address of segments 129 | for(i=1;i<=seg_qty;i++) 130 | { 131 | curseg = getnseg(i-1); 132 | strcpy( (char *)obj[i].segname, get_true_segm_name(curseg)); 133 | sprintf(addrbuf,"%08X",curseg->startEA); 134 | strcpy( (char *)obj[i].startEA, addrbuf); 135 | sprintf(addrbuf,"%08X",curseg->endEA); 136 | strcpy( (char *)obj[i].endEA, addrbuf); 137 | 138 | } 139 | //return pointer to object 140 | return obj; 141 | } 142 | 143 | //callback function for choose2() -> number of lines 144 | ulong get_item_qty(void *obj) 145 | { 146 | return get_segm_qty(); 147 | } 148 | 149 | //callback function for choose2() -> returns the n-th line 150 | void getn_item_text(void *obj,ulong n,char * const*buf) 151 | { 152 | line *ptr = (line *)obj; 153 | line *bufptr = (line *)buf; 154 | 155 | strcpy((char *)buf[0],(char *)ptr[n].segname); 156 | strcpy((char *)buf[1],(char *)ptr[n].startEA); 157 | strcpy((char *)buf[2],(char *)ptr[n].endEA); 158 | return; 159 | } 160 | 161 | 162 | int idaapi init(void) 163 | { 164 | return PLUGIN_KEEP; 165 | } 166 | 167 | 168 | void idaapi term(void) 169 | { 170 | 171 | } 172 | 173 | void idaapi run(int arg) 174 | { 175 | 176 | //Credits to Halvar for his choose2() example code! 177 | 178 | //build the listbox object! 179 | line *obj = build_segm_obj(); 180 | 181 | choose2( 182 | CH_MODAL, 183 | -1,30, // x0=-1 for autoposition 184 | 50,70, 185 | obj, // our listbox object 186 | 3, // Number of columns 187 | NULL, // Widths of columns (may be NULL) 188 | get_item_qty,// Number of items 189 | getn_item_text, // get string of n-th item (1..n) 190 | // 0-th item if header line 191 | "DumpSeg Plugin by Dennis Elser", // menu title (includes ptr to help) 192 | 21, // number of icon to display 193 | 1, // starting item 194 | NULL, // multi-selection callback for "Delete" (may be NULL) 195 | NULL, // callback for "New" (may be NULL) 196 | NULL,// callback for "Update"(may be NULL) 197 | // update the whole list 198 | // returns the new location of item 'n' 199 | dump_seg, // callback for "Edit" (may be NULL) 200 | NULL, // callback for non-modal "Enter" (may be NULL) 201 | NULL, // callback to call when the window is closed (may be NULL) 202 | popupnames, // Default: insert, delete, edit, refresh 203 | NULL); 204 | 205 | //free and destroy listbox object 206 | free(obj); 207 | return; 208 | 209 | } 210 | 211 | //-------------------------------------------------------------------------- 212 | char comment[] = "Segment dumper plugin by Dennis Elser"; 213 | 214 | char help[] = 215 | "With this plugin you can dump (memory) segments to disc\n"; 216 | 217 | char wanted_name[] = "Dump segment to disk"; 218 | 219 | char wanted_hotkey[] = "Alt-4"; 220 | 221 | 222 | plugin_t PLUGIN = 223 | { 224 | IDP_INTERFACE_VERSION, 225 | 0, // plugin flags 226 | init, // initialize 227 | 228 | term, // terminate. this pointer may be NULL. 229 | 230 | run, // invoke plugin 231 | 232 | comment, // long comment about the plugin 233 | // it could appear in the status line 234 | // or as a hint 235 | 236 | help, // multiline help about the plugin 237 | 238 | wanted_name, // the preferred short name of the plugin 239 | wanted_hotkey // the preferred hotkey to run the plugin 240 | }; 241 | -------------------------------------------------------------------------------- /segdump/src/segdump.hpp: -------------------------------------------------------------------------------- 1 | struct line 2 | { 3 | char segname[MAXSTR]; 4 | char startEA[30]; 5 | char endEA[30]; 6 | }; 7 | -------------------------------------------------------------------------------- /snapshot/readme: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////// 2 | // 3 | // Snapshot! plugin for IDA PRO 4 | // written by Dennis Elser. 5 | // 6 | // ------------------------------------------- 7 | // 8 | // This plugin creates a snapshot of a 9 | // running process on your harddisk, which 10 | // can later be restored again. 11 | // You can also analyse and compare different 12 | // dumps. 13 | // 14 | // ------------------------------------------- 15 | // 16 | // history: 17 | // -------- 18 | // - 10.10.2004: 19 | // initial version 20 | // 21 | // 22 | // (c) 2004, Dennis Elser 23 | // 24 | ////////////////////////////////////////////////// -------------------------------------------------------------------------------- /snapshot/src/snapshot.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////// 2 | // 3 | // Snapshot! plugin for IDA PRO 4 | // written by Dennis Elser. 5 | // 6 | // ------------------------------------------- 7 | // 8 | // This plugin creates a snapshot of a 9 | // running process on your harddisk, which 10 | // can later be restored again. 11 | // You can also analyse and compare different 12 | // dumps. 13 | // 14 | // 15 | // ------------------------------------------- 16 | // 17 | // history: 18 | // -------- 19 | // - 10.10.2004: 20 | // initial version 21 | // 22 | // 23 | // (c) 2004, Dennis Elser 24 | // 25 | ////////////////////////////////////////////////// 26 | 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | 38 | const char dlg[] = //Taken from J.C.Roberts' Examples, thanks! 39 | "STARTITEM 0\n" 40 | "HELP\n" // Help 41 | "This plugin can create a snapshot of the current process\n" 42 | "and revert to this state at a later point of time.\n" 43 | "ENDHELP\n" 44 | 45 | "Snapshot!\n" // Title 46 | "Snapshot! plugin by Dennis Elser.\n\n" // Dialog Text 47 | 48 | " Please select\n" // Dialog Text 49 | // Group #1 Radio Buttons NOTE: using capital "R" 50 | "<#Create a snapshot of the current process.#" // hint radio0 51 | "Create a snapshot:R>" // text radio0 52 | 53 | "<#Create a complete dump of the current process.#" // hint radio0 54 | "Create a complete snapshot:R>" // text radio0 55 | 56 | "<#Revert to a previous state.#" // hint radio1 57 | "Revert:R>>\n\n\n\n\n" // text radio1 58 | 59 | ; // End Dialog Format String 60 | 61 | 62 | 63 | 64 | uchar *free_data(uchar *mem) 65 | { 66 | if(mem!=NULL) free(mem); 67 | return NULL; 68 | } 69 | 70 | 71 | uchar *get_segment_data(ea_t s_a, ea_t e_a, ea_t size) 72 | { 73 | int i; 74 | uchar *mem; 75 | 76 | mem = (uchar *)malloc(size+1); 77 | 78 | get_many_bytes(s_a,mem,size); 79 | return mem; 80 | for(i=s_a;i<=e_a;i++) 81 | { 82 | mem[i-s_a]=get_byte(i); 83 | } 84 | return mem; 85 | } 86 | 87 | uchar *get_file_data(FILE *file, ea_t size) 88 | { 89 | uchar *mem; 90 | 91 | mem = (uchar *)malloc(size+1); 92 | eread(file,mem,size); 93 | return mem; 94 | } 95 | 96 | 97 | int getsegsize(segment_t *segment) 98 | { 99 | return (segment->endEA - segment->startEA); 100 | } 101 | 102 | ea_t getreg(char *regname) 103 | { 104 | regval_t eip; 105 | get_reg_val(regname,&eip); 106 | return eip.ival; 107 | } 108 | 109 | void setreg(const char *regname, ea_t regval) 110 | { 111 | set_reg_val(regname, regval); 112 | } 113 | 114 | bool save_reg(char *filename) 115 | { 116 | FILE *reg; 117 | ea_t regval; 118 | char regfile[MAXSTR]; 119 | 120 | strcpy(regfile,filename); 121 | 122 | strcat(regfile,".reg"); 123 | 124 | reg = fopenWB(regfile); 125 | ewrite(reg, &(regval=getreg("eax")),sizeof(ea_t)); 126 | ewrite(reg, &(regval=getreg("ebx")),sizeof(ea_t)); 127 | ewrite(reg, &(regval=getreg("ecx")),sizeof(ea_t)); 128 | ewrite(reg, &(regval=getreg("edx")),sizeof(ea_t)); 129 | ewrite(reg, &(regval=getreg("esi")),sizeof(ea_t)); 130 | ewrite(reg, &(regval=getreg("edi")),sizeof(ea_t)); 131 | ewrite(reg, &(regval=getreg("ebp")),sizeof(ea_t)); 132 | ewrite(reg, &(regval=getreg("esp")),sizeof(ea_t)); 133 | ewrite(reg, &(regval=getreg("eip")),sizeof(ea_t)); 134 | ewrite(reg, &(regval=getreg("efl")),sizeof(ea_t)); 135 | eclose(reg); 136 | 137 | return true; 138 | } 139 | 140 | 141 | bool load_reg(char *filename) 142 | { 143 | FILE *reg; 144 | ea_t regval; 145 | char regfile[MAXSTR]; 146 | 147 | strcpy(regfile,filename); 148 | 149 | if(hasExt(regfile) != NULL) 150 | strcpy ((char *)hasExt(regfile),"reg"); 151 | 152 | reg = fopenRB(regfile); 153 | 154 | eread(reg, ®val,4); 155 | setreg("eax",regval); 156 | eread(reg, ®val,4); 157 | setreg("ebx",regval); 158 | eread(reg, ®val,4); 159 | setreg("ecx",regval); 160 | eread(reg, ®val,4); 161 | setreg("edx",regval); 162 | eread(reg, ®val,4); 163 | setreg("esi",regval); 164 | eread(reg, ®val,4); 165 | setreg("edi",regval); 166 | eread(reg, ®val,4); 167 | setreg("ebp",regval); 168 | eread(reg, ®val,4); 169 | setreg("esp",regval); 170 | eread(reg, ®val,4); 171 | setreg("eip",regval); 172 | eread(reg, ®val,4); 173 | setreg("efl",regval); 174 | 175 | eclose(reg); 176 | 177 | return true; 178 | } 179 | 180 | bool save_cfgdata(char *filename, bool dumpall) 181 | { 182 | segment_t *curseg; 183 | int segqty; 184 | ea_t i; 185 | FILE *cfg; 186 | FILE *snp; 187 | uchar *segdata; 188 | char cfgfile[MAXSTR]; 189 | char snpfile[MAXSTR]; 190 | 191 | 192 | strcpy(cfgfile,filename); 193 | strcpy(snpfile,filename); 194 | 195 | strcat(cfgfile,".cfg"); 196 | strcat(snpfile,".snp"); 197 | 198 | cfg = fopenWB(cfgfile); 199 | snp = fopenWB(snpfile); 200 | 201 | segqty = get_segm_qty(); 202 | for(i=0;iperm & SEGPERM_WRITE) && (curseg->perm & SEGPERM_READ) ) 206 | { 207 | msg("Saving %s [%08X %08X]...",get_true_segm_name(curseg),curseg->startEA,curseg->endEA); 208 | ewrite(cfg, &curseg->startEA,sizeof(curseg->startEA) ); 209 | ewrite(cfg, &curseg->endEA,sizeof(curseg->endEA) ); 210 | segdata = get_segment_data(curseg->startEA, curseg->endEA, getsegsize(curseg)); 211 | ewrite(snp, segdata, getsegsize(curseg)); 212 | free_data(segdata); 213 | msg("done\n"); 214 | } 215 | else if(dumpall) 216 | { 217 | msg("Saving %s [%08X %08X]...",get_true_segm_name(curseg),curseg->startEA,curseg->endEA); 218 | ewrite(cfg, &curseg->startEA,sizeof(curseg->startEA) ); 219 | ewrite(cfg, &curseg->endEA,sizeof(curseg->endEA) ); 220 | segdata = get_segment_data(curseg->startEA, curseg->endEA, getsegsize(curseg)); 221 | ewrite(snp, segdata, getsegsize(curseg)); 222 | free_data(segdata); 223 | msg("done\n"); 224 | } 225 | } 226 | eclose(cfg); 227 | eclose(snp); 228 | return true; 229 | } 230 | 231 | 232 | bool is_segment(ea_t start_address, ea_t end_address) 233 | { 234 | segment_t *curseg; 235 | int segqty; 236 | int i; 237 | 238 | segqty = get_segm_qty(); 239 | for(i=0;iperm & SEGPERM_WRITE) && (curseg->perm & SEGPERM_READ) ) 243 | { 244 | if(start_address == curseg->startEA && end_address == curseg->endEA) 245 | { 246 | return true; 247 | } 248 | } 249 | 250 | } 251 | return false; 252 | 253 | } 254 | 255 | bool eof(FILE *file) 256 | { 257 | if(qftell(file) == efilelength(file)) 258 | return true; 259 | 260 | return false; 261 | } 262 | 263 | 264 | int get_probs_qty(char *filename) 265 | { 266 | long offset=0; 267 | ea_t size; 268 | FILE *cfg; 269 | int probs=0; 270 | ea_t start_address; 271 | ea_t end_address; 272 | 273 | cfg = fopenRB(filename); 274 | 275 | while(!eof(cfg)) 276 | { 277 | eread(cfg,&start_address,4); 278 | eread(cfg,&end_address,4); 279 | size = end_address-start_address-1; 280 | 281 | if(!is_segment(start_address, end_address)) 282 | { 283 | probs++; 284 | } 285 | offset+=size; 286 | } 287 | eclose(cfg); 288 | return probs; 289 | } 290 | 291 | bool load_cfgdata(char *filename) 292 | { 293 | //ea_t i; 294 | FILE *cfg; 295 | FILE *snp; 296 | ea_t start_address; 297 | ea_t end_address; 298 | long offset=0; 299 | ea_t size; 300 | uchar *mem; 301 | char snpfile[MAXSTR]; 302 | 303 | strcpy(snpfile,filename); 304 | 305 | if(hasExt(snpfile ) != NULL) 306 | strcpy((char *)hasExt(snpfile),"snp"); 307 | 308 | cfg = fopenRB(filename); 309 | snp = fopenRB(snpfile); 310 | 311 | while(!eof(cfg)) 312 | { 313 | eread(cfg,&start_address,4); 314 | eread(cfg,&end_address,4); 315 | size = end_address-start_address; 316 | 317 | msg("Restoring %s [%08X %08X]...",get_true_segm_name(getseg(start_address)),start_address,end_address); 318 | if(is_segment(start_address, end_address)) 319 | { 320 | eseek(snp,offset); 321 | mem = get_file_data(snp,size); 322 | put_many_bytes(start_address,mem, size); 323 | /* 324 | for(i=start_address;i0) 351 | { 352 | if ( askyn_c(1,"There were %d mismatches. Restore state anyway?\n",x) != 1) 353 | return false; 354 | } 355 | load_cfgdata(filename); 356 | load_reg(filename); 357 | msg("Previous state restored!\n"); 358 | return true; 359 | } 360 | 361 | bool make_snapshot(char *filename, bool dumpall) 362 | { 363 | save_cfgdata(filename,dumpall); 364 | save_reg(filename); 365 | msg("Snapshot saved!\n"); 366 | return true; 367 | } 368 | 369 | int idaapi init(void) 370 | { 371 | if ( inf.filetype == f_ELF ) return PLUGIN_SKIP; 372 | 373 | return PLUGIN_KEEP; 374 | } 375 | 376 | 377 | void idaapi term(void) 378 | { 379 | 380 | } 381 | 382 | void idaapi run(int arg) 383 | { 384 | int status=0; 385 | char *answer; 386 | char filename[MAXSTR]; 387 | 388 | if(get_process_state() == 0) 389 | { 390 | msg("This plugin can only take a snapshot of a running process!\n"); 391 | return; 392 | } 393 | 394 | 395 | if ( AskUsingForm_c(dlg,&status) == 0) 396 | { 397 | msg("aborted.\n"); 398 | return; 399 | } 400 | switch(status) 401 | { 402 | case 0: 403 | answer = askfile_cv(1,NULL,"Enter a filename for the snapshot:",0); 404 | if(answer == NULL) 405 | { 406 | msg("aborted.\n"); 407 | return; 408 | } 409 | strncpy(filename,answer,MAXSTR-strlen(".ext")+1); 410 | make_snapshot(filename,false); 411 | break; 412 | case 1: 413 | answer = askfile_cv(1,NULL,"Enter a filename for the snapshot:",0); 414 | if(answer == NULL) 415 | { 416 | msg("aborted.\n"); 417 | return; 418 | } 419 | strncpy(filename,answer,MAXSTR-strlen(".ext")+1); 420 | make_snapshot(filename,true); 421 | break; 422 | case 2: 423 | answer = askfile_cv(0,"*.cfg","Open a snapshot file:",0); 424 | if(answer == NULL) 425 | { 426 | msg("aborted.\n"); 427 | return; 428 | } 429 | strncpy(filename,answer,MAXSTR-strlen(".ext")+1); 430 | revert_to_snapshot(filename); 431 | break; 432 | } 433 | } 434 | 435 | //-------------------------------------------------------------------------- 436 | char comment[] = "Snapshot! plugin by Dennis Elser"; 437 | 438 | char help[] = 439 | "This plugin can create a snapshot of the current process\n"; 440 | 441 | //-------------------------------------------------------------------------- 442 | // This is the preferred name of the plugin module in the menu system 443 | // The preferred name may be overriden in plugins.cfg file 444 | 445 | char wanted_name[] = "Snapshot!"; 446 | 447 | 448 | // This is the preferred hotkey for the plugin module 449 | // The preferred hotkey may be overriden in plugins.cfg file 450 | // Note: IDA won't tell you if the hotkey is not correct 451 | // It will just disable the hotkey. 452 | 453 | char wanted_hotkey[] = "Alt-5"; 454 | 455 | 456 | //-------------------------------------------------------------------------- 457 | // 458 | // PLUGIN DESCRIPTION BLOCK 459 | // 460 | //-------------------------------------------------------------------------- 461 | plugin_t PLUGIN = 462 | { 463 | IDP_INTERFACE_VERSION, 464 | 0, // plugin flags 465 | init, // initialize 466 | 467 | term, // terminate. this pointer may be NULL. 468 | 469 | run, // invoke plugin 470 | 471 | comment, // long comment about the plugin 472 | // it could appear in the status line 473 | // or as a hint 474 | 475 | help, // multiline help about the plugin 476 | 477 | wanted_name, // the preferred short name of the plugin 478 | wanted_hotkey // the preferred hotkey to run the plugin 479 | }; 480 | -------------------------------------------------------------------------------- /vscp/vscp.cpp: -------------------------------------------------------------------------------- 1 | // * Very Simple Code Profiling plugin by Dennis Elser 2 | // * 3 | // * This plugin shows you how often a function 4 | // * during a runtime debugging session is called. 5 | // * 6 | // * This code is (C) by Dennis Elser 7 | // * 8 | 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | bool profile=true; 20 | 21 | static int idaapi dbg_callback(void * /*user_data*/, int event_id, va_list /*va*/) 22 | { 23 | regval_t eip; 24 | int numfuncs; 25 | int i; 26 | func_t *f; 27 | bpt_t cur_bp; 28 | 29 | //is the process about to start? 30 | if(event_id==dbg_process_start) 31 | { 32 | if( askyn_cv(1,"VSCP - Want to profile the process?",0) !=1) 33 | { 34 | //only profile, if user clicked "yes" 35 | profile=false; 36 | return 0; 37 | } 38 | else profile=true; 39 | 40 | //get number of total functions from the idb 41 | numfuncs=get_func_qty(); 42 | 43 | msg("Setting %d breakpoints, please wait..",numfuncs); 44 | 45 | //set breakpoint on each function, with flagtype = BPT_TRACE 46 | //these are breakpoints which don't suspend the debugger 47 | for (i=0;i<=numfuncs-1;i++) 48 | { 49 | f = getn_func(i); 50 | add_bpt(f->startEA,0,-1); 51 | getn_bpt(i, &cur_bp); 52 | cur_bp.flags=BPT_TRACE; 53 | update_bpt(&cur_bp); 54 | } 55 | msg("done!\n"); 56 | } 57 | 58 | //this code makes sure that the process is being 59 | //resumed if a breakpoint triggers, which the user didnt set 60 | else if(event_id==dbg_breakpoint && profile) 61 | { 62 | continue_process(); 63 | } 64 | 65 | //Notify the user to clear the breakpoints if he doesn't need them 66 | //anymore 67 | else if(event_id==dbg_process_exit && profile) 68 | { 69 | msg( 70 | "Process terminated.. be sure to check out the breakpoint list!\n" 71 | "Press alt-8 to delete the breakpoint list.\n" 72 | ); 73 | } 74 | 75 | return 0; 76 | } 77 | 78 | 79 | int idaapi init(void) 80 | { 81 | //skip plugin if a non-pe file has been loaded 82 | //since the debugger supports PE files only 83 | //at the time of this writing 84 | if ( inf.filetype != f_PE ) return PLUGIN_SKIP; 85 | 86 | //register the debugger callback 87 | hook_to_notification_point(HT_DBG, dbg_callback, NULL); 88 | msg("VSCP is active.\n"); 89 | 90 | return PLUGIN_KEEP; 91 | } 92 | 93 | void idaapi term(void) 94 | { 95 | //unregister callback 96 | unhook_from_notification_point(HT_DBG, dbg_callback); 97 | } 98 | 99 | void idaapi run(int arg) 100 | { 101 | int numfuncs; 102 | int i; 103 | func_t *f; 104 | numfuncs=get_func_qty(); 105 | 106 | //this function will be run if the user presses alt-8 107 | //or selects the plugin from the menu 108 | //it deletes all the breakpoints and clears the bp-list 109 | msg("Deleting %d breakpoints, please wait..",numfuncs); 110 | for (i=0;i<=numfuncs-1;i++) 111 | { 112 | f = getn_func(i); 113 | del_bpt(f->startEA); 114 | } 115 | msg("done!\n"); 116 | } 117 | 118 | //-------------------------------------------------------------------------- 119 | char comment[] = "VSCP"; 120 | char help[] = "VSCP\n"; 121 | char wanted_name[] = "VSCP - Erase all profiling breakpoints"; 122 | char wanted_hotkey[] = "Alt-8"; 123 | 124 | plugin_t PLUGIN = 125 | { 126 | IDP_INTERFACE_VERSION, 127 | 0, 128 | init, 129 | term, 130 | run, 131 | comment, 132 | help, 133 | wanted_name, 134 | wanted_hotkey 135 | }; 136 | --------------------------------------------------------------------------------