Author Topic: Hooking VB declarations  (Read 3848 times)

0 Members and 1 Guest are viewing this topic.

Offline Apollo

  • Newbie
  • *
  • Posts: 10
    • View Profile
Hooking VB declarations
« on: June 05, 2006, 03:53:09 am »
One of the hardest things about reverse engineering Visual Basic applications is the obscurity of system calls.  You can't simply patch the IAT to obtain a hook to your desired function.  It is pretty obvious that the libraries are loaded dynamically because of the run-time errors generated when libraries aren't found.  This quick guide will show you how VB makes library calls in assembly and then show you how to hook VB's DllFunctionCall() in order to call your own functions.

How does VB handle declarations? Well, let's look at some assembly!
Each declaration has a short stub that checks to see if the pointer to that function exists and if not, calls DllFunctionCall() to get it.  For this example we'll see how GetWindowThreadProcessId() in user32.dll is called.
That function looks like this
Code: [Select]
DWORD GetWindowThreadProcessId(     

    HWND hWnd,
    LPDWORD lpdwProcessId
);

When a VB application calls this function it will look like this
Code: [Select]
push lpdwProcessId
push hWnd
call sub_403208 ; stub for GetWindowThreadProcessId

The stub that it calls looks like this
Code: [Select]
.text:004031F0                 dd offset aUser32 ; offset to "user32"
.text:004031F4                 dd offset aGetWindowThreadProcessId ; offset to "GetWindowThreadProcessId"
.text:004031F8                 dd 40000h, 41A3A0h, 2 dup(0)
.text:00403208
.text:00403208
.text:00403208 sub_403208      proc near
.text:00403208                 mov     eax, dword_41A3A8 ; move address of GetWindowThreadProcessId into eax
.text:0040320D                 or      eax, eax ; sets zf if the function address == 0
.text:0040320F                 jz      short loc_403213 ; if function address == 0 then load the library and get the address
.text:00403211                 jmp     eax ; else jmp to the function (no need to use call, the ret address is already on the stack)
.text:00403213 loc_403213:
.text:00403213                 push    offset off_4031F0 ; put the struct pointer argument on the stack
.text:00403218                 mov     eax, offset DllFunctionCall
.text:0040321D                 call    eax ; DllFunctionCall
.text:0040321F                 jmp     eax ; jmp to the returned function
.text:0040321F sub_403208      endp

Now, without looking at the internals of DllFunctionCall() you can guess what it does.  It returns a pointer to the address of the function we are requesting.  How then, does dword_41A3A8 get set to the address of our function?  Well DllFunctionCall() must also modify the structure we passed to it earlier!  We can see that structure looks like this in C:
Code: [Select]
struct DllCallData {
     char * library;
     char * funcName;
     DWORD * unknown1;
     DWORD * unknown2;
};

We can see from our data that unknown1 = 40000h and unknown2 = 41A3A0h.  By observation we can see that dword_41A3A8 is only 8 bytes away from unknown2.  So dword_41A3A8 must be the 2nd index of that array.

Now putting it all together our hooked function will look something like this:
Code: [Select]
DWORD __stdcall MyDllFunctionCall(struct DllCallData * callData)
{
     DWORD ret = RealDllFunctionCall(callData); // call the actual DllFunctionCall from MSVBVM60.dll

     if (strnicmp(callData->library, "user32", 6) == 0 &&
          stricmp(callData->funcName, "GetWindowThreadProcessId") == 0) {
               ret = callData->unknown2[2] = (DWORD)&MyGetWindowThreadProcessId;
     }

     return ret;
}

Every time GetWindowThreadProcessId() is called from within our application now your function will be called.  Whooo!
« Last Edit: June 05, 2006, 03:57:15 am by Apollo »

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: Hooking VB declarations
« Reply #1 on: June 05, 2006, 08:17:35 am »
I can't believe you still waste your time on reverse engineering VB!  :-P

But seriously, good work -- it's not useful to me, but I bet this'll make somebody's life better.