Page 1 of 1

DISASSEMBLING VISUAL BASIC APPLICATIONS - II Rate Topic: -----

#1 born2c0de  Icon User is offline

  • printf("I'm a %XR",195936478);
  • member icon

Reputation: 180
  • View blog
  • Posts: 4,667
  • Joined: 26-November 04

Posted 13 November 2006 - 04:34 AM

Here's the update of the first version.
It has a few added sections, with some minor changes to the text of the first part.

This is the end of the 'updating' series.
The next one continues where this one stops and the next few tutorials on the subject are going to be like chapters of a book.

So go ahead and read this one, so you can make the most of the big one's...coming up real soon.

Here's the tutorial embedded into the post (Not Complete).
You can also download the Complete Text version.

********************************************************************************
*				   DISASSEMBLING VISUAL BASIC APPLICATIONS - II			   *
*												   - Sanchit Karve			*
*																			  *
*													  born2c0de			   *
*											   printf("I'm a %XR",195936478); *
*																			  *
*	   CONTACT ME :	   born2c0de AT dreamincode DOT net					*
*																			  *
********************************************************************************

						 LAST UPDATED :  13 NOVEMBER 2006

--------------------------------------------------------------------------------
							  INDEX [INDX]


I.		 DISCLAIMER AND NOTICE		  [DISN]
II.		READING THIS TUTORIAL		  [RTUT]
III.	   ASSUMPTIONS					[ASPT]
IV.		REQUIRED TOOLS AND DOCS		[RQRT]
V.		 VB AS A LANGUAGE			   [VBAL]
VI.		INTRODUCTION				   [ITRO]
VII.	   STRUCTURE OF A VB PROGRAM	  [SVBP]
VIII.	  OUR FIRST PROGRAM			  [OFPR]
IX.		STRING COMPARISON			  [STR1]
X.		 DECIPHERING A KEY GENERATOR	[DKGN]
XI.		CONCLUSION					 [END1]


--------------------------------------------------------------------------------



--------------------------------------------------------------------------------

I.		 DISCLAIMER AND NOTICE		  [DISN]

This tutorial is meant for educational purposes only.

If the Reader chooses to break Protection Mechamisms after reading this
tutorial, he/she shall alone be responsible for the damages caused and not the
Author.

If you wish to post portions of this tutorial on a WebSite, you are free to do
so as long as you abide by these rules:

-> Post the selected portion in unedited form.
-> Mention the Author's Name,Email Address and Name of this tutorial above or
   below the selected text.
-> Inform the Author.

The Author has not copied text or any other information directly from a Source.
However, some information from some sources has been used to write this tutorial.
These Sources have been mentioned in the References Section.

You are permitted to continue reading the tutorial only if you agree to the text
given above.

--------------------------------------------------------------------------------

II.		READING THIS TUTORIAL		  [RTUT]

Each Section in this Tutorial has a specific Topic Code enclosed in square
brackets. This arrangement has been made so that you can jump to a specific
topic simply by searching for the topic code from your Browser.

At many places in the tutorial, I've explained a few things which are almost
unnecessary to know when dealing with Visual BASIC programs but I've written
them for those who have a thirst for knowledge.

The Topic Code Tags [XTRA] and [/XTRA] have been given for "extra-information"
sections and you are free to skip them.
Text within the [XTRA]...[/XTRA] blocks is given for extra information.
You can search for the Extra Information using the Topic Code.

--------------------------------------------------------------------------------

III.	   ASSUMPTIONS					[ASPT]

You are required to have a basic understanding of:
: Visual BASIC
: C/C++
: Win31 API
: 80x86 Microprocessor Assembly Language.

--------------------------------------------------------------------------------

IV.		REQUIRED TOOLS AND DOCS		[RQRT]

You will need the following tools to proceed with the Tutorial.
: COMPILER	 : Visual Basic 6.0
: DISASSEMBLER : IDA Pro 4.x or higher
: DEBUGGER	 : OllyDebug Ver. 1.09d or higher
: WINDOWS API DOCUMENTATION

You can also use these tools for your own experiments.
: NuMeGa SmartCheck 6.x		-> A Good VB Debugger with lots of features.
: VBDE version 0.85 by iorior  -> gives offsets of VB procedures
: VBReformer				   -> can change properties of VB Controls


