Jump to content
Nytro

[SNIPPET] Improvements to GetProcAddress()

Recommended Posts

[sNIPPET] Improvements to GetProcAddress()

//      GetProcAddress2 - by Darawk 
// Featured @ www.RealmGX.com & www.Darawk.com
//
// GetProcAddress2 is essentially identical to the
// windows API function GetProcAddress, with one
// key difference. GetProcAddress2 does not check
// to make sure the module handle that's passed to
// it is in the loaded modules list. GetProcAddress2
// is designed to be used in conjunction with ManualMap
// or CloakDll. It allows you to access functions that
// have been exported from a dll loaded by ManualMap or
// cloaked by CloakDll. This functionality is necessary
// for plugin-based applications and late-binding functions.
#include <windows.h></windows.h>

#define IMAGE_DIRECTORY_ENTRY_EXPORT 0

// Pietrek's macro
//
// MakePtr is a macro that allows you to easily add to values (including
// pointers) together without dealing with C's pointer arithmetic. It
// essentially treats the last two parameters as DWORDs. The first
// parameter is used to typecast the result to the appropriate pointer type.
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD_PTR)(ptr) + (DWORD_PTR)(addValue))

// This one is mine, but obviously..."adapted" from matt's original idea =p
#define MakeDelta(cast, x, y) (cast) ( (DWORD_PTR)(x) - (DWORD_PTR)(y))

// My modified version of pietrek's function, to work with PE files that have
// already been mapped into memory.
LPVOID GetPtrFromRVA( DWORD, IMAGE_NT_HEADERS *, PBYTE, bool);

FARPROC GetProcAddress2(HMODULE hMod, char *func)
{
IMAGE_DOS_HEADER *dosHd;
IMAGE_NT_HEADERS *ntHd;
IMAGE_EXPORT_DIRECTORY *ied;
char **names;
unsigned short *ordinals;
FARPROC *funcs;

// Make sure we got a valid pointer
if(!hMod || hMod == INVALID_HANDLE_VALUE)
return NULL;

dosHd = (IMAGE_DOS_HEADER *)hMod;

// Verify the DOS header
if(dosHd->e_magic != IMAGE_DOS_SIGNATURE)
return NULL;

ntHd = MakePtr(IMAGE_NT_HEADERS *, hMod, dosHd->e_lfanew);

// Verify the NT header
if(ntHd->Signature != IMAGE_NT_SIGNATURE)
return NULL;

ied = (IMAGE_EXPORT_DIRECTORY *)GetPtrFromRVA((DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress),
ntHd,
(PBYTE)hMod, true);

names = (char **)GetPtrFromRVA(ied->AddressOfNames, ntHd, (PBYTE)hMod, true);
ordinals = (unsigned short *)GetPtrFromRVA(ied->AddressOfNameOrdinals, ntHd, (PBYTE)hMod, true);
funcs = (FARPROC *)GetPtrFromRVA(ied->AddressOfFunctions, ntHd, (PBYTE)hMod, true);

unsigned int i;
for(i = 0; i < ied->NumberOfNames; i++)
if(!stricmp((char *)GetPtrFromRVA((DWORD)names[i], ntHd, (PBYTE)hMod, true), func))
break;

if(i >= ied->NumberOfNames)
return NULL;

return MakePtr(FARPROC, hMod, funcs[ordinals[i]]);
}

// Matt Pietrek's function
PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva, PIMAGE_NT_HEADERS pNTHeader)
{
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
unsigned int i;

for ( i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
{
// This 3 line idiocy is because Watcom's linker actually sets the
// Misc.VirtualSize field to 0. (!!! - Retards....!!!)
DWORD size = section->Misc.VirtualSize;
if ( 0 == size )
size = section->SizeOfRawData;

// Is the RVA within this section?
if ( (rva >= section->VirtualAddress) &&
(rva < (section->VirtualAddress + size)))
return section;
}

return 0;
}

unsigned long GetMappedSectionOffset(IMAGE_NT_HEADERS *ntHd, IMAGE_SECTION_HEADER *seHd, void *base)
{
IMAGE_SECTION_HEADER *section = IMAGE_FIRST_SECTION(ntHd);
unsigned int i;
unsigned long offset = MakeDelta(unsigned long, section, base);

for(i = 0; i < ntHd->FileHeader.NumberOfSections; i++, section++)
{
if(section->Name == seHd->Name)
{
offset = MakeDelta(unsigned long, section->VirtualAddress, section->PointerToRawData);
break;
}

//offset += (section->SizeOfRawData > ntHd->OptionalHeader.SectionAlignment ?
// section->SizeOfRawData - ntHd->OptionalHeader.SectionAlignment :
// ntHd->OptionalHeader.SectionAlignment - section->SizeOfRawData);
}

return offset;
}

// This function is also Pietrek's
LPVOID GetPtrFromRVA( DWORD rva, IMAGE_NT_HEADERS *pNTHeader, PBYTE imageBase, bool mapped )
{
PIMAGE_SECTION_HEADER pSectionHdr;
INT delta;
unsigned long offset = 0;

pSectionHdr = GetEnclosingSectionHeader( rva, pNTHeader );

if(mapped)
offset = GetMappedSectionOffset(pNTHeader, pSectionHdr, imageBase);

if ( !pSectionHdr )
return 0;

delta = (INT)(pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData);
return (PVOID) ( imageBase + rva - delta + offset);
}

Sursa: ic0de.org

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...