GetProcAddress2 - by Darawk

On viernes, 28 de enero de 2011 0 comentarios

//      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

#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);
}

0 comentarios:

Publicar un comentario