You can refer to API Documentation from MSDN or you can use the
API Text Viewer Tool supplied with Visual Studio or browse
MSDN Online (msdn.microsoft.com).
Certain Applications like APIViewer 2004 will also do.

It would be advisable to have a copy of Intel's 80x86 Instruction Set Manual.
Intel provides this manual free of charge.

The Software Developer's Manual consists of 3 volumes:
: Basic Architecture		- Order Number 243190
: Instruction Set Reference - Order Number 243191
: System Programming Guide  - Order Number 243192

You can obtain these manuals at [url=http://developer.intel.com]http://developer.intel.com[/url]

I have given the names of the Tools that I have used. But you are free to use
any disassembler and debugger as long as you are comfortable using it but I
advice you to use the tools that I have used above. SoftIce is better than
OllyDebug but the latter is good enough so it doesn't matter which one you use.
But I strongly recommend the use of IDA Pro as it's the best disassembler that I
have seen so far.

--------------------------------------------------------------------------------
My First Version of this Tutorial got me a lot of comments and emails from 
people reminding me of all the advantages of VB. They've told me not to overlook
the advantages of VB and that there is a reason why VB is slow.
I agree with them. Looks like I was focussed on only VB's shortcomings I guess.
In this tutorial, I wish to get things clear and let VB get the praise it 
deserves.
--------------------------------------------------------------------------------

V.		 VB AS A LANGUAGE			   [VBAL]

It's like they say:"Everything has a reason."
After this section I am just going to focus on the internal details of Visual
BASIC and I just might say that the code generated by VB is pathetic. But before
I can do that, I want to ensure that you know the advantages that VB offers as 
well.
I want to do this so that the next time you are writing an application, you can 
decide whether or not to use Visual BASIC based on your priorities.

Visual BASIC is a well crafted language simply because learning to write code 
doesn't take much time and yet VB is capable of generating Powerful Applications.
Many times when you don't have much time at your disposal, Visual Basic is the 
best way to go as you can make your App do the same work (which another language
would let you do) in a shorter amount of time without compromising much on the 
Application performance.

VB's library functions are DLL function calls to MSVBM60.DLL
Though this doesn't help in speeding up the App, it has a lot of advantages:
--> Core Code is written in the Runtime Files itself, making Visual BASIC 
	programs as small as possible.
--> Because of this architecture, the code is extremely easy to port to other
	Windows Operating Systems. Consider this example.
--> VB does a lot of work by itself. C/C++ and other languages would require you
	to write a lot of functions to even write a simple Windows Application.

[ THIS IS ONLY AN EXAMPLE. IT MAY NOT BE NECESSARILY TRUE ]

Suppose an API Function APIFunc() that exists in a DLL file in Windows XP is
removed from Windows Vista but Microsoft decides to include an alternate
function and names it AlternateAPIFunc() and puts it in another DLL file.
(Assuming all parameters and return value contents are the same)


We plan to write this in C.
Now comes the problem.
If we wish to use our app to work in Windows XP, we need to use the the function
APIFunc() in our applications and if we want it to work on Windows Vista we have
to replace every APIFunc() function call in our app to AlternateAPIFunc().

Isn't it cumbersome and tiring?

Now if we decide to use VB.
We continue to use the same code.
VB Functions call API Functions from the Runtime Files.
So nothing needs to be done because Windows XP will have a seperate set of
runtime files using the APIFunc() Function while the Vista Runtime Files would
use the AlternateAPIFunc() Function.

Doesn't that make the programmers job much much easier?
This is based on the Java portability technique where the Runtime Files of
Windows OS's can be thought of like Java Virtual Machines.

VB also includes support for Memory Handling and Stack Checks which otherwise
would have to be done manually by the programmer in another language.

So What I'm saying is all these features cost you on performance. But the
relative lag in performance is ingorable as the advantages outperform VB's
shortcomings.

So what follows below is just having a look at VB's Code Generation results and
Runtime Files code.
So when I talk about some code being inefficient, remember that it is so because
of the advantages that VB offers.

The topic of this tutorial concerns disassembling VB Applications and I will
look at only the Assembly code without being concerned of how VB is at the user
level.

Once you are clear about this, go ahead.
Please don't mail me stating that I could not appreciate the features of VB and 
things like that.

--------------------------------------------------------------------------------

VI.		INTRODUCTION				   [ITRO]

If you have disassembled programs written in C/C++ or Pascal before, you would
know that it is not difficult to understand what the assembly instructions are
trying to achieve. These Languages generate neat,well written code and hence are
easier to read and comprehend when they are disassembled.

Try disassembling a program written in Visual BASIC. Most Disassemblers fail to
disassemble these programs because they assume that the structure of the
executable file is similar to that of C/C++ compiled programs.
Hence many people think that it is extremely difficult to disassemble and
understand programs written in Visual BASIC. However it is not so.

The executable file structure is entirely different in Visual Basic programs.
Once we get to know how Object data, strings and functions are stored and how
events are implemented then comprehending Disassembled Listings of Visual Basic
programs gets a lot easier.

So this tutorial does just that. Along with that it also gives ample proof to
show why Visual BASIC is never used by experts to write Fast and efficient code.
You will see in later examples why programs generated by Visual BASIC are slow.

The Tutorial will talk about executable files compiled in Visual BASIC in
Native Code and not p-code.

After reading this tutorial, you should be able to disassemble,debug and
understand Visual Basic Applications. You may also be able to reverse engineer
Protection Mechanisms written in Visual BASIC and by doing that you are putting
yourself to risk and not the author.

So now that you know what to expect from this tutorial, let's go ahead.

--------------------------------------------------------------------------------

VII.	   STRUCTURE OF A VB PROGRAM	  [SVBP]

When you open a VB Program in IDA, you'll end up with the following code.

start:
				 push	offset dword_4012B4
				 call	ThunRTMain
; ---------------------------------------------------------------------------
				 dd 0, 300000h, 400000h, 0, 0E9960000h, 82E6FCDFh, 939C4C23h
				 dd 0EB969B2Fh, 73D5h, 0, 1, 34303230h, 72503033h, 63656A6Fh
			; etc etc etc


This doesn't make any sense does it? If you keep scrolling further you will see
sections of code and data. Each Section has a meaning in VB Programs and you can
see a general idea of a Visual BASIC program's Section Map below.


00401000:
... IAT (First Thunk ok apis)

Next Section(NS):
... some data

NS:
... transfer area (Jumps to imported functions)

NS:
... lots of data

NS:
... local transfer area (for internal event handlers)

NS:
... other data

NS:
... code

NS:
... lots of data

NS:
... .data Section



Let us now start analysis from the entry point of the program.

push	offset RT_Struct
call	ThunRTMain

It's C equivalent would have been:
ThunRTMain(&RT_Struct);

A function ThunRTMain is called which accepts one parameter. We'll soon find out
that the parameter is a structure.
Simply putting a step over command on the CALL statement results in the
execution of the Application.
Wierd Isn't it?
For Pascal,C and C++ Programs there is always a start() function that takes all
CommandLine Parameters,Gets ProcessThreads,Module Handles etc. We didn't see
anything of the sort in a Visual BASIC Program.

But actually, VB does have a start function. The start function code is placed
in the ThunRTMain Function. Let's verify that by disassembling the MSVBM60.DLL
and viewing the ThunRTMain Function. I've mentioned only a part of the
ThunRTMain Function Code.


 ThunRTMain	  proc near

 arg_0		   = dword ptr  8

				 mov	 esi, [ebp+arg_0]
				 mov	 dword_7352F7DC, esi
				 and	 [ebp+var_4], 0
				 lea	 eax, [ebp+StartupInfo]
				 push	eax		; lpStartupInfo
				 lea	 eax, [ebp+StartupInfo]
				 push	eax		; lpStartupInfo
				 call	ds:GetStartupInfoA
				 movzx   eax, [ebp+StartupInfo.wShowWindow]
				 mov	 dword_7352F7D8, eax
				 push	hModule
				 push	esi
				 mov	 esi, offset dword_7352F470
				 mov	 ecx, esi
				 call	sub_7342DECD
				 mov	 [ebp+var_1C], eax
				 test	eax, eax
				 jl	  short loc_7342DEC5
				 push	0			 ; lParam
				 push	0			 ; wParam
				 push	1069h		 ; Msg
				 call	ds:GetCurrentThreadId
				 push	eax		; idThread
				 call	ds:PostThreadMessageA
			; Other Code

				 or	  [ebp+var_4], 0FFFFFFFFh
				 push	0			 ; uExitCode
				 call	ds:ExitProcess
				 jmp	 loc_734619B3

 loc_7342DEC5:						 ; CODE XREF: ThunRTMain+60j
				 push	eax
				 call	sub_Free_Memory
				 jmp	 short loc_7342DEB4
endp

As you can see, it does call all the Functions that the start() function does in
C and PASCAL programs. But what about CommandLine() Function from KERNEL32.DLL?
MSVBM60.DLL does call that function as well but that function call is placed in 
deeply nested function calls. You can open the Imports Window to see the
Imported Function and see the cross-reference to a procedure in MSVBM60.DLL

The sub_Free_Memory procedure calls various API Functions but if you keep
reading the procedure, you'll soon come across the HeapFree() Function which is
imported from kernel32.dll.

Now I guess you now know the purpose of the ThunRTMain Function.
Let us now see what structure is passed to it.

If we double-click on the RT_Struct offset, we reach an address containing
certain values.
It is a huge structure and each part needs to be seen one at a time.

Explaining the Structure will take up a lot of time and since I want to focus on
the Code Constructs of Visual BASIC, I won't entirely explain the Structure
passed to ThunRTMain.

We shall discuss the contents of this structure a little later.

I would also suggest you to read the article
"VISUAL BASIC REVERSED - A decompiling approach" by Andrea Geddon as it
does talk about the Structure passed to ThunRTMain in detail.

--------------------------------------------------------------------------------

VIII.	  OUR FIRST PROGRAM			  [OFPR]

Create a Form with a CommandButton. Click the CommandButton and add a simple 
Msgbox Code as shown below:

Private Sub Command1_Click()
		Msgbox "Ssup"
End Sub

Open the Compiled EXE File with IDA Pro.
Click the Strings Tab to find the "Ssup" String.
Double-Click the String to find its cross-reference.
Scroll up to the top of the procedure.
You should see something like this:

[Explanation is partly given by comments after an instruction.]

Command1_Click  proc near

 var_64		  = dword ptr -64h
 var_5C		  = dword ptr -5Ch
 var_54		  = dword ptr -54h
 var_4C		  = dword ptr -4Ch
 var_44		  = dword ptr -44h
 var_3C		  = dword ptr -3Ch
 var_34		  = dword ptr -34h
 var_2C		  = dword ptr -2Ch
 var_24		  = dword ptr -24h
 var_14		  = dword ptr -14h
 var_C		   = dword ptr -0Ch
 var_8		   = dword ptr -8; Destructor Object
 var_4		   = dword ptr -4
 form_object	 = dword ptr  8

				 push	ebp				; These two instructions
				 mov	 ebp, esp		; open the Stack Frame.
				 sub	 esp, 0Ch		; Allocates 12 bytes on stack
				 push	(offset exception_handler+1); Starts Exception Handler
				 mov	 eax, large fs:0
				 push	eax
				 mov	 large fs:0, esp
				 sub	 esp, 88h		; Allocates 136 bytes on stack
				 push	ebx
				 push	esi				; Saves Values of Registers
				 push	edi

											; Loads the Destructor
				 mov	 [ebp+var_C], esp
				 mov	 [ebp+var_8], offset destructor

										; Allocating Dynamic Resources
				 mov	 eax, [ebp+form_object]
				 mov	 ecx, eax
				 and	 ecx, 1
				 mov	 [ebp+var_4], ecx
				 and	 al, 0FEh
				 push	eax
				 mov	 [ebp+form_object], eax
				 mov	 edx, [eax]
				 call	dword ptr [edx+4]; Calls MSVBM60.Zombie_AddRef
				 mov	 ecx, 80020004h
				 xor	 esi, esi
				 mov	 [ebp+var_4C], ecx
				 mov	 eax, 0Ah
				 mov	 [ebp+var_3C], ecx
				 mov	 [ebp+var_2C], ecx
				 mov	 [ebp+var_34], esi
				 mov	 [ebp+var_44], esi
				 mov	 [ebp+var_54], esi
				 mov	 [ebp+var_64], esi
				 lea	 edx, [ebp+var_64]
				 lea	 ecx, [ebp+var_24]
				 mov	 [ebp+var_24], esi
				 mov	 [ebp+var_54], eax
				 mov	 [ebp+var_44], eax
				 mov	 [ebp+var_34], eax
				 mov	 [ebp+var_5C], offset aSsup; "Ssup"
				 mov	 [ebp+var_64], 8
				 call	ds:__vbaVarDup
				 lea	 eax, [ebp+var_54]
				 lea	 ecx, [ebp+var_44]
				 push	eax
				 lea	 edx, [ebp+var_34]
				 push	ecx
				 push	edx
				 lea	 eax, [ebp+var_24]
				 push	esi
				 push	eax
				 call	ds:rtcMsgBox		; Calls the MsgBox Function
				 lea	 ecx, [ebp+var_54]
				 lea	 edx, [ebp+var_44]
				 push	ecx
				 lea	 eax, [ebp+var_34]
				 push	edx
				 lea	 ecx, [ebp+var_24]
				 push	eax
				 push	ecx
				 push	4
				 call	ds:__vbaFreeVarList
				 add	 esp, 14h
				 mov	 [ebp+var_4], esi
				 push	offset continue_after_jump
				 jmp	 short fake_a_call_instr

				 lea	 edx, [ebp+var_54]
				 lea	 eax, [ebp+var_44]
				 push	edx
				 lea	 ecx, [ebp+var_34]
				 push	eax
				 lea	 edx, [ebp+var_24]
				 push	ecx
				 push	edx
				 push	4
				 call	ds:__vbaFreeVarList
				 add	 esp, 14h
				 retn
; ---------------------------------------------------------------------------

 fake_a_call_instr:
				 retn
; ---------------------------------------------------------------------------

 continue_after_jump:
				 mov	 eax, [ebp+arg_0]
				 push	eax
				 mov	 ecx, [eax]
				 call	dword ptr [ecx+8]; Calls MSVBM60.Zombie_Release
				 mov	 eax, [ebp+var_4]
				 mov	 ecx, [ebp+var_14]
				 pop	 edi
				 pop	 esi
				 mov	 large fs:0, ecx
				 pop	 ebx
				 mov	 esp, ebp
				 pop	 ebp			; Closes Stack Frame
				 retn	4
Command1_Click  endp


Simply by looking at the entire procedure you can't exactly figure out what the
hell happens when the whole subroutine is executed. If you know Assembly well
and have had the patience to read through the code, you should notice a few neat
things in the code.

[XTRA]

Before I begin explaining the procedure, I want to teach you how to recognise a
procedure in Visual BASIC. They can be called Procedure Signatures.
1) A Procedure has the open and close Stack Frame instructions.
2) The First Procedure in a VB Program is always preceded by
   12 0xCC Bytes (which corresponds to the INT 3 Instruction) followed by
	4 'T' bytes (0xE9) followed by 12 0xCC bytes.
