tags:

views:

143

answers:

3

As I mentioned on one my previous questions I am playing with simulating GetProcAddress() in my code. The following code is successful in doing this, however it causes the application to crash on windows 7

void *GetFuncAddr(HMODULE hModule, char *fname) 
{
    unsigned int count = 1;
    IMAGE_DOS_HEADER *DosHeader;
    IMAGE_NT_HEADERS *NtHeaders;
    IMAGE_OPTIONAL_HEADER *OptionalHeader;
    IMAGE_DATA_DIRECTORY *DataDirectory;
    IMAGE_EXPORT_DIRECTORY *Exp;
    ULONG *addrof;
    char *fullfname;
    ULONG *faddr;

    DosHeader = (IMAGE_DOS_HEADER *)hModule; 
    if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) 
    { 
     return NULL;
    } 

    NtHeaders = (IMAGE_NT_HEADERS *)(((BYTE *)DosHeader) + DosHeader->e_lfanew); 
    if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
    { 
     return NULL;
    } 

    OptionalHeader = &NtHeaders->OptionalHeader; 
    DataDirectory = &OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 

    Exp = (IMAGE_EXPORT_DIRECTORY *)((size_t)DosHeader + DataDirectory->VirtualAddress); 

    addrof = (ULONG *)((BYTE*) hModule + Exp->addrof);
    faddr = (ULONG*) ((BYTE*) hModule + Exp->AddressOfFunctions);

    for(count = 0; count < Exp->NumberOfNames; count++)
    {
     fullfname = (char*)((BYTE*) hModule + addrof[count]);  
     if(strcmp(fullfname, fname) == 0)
     { 
      return (void*)((BYTE*) hModule + faddr[count]);
     }
    }

    return NULL;
}

It doesn't matter what function I tried loading using this the application crashes. The crashes occurs when calling the imported function so my guess is that the pointer returned might be the offending thing here. This occurs on both x86 and x64. Is there any visible reason for this in this code?

I tried setting the function to return FARPROC but I'm getting all confused about how to cast the return on ((BYTE*) hModule + faddr[count]);

Anyway, any ideas? solutions? Any help is appreciated.

Thanks. jess.

EDIT The error returned by some of the API's i am importing is error 18, the parameter is incorrect.

+1  A: 

It looks like you are assuming Ordinal # = offset in table. Maybe that's not true in Windows 7 DLLs.

Joshua
If you just print the function names and their addresses it seems to be OK even on windows 7. GetProcAddress returns the same address
Jessica
You might be onto something: this is what happens when you import GetWindowThreadProcessId: with GetProcAddress I get 0x7553ed3c as the address and with my code I get 0x75566420. This doesn't happen with the functions that are imported from Kernel32, only those imported from User32 and other DLLs. any comments?
Jessica
A little correction, it does occasionally happens with Kernel32 as in the case of CreateToolhelp32Snapshot
Jessica
A: 

How do you create the handle hModule? And why don't you just use GetProcAddress (your function seems to duplicate the behaviour of your function)?

frunsi
hModule comes from LoadLibrary. and I don't want to use GetProcAddress, hence the code I posted which, as you mentioned, does indeed replicate the functionality, or tries.
Jessica
+3  A: 

I think you may need to do an additional lookup.

USHORT *ford;
...
ford = (USHORT*) ((BYTE*) hModule + Exp->AddressOfNameOrdinals);

and then offset by the ordinal:

            return (void*)((BYTE*) hModule + faddr[ford[count]]);

This article talks about it some: http://msdn.microsoft.com/en-us/magazine/cc301808.aspx

Mark Wilkins
That did it. Thanks so much.
Jessica
Cool. I learned something about it while looking at it, so that's good too. And if you give me an up vote, I'll get 10 more points in this game :)
Mark Wilkins