一段仿真PE加载器行为的程序

转载 2007年10月14日 13:56:00
【  标题  】 一段仿真PE加载器行为的程序
【  声明  】 水平有限,不对之处敬请各位大侠赐教!

以下程序假定PE文件是合法的,所以很多地方都没有提供容错处理

bool PELoader(char *lpStaticPEBuff, long lStaticPELen)
{
  long lPESignOffset = *(long *)(lpStaticPEBuff + 0x3c);
  IMAGE_NT_HEADERS *pINH = (IMAGE_NT_HEADERS *)(lpStaticPEBuff + lPESignOffset);

  //取加载到内存中大小
  long lImageSize = pINH->OptionalHeader.SizeOfImage;
  char *lpDynPEBuff = new char[lImageSize];
  if(lpDynPEBuff == NULL)
  {
    return false;
  }
  memset(lpDynPEBuff, 0, lImageSize);

  //取PE文件的节数量
  long lSectionNum = pINH->FileHeader.NumberOfSections;

  //计算PE头信息及节表信息占用内存大小
  long lPEHeadSize = lPESignOffset + sizeof(IMAGE_NT_HEADERS) + lSectionNum * sizeof(IMAGE_SECTION_HEADER);
  
  //加载PE头部信息及其各个节表
  memcpy(lpDynPEBuff, lpStaticPEBuff, lPEHeadSize);

  //加载各个节
  long lFileAlignMask = pINH->OptionalHeader.FileAlignment - 1;        //各节在磁盘中的对齐掩码
  long lSectionAlignMask = pINH->OptionalHeader.SectionAlignment - 1;  //各节在load后内存中的对齐掩码
  IMAGE_SECTION_HEADER *pISH = (IMAGE_SECTION_HEADER *)((char *)pINH + sizeof(IMAGE_NT_HEADERS));
  for(int nIndex = 0; nIndex < lSectionNum; nIndex++, pISH++)
  {
    //判定各节的对齐属性,合法不
    if((pISH->VirtualAddress & lSectionAlignMask) || (pISH->SizeOfRawData & lFileAlignMask))
    {
      //出现非法节
      delete lpDynPEBuff;
      return false;
    }

    //加载改节
    memcpy(lpDynPEBuff + pISH->VirtualAddress, lpStaticPEBuff + pISH->PointerToRawData, pISH->SizeOfRawData);
  }

  //修改导入表,导入程序执行过程中要用到的API函数地址
  if(pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size > 0) //大于0说明有导入表
  {
    IMAGE_IMPORT_DESCRIPTOR *pIID = (IMAGE_IMPORT_DESCRIPTOR *)(lpDynPEBuff + /
      pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

    //循环扫描每个将有函数导入的dll
    for(; pIID->Name != NULL; pIID++)
    {
      /*曾看过OllyDump源代码,那里在重建导入表的时候,并没有初始化OriginalFirstThunk这个字段,
      所以这里也不对OriginalFirstThunk这个字段进行处理了*/
      IMAGE_THUNK_DATA *pITD = (IMAGE_THUNK_DATA *)(lpDynPEBuff + pIID->FirstThunk);

      HINSTANCE hInstance = LoadLibrary(lpDynPEBuff + pIID->Name);
      if(hInstance == NULL)
      {
        //导入这个dll失败
        delete lpDynPEBuff;
        return false;
      }

      //循环扫描dll内每个被导入函数
      for(; pITD->u1.Ordinal != 0; pITD++)
      {
        FARPROC fpFun;
        if(pITD->u1.Ordinal & IMAGE_ORDINAL_FLAG32)
        {
          //函数是以序号的方式导入的
          fpFun = GetProcAddress(hInstance, (LPCSTR)(pITD->u1.Ordinal & 0x0000ffff));
        }
        else
        {
          //函数是以名称方式导入的
          IMAGE_IMPORT_BY_NAME * pIIBN = (IMAGE_IMPORT_BY_NAME *)(lpDynPEBuff + pITD->u1.Ordinal);
          fpFun = GetProcAddress(hInstance, (LPCSTR)pIIBN->Name);
        }

        if(fpFun == NULL)
        {
          //导出这个函数失败
          delete lpDynPEBuff;
          return false;
        }

        pITD->u1.Ordinal = (long)fpFun;
      }

      FreeLibrary(hInstance);
    }
  }


  //重定位处理
  if(pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size > 0)
  {
    //取第一个重定位块
    IMAGE_BASE_RELOCATION *pIBR = (IMAGE_BASE_RELOCATION *)(lpDynPEBuff + /
      pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);

    long lDifference = (long)lpDynPEBuff - pINH->OptionalHeader.ImageBase;

    //循环每个重定位块
    for(; pIBR->VirtualAddress != 0; )
    {
      char *lpMemPage = lpDynPEBuff + pIBR->VirtualAddress;
      long lCount = (pIBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) >> 1;

      //对这个页面中的每个需重定位的项进行处理
      short int *pRelocationItem = (short int *)((char *)pIBR + sizeof(IMAGE_BASE_RELOCATION));
      for(int nIndex = 0; nIndex < lCount; nIndex++)
      {
        int nOffset = pRelocationItem[nIndex] &0x0fff;
        int nType = pRelocationItem[nIndex] >> 12;

        //虽然windows定义了很多重定位类型,但是在PE文件中只能见到0和3两种
        if(nType == 3)
        {
          *(long *)(lpDynPEBuff + nOffset) += lDifference;
        }
        else if(nType == 0)
        {
          //什么也不做
        }
      }

      //pIBR指向下一个重定位块
      pIBR = (IMAGE_BASE_RELOCATION *)(pRelocationItem + lCount);
    }

  }

  delete lpDynPEBuff;

  return true;
}
 
 

一段仿真PE加载器行为的程序

标 题: 【原创】一段仿真PE加载器行为的程序 作 者: linxer 时 间: 2006-06-10,00:50:49 链 接: http://bbs.pediy.com/showthre...
  • cosmoslife
  • cosmoslife
  • 2014年04月02日 22:19
  • 1266

向PE中注入代码

This article demonstrates five steps to inject your code in a portable executable (EXE, DLL, OCX,......
  • jacksonfan
  • jacksonfan
  • 2015年07月26日 23:28
  • 1775

xilinx fpga 学习笔记6:行为仿真

6.2.1 测试向量   HDL还可以描述变化的测试信号,描述测试信号的变化和测试过程的模块叫做测试平台testbench,它可以对任何一个HDL模块进行动态的全面的测试,通过对被测试模块的输出信号...
  • dnfestivi
  • dnfestivi
  • 2016年08月22日 21:38
  • 575

游戏人工智能开发之人群的动态行为交互仿真

博主把实验效果做成了视频,可以先看一下: youtube(清晰):https://youtu.be/S5wLx-zMrIE 优酷:http://v.youku.com/v_show/id_XMTMxO...
  • wolf96
  • wolf96
  • 2015年08月26日 09:05
  • 2038

基于网站的用户行为分析

谁在使用我的网站——用户行为分析 前面根据用户的特征对用户做了分类,设定了一些常用的用户指标和值得关注的用户指标,基于这些分类用户指标的分析可以发现用户运营和推广中的诸多问题,其中活跃用户和流失...
  • jasonjwl
  • jasonjwl
  • 2014年12月03日 20:21
  • 477

【EXE PE】初识pe结构--手写可执行程序

原文地址http://bbs.pediy.com/showthread.php?t=48590 【文章标题】: 手写可执行程序 【文章作者】: dncwbc 【作者邮箱】: dnc2588@...
  • zfpigpig
  • zfpigpig
  • 2013年09月06日 11:12
  • 4435

RTL行为级仿真、综合后门级功能仿真和时序仿真

数字电路设计中一般有源代码输入、综合、实现等三个比较大的阶段,而电路仿真的切入点也基本与这些阶段相吻合,根据适用的设计阶段的不同仿真可以分为RTL行为级仿真、综合后门级功能仿真和时序仿真。这种仿真轮廓...
  • limanjihe
  • limanjihe
  • 2016年04月14日 16:27
  • 1312

PE程序壳编写学习过程(一)PE文件的读取

参考书籍《加密与解密》第三版 一,头文件的包含。 由于使用WinGw编译,需要包含windef.h。然后为了windows文件的读取,包含winbase.h。又由于提示缺少va_list的声明,包...
  • l470279614
  • l470279614
  • 2016年08月26日 09:14
  • 152

仿真WINDOWS PE加载器的程序

此程序用来仿真PE加载器,可以直接运行内存中的程序。  bool PELoader(char *lpStaticPEBuff, long lStaticPELen) {   long lPE...
  • cosmoslife
  • cosmoslife
  • 2013年12月19日 23:25
  • 1422

Windows可执行文件(PE文件)壳的设计过程

PE文件壳的设计过程 标题:pe文件壳的设计过程 作者:baccon(PEDIY论坛),或chenxiang(软件发布者) 时间:2013年10月26日星期六...
  • adebies
  • adebies
  • 2014年10月04日 00:38
  • 1276
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一段仿真PE加载器行为的程序
举报原因:
原因补充:

(最多只允许输入30个字)