3) Procedures other than the first are preceded by 10 NOP(0x90) Instructions.

: 1) STACK FRAME:

The Open/Close Stack Frame Instructions are even found in C/C++ and Pascal
programs and hence can be termed as a universal method of determining procedures.
However that is not always the case.

--> Many compilers just JMP instructions to fake a Call Instruction. This Jump
	is at times a CALL to a procedure. IDA Pro does not detect such
	CALL 'emulating' instructions but OllyDebug does recognise such
	code patterns.

--> Visual C++ allows the programmer to write naked functions. Naked functions
	mean that the compiler does not allocate space for its arguments nor does it
	include the stack open and close frame instructions.

But since we are dealing with Visual BASIC, we can ignore the second case. You
will see an example of the first case shortly.


: 2) THE 0xCC BYTE

The 0xCC Byte is used to Generate the INT 3 Exception, which is known as the
"CALL TO INTERRUPT" Procedure. It is used by Debuggers such as OllyDebug and
SoftIce to set software Breakpoints. Debuggers insert the 0xCC byte before the
instruction which it wants to set a breakpoint on. As soon as the INT 3
Instruction is executed, Control is passed onto the Debuggers Exception Handler.

Here is the description taken directly from Intel's Software Developers Manual
Volume 2 : Instruction Set Reference.
"The INT 3 instruction generates a special one byte opcode (CC) that is intended
for calling the debug exception handler. (This one byte form is valuable because
it can be used to replace the first byte of any instruction with a breakpoint,
including other one byte instructions, without over-writing other code). To
further support its function as a debug breakpoint, the interrupt generated with
the CC opcode also differs from the regular software interrupts as follows:
• Interrupt redirection does not happen when in VME mode; the interrupt is
  handled by a protected-mode handler.
