从堆栈查找Kernel32.DLL基址

原理是这样的:

每个用户态进程的WinMain代码都是由启动代码(CRTStartup)调用的,而启动代码是kernel32.dll里的某个函数调用的,当然也可能没有WinMain和WinMainCRTStart之类的函数(如Delphi编译出的代码),但进程启动后,kernel32.dll中的一个的未知代码位置一定保存在堆栈里的,所以从顶往底测试堆栈里的元素,一定可以找到kernel32.dll的基址,写了一小段代码,在Win XP SP2,VC++ 6.0 SP5下测试通过,可以找到我机器上的kernel32.dll的基址是0x7C800000.
CODE:


#include
#include
#include

DWORD GetKernel32(void)
{
DWORD TryAddr=0;
PIMAGE_DOS_HEADER pdos=NULL;
PIMAGE_NT_HEADERS pnt=NULL;
PIMAGE_EXPORT_DIRECTORY pied=NULL;
DWORD *pKernel=NULL;
int i=0;

PDWORD pEsp=(PDWORD)&pEsp;
BOOL bFound=FALSE;
do
{
  __try
  {
   TryAddr=*pEsp;
   
   for(i=0;i<4;i++)
   {
    TryAddr&=0xffff0000<<(i<<2);

    pdos=(PIMAGE_DOS_HEADER)TryAddr;
    pnt=(PIMAGE_NT_HEADERS)(TryAddr+pdos->e_lfanew);
   
    if(pdos->e_magic=='ZM'&&pnt->Signature=='EP')
    {
     pied=(PIMAGE_EXPORT_DIRECTORY)(TryAddr+pnt->OptionalHeader.DataDirectory[0].VirtualAddress);
     pKernel=(DWORD *)(TryAddr+pied->Name);

     //KERNEL32 or Kernel32
     if((*pKernel=='NREK'&&*(pKernel+1)=='23LE')||
      (*pKernel=='nreK'&&*(pKernel+1)=='23le'))
     {
      bFound=TRUE;
      break;
     };//end if pKernel

    }//end if pdos

   }//end for i
  }
  __except(1)
  {
   NULL;
  }
  pEsp++;
}while(!bFound);

return TryAddr;
}

int main(void)
{
printf("KERNEL32.DLL at:0x%.8X/n",GetKernel32());
return getchar();
}

你可能感兴趣的:(WINDOWS)