免费教程_免费网赚教程_破解版软件-寂涯网络学习基地

当前位置: 主页 > 系统综合 > 各类编程 > 如何动态获取API入口地址(2)

如何动态获取API入口地址(2)

时间:2011-12-15 17:25来源:未知 整理:寂涯网络 点击:

 
mov eax , [ebp]
  mov eax , [eax+4]
  mov addr,eax

这段代码是工程 GetApiAddr 中的实现方法,因为病毒代码并不需要经过启动代码,所
以工程 virus 的实现方法略有所不同,但跟踪分析的原理是一样的,读者可以去分析练习一
下。
 搜索 kernel32.dll 的基址

按 windows系统的设计,装入 dll 文件时要从一个独立页开始,装载基址处的内容也是
一个标准 PE 文件的开始。我们可以搜索返回地址低地址附近几个页的开始位置,看看是否
具有 DOS 文件头,NT 文件头等 PE 文件的起始标志,有这个标志的页就是 kernel32.dll 装
载的起始页。按这个方法,首先要得到返回地址所在页的起始地址,方法如下:
KernelBase = KernelBase & 0Xffff0000; //与后面的值进行并操作,得到页起始地址
然后检查本页起始处是否有PE文件的起始标志,如果没有则查找低地址页的起始位置,
循环下去直到找到kernel32.dll的基址。代码如下:

IMAGE_DOS_HEADER *doshead;
while(KernelBase >= 0X70000000) 

寻找 GetProcAddress的内存地址
//如果搜索到0X70000000,还没有找到的话说明已经不可能再找到了,直接退出
//此句防止一个错误的值使程序出现异常
{
 //首先检查dos文件头
  doshead = (IMAGE_DOS_HEADER*)KernelBase;
 if(doshead->e_magic == IMAGE_DOS_SIGNATURE)
 {
  //再检查 NT 文件头
   IMAGE_NT_HEADERS* nthead;
   nthead = (IMAGE_NT_HEADERS*)((LPBYTE)doshead+doshead->e_lfanew);
  if(nthead->Signature == IMAGE_NT_SIGNATURE)
  {
   break; //成功了,退出
  }
 }
 KernelBase-=0x10000; //向低地址移动一个页面
}

寻找 GetProcAddress的内存地址

这个搜索过程的原理是搜索 kernel32.dll 的导出表,把导出函数的名字与字符串
GetProcAddress进行匹配,相等时,就可以得到函数的基址了。学习这部分关键是对PE文
件的导出表格式要有所了解,详细知识可以去参考罗云彬的《windows 环境下 32 位汇编语
言程序设计》,看雪论坛的《加密与解密》等书,这里我就不费篇幅去写了。代码如下:  
 
DWORD AddrOfGetProcAddr , AddrOfLoadLib;
IMAGE_DOS_HEADER* pFile1; //指向dos文件头
IMAGE_NT_HEADERS* pFile2; //指向 nt文件头
pFile1 = (IMAGE_DOS_HEADER* )KernelBase;
pFile2 = (IMAGE_NT_HEADERS*)((PBYTE)pFile1 + pFile1->e_lfanew);
//检查文件的合法性,此处略去,详见源代码
IMAGE_EXPORT_DIRECTORY *pExport;
pExport=(IMAGE_EXPORT_DIRECTORY*)((PBYTE)pFile1+pFile2->OptionalHeader.
DataDirectory[0].VirtualAddress);
//以下在导出表中搜索名字为"GetProcAddress"的导出函数
char *FunName;
DWORD *AddrOfNameRVA;
WORD *AddrOfNameOrRVA;
AddrOfNameRVA = (DWORD*)(KernelBase + pExport->AddressOfNames);
for (int i = 0 ; i < (int)pExport->NumberOfNames ; i++)
{
 //得到一个导出函数的名字  
 
  FunName = (char*)(KernelBase + AddrOfNameRVA[i]);
 //函数名与字符串"GetProcAddress"进行比较
//为避免使用API,此处必须自己实现比较过程
 BOOL eql = 1;  //布尔类型变量
 for (int j = 0 ; j < 15 ; j ++)
 {
  if (GetProcAddrName[j] != FunName[j])
  {
    eql = 0;
   break;
  }
 }
 //如果 eql为 1,说明找到了,再去得到这个导出函数的基址
 if (eql)
 {
 AddrOfNameOrRVA=(WORD*)(KernelBase+pExport->AddressOfNameOrdinals)

;
 int num = 0;
  num = pExport->Base + AddrOfNameOrRVA[i];
  DWORD *AddrOfFun;
 AddrOfFun = (DWORD*)(KernelBase + pExport->AddressOfFunctions);
 //地址保存在变量AddrOfGetProcAddr中
  AddrOfGetProcAddr = KernelBase + AddrOfFun[num - 1];
 break;
 }

此时我们已经得到了 GetProcAddress 的基址,下面是调用这个函数得到 LoadLibrary
的基址,然后再调用LoadLibrary导入 User32.dll,再用 GetProcAddress得到MessageBox
的基址。这些代码都很简单,这里不再列举了。需要注意的是在Virus工程中的VirusCode
函数中,不能出现任何的函数调用,甚至 cout 都不行。另外,病毒代码中也不能出现任何

本页地址 http://www.jybase.net/biancheng/20111215718.html

百度搜索更多

谷歌搜索更多

顶一下
(1)
100%
踩一下
(0)
0%
------分隔线----------------------------

评价:
昵称: 验证码:点击我更换图片
推荐内容
赞助商
赞助商


关于本站免责声明视频更新google百度地图视频地图RRS订阅

如有什么问题请在本站留言,或发邮件到 hxt167#foxmail.com