• The virtual-8086 mode IOPL checks do not occur. The interrupt is taken without
  faulting at any IOPL level."

That's how debuggers work. That's also the concept of certain anti-debugging
techniques. Since the 0xCC code is injected by Debuggers before an instruction,
the CRC (Cyclic Redundancy Check) Value of the code also changes. Some
Antidebugging techniques encrypt the program with a key which is the CRC value
of the program. When a program is being debugged, its CRC value changes and with
the result the program doesn't get decrypted.
Such methods are effective in stopping amateur wannabe hackers from
understanding their code but its not foolproof and an expert hacker can get past
this technique with ease.

So much for what '0xCC' is. But why is it placed before the First Procedure in
VB Programs?
I've found no answer to that so far. This wastes a lot of space in a program.

If you try to disassemble a Console Program written in Visual C++, you'll find
many instructions which set parts of the stack to the '0xCC' value. You will
also find 0xCC bytes scattered across the disassembled listing.

If only Visual Studio was Open Source, we could have seen the code generation
code and come up with an answer and improve the code generation code too.
I hope you also realise why Open Source is slowly gaining momentum.


3) The 0x90 Byte

Here is the description taken directly from Intel's Software Developers Manual
Volume 2 : Instruction Set Reference.

"Performs no operation. This instruction is a one-byte instruction that takes up
space in the instruction stream but does not affect the machine context,
except the EIP register.
The NOP instruction is an alias mnemonic for the XCHG EAX, EAX instruction."

