PE文件填充.dll原理解析

作为和杀毒软件的对抗技术出现的无特征码处理中一个比较小众,但是效果明显的技术就是.dll填充。而且作为一个上手即可使用毫无副作用的技术,作为预处理效果也非常明显。但是一直很疑惑为什么可以把输入表中的.dll填充了却不会影响程序的运行。下面会从PE装载器和loadlibrary的汇编代码角度解析这个问题。

.dll填充简介:
c32载入文件,把输入表中一些关键dll的.dll4个字节填充为0000。原始
改后

填充之后并不会影响其运行加载。

原理解析:
1.PE装载器会从可选头部信息中找到输入表的所在处
2.PE装载器找到IMAGE_IMPORT_DESCRIPTOR结构体
3.从结构体中定位到Name成员地址(指向)—->kernel32.dll
4.得到kernel32.dll,调用LoadLibrary(kernel32.dll);加载dll,再用getprocaddress获得函数实际地址填充FirstThunk区域
附这部分的仿真代码:

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

5.LoadLibrary(kernel32.dll)和LoadLibrary(kernel32)等价
6.OD跟踪LoadLibrary的实现
LoadLibrary—>LoadLibraryA—->LoadLibraryExA—>LoadLibraryExW
LoadLibraryExW内部通过调用rtldosApplyFileIUsolationRedirection函数使得即使没有.dll后缀的dll文件补全

7.加载完成

猜你喜欢

转载自blog.csdn.net/joliph/article/details/79850739