├── README.md └── VB-Parser.py /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vic4key/VB-Exe-Parser/1dba50dbc5ffef8a4abf992060720a5602a1855b/README.md -------------------------------------------------------------------------------- /VB-Parser.py: -------------------------------------------------------------------------------- 1 | # Script : VB Exe Parser 2 | # Version : 1.0 3 | # Author : Vic P. aka vic4key 4 | # Date : Oct 2016 5 | # E-mail: : vic4key[at]gmail.com 6 | # Blog : http://viclab.biz/ 7 | # Website : http://cin1team.biz/ 8 | 9 | import ctypes, inspect 10 | 11 | class CVBHeader(ctypes.Structure): 12 | _fields_ = [ 13 | ("szVbMagic", ctypes.c_ubyte*4), # 0x0. "VB5!"" String 14 | ("wRuntimeBuild", ctypes.c_ushort), # 0x4. Build of the VB6 Runtime 15 | ("szLangDll", ctypes.c_ubyte*14), # 0x6. Language Extension DLL 16 | ("szSecLangDll", ctypes.c_ubyte*14), # 0x14. 2nd Language Extension DLL 17 | ("wRuntimeRevision", ctypes.c_ushort), # 0x22. Internal Runtime Revision 18 | ("dwLCID", ctypes.c_ulong), # 0x24. LCID of Language DLL 19 | ("dwSecLCID", ctypes.c_ulong), # 0x28. LCID of 2nd Language DLL 20 | ("lpSubMain", ctypes.c_ulong), # 0x2C. Pointer to Sub Main Code 21 | ("lpProjectData", ctypes.c_ulong), # 0x30. Pointer to Project Data 22 | ("fMdlIntCtls", ctypes.c_ulong), # 0x34. VB Control Flags for IDs < 32 23 | ("fMdlIntCtls2", ctypes.c_ulong), # 0x38. VB Control Flags for IDs > 32 24 | ("dwThreadFlags", ctypes.c_ulong), # 0x3C. Threading Mode 25 | ("dwThreadCount", ctypes.c_ulong), # 0x40. Threads to support in pool 26 | ("wFormCount", ctypes.c_ushort), # 0x44. Number of forms present 27 | ("wExternalCount", ctypes.c_ushort), # 0x46. Number of external controls 28 | ("dwThunkCount", ctypes.c_ulong), # 0x48. Number of thunks to create 29 | ("lpGuiTable", ctypes.c_ulong), # 0x4C. Pointer to GUI Table 30 | ("lpExternalTable", ctypes.c_ulong), # 0x50. Pointer to External Table 31 | ("lpComRegisterData", ctypes.c_ulong), # 0x54. Pointer to COM Information 32 | ("bSZProjectDescription", ctypes.c_ulong), # 0x58. Offset to Project Description 33 | ("bSZProjectExeName", ctypes.c_ulong), # 0x5C. Offset to Project EXE Name 34 | ("bSZProjectHelpFile", ctypes.c_ulong), # 0x60. Offset to Project Help File 35 | ("bSZProjectName", ctypes.c_ulong) # 0x64. Offset to Project Name 36 | ] 37 | 38 | class CVBProjectInfo(ctypes.Structure): 39 | _fields_ = [ 40 | ("dwVersion", ctypes.c_ulong), # 0x0. 5.00 in Hex (0x1F4). Version. 41 | ("lpObjectTable", ctypes.c_ulong), # 0x4. Pointer to the Object Table 42 | ("dwNull", ctypes.c_ulong), # 0x8. Unused value after compilation. 43 | ("lpCodeStart", ctypes.c_ulong), # 0xC. Points to start of code. Unused. 44 | ("lpCodeEnd", ctypes.c_ulong), # 0x10. Points to end of code. Unused. 45 | ("dwDataSize", ctypes.c_ulong), # 0x14. Size of VB Object Structures. Unused. 46 | ("lpThreadSpace", ctypes.c_ulong), # 0x18. Pointer to Pointer to Thread Object. 47 | ("lpVbaSeh", ctypes.c_ulong), # 0x1C. Pointer to VBA Exception Handler 48 | ("lpNativeCode", ctypes.c_ulong), # 0x20. Pointer to .DATA section. 49 | ("szPathInformation", ctypes.c_ubyte*528), # 0x24. Contains Path and ID string. < SP6 50 | ("lpExternalTable", ctypes.c_ulong), # 0x234. Pointer to External Table. 51 | ("dwExternalCount", ctypes.c_ulong) # 0x238. Objects in the External Table. 52 | ] 53 | 54 | class CVBProjectInfo2(ctypes.Structure): 55 | _fields_ = [ 56 | ("lpHeapLink", ctypes.c_ulong), # 0x0. Unused after compilation, always 0. 57 | ("lpObjectTable", ctypes.c_ulong), # 0x4. Back-Pointer to the Object Table. 58 | ("dwReserved", ctypes.c_ulong), # 0x8. Always set to -1 after compiling. Unused 59 | ("dwUnused", ctypes.c_ulong), # 0xC. Not written or read in any case. 60 | ("lpObjectList", ctypes.c_ulong), # 0x10. Pointer to Object Descriptor Pointers. 61 | ("dwUnused2", ctypes.c_ulong), # 0x14. Not written or read in any case. 62 | ("szProjectDescription", ctypes.c_ulong), # 0x18. Pointer to Project Description 63 | ("szProjectHelpFile", ctypes.c_ulong), # 0x1C. Pointer to Project Help File 64 | ("dwReserved2", ctypes.c_ulong), # 0x20. Always set to -1 after compiling. Unused 65 | ("dwHelpContextId", ctypes.c_ulong) # 0x24. Help Context ID set in Project Settings. 66 | ] 67 | 68 | class CVBObjectTable(ctypes.Structure): 69 | _fields_ = [ 70 | ("lpHeapLink", ctypes.c_ulong), # 0x0. Unused after compilation, always 0. 71 | ("lpExecProj", ctypes.c_ulong), # 0x4. Pointer to VB Project Exec COM Object. 72 | ("lpProjectInfo2", ctypes.c_ulong), # 0x8. Secondary Project Information. 73 | ("dwReserved", ctypes.c_ulong), # 0xC. Always set to -1 after compiling. Unused. 74 | ("dwNull", ctypes.c_ulong), # 0x10. Not used in compiled mode. 75 | ("lpProjectObject", ctypes.c_ulong), # 0x14. Pointer to in-memory Project Data. 76 | ("uuidObject", ctypes.c_ubyte*16), # 0x18. GUID of the Object Table. 77 | ("fCompileState", ctypes.c_ushort), # 0x28. Internal flag used during compilation. 78 | ("dwTotalObjects", ctypes.c_ushort), # 0x2A. Total objects present in Project. 79 | ("dwCompiledObjects", ctypes.c_ushort), # 0x2C. Equal to above after compiling. 80 | ("dwObjectsInUse", ctypes.c_ushort), # 0x2E. Usually equal to above after compile. 81 | ("lpObjectArray", ctypes.c_ulong), # 0x30. Pointer to Object Descriptors 82 | ("fIdeFlag", ctypes.c_ulong), # 0x34. Flag/Pointer used in IDE only. 83 | ("lpIdeData", ctypes.c_ulong), # 0x38. Flag/Pointer used in IDE only. 84 | ("lpIdeData2", ctypes.c_ulong), # 0x3C. Flag/Pointer used in IDE only. 85 | ("lpszProjectName", ctypes.c_ulong), # 0x40. Pointer to Project Name. 86 | ("dwLcid", ctypes.c_ulong), # 0x44. LCID of Project. 87 | ("dwLcid2", ctypes.c_ulong), # 0x48. Alternate LCID of Project. 88 | ("lpIdeData3", ctypes.c_ulong), # 0x4C. Flag/Pointer used in IDE only. 89 | ("dwIdentifier", ctypes.c_ulong) # 0x50. Template Version of Structure. 90 | ] 91 | 92 | class CVBPublicObjectDescriptors(ctypes.Structure): 93 | _fields_ = [ 94 | ("lpObjectInfo", ctypes.c_ulong), # 0x0. Pointer to the Object Info for this Object. 95 | ("dwReserved", ctypes.c_ulong), # 0x4. Always set to -1 after compiling. 96 | ("lpPublicBytes", ctypes.c_ulong), # 0x8. Pointer to Public Variable Size integers. 97 | ("lpStaticBytes", ctypes.c_ulong), # 0xC. Pointer to Static Variable Size integers. 98 | ("lpModulePublic", ctypes.c_ulong), # 0x10. Pointer to Public Variables in DATA section 99 | ("lpModuleStatic", ctypes.c_ulong), # 0x14. Pointer to Static Variables in DATA section 100 | ("lpszObjectName", ctypes.c_ulong), # 0x18. Name of the Object. 101 | ("dwMethodCount", ctypes.c_ulong), # 0x1C. Number of Methods in Object. 102 | ("lpMethodNames", ctypes.c_ulong), # 0x20. If present, pointer to Method names array. 103 | ("bStaticVars", ctypes.c_ulong), # 0x24. Offset to where to copy Static Variables. 104 | ("fObjectType", ctypes.c_ulong), # 0x28. Flags defining the Object Type. 105 | ("dwNull", ctypes.c_ulong) # 0x2C. Not valid after compilation 106 | ] 107 | 108 | class CVBPrivateObjectDescriptors(ctypes.Structure): 109 | _fields_ = [ 110 | ("lpHeapLink", ctypes.c_ulong), # 0x0. Unused after compilation, always 0. 111 | ("lpObjectInfo", ctypes.c_ulong), # 0x4. Pointer to the Object Info for this Object. 112 | ("dwReserved", ctypes.c_ulong), # 0x8. Always set to -1 after compiling. 113 | ("dwIdeData", ctypes.c_ulong*3), # 0xC. Not valid after compilation. 114 | ("lpObjectList", ctypes.c_ulong), # 0x18. Points to the Parent Structure (Array) 115 | ("dwIdeData2", ctypes.c_ulong), # 0x1C. Not valid after compilation. 116 | ("lpObjectList2", ctypes.c_ulong*3), # 0x20. Points to the Parent Structure (Array). 117 | ("dwIdeData3", ctypes.c_ulong*3), # 0x2C. Not valid after compilation. 118 | ("dwObjectType", ctypes.c_ulong), # 0x38. Type of the Object described. 119 | ("dwIdentifier", ctypes.c_ulong) # 0x3C. Template Version of Structure. 120 | ] 121 | 122 | class CVBObjectInfo(ctypes.Structure): 123 | _fields_ = [ 124 | ("wRefCount", ctypes.c_ushort), # 0x0. Always 1 after compilation. 125 | ("wObjectIndex", ctypes.c_ushort), # 0x2. Index of this Object. 126 | ("lpObjectTable", ctypes.c_ulong), # 0x4. Pointer to the Object Table 127 | ("lpIdeData", ctypes.c_ulong), # 0x8. Zero after compilation. Used in IDE only. 128 | ("lpPrivateObject", ctypes.c_ulong), # 0xC. Pointer to Private Object Descriptor. 129 | ("dwReserved", ctypes.c_ulong), # 0x10. Always -1 after compilation. 130 | ("dwNull", ctypes.c_ulong), # 0x14. Unused. 131 | ("lpObject", ctypes.c_ulong), # 0x18. Back-Pointer to Public Object Descriptor. 132 | ("lpProjectData", ctypes.c_ulong), # 0x1C. Pointer to in-memory Project Object. 133 | ("wMethodCount", ctypes.c_ushort), # 0x20. Number of Methods 134 | ("wMethodCount2", ctypes.c_ushort), # 0x22. Zeroed out after compilation. IDE only. 135 | ("lpMethods", ctypes.c_ulong), # 0x24. Pointer to Array of Methods. 136 | ("wConstants", ctypes.c_ushort), # 0x28. Number of Constants in Constant Pool. 137 | ("wMaxConstants", ctypes.c_ushort), # 0x2A. Constants to allocate in Constant Pool. 138 | ("lpIdeData2", ctypes.c_ulong), # 0x2C. Valid in IDE only. 139 | ("lpIdeData3", ctypes.c_ulong), # 0x30. Valid in IDE only. 140 | ("lpConstants", ctypes.c_ulong) # 0x34. Pointer to Constants Pool. 141 | ] 142 | 143 | class CVBOptionalObjectInfo(ctypes.Structure): 144 | _fields_ = [ 145 | ("dwObjectGuids", ctypes.c_ulong), # 0x0. How many GUIDs to Register. 2 = Designer 146 | ("lpObjectGuid", ctypes.c_ulong), # 0x4. Unique GUID of the Object *VERIFY* 147 | ("dwNull", ctypes.c_ulong), # 0x8. Unused. 148 | ("lpuuidObjectTypes", ctypes.c_ulong), # 0xC. Pointer to Array of Object Interface GUIDs 149 | ("dwObjectTypeGuids", ctypes.c_ulong), # 0x10. How many GUIDs in the Array above. 150 | ("lpControls2", ctypes.c_ulong), # 0x14. Usually the same as lpControls. 151 | ("dwNull2", ctypes.c_ulong), # 0x18. Unused. 152 | ("lpObjectGuid2", ctypes.c_ulong), # 0x1C. Pointer to Array of Object GUIDs. 153 | ("dwControlCount", ctypes.c_ulong), # 0x20. Number of Controls in array below. 154 | ("lpControls", ctypes.c_ulong), # 0x24. Pointer to Controls Array. 155 | ("wEventCount", ctypes.c_ushort), # 0x28. Number of Events in Event Array. 156 | ("wPCodeCount", ctypes.c_ushort), # 0x2A. Number of P-Codes used by this Object. 157 | ("bWInitializeEvent", ctypes.c_ushort), # 0x2C. Offset to Initialize Event from Event Table. 158 | ("bWTerminateEvent", ctypes.c_ushort), # 0x2E. Offset to Terminate Event in Event Table. 159 | ("lpEvents", ctypes.c_ulong), # 0x30. Pointer to Events Array. 160 | ("lpBasicClassObject", ctypes.c_ulong), # 0x34. Pointer to in-memory Class Objects. 161 | ("dwNull3", ctypes.c_ulong), # 0x38. Unused. 162 | ("lpIdeData", ctypes.c_ulong) # 0x3C. Only valid in IDE. 163 | ] 164 | 165 | class CVBControlInfo(ctypes.Structure): 166 | _fields_ = [ 167 | #("wFlagImplement", ctypes.c_ushort), 168 | #("wEventHandlerCount", ctypes.c_ushort), 169 | #("wFlagIndexRef", ctypes.c_ushort), 170 | 171 | #("fControlType", ctypes.c_ulong), # 0x0. Type of control. 172 | 173 | ("wUnused", ctypes.c_ushort), # 0x0. Type of control. # Mine 174 | ("fControlType", ctypes.c_ushort), # 0x0. Type of control. # Mine 175 | 176 | ("wEventcount", ctypes.c_ushort), # 0x4. Number of Event Handlers supported. 177 | ("bWEventsOffset", ctypes.c_ushort), # 0x6. Offset in to Memory struct to copy Events. 178 | ("lpGuid", ctypes.c_ulong), # 0x8. Pointer to GUID of this Control. 179 | ("dwIndex", ctypes.c_ulong), # 0xC. Index ID of this Control. 180 | ("dwNull", ctypes.c_ulong), # 0x10. Unused. 181 | ("dwNull2", ctypes.c_ulong), # 0x14. Unused. 182 | ("lpEventTable", ctypes.c_ulong), # 0x18. Pointer to Event Handler Table. 183 | ("lpIdeData", ctypes.c_ulong), # 0x1C. Valid in IDE only. 184 | ("lpszName", ctypes.c_ulong), # 0x20. Name of this Control. 185 | ("dwIndexCopy", ctypes.c_ulong) # 0x24. Secondary Index ID of this Control 186 | ] 187 | 188 | class CVBEventHandlerTable(ctypes.Structure): 189 | _fields_ = [ 190 | ("dwNull", ctypes.c_ulong), # 0x0. Unused 191 | ("lpControls", ctypes.c_ulong), # 0x4. refer to CVBControlInfo / Controls List 192 | ("lpObjectInfo", ctypes.c_ulong), # 0x8. refer to CVBObjectInfo / Form Descriptor 193 | ("lpEVENT_SINK_QueryInterface", ctypes.c_ulong), # 0xC. 194 | ("lpEVENT_SINK_Release", ctypes.c_ulong), # 0x10. 195 | ("lpRelease", ctypes.c_ulong) # 0x14. 196 | ] 197 | 198 | class CVBGUID(ctypes.Structure): 199 | _fields_ = [ 200 | ("Data1", ctypes.c_ulong), # Specifies the first 8 hexadecimal digits of the GUID. 201 | ("Data2", ctypes.c_ushort), # Specifies the first group of 4 hexadecimal digits. 202 | ("Data3", ctypes.c_ushort), # Specifies the second group of 4 hexadecimal digits. 203 | ("Data4", ctypes.c_ubyte*8) # Array of 8 bytes. The first 2 bytes contain the third group of 4 hexadecimal digits. 204 | # The remaining 6 bytes contain the final 12 hexadecimal digits. 205 | ] 206 | 207 | MDLInternalControlFlags = [ 208 | (0x00, 0x00000001, "PictureBox Object"), 209 | (0x01, 0x00000002, "Label Object"), 210 | (0x02, 0x00000004, "TextBox Object"), 211 | (0x03, 0x00000008, "Frame Object"), 212 | (0x04, 0x00000010, "CommandButton Object"), 213 | (0x05, 0x00000020, "CheckBox Object"), 214 | (0x06, 0x00000040, "OptionButton Object"), 215 | (0x07, 0x00000080, "ComboBox Object"), 216 | (0x08, 0x00000100, "ListBox Object"), 217 | (0x09, 0x00000200, "HScrollBar Object"), 218 | (0x0A, 0x00000400, "VScrollBar Object"), 219 | (0x0B, 0x00000800, "Timer Object"), 220 | (0x0C, 0x00001000, "Print Object"), 221 | (0x0D, 0x00002000, "Form Object"), 222 | (0x0E, 0x00004000, "Screen Object"), 223 | (0x0F, 0x00008000, "Clipboard Object"), 224 | (0x10, 0x00010000, "Drive Object"), 225 | (0x11, 0x00020000, "Dir Object"), 226 | (0x12, 0x00040000, "FileListBox Object"), 227 | (0x13, 0x00080000, "Menu Object"), 228 | (0x14, 0x00100000, "MDIForm Object"), 229 | (0x15, 0x00200000, "App Object"), 230 | (0x16, 0x00400000, "Shape Object"), 231 | (0x17, 0x00800000, "Line Object"), 232 | (0x18, 0x01000000, "Image Object"), 233 | (0x19, 0x02000000, "Unsupported"), 234 | (0x1A, 0x04000000, "Unsupported"), 235 | (0x1B, 0x08000000, "Unsupported"), 236 | (0x1C, 0x10000000, "Unsupported"), 237 | (0x1D, 0x20000000, "Unsupported"), 238 | (0x1E, 0x40000000, "Unsupported"), 239 | (0x1F, 0x80000000, "Unsupported") 240 | ] 241 | 242 | CtrlFlags = [ 243 | (0x00, 0x0000001A, "PictureBox"), 244 | (0x01, 0x00000012, "Label"), 245 | (0x02, 0x00000018, "TextBox"), 246 | (0x03, 0x0000000D, "Frame"), 247 | (0x04, 0x00000011, "CommandButton"), 248 | (0x05, 0x00000000, "CheckBox"), 249 | (0x06, 0x00000013, "OptionButton"), 250 | (0x07, 0x00000000, "ComboBox"), 251 | (0x08, 0x00000015, "ListBox"), 252 | (0x09, 0x00000000, "HScrollBar"), 253 | (0x0A, 0x00000000, "VScrollBar"), 254 | (0x0B, 0x00000001, "Timer"), 255 | (0x0C, 0x00000000, "Print"), 256 | (0x0D, 0x00000000, "Form"), 257 | (0x0E, 0x00000000, "Screen"), 258 | (0x0F, 0x00000000, "Clipboard"), 259 | (0x10, 0x00000000, "Drive"), 260 | (0x11, 0x00000014, "Dir"), 261 | (0x12, 0x00000000, "FileListBox"), 262 | (0x13, 0x00000000, "Menu"), 263 | (0x14, 0x00000000, "MDIForm"), 264 | (0x15, 0x00000000, "App"), 265 | (0x16, 0x00000000, "Shape"), 266 | (0x17, 0x00000000, "Line"), 267 | (0x18, 0x0000000D, "Image"), 268 | (0x19, 0x0000001D, "Grid"), 269 | (0x1A, 0x00000016, "StatusBar"), 270 | (0x1B, 0x0000000A, "Communication"), 271 | (0x1C, 0x00000000, "Unsupported"), 272 | (0x1D, 0x00000000, "Unsupported"), 273 | (0x1E, 0x00000000, "Unsupported"), 274 | (0x1F, 0x00000000, "Unsupported") 275 | ] 276 | 277 | ''' 278 | [ # 2nd Flag Zone 2nd Flag Zone 2nd Flag Zone 279 | (0x20, 0x00000001, "Unsupported"), 280 | (0x21, 0x00000002, "Unsupported"), 281 | (0x22, 0x00000004, "Unsupported"), 282 | (0x23, 0x00000008, "Unsupported"), 283 | (0x24, 0x00000010, "Unsupported"), 284 | (0x25, 0x00000020, "DataQuery Object"), 285 | (0x26, 0x00000040, "OLE Object"), 286 | (0x27, 0x00000080, "Unsupported"), 287 | (0x28, 0x00000100, "UserControl Object"), 288 | (0x29, 0x00000200, "PropertyPage Object"), 289 | (0x2A, 0x00000400, "Document Object"), 290 | (0x2B, 0x00000800, "Unsupported") 291 | ] 292 | ''' 293 | 294 | CtrlButtonEvents = { 295 | 0x0: "Click", 296 | 0x1: "DragDrop", 297 | 0x2: "DragOver", 298 | 0x3: "GotFocus", 299 | 0x4: "KeyDown", 300 | 0x5: "KeyPress", 301 | 0x6: "KeyUp", 302 | 0x7: "LostFocus", 303 | 0x8: "MouseDown", 304 | 0x9: "MouseMove", 305 | 0xA: "MouseUp", 306 | 0xB: "OLEDragOver", 307 | 0xC: "OLEDragDrop", 308 | 0xD: "OLEGiveFeedback", 309 | 0xE: "OLEStartDrag", 310 | 0xF: "OLESetData", 311 | 0x10: "OLECompleteDrag" 312 | } 313 | 314 | CtrlTextboxEvents = { 315 | 0x0: "Change", 316 | 0x1: "DragDrop", 317 | 0x2: "DragOver", 318 | 0x3: "GotFocus", 319 | 0x4: "KeyDown", 320 | 0x5: "KeyPress", 321 | 0x6: "KeyUp", 322 | 0x7: "LinkClose", 323 | 0x8: "LinkError", 324 | 0x9: "LinkOpen", 325 | 0xA: "LostFocus", 326 | 0xB: "LinkNotify", 327 | 0xC: "MouseDown", 328 | 0xD: "MouseMove", 329 | 0xE: "MouseUp", 330 | 0xF: "Click", 331 | 0x10: "DblClick", 332 | 0x11: "OLEDragOver", 333 | 0x12: "OLEDragDrop", 334 | 0x13: "OLEGiveFeedback", 335 | 0x14: "OLEStartDrag", 336 | 0x15: "OLESetData", 337 | 0x16: "OLECompleteDrag", 338 | 0x17: "Validate" 339 | } 340 | 341 | CtrlFormEvents = { 342 | 0x0: "DragDrop", 343 | 0x1: "DragOver", 344 | 0x2: "LinkClose", 345 | 0x3: "LinkError", 346 | 0x4: "LinkExecute", 347 | 0x5: "LinkOpen", 348 | 0x6: "Load", 349 | 0x7: "Resize", 350 | 0x8: "Unload", 351 | 0x9: "QueryUnload", 352 | 0xA: "Activate", 353 | 0xB: "Deactivate", 354 | 0xC: "Click", 355 | 0xD: "DblClick", 356 | 0xE: "GotFocus", 357 | 0xF: "KeyDown", 358 | 0x10: "KeyPress", 359 | 0x11: "KeyUp", 360 | 0x12: "LostFocus", 361 | 0x13: "MouseDown", 362 | 0x14: "MouseMove", 363 | 0x15: "MouseUp", 364 | 0x16: "Paint", 365 | 0x17: "Initialize", 366 | 0x18: "Terminate", 367 | 0x19: "OLEDragOver", 368 | 0x1A: "OLEDragDrop", 369 | 0x1B: "OLEGiveFeedback", 370 | 0x1C: "OLEStartDrag", 371 | 0x1D: "OLESetData", 372 | 0x1E: "OLECompleteDrag" 373 | } 374 | 375 | CtrlFileEvents = { 376 | 0x0: "Click", 377 | 0x1: "DblClick", 378 | 0x2: "DragDrop", 379 | 0x3: "DragOver", 380 | 0x4: "GotFocus", 381 | 0x5: "KeyDown", 382 | 0x6: "KeyPress", 383 | 0x7: "KeyUp", 384 | 0x8: "LostFocus", 385 | 0x9: "MouseDown", 386 | 0xA: "MouseMove", 387 | 0xB: "MouseUp", 388 | 0xC: "PathChange", 389 | 0xD: "PatternChange", 390 | 0xE: "OLEDragOver", 391 | 0xF: "OLEDragDrop", 392 | 0x10: "OLEGiveFeedback", 393 | 0x11: "OLEStartDrag", 394 | 0x12: "OLESetData", 395 | 0x13: "OLECompleteDrag", 396 | 0x14: "Scroll", 397 | 0x15: "Validate" 398 | } 399 | 400 | CtrlOptionEvents = { 401 | 0x0: "Click", 402 | 0x1: "DblClick", 403 | 0x2: "DragDrop", 404 | 0x3: "DragOver", 405 | 0x4: "GotFocus", 406 | 0x5: "KeyDown", 407 | 0x6: "KeyPress", 408 | 0x7: "KeyUp", 409 | 0x8: "LostFocus", 410 | 0x9: "MouseDown", 411 | 0xA: "MouseMove", 412 | 0xB: "MouseUp", 413 | 0xC: "OLEDragOver", 414 | 0xD: "OLEDragDrop", 415 | 0xE: "OLEGiveFeedback", 416 | 0xF: "OLEStartDrag", 417 | 0x10: "OLESetData", 418 | 0x11: "OLECompleteDrag", 419 | 0x12: "Validate" 420 | } 421 | 422 | CtrlComboEvents = { 423 | 0x0: "Change", 424 | 0x1: "Click", 425 | 0x2: "DblClick", 426 | 0x3: "DragDrop", 427 | 0x4: "DragOver", 428 | 0x5: "DropDown", 429 | 0x6: "GotFocus", 430 | 0x7: "KeyDown", 431 | 0x8: "KeyPress", 432 | 0x9: "KeyUp", 433 | 0xA: "LostFocus", 434 | 0xB: "OLEDragOver", 435 | 0xC: "OLEDragDrop", 436 | 0xD: "OLEGiveFeedback", 437 | 0xE: "OLEStartDrag", 438 | 0xF: "OLESetData", 439 | 0x10: "OLECompleteDrag", 440 | 0x11: "Scroll", 441 | 0x12: "Validate" 442 | } 443 | 444 | CtrlLabelEvents = { 445 | 0x0: "Change", 446 | 0x1: "Click", 447 | 0x2: "DblClick", 448 | 0x3: "DragDrop", 449 | 0x4: "DragOver", 450 | 0x5: "LinkClose", 451 | 0x6: "LinkError", 452 | 0x7: "LinkOpen", 453 | 0x8: "MouseDown", 454 | 0x9: "MouseMove", 455 | 0xA: "MouseUp", 456 | 0xB: "LinkNotify", 457 | 0xC: "OLEDragOver", 458 | 0xD: "OLEDragDrop", 459 | 0xE: "OLEGiveFeedback", 460 | 0xF: "OLEStartDrag", 461 | 0x10: "OLESetData", 462 | 0x11: "OLECompleteDrag" 463 | } 464 | 465 | CtrlMenuEvents = { 466 | 0x0: "Click" 467 | } 468 | 469 | CtrlTimerEvents = { 470 | 0x0: "Timer" 471 | } 472 | 473 | CT_BUTTON = 0x33AD4EF2 474 | CT_TEXTBOX = 0x33AD4EE2 475 | CT_TIMER = 0x33AD4F2A 476 | CT_FORM = 0x33AD4F3A 477 | CT_FILE = 0x33AD4F62 478 | CT_OPTION = 0x33AD4F02 479 | CT_COMBOBOX = 0x33AD4F03 480 | CT_COMBOBOX2 = 0x33AD4F0A 481 | CT_MENU = 0x33AD4F6A 482 | CT_LABEL = 0x33AD4EDA 483 | 484 | CtrlEvents = { 485 | CT_BUTTON : CtrlButtonEvents, 486 | CT_TEXTBOX : CtrlTextboxEvents, 487 | CT_TIMER : CtrlTimerEvents, 488 | CT_FORM : CtrlFormEvents, 489 | CT_FILE : CtrlFileEvents, 490 | CT_OPTION : CtrlOptionEvents, 491 | CT_COMBOBOX : CtrlComboEvents, 492 | CT_COMBOBOX2 : CtrlComboEvents, 493 | CT_MENU : CtrlMenuEvents, 494 | CT_LABEL : CtrlLabelEvents 495 | } 496 | 497 | B2S = lambda M: "".join(map(chr, M)) 498 | 499 | HF_LENGTH = 100 # Header & Footer : Fixed Length 500 | 501 | def STATUS(): 502 | list_caller_info = inspect.getouterframes(inspect.currentframe()) 503 | if len(list_caller_info) > 1: caller_info = list_caller_info[1] 504 | else: return ("", "", -1) 505 | u0, u1, line_number, function_name, u2, u3 = caller_info[0:len(caller_info)] 506 | result = (function_name, line_number) 507 | return result 508 | 509 | def ParseStructure(a, t): 510 | p = GetManyBytes(a, sizeof(t)) 511 | if p == 0: return None 512 | return ctypes.cast(p, ctypes.POINTER(t)).contents 513 | 514 | ''' 515 | def GetDWORD(address, min_address = 0, max_address = 0): 516 | if min_address == 0: 517 | min_address = MinEA() 518 | if min_address == 0: return 0 519 | if max_address == 0: 520 | max_address = MinEA() 521 | if max_address == 0: return 0 522 | if min_address <= address <= max_address: return Dword(address) 523 | else: return 0 524 | ''' 525 | 526 | def GetControlDescriptionByTypeID(TypeID): 527 | result = "" 528 | for e in CtrlFlags: 529 | index, typeid, description = e[0:len(e)] 530 | if typeid == TypeID: 531 | if len(result) != 0: result += (" or " + description) 532 | else: result = description 533 | return result 534 | 535 | def CreateFunction(address, name): 536 | result = True 537 | result &= MakeFunction(address) 538 | result &= MakeName(address, name) 539 | return result 540 | 541 | def GetEventByID(ctrl_type, event_id): 542 | ctrl_events, result = None, "Unknown" 543 | for ctrlType in CtrlEvents.keys(): 544 | if ctrlType == ctrl_type: 545 | ctrl_events = CtrlEvents[ctrlType] 546 | break 547 | if ctrl_events == None: return result 548 | for eventID in ctrl_events.keys(): 549 | if eventID == event_id: 550 | result = ctrl_events[eventID] 551 | break 552 | return result 553 | 554 | def main(): 555 | print " VB Exe Parser ".center(HF_LENGTH, "-") 556 | 557 | OEO = GetEntryOrdinal(0) 558 | OEP = GetEntryPoint(OEO) 559 | print "%08X -> `OEP`" % OEP 560 | 561 | MIN, MAX = MinEA(), MaxEA() 562 | IsAddressValid = lambda address: MIN <= address <= MAX 563 | 564 | ### VB HEADER 565 | addr_vb_header = GetOperandValue(OEP, 0); 566 | if not IsAddressValid(addr_vb_header): return STATUS() 567 | print "%08X -> `VB HEADER`" % addr_vb_header 568 | 569 | VBHeader = ParseStructure(addr_vb_header, CVBHeader) 570 | print "\tSignature : '%s'" % B2S(VBHeader.szVbMagic) 571 | 572 | ### PROJECT INFO ### 573 | if not IsAddressValid(VBHeader.lpProjectData): return STATUS() 574 | print "%08X -> `PROJECT INFO`" % VBHeader.lpProjectData 575 | VBProjectInfo = ParseStructure(VBHeader.lpProjectData, CVBProjectInfo) 576 | print "\tVersion : %08X" % VBProjectInfo.dwVersion 577 | 578 | ### OBJECT TABLE ### 579 | if not IsAddressValid(VBProjectInfo.lpObjectTable): return STATUS() 580 | print "%08X -> `OBJECT TABLE`" % VBProjectInfo.lpObjectTable 581 | VBObjectTable = ParseStructure(VBProjectInfo.lpObjectTable, CVBObjectTable) 582 | print "\tProject Name: '%s'" % GetString(VBObjectTable.lpszProjectName) 583 | print "\tTotal Objects: %d" % VBObjectTable.dwTotalObjects 584 | 585 | ### PUBLIC OBJECT DESCRIPTORS ### 586 | if not IsAddressValid(VBObjectTable.lpObjectArray): return STATUS() 587 | #VBPublicObjectDescriptors = [] 588 | for i in xrange(0, VBObjectTable.dwTotalObjects): 589 | addr_vb_public_object_descriptors = VBObjectTable.lpObjectArray + i*sizeof(CVBPublicObjectDescriptors) 590 | if not IsAddressValid(addr_vb_public_object_descriptors): return STATUS() 591 | print "%08X -> `PUBLIC OBJECT DESCRIPTORS #%d`" % (addr_vb_public_object_descriptors, i) 592 | VBPublicObjectDescriptor = ParseStructure(addr_vb_public_object_descriptors, CVBPublicObjectDescriptors) 593 | #VBPublicObjectDescriptors.append(VBPublicObjectDescriptor) 594 | object_name = GetString(VBPublicObjectDescriptor.lpszObjectName) 595 | print "\tObject Name: '%s' (%d)" % (object_name, VBPublicObjectDescriptor.dwMethodCount) 596 | #if object_name != "Form1": continue 597 | # Methods 598 | print "\t%08X -> Methods (%d)" % (VBPublicObjectDescriptor.lpMethodNames, VBPublicObjectDescriptor.dwMethodCount) 599 | for j in xrange(0, VBPublicObjectDescriptor.dwMethodCount): 600 | addr_vb_method_name_eat = VBPublicObjectDescriptor.lpMethodNames + j*4 601 | #if not IsAddressValid(addr_vb_method_name_eat): return STATUS() 602 | addr_method_name = Dword(addr_vb_method_name_eat) 603 | if IsAddressValid(addr_method_name): 604 | method_name = GetString(addr_method_name) 605 | if method_name == None: method_name = "" 606 | print "\t\t%08X -> '%s'" % (addr_method_name, method_name) 607 | 608 | ### OBJECT INFO ### 609 | if not IsAddressValid(VBPublicObjectDescriptor.lpObjectInfo): return STATUS() 610 | print "\t%08X -> `OBJECT_INFO`" % VBPublicObjectDescriptor.lpObjectInfo 611 | VBObjectInfo = ParseStructure(VBPublicObjectDescriptor.lpObjectInfo, CVBObjectInfo) 612 | 613 | ### OPTIONAL OBJECT INFO ### 614 | addr_vb_optional_object_info = VBPublicObjectDescriptor.lpObjectInfo + sizeof(CVBObjectInfo) 615 | if VBObjectInfo.lpConstants != addr_vb_optional_object_info: 616 | if not IsAddressValid(addr_vb_optional_object_info): return STATUS() 617 | print "\t%08X -> `OPTIONAL OBJECT INFO #%d`" % (addr_vb_optional_object_info, i) 618 | VBOptionalObjectInfo = ParseStructure(addr_vb_optional_object_info, CVBOptionalObjectInfo) 619 | 620 | # Controls 621 | print "\t\t%08X -> Controls (%d)" % (VBOptionalObjectInfo.lpControls, VBOptionalObjectInfo.dwControlCount) 622 | for j in xrange(0, VBOptionalObjectInfo.dwControlCount): 623 | ### CONTROL INFO ### 624 | addr_vb_control_info = VBOptionalObjectInfo.lpControls + j*sizeof(CVBControlInfo) 625 | print "\t\t\t%08X -> `CONTROL INFO #%d`" % (addr_vb_control_info, j) 626 | 627 | if IsAddressValid(addr_vb_control_info ): 628 | VBControlInfo = ParseStructure(addr_vb_control_info, CVBControlInfo) 629 | control_name = GetString(VBControlInfo.lpszName) 630 | VBGUID = ParseStructure(VBControlInfo.lpGuid, CVBGUID) 631 | control_type = VBGUID.Data1 632 | ''' 633 | if VBControlInfo.dwIndex != 0xFFFFFFFF: 634 | print "\t\t\t\t%08X. '%s' (%04X - '%s')" % (\ 635 | VBControlInfo.dwIndex,\ 636 | GetString(VBControlInfo.lpszName),\ 637 | VBControlInfo.fControlType,\ 638 | GetControlDescriptionByTypeID(VBControlInfo.fControlType) 639 | ) 640 | ''' 641 | VBEventHandlerTable = ParseStructure(addr_vb_control_info, CVBEventHandlerTable) 642 | entry_point = VBControlInfo.lpEventTable + sizeof(CVBEventHandlerTable) 643 | for control_id in xrange(0, VBControlInfo.fControlType): 644 | p = entry_point + 4*control_id 645 | if IsAddressValid(p): 646 | addr_event = Dword(p) 647 | # 816C24 04 XXXXXXXX | SUB DWORD PTR SS:[ESP+4h],XXXX 648 | # E9 XXXXXXXX | JMP XXXXXXXX <- This is real address of event 649 | if IsAddressValid(addr_event): 650 | stub = Dword(addr_event) & 0xFFFFFF00 651 | if stub == 0x04246C00: # SUB DWORD PTR SS:[ESP+4h] 652 | stub = Byte(addr_event + 8) 653 | if stub == 0xE9: # JMP 654 | event_rel = Dword(addr_event + 8 + 1) 655 | event = addr_event + 8 + event_rel + 5 656 | #print "\t\t\t\t%08X -> %s_[%08X]" % (addr_event, control_name, event) 657 | event_name = "fn_%s_%s_%s" % (object_name, control_name, GetEventByID(control_type, control_id)) 658 | print "\t\t\t\t%08X -> %s" % (addr_event, event_name) 659 | CreateFunction(event, event_name) 660 | 661 | # Events 662 | print "\t\t%08X -> Events (%d)" % (VBOptionalObjectInfo.lpEvents, VBOptionalObjectInfo.wEventCount) 663 | for j in xrange(0, VBOptionalObjectInfo.wEventCount): 664 | addr_vb_event = VBOptionalObjectInfo.lpEvents + j*4 665 | if not IsAddressValid(addr_vb_event): return STATUS() 666 | event_eat = Dword(addr_vb_event) # eat: event address table 667 | if not IsAddressValid(event_eat): return STATUS() 668 | 669 | # This method belongs VB Table or User Defined? 0xFFFF -> User Defined. 670 | addr_magic = event_eat - 4 671 | if not IsAddressValid(addr_magic): return STATUS() 672 | magic = Dword(addr_magic) 673 | is_user_defined = (magic == 0xFFFF) 674 | 675 | # Get the destination address of this jump instruction 676 | if Byte(event_eat) == 0xE9: # JMP 677 | event_rel = Dword(event_eat + 1) 678 | #event = 0 679 | #if (event_rel & 0xFFFF0000) >> 2**4 != 0xFFFF: event = event_eat + event_rel + 5 680 | #else: pass # not verified 681 | event = event_eat + event_rel + 5 682 | if is_user_defined == True: 683 | event_name = "fn_Unknown_%08X" % event 684 | print "\t\t\t%08X -> %s" % (event_eat, event_name) 685 | CreateFunction(event, event_name) 686 | else: print "\t\t\t%08X -> %08X (refer to #KnownEvent)" % (event_eat, event) 687 | 688 | # GUIDs 689 | print "\t\t%08X -> GUIDs (%d)" % (VBOptionalObjectInfo.lpObjectGuid2, VBOptionalObjectInfo.dwObjectGuids) 690 | for j in xrange(0, VBOptionalObjectInfo.dwObjectGuids): 691 | addr_vb_guid = VBOptionalObjectInfo.lpObjectGuid2 + j*4 692 | if not IsAddressValid(addr_vb_guid): return STATUS() 693 | print "\t\t\t%08X -> GUID #%d" % (Dword(addr_vb_guid), j) 694 | 695 | print " Done ".center(HF_LENGTH, "-") 696 | return 697 | 698 | if __name__ == "__main__": print main() --------------------------------------------------------------------------------