This byte is injected into serial generation/checking procedures by amateur
hackers where the protection mechanism is weak. This is known as bit-hacking.
Sadly enough, bit-hacking STILL works for defeating plenty of today's Commercial
Applications. Guess they never realised the importance for code-security.

While writing programs in Assembly Language, if you use Forward Referencing in a
few situations or use a wrong Jump Instruction to jump to certain addresses,
chances are quite bright that the Assembler will fill in some bytes with the NOP
instruction.
As a result, having the presence of the 0x90 Instruction in your code is
considered bad programming.

But again, I see no reason why the 0x90 Byte is present in Visual BASIC.
Removing such entries will reduce the executable size drastically.

Programs like VBDE rely on such Procedure Signatures to identify where a
procedure is present.

[/XTRA]

Let us start by analyzing the procedure in portions.
First the Procedure opens the Stack Frame. Then it allocates 12 Bytes on the 
stack for the Destructor and other variables. ( We shall see the Destructor in
detail after a short while. )
Then it allocates Dynamic Resources and calls the Zombie_AddRef Function.

Zombie is a state in which the only valid consumer action on a COM object is
generally to release that object.

Here is the description of the use of Zombie_Addref and Zombie_Release Functions 
from MSDN.

[XTRA]
The first three methods in a COM interface are required to be the same for all
COM interfaces. These are the methods of the IUnknown interface:
QueryInterface, AddRef, and Release.

