Native code emulator is better than ever in VB Decompiler 11
After three months of hard work and several months of preparations, we are happy to introduce a major update of VB Decompiler. Among many things that we have improved, the most important one is probably the completely redesigned Visual Basic native code emulator/decompiler.
VB6 programming is based on calling COM/OLE objects' properties and methods. It involves early and late bindings, and object calls via a Virtual Methods Table and Dispatch ID. An object can also be called by its UUID/GUID, or directly by its name. MSVBVM60.DLL provides 24 functions that can be used to work with objects' methods and properties. Moreover, it provides functions for creating an object, checking the existence of a created object, and unloading an object. All of these functions are intended for native code. On top of that, there are different functions for P-Code!
Naturally, we had to use tons of samples and run hundreds of compilations and tests. The new version of our product can better decompile native code, supports more calls, and processes them correctly. We are especially proud of it because now it supports nested calls like Object.SubClass(Index).SubClass2(Index).Property. In the vast majority of cases, VB Decompiler 11 handles such calls correctly, provided that its knowledge base contains information about the respective ActiveX libraries. The only exception are named calls (the object's UUID is not passed when the object is called).
Now VB Decompiler can better process object creation and the passing of the object's address. When many objects' methods and properties are called within a single procedure, the decompiler must monitor each call to the current object. Compiled code optimization means that an object may be accessed in different ways: The object may be created, its existence may be checked after its creation, temporary variables may be used, the memory address of the object created in a different procedure may be involved, and so on. In most cases, VB Decompiler can handle any object calls, even when they are very confusing!
Our clients who have a license with tracing enabled have been asking us for a long time to add support for P-Code tracing, too. Even before the release of the latest version, VB Decompiler allowed you to enable/disable the decompiled code optimizer, disable stack processing, and display the compiler's opcodes. Now it also allows you to see how variables are changing and decompiled code is being formed step by step.
As for native code tracing, we have added search functionality for the variable list. Moreover, now the tracer can display the type of the current object (This, Me), including a form control. We have also improved the output of value comparison for CMP and TEST.
VB Decompiler provides two decompilation modes: normal and fast. You can select the desired decompilation mode in the settings. In the normal mode, VB Decompiler will first create a tree of forms, modules, and classes with function addresses, and then decompile each function or method. This approach allows the decompiler to check whether the current object is a function or procedure, and how many parameters it has got (if any). VB Decompiler can use the data obtained for further decompilation. In the fast mode, VB Decompiler first processes the object tree and housekeeping structures only; the actual code will be decompiled when it is invoked. This way, the file can be opened quickly for fast analysis, but the decompilation quality will not be as good as in the normal mode. VB Decompiler is unaware of the program's other private functions called in the code and implies that all the parameters in the stack are passed in that call.
To make sure that the decompilation quality is good even in the fast mode, we added a pre-analyzer of private functions. Though it will take the decompiler a little bit more time to open the file for analysis, it will be a fraction of the file opening time in the normal mode. The pre-analyzer is available in the settings, and we recommend that you enable it.
Five years ago, we added the ability to process the "If ... Else ... End If" constructs in programs compiled into P-Code. In this release, we have finally added emulation and processing of such constructs for programs compiled into native code. We have worked hard, and now VB Decompiler can process any compiler optimizations, and our emulator's knowledge base contains information about all kinds of complex constructs that can be inside or before "Else" blocks. Our decompiler can verify that an object has been created, check for overflow, and so on. You can enable support for "Else" constructs in the settings.
When developing VB Decompiler 11, we continued improving the algorithms for decompiling all kinds of arrays in native code. Because of native code specifics and different optimizations, there are many ways to access arrays and their contents. With each new major release of VB Decompiler, we improve support for arrays.
For many years, our native code emulator used a stack of 16 elements. It was enough for most code samples developed in Visual Basic. When working on support for Late calls and their nesting, especially in case of databases, we decided to extend the stack. Now our native code emulator uses a stack of 64 elements of 4 bytes (dword). The extended stack allows VB Decompiler to decompile calls with dozens of parameters and nested objects.
With each new major release, VB Decompiler becomes faster, and version 11 is not an exception! File packing is checked faster. Large functions containing more than 100,000 lines of code are processed faster. Files are saved faster. We have optimized the most critical modules in the emulator, and now it works faster. We have optimized the external-ActiveX knowledge base, and now it loads faster.
When compiling files, Visual Basic stores very little information about user-defined types (UDT). User-defined types are structures declared in a form's or module's header.
Nonetheless, VB Decompiler now supports UDT declaration in object headers and can display references to them in the code. Because binary files contain very little information about UDT, our decompiler can only find out the UDT size in bytes and the number of string fields.
VB Decompiler now supports "Case" constructs that have more than 255 elements. Its disassembler filters out the state transition tables for "Case" blocks (such tables are located at the end of functions). We have also optimized our product to ensure more accurate, high-quality decompilation.
We have significantly extended the VB Decompiler knowledge base. Quite a few object properties return a reference to another object. We have added support for such objects. We have implemented decompilation of properties and methods for the RegExp2 class in vbscript.dll. VB Decompiler now also supports calls to object arrays via Form.Controls.X, MDIForm.Controls.X, UserControl.Controls.X, PpropertyPage.Controls.X, UserDocument.Controls.X, and ListView.Items.X.
Sometimes you might want to see only the code, without a memory address for each line. In some cases, such option may also be useful when saving a project. It was not so easy for us to implement that option: VB Decompiler must process each reference, otherwise it may lose the labels for GoTo, GoSub, Resume, On Error, and other transitions. Starting with version 11, you can view the code without memory addresses regardless if it's native code or P-Code. (You only need to disable the displaying of memory addresses in the settings.)
As the prototype analyzer is available, you might want to take a look at the object tree and see at once if a specific item is an event, function, or procedure. To make things easier, VB Decompiler 11 uses different colors for events, functions, and procedures.
Sometimes, when using VB Decompiler, you might want to open a shortcut that references an executable file. Windows shortcut files have a specific format, and it's not so easy to get the address of the file they reference (especially if you don't want to use external libraries to avoid unnecessary dependencies). We added support for shortcut files without using external calls, and now VB Decompiler supports most shortcuts.
Now VB Decompiler supports 28 more functions of the Visual Basic runtime library. It means that our decompiler supports almost any MSVBVMXX.DLL API, so it can decompile files correctly.
As always, we've also improved a lot of other things. Now, when exporting files, VB Decompiler can add the date and time. We improved the user interface. We added more GUI languages and localized help versions. We optimized and refactored VB Decompiler, and fixed some bugs. We improved the tracer. We extended the functionality of the FPU command emulator. We optimized the .NET disassembler.
With each new release of VB Decompiler, it becomes faster and better. We'll be happy to see you among our clients!
Decompilation of LateMem, LateID, and named calls
VB6 programming is based on calling COM/OLE objects' properties and methods. It involves early and late bindings, and object calls via a Virtual Methods Table and Dispatch ID. An object can also be called by its UUID/GUID, or directly by its name. MSVBVM60.DLL provides 24 functions that can be used to work with objects' methods and properties. Moreover, it provides functions for creating an object, checking the existence of a created object, and unloading an object. All of these functions are intended for native code. On top of that, there are different functions for P-Code!
Naturally, we had to use tons of samples and run hundreds of compilations and tests. The new version of our product can better decompile native code, supports more calls, and processes them correctly. We are especially proud of it because now it supports nested calls like Object.SubClass(Index).SubClass2(Index).Property. In the vast majority of cases, VB Decompiler 11 handles such calls correctly, provided that its knowledge base contains information about the respective ActiveX libraries. The only exception are named calls (the object's UUID is not passed when the object is called).
Processing of object creation
Now VB Decompiler can better process object creation and the passing of the object's address. When many objects' methods and properties are called within a single procedure, the decompiler must monitor each call to the current object. Compiled code optimization means that an object may be accessed in different ways: The object may be created, its existence may be checked after its creation, temporary variables may be used, the memory address of the object created in a different procedure may be involved, and so on. In most cases, VB Decompiler can handle any object calls, even when they are very confusing!
P-Code tracing
Our clients who have a license with tracing enabled have been asking us for a long time to add support for P-Code tracing, too. Even before the release of the latest version, VB Decompiler allowed you to enable/disable the decompiled code optimizer, disable stack processing, and display the compiler's opcodes. Now it also allows you to see how variables are changing and decompiled code is being formed step by step.
As for native code tracing, we have added search functionality for the variable list. Moreover, now the tracer can display the type of the current object (This, Me), including a form control. We have also improved the output of value comparison for CMP and TEST.
Prototype analyzer
VB Decompiler provides two decompilation modes: normal and fast. You can select the desired decompilation mode in the settings. In the normal mode, VB Decompiler will first create a tree of forms, modules, and classes with function addresses, and then decompile each function or method. This approach allows the decompiler to check whether the current object is a function or procedure, and how many parameters it has got (if any). VB Decompiler can use the data obtained for further decompilation. In the fast mode, VB Decompiler first processes the object tree and housekeeping structures only; the actual code will be decompiled when it is invoked. This way, the file can be opened quickly for fast analysis, but the decompilation quality will not be as good as in the normal mode. VB Decompiler is unaware of the program's other private functions called in the code and implies that all the parameters in the stack are passed in that call.
To make sure that the decompilation quality is good even in the fast mode, we added a pre-analyzer of private functions. Though it will take the decompiler a little bit more time to open the file for analysis, it will be a fraction of the file opening time in the normal mode. The pre-analyzer is available in the settings, and we recommend that you enable it.
Processing of "Else" constructs in native code
Five years ago, we added the ability to process the "If ... Else ... End If" constructs in programs compiled into P-Code. In this release, we have finally added emulation and processing of such constructs for programs compiled into native code. We have worked hard, and now VB Decompiler can process any compiler optimizations, and our emulator's knowledge base contains information about all kinds of complex constructs that can be inside or before "Else" blocks. Our decompiler can verify that an object has been created, check for overflow, and so on. You can enable support for "Else" constructs in the settings.
Support for arrays
When developing VB Decompiler 11, we continued improving the algorithms for decompiling all kinds of arrays in native code. Because of native code specifics and different optimizations, there are many ways to access arrays and their contents. With each new major release of VB Decompiler, we improve support for arrays.
Extended emulator stack
For many years, our native code emulator used a stack of 16 elements. It was enough for most code samples developed in Visual Basic. When working on support for Late calls and their nesting, especially in case of databases, we decided to extend the stack. Now our native code emulator uses a stack of 64 elements of 4 bytes (dword). The extended stack allows VB Decompiler to decompile calls with dozens of parameters and nested objects.
Faster operation
With each new major release, VB Decompiler becomes faster, and version 11 is not an exception! File packing is checked faster. Large functions containing more than 100,000 lines of code are processed faster. Files are saved faster. We have optimized the most critical modules in the emulator, and now it works faster. We have optimized the external-ActiveX knowledge base, and now it loads faster.
User-defined types
When compiling files, Visual Basic stores very little information about user-defined types (UDT). User-defined types are structures declared in a form's or module's header.
Nonetheless, VB Decompiler now supports UDT declaration in object headers and can display references to them in the code. Because binary files contain very little information about UDT, our decompiler can only find out the UDT size in bytes and the number of string fields.
Extended support for "Case" constructs
VB Decompiler now supports "Case" constructs that have more than 255 elements. Its disassembler filters out the state transition tables for "Case" blocks (such tables are located at the end of functions). We have also optimized our product to ensure more accurate, high-quality decompilation.
Decompilation of external or internal COM/OLE objects
We have significantly extended the VB Decompiler knowledge base. Quite a few object properties return a reference to another object. We have added support for such objects. We have implemented decompilation of properties and methods for the RegExp2 class in vbscript.dll. VB Decompiler now also supports calls to object arrays via Form.Controls.X, MDIForm.Controls.X, UserControl.Controls.X, PpropertyPage.Controls.X, UserDocument.Controls.X, and ListView.Items.X.
Ability to disable the displaying of memory addresses in P-Code
Sometimes you might want to see only the code, without a memory address for each line. In some cases, such option may also be useful when saving a project. It was not so easy for us to implement that option: VB Decompiler must process each reference, otherwise it may lose the labels for GoTo, GoSub, Resume, On Error, and other transitions. Starting with version 11, you can view the code without memory addresses regardless if it's native code or P-Code. (You only need to disable the displaying of memory addresses in the settings.)
Different colors for procedures and functions
As the prototype analyzer is available, you might want to take a look at the object tree and see at once if a specific item is an event, function, or procedure. To make things easier, VB Decompiler 11 uses different colors for events, functions, and procedures.
Support for .lnk shortcuts
Sometimes, when using VB Decompiler, you might want to open a shortcut that references an executable file. Windows shortcut files have a specific format, and it's not so easy to get the address of the file they reference (especially if you don't want to use external libraries to avoid unnecessary dependencies). We added support for shortcut files without using external calls, and now VB Decompiler supports most shortcuts.
Support for almost any API in MSVBVMXX.DLL
Now VB Decompiler supports 28 more functions of the Visual Basic runtime library. It means that our decompiler supports almost any MSVBVMXX.DLL API, so it can decompile files correctly.
Other improvements
As always, we've also improved a lot of other things. Now, when exporting files, VB Decompiler can add the date and time. We improved the user interface. We added more GUI languages and localized help versions. We optimized and refactored VB Decompiler, and fixed some bugs. We improved the tracer. We extended the functionality of the FPU command emulator. We optimized the .NET disassembler.
With each new release of VB Decompiler, it becomes faster and better. We'll be happy to see you among our clients!
May 23, 2018
(C) Sergey Chubchenko, VB Decompiler's main developer