• Welcome to Valhalla Legends Archive.
 

[VB/C++/ASM] Disassemble

Started by n00blar, January 23, 2003, 01:05 PM

Previous topic - Next topic

n00blar

I have noticed recently quite a few people are wanting to do things dealing with hacking and visual basic.  I posted a link to this article a while ago however it's currently broken so I thought I would just post the article here -- it shows the disassembly of a normal visual basic function and explains the parts of it enjoy!

Original Visual Basic 6.0 Code

Public LongVal as Long

Public Function AddLONG(ByVal x as Long)
LongVal = LongVal + x
End Function

Disassembly & Explanation of above function

// Check Notes 1.0 //
Push EBP                              ; save current frame pointer on stack
Mov EBP, ESP                          ; Activate the new frame
Sub ESP, 00000008                     ; Subtract, Set ESP at the end of the frame

// Check Notes 1.1 //
Push 004010A6                        ; Push the Exception Handler Address
Mov EAX, DWORD PTR FS:[00000000]      ; Temporarily store the previous EXCEPTION_REGISTRATION
Push EAX                        ; Push the previous EXCEPTION_REGISTRATION on the stack
Mov DWORD PTR FS:[00000000]            ; Move own EXCEPTION_REGISTRATION address into FS:[0]

Sub ESP, 00000014

Push EBX                        ; Preserve These Three Registers
Push ESI
Push EDI

Mov Dword Ptr [EBP-08], ESP            
Mov [EBP-04], 00401090

Mov EAX, Dword Ptr [EBP+0C]            ; Move Address of Parameter Uno/One into EAX
Mov EDX, Dword Ptr [00402024]            ; Move Variable/Memory into EDX

Mov [EBP-20], 00000000                  ; Null [EBP-20]
Push 00401B37                        ; Push 00401B37 on stack

Mov ECX, Dword Ptr [EAX]            ; Move Contents of Parameter Uno/One into ECX
Add ECX, EDX                        ; Add The Two Registers

Jo 00401B66                        ; Jump OverFlow
Mov Dword Ptr [00402024], ECX            ; Finish Function (Store in Variable/Memory)
Jmp 00401B36                        ; Jump to Cleanup

// Check Notes 1.2 //
Lea ECX, Dword Ptr [EBP-20]            ;# Next Three Lines are an Exception Block
Call Dword Ptr [00401008]            
Ret                              ;# Ret Addr = 00401B37 (Push 00401B37)

// 00401B36 (Cleanup) //
Ret                               ;# Ret Addr = 00401B37 (Push 00401B37)
Mov EAX, Dword Ptr [EBP+08]            
Mov ECX, Dword Ptr [EBP-20]            ; Should Null ECX
Mov EDX, EAX                        ; EDX = EAX; EAX=Dword Ptr [EBP+08]

Pop EDI                              ; Restore These Three Registers
Pop ESI
Pop EBX

Mov Dword Ptr [EDX], ECX
Mov ECX, Dword Ptr [EBP-1C]
Mov Dword Ptr [EDX+04], ECX
Mov ECX, Dword Ptr [EBP-18]
Mov Dword Ptr [EDX+08], ECX
Mov ECX, Dword Ptr [EBP-14]            
Mov Dword Ptr [EDX+0C], ECX  
Mov ECX, Dword Ptr [EBP-10]            ; [EBP-10] = Previous EXCEPTION_RECORD
Mov Dword Ptr FS:[00000000], ECX      ; EXCEPTION_RECORD Head = Prev EXCEPTION_RECORD
 
Mov ESP, EBP    
Pop EBP                           ; activate caller's frame
Ret 0008                               ; return to the caller

// Notes 1.0 //
Any comment that has a # before it is considered to be an assumption or a guess.

// Notes 1.1 //
I will consider exceptions to be those that are explicitly thrown or occur due to conditions like divide by zero or null pointer access. When exception occurs, interrupt is generated and control is transferred to the operating system. Operating System, in turn, calls the exception handler that inspects the function call sequence starting from the current function from where the exception originated, and performs its job of stack unwinding and control transfer. We can write our own exception handler and register it with the operating system that it would call in the event of an exception.

Windows defines a special structure for registration, called EXCEPTION_REGISTRATION:

struct EXCEPTION_REGISTRATION
{
   EXCEPTION_REGISTRATION *prev;
   DWORD handler;
};

To register your own exception handler, create this structure and store its address at offset zero of the segment pointed to by FS register. Prev field signifies linked list EXCEPTION_REGISTRATION structures. When we register EXCEPTIOn_REGISTRATION structure, we store the address of the previously registered structure in prev field.

// Notes 1.2 //
This block of code seems to be the _except() block of the code but I have not verified this yet!

Adron

#1
VB6 really makes an exception frame in each function? I was looking at the exception handler chain for a VB5 program and only saw one VB5 frame for several functions. It seemed to handle all exceptions.

Do you have any information on VB5? I'm also interested in pcode applications, specifically I would like to instate a default error handler. Instead of just popping a msgbox it would write a log file, generate a minidump, possibly a stack trace, or at least give the line number info for the failure.

n00blar

#2
Im not sure about earler versions, however, VB5 and VB6 both insert a default exception handler for every function.. and yes it does use one handler for all the default exception chains and its found at 0x004010A6 in that program.  I think what you are wanting to do is 100% possible and I look forward to talking to you on bnet (im Dword)