The QueryInterface method takes an interface ID (an IID) and returns the
requested COM interface on the same object. The set of interface IDs
accessible via QueryInterface is the same from every interface on the object.


Each interface has a nominal reference count associated with it.
When a piece of code receives an interface, it should assume the reference count
is notionally 1 unless it has other knowledge.

AddRef increments the count, Release decrements it.

When the client has made one more call to Release than to
AddRef (meaning that the nominal count is zero), then it must assume that the
interface pointer is invalid. The provider of the interface may choose to
invalidate the interface pointer at that point (or not), but not before.
Some implementations have more relaxed behavior (for example, sharing
reference counts for all interfaces and/or only invalidating interface pointers
when the object is freed), but such behavior is not required, and should
certainly not be depended on. Although AddRef and Release return a ULONG, the
value returned is not required to have any meaning. Client code should not
depend in any way on the value returned. It exists solely for debugging code
to use, typically to return the new object reference count.

The reference-counting rules are very simple. When a client calls a member
function and passes one or more interface pointers:

The callee should AddRef its interface parameters if it wants them to stay around after it has gone.


The caller should Release the callee's returned interfaces when it
is done with them.
A straightforward consequence of the above rules is that QueryInterface does
an implicit AddRef on the returned interface, as do the
application programming interfaces (APIs) that create objects,
such as CoCreateInstance.
[/XTRA]

