在win7下kernel32.dll地址获取

#include 
#include 


__inline __declspec(naked) unsigned int findkerneldll(){
  __asm{
    push esi
  push edi
  push ecx
    xor ecx, ecx
    mov esi, fs:0x30
    mov esi, [esi + 0x0c]
    mov esi, [esi + 0x1c]
next_module:
    mov eax, [esi + 0x8]
    mov edi,[esi+0x20]
    mov esi ,[esi]
    cmp [edi+12*2],cx
    jne next_module
  pop ecx
  pop edi
    pop esi
    Ret
  }
}
unsigned int GetFunctionByName(unsigned int ImageBase,const char*FuncName,int flen)
{
  unsigned int FunNameArray,PE,Count=0,*IED;
  __asm
  {
    mov eax,ImageBase
      add eax,0x3c//指向PE头部偏移值e_lfanew
      mov eax,[eax]//取得e_lfanew值
      add eax,ImageBase//指向PE header
      //cmp [eax],0x00004550
      //jne NotFound//如果ImageBase句柄有错
      mov PE,eax
      mov eax,[eax+0x78]
      add eax,ImageBase
      mov [IED],eax//指向IMAGE_EXPORT_DIRECTORY

      mov eax,[eax+0x20]
      add eax,ImageBase
      mov FunNameArray,eax//保存函数名称指针数组的指针值
      mov ecx,[IED]
      mov ecx,[ecx+0x14]//根据引出函数个数NumberOfFunctions设置最大查找次数
FindLoop:
    push ecx//使用一个小技巧,使用程序循环更简单
      mov eax,[eax]
      add eax,ImageBase
      mov esi,FuncName
      mov edi,eax
      mov ecx,flen//逐个字符比较,如果相同则为找到函数,注意这里的ecx值
      cld
      rep cmpsb
      jne FindNext//如果当前函数不是指定的函数则查找下一个
      add esp,4//如果查找成功,则清除用于控制外层循环而压入的Ecx,准备返回
      mov eax,[IED]
      mov eax,[eax+0x1c]
      add eax,ImageBase//获得函数地址表
      shl Count,2//根据函数索引计算函数地址指针=函数地址表基址+(函数索引*4)
      add eax,Count
      mov eax,[eax]//获得函数地址相对偏移量
      add eax,ImageBase//计算函数真实地址,并通过Eax返回给调用者
      jmp Found
FindNext:
    inc Count//记录函数索引
      add [FunNameArray],4//下一个函数名指针
      mov eax,FunNameArray
      pop ecx//恢复压入的ecx(NumberOfFunctions),进行计数循环
      loop FindLoop//如果ecx不为0则递减并回到FindLoop,往后查找
NotFound:xor eax,eax//如果没有找到,则返回0
Found: nop
  }
}


typedef HMODULE (WINAPI *fun_ptr)(LPCSTR); 
int main()
{

  unsigned int keradd;
  unsigned int loadlibfun,getprofun;
  HANDLE lh,mytest;
  fun_ptr pmytestfun;

  unsigned int test;
  char title[]="test",user32[]="user32.dll",msgf[]="MessageBoxA";



  lh = LoadLibraryA("kernel32.dll");
  printf("real--kernel32.dll--:%x\n",lh);
  printf("real\"LoadLibraryA\" :%x\n",(unsigned int)LoadLibraryA);
  printf("real\"GetProcAddress\" :%x\n",(unsigned int)GetProcAddress);

  lh = LoadLibraryA("user32.dll");
  printf("real--user32.dll--:%x\n",lh);
  test = (unsigned int)GetProcAddress(lh,"MessageBoxA");
  printf("real\"MessageBoxA\":%x\n\n",(unsigned int)MessageBoxA);


  keradd = findkerneldll();
  printf("my kernel32.dll:%x\n",keradd);

  
  getprofun=GetFunctionByName(keradd,"GetProcAddress",14);
  loadlibfun=GetFunctionByName(keradd,"LoadLibraryA",12);
  
  
  printf("my \"LoadLibraryA\":%x\n",loadlibfun);
  printf("my \"GetProcAddress\":%x\n",getprofun);
  pmytestfun=(fun_ptr)loadlibfun;
  mytest=pmytestfun("user32.dll");
  printf("my user32.dll:%x\n",(unsigned int)mytest );
  printf("my \"MessageBoxA\":%x\n",GetFunctionByName((unsigned int)mytest,"MessageBoxA",11));
  

//   __asm
//   {
//     lea eax,user32
//       push eax
//       call dword ptr loadlibfun //相当于执行LoadLibrary("user32");
//       lea ebx,msgf
//       push 0x0b//"MessageBoxA"的长度
//       push ebx
//       push eax
//       call GetFunctionByName
//       mov ebx,eax
//       add esp,0x0c//GetFunctionByName使用C调用约定,由调用者调整堆栈
//       push 0
//       lea eax,title
//       push eax
//       push eax
//       push 0
//       call ebx//相当于执行MessageBox(NULL,"test","test",MB_OK)
//   }



  return 0;
}


你可能感兴趣的:(PE文件分析)