Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - Apollo

Pages: [1]
1
Introductions! / g'day mates
« on: June 05, 2006, 04:05:13 am »
Hello, my name is Apollo.  Some of you may know me as Maddox/Madd0x and I've been around for a while.  I just finished my first year as an Electrical Engineering student at Georgia Tech.

I'm currently taking classes this summer as I plan on doing an Engineering co-op in the fall.  I also work on campus maintaining Linux server clusters for Aerospace research.

Course schedule for the summer:
    * Computer Science 4210. Advanced Operating Systems
    * Mathematics 2403. Differential Equations(A3)
    * Electrical & Computer Engr 2025. Introduction to Signal Processing(A)
    * Physics 2212. Introductory Physics II(Ka7)

You can check out my tutorial on hooking VB declarations here: http://www.x86labs.org:81/forum/index.php/topic,6097.msg72314.html

Besides computers, I like sports, particularly baseball, going to the gym, and wetting my whistle.

2
Tutorials, References, and Examples / 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!

Pages: [1]