After reading the text above, you would understand why the AddRef and Release
Functions are present.

What does the Zombie_AddRef Function do? It Takes the Object Reference.
In this function the parent object (in this case Form) is passed as a parameter
and uses AddRef to increment reference count of the object (instantiation).
Since COM objects are responsible for their lifetime, the resources they use are
allocated until the reference count is 0, when it reaches 0 the objects enter
zombie state & can be deallocated to free resources.
Refer COM object management documentation for more detailed information.

Right after the call of the Zombie_AddRef Function there are MOV instructions
which assigns values to many variables. That follows a reference to the "Ssup"
string followed by a call to the rtcMsgbox procedure.

Why does it seem so wierd? Shouldn't it simply call the rtcMsgbox Function?
No, because it is a requirement to call QueryInterface,AddRef and Release 
functions in Applications using COM Technology.

Now about the rtcMsgbox function.
Intuition tells us that no matter what the function does, it will end up calling
the MessageBoxA or the MessageBoxW Function. So let's set a breakpoint on the
MessageBoxA and MessageBoxW Functions.

To do that, start OllyDebug and load the Executable file by pressing F3.
After the program is loaded, press Alt+E to open the Executable Modules window.
Double click USER32.DLL to open the disassembled listing of the User32.dll file.
From there press Ctrl+N to open the Imports/Exports window. Then Scroll over
till you see the MessageBoxA and MessageBoxW Functions. Click them one at a time
and press F2 to set a breakpoint.

Now press F9 to run the program. The Application should open. Click the 
CommandButton. Now instead of the Debugger halting at a breakpoint of MessageBox,
the MessageBox comes up without any halt to the Debugger.

Why does this happen? Does this mean that rtcMsgBox has a seperate copy of the
MessageBox code within itself? Though it seems like a possible reason, it is
unlikely to happen as Microsoft Developers built the Windows API so that they
could be reused for performance. So that means that some API Function is called 
which displays the MessageBox.
So let us try another experiment. In the same Imports/Exports Section of
User32.dll we see 2 more MessageBox functions which are MessageBoxIndirectA and
MessageBoxIndirectW. Let's try setting a breakpoint on both these Messages.

After the breakpoint is set, press F9, and click the Command Button.
This time, the Debugger halts at the MessageBoxIndirectA function.
Interesting isn't it? All Visual BASIC Applications which use the Msgbox()
Function are actually calls to MessageBoxIndirectA and not MessageBox as thought.

This is an important characteristic. So the Next time you set a breakpoint on 
the MessageBox function and the debugger halts at a breakpoint, you can be
pretty sure that someone has used the MessageBox() API Directly by consulting
the API Text Viewer for the VB Declaration.

Let us now see the prototype of the MessageBoxIndirect() API Function.

Private Declare Function MessageBoxIndirect Lib "user32" Alias
"MessageBoxIndirectA" (lpMsgBoxParams As MSGBOXPARAMS) As Long

Only One Parameter? So then how is the Message Body and Title passed to the
Function? For that we'll need to see the declaration of the MSGBOXPARAMS
Structure.

Private Type MSGBOXPARAMS
	cbSize As Long
	hwndOwner As Long
	hInstance As Long
	lpszText As String
	lpszCaption As String
	dwStyle As Long
	lpszIcon As String
	dwContextHelpId As Long
	lpfnMsgBoxCallback As Long
	dwLanguageId As Long
End Type

This suggests that the required parameters are assigned to variables and the
reference to that object is passed to that function.
So That suggests that the many MOV instructions found before the rtcMsgbox call
are used to initialise the MSGBOXPARAMS Structure.

To confirm our doubt, let's compare the MOV instructions with the code found
before the MessageBoxIndirect function is called.


  mov	 edx, [eax]
  mov	 [ebp+hWnd.lpszText], ecx
  mov	 ecx, [eax+8]
  mov	 eax, [eax+0Ch]
  push	esi
  push	ebx
  test	ah, 40h
  mov	 [ebp+hWnd.hInstance], edi
  mov	 [ebp+hWnd.lpszIcon], edi
  mov	 [ebp+hWnd.lpfnMsgBoxCallback], edi
  mov	 [ebp+hWnd.cbSize], 28h
  mov	 [ebp+hWnd.hwndOwner], edx
  mov	 [ebp+hWnd.lpszCaption], ecx
  mov	 [ebp+hWnd.dwStyle], eax
  mov	 [ebp+hWnd.dwLanguageId], edi
  jz	  short loc_734A6133
  mov	 [ebp+hWnd.lpfnMsgBoxCallback], offset sub_734A6098

loc_734A6133:

  mov	 esi, ds:MessageBoxIndirectA
  lea	 eax, [ebp+hWnd]
  push	eax		; LPMSGBOXPARAMSA
  call	esi; MessageBoxIndirectA

Interesting to see that....Isn't it?

Next comes the __vbaFreeVarList Function. From its name we can see that it
deallocates the address of a certain number of variables. This function actually
does no work except call the __vbaFreeVar Function multiple number of times.

Let us see how both functions work.

__vbaFreeVar			  : Frees a Temporary Variable.

__vbaFreeVar accepts only 1 Argument, which is the address of the variable to be
deleted. This argument is ALWAYS passed through ECX.
Uses the API Function __imp_SysFreeString()[Ordinal Number 6] from OLEAUT32.DLL
that carries out the actual deallocation of a variable.



__vbaFreeVarList		  : Frees Temporary Variables.

Have a look at this Snippet:

				 lea	 ecx, [ebp+var_54]; Variable 1 stored in ecx
				 lea	 edx, [ebp+var_44]; Variable 2 => edx
				 push	ecx			  ; Variable 1 pushed
				 lea	 eax, [ebp+var_34]; Variable 3 => eax
				 push	edx			  ; Variable 2 pushed
				 lea	 ecx, [ebp+var_24]; Variable 4 => ecx
				 push	eax			  ; Variable 3 pushed
				 push	ecx			  ; Variable 4 pushed
				 push	4				; Free 4 Temp. Variables
				 call	ds:__vbaFreeVarList

The code is pretty easy to understand. This function frees temporary variables
that are passed as arguments to it.Interestingly each memory location is
16 bytes wide.
This is an interesting function as it can accept variable arguments.
It's equivalent function call in C would be:
__vbaFreeVarList(4,&var_24,&var_34,&var_44,&var_54);

where its declaration would be:

int __vbaFreeVarList(int NUMBER_OF_VARIABLES_TO_FREE,<addresses of the vars>...)
{
   // CODE
}

Attached File(s)



Is This A Good Question/Topic? 0
  • +

Replies To: DISASSEMBLING VISUAL BASIC APPLICATIONS - II

#2 Tuzoid  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 3
  • View blog
  • Posts: 120
  • Joined: 20-August 06

Posted 13 November 2006 - 07:31 AM

It has been a while since I have coded VB, however this looks like a good tutorial

Good Job!
Was This Post Helpful? 0
  • +
  • -

#3 m2s87  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 21
  • View blog
  • Posts: 390
  • Joined: 28-November 06

Posted 15 January 2007 - 05:52 PM

In my point of view: 2 part gives an overview HoTo disassemble VB classic programs, and what should one notice while doing it.

I found what i where looking for in the topic and think, this is a better tutorial then the first one.

Tough i see no practical use of my new skill, but to understand that i am more enlightened now, i do think this is a useful tutorial to read. :D
Was This Post Helpful? 0
  • +
  • -

#4 born2c0de  Icon User is offline

  • printf("I'm a %XR",195936478);
  • member icon

Reputation: 180
  • View blog
  • Posts: 4,667
  • Joined: 26-November 04

Posted 16 January 2007 - 07:21 AM

Thanks, The third part is totally different and will be much better as it will focus on many other topics.

There are plenty of practical applications of this, but for a software developer its negligible.

This is more for someone keen on Application Security.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1