压缩壳的实现

壳的分类

压缩壳:减少PE体积
代表:UPX
加密壳:代码混淆
壳界4大金刚:encryptedPE(VMPprotect)、 穿山甲(armdillo)、themida、asprotect

压缩壳

压缩完的PE文件提供两个节
第一个节:空节,大小大于原PE文件的节区总大小,用来放解压后的节区数据
第二个节:放解压缩代码和压缩后的数据
程序运行,装载压缩后的PE
压缩后的PE从伪程序入口点(解压缩代码处)开始解压,将压缩数据解压后放置正常的节区内
解压完毕,将入口点指向真正的OEP位置
注意:解压缩和跳入口点前后需要保存寄存器环境

为什么那么多壳都是选择把被加壳程序的区段放到第一个区段?

因为不放入第一个区段,定位地址会有问题,因为你拷贝的是原来的PE头,表的偏移位置都确定了,如果不放到第一个节区的话,就要修改PE的头的很多位置的偏移,如定位导入表,还有就是有些exe程序如果没有重定位表的话,自己还要构建重定位表,太麻烦

在这里插入图片描述
压缩壳代码如下
CMaker.h

#pragma once
#include <string>
#include <windows.h>
using namespace std;

class CMaker
{
public:
  bool Make(string strSrcPath, string strDstPath);

  //解析PE格式
private:
  bool AnalyzePE(string strSrcPath);
  PIMAGE_DOS_HEADER m_pDosHdr = nullptr;
  PIMAGE_NT_HEADERS m_pNtHdr = nullptr;
  PIMAGE_SECTION_HEADER m_pSecHdrs = nullptr;

private:
  struct CompressDataInfo
  {
    int m_nSrcSize = 0; //压缩前数据的大小
    int m_nComSize = 0; //压缩数据后的大小
    char* m_pComData = nullptr; //压缩后的数据
  };
  CompressDataInfo* m_pCompressDatas = nullptr; //压缩后的节数据
  bool CompressSectionsData();

  //解压缩代码
private:
  bool GetDecomcode();
  char* m_pDecompressCodeBuff = nullptr;
  int m_nDecompressCodeSize = 0;


private:
  bool GetDeCodeSec(); //构建解压缩代码节
  char* m_pDecodeSecData = nullptr;
  int m_nsizeOfDecodeSec = 0;

private:
  bool GetCompressDataSec(); //构建压缩数据节
  char* m_pCompressSecData = nullptr;
  int m_nSizeOfCompressSec = 0;

private:
  bool GetNewSectionHeaders(); //构建节表
  PIMAGE_SECTION_HEADER m_pNewSecHdrs = nullptr;
  int m_nNumberOfNewSecs = 0;

private:
  bool GetNewPeHdr();
  char* m_pNewPeHdr = nullptr;
  int m_nSizeOfNewPeHdr = 0;

private:
  bool WriteNewPeFile(string strDstPath);

private:
  int GetAlinValue(int nValue, int nAlign);
};


CMaker.cpp

#include "pch.h"
#include "CMaker.h"
#include <compressapi.h>
#pragma comment(lib, "Cabinet.lib")

bool CMaker::Make(string strSrcPath, string strDstPath)
{
  bool bRet = false;

  //1. 解析原PE的格式
  bRet = AnalyzePE(strSrcPath);

  //2. 获取压缩数据
  bRet = CompressSectionsData();

  //3. 获取解压缩代码
  bRet = GetDecomcode();

  //4. 生成新PE

  //4.1 构建节区数据
  bRet = GetCompressDataSec(); //构造压缩数据节
  bRet = GetDeCodeSec();//构造解压缩代码节

  //4.2 构建节表
  bRet = GetNewSectionHeaders();

  //4.3 构建PE头
  bRet = GetNewPeHdr();

  //4.4 写入文件
  bRet = WriteNewPeFile(strDstPath);

  return bRet;
}

bool CMaker::AnalyzePE(string strSrcPath)
{
  //打开文件
  HANDLE hFle = CreateFile(strSrcPath.c_str(), 
    FILE_GENERIC_READ | FILE_GENERIC_WRITE,
    FILE_SHARE_READ,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL);
  if (hFle == (HANDLE)-1)
  {
    return false;
  }
  HANDLE hFileMap = CreateFileMapping(
    hFle,    // Current file handle. 
    NULL,                              // Default security. 
    PAGE_READWRITE,                    // Read/write permission. 
    0,                                 // Max. object size. 
    0,                                 // Size of hFile. 
    NULL);            // Name of mapping object. 
  if (hFileMap == NULL)
  {
    return false;
  }

  LPVOID lpMapAddress = MapViewOfFile(
    hFileMap, // Handle to mapping object. 
    FILE_MAP_ALL_ACCESS,               // Read/write permission. 
    0,                                 // Max. object size. 
    0,                                 // Size of hFile. 
    0);                                // Map entire file. 

  if (lpMapAddress == NULL)
  {
    return false;
  }

  //分析PE格式
  m_pDosHdr = (PIMAGE_DOS_HEADER)lpMapAddress;
  m_pNtHdr = (PIMAGE_NT_HEADERS)((char*)lpMapAddress + m_pDosHdr->e_lfanew);
  m_pSecHdrs = (PIMAGE_SECTION_HEADER)
    ((char*)&m_pNtHdr->OptionalHeader + m_pNtHdr->FileHeader.SizeOfOptionalHeader);

  return false;
}

bool CMaker::CompressSectionsData()
{
  //遍历节表, 压缩每一个节数据
  int nNumberOfSections = m_pNtHdr->FileHeader.NumberOfSections;
  m_pCompressDatas = new CompressDataInfo[nNumberOfSections];

  for (int i = 0; i < nNumberOfSections; i++)
  {
    char* pSecData = (char*)m_pDosHdr + m_pSecHdrs[i].PointerToRawData;//节数据
    int  nSizeOfSecData = m_pSecHdrs[i].SizeOfRawData; //节数据的大小

    //压缩
    COMPRESSOR_HANDLE hCompressor;
    BOOL bSuccess = CreateCompressor(
      COMPRESS_ALGORITHM_XPRESS_HUFF, //  Compression Algorithm
      NULL,                           //  Optional allocation routine
      &hCompressor);                   //  Handle

    if (!bSuccess)
    {
      return false;
    }

    //  计算压缩数据所需要的缓冲区大小
    SIZE_T nCompressedBufferSize = 0;
    bSuccess = Compress(
      hCompressor,                  //  Compressor Handle
      pSecData,                 //  Input buffer, Uncompressed data
      nSizeOfSecData,               //  Uncompressed data size
      NULL,                        //  Compressed Buffer
      0,                           //  Compressed Buffer size
      &nCompressedBufferSize);      //  Compressed Data size

    char* pCompressDataBuff = nullptr;
    if (!bSuccess)
    {
      //申请内存,用于保存压缩后的数据
      pCompressDataBuff = (char*)malloc(nCompressedBufferSize);
      if (pCompressDataBuff == nullptr)
      {
        return false;
      }
    }

    //  压缩数据
    SIZE_T nRealCompressSize = 0;
    bSuccess = Compress(
      hCompressor,             //  Compressor Handle
      pSecData,            //  Input buffer, Uncompressed data
      nSizeOfSecData,          //  Uncompressed data size
      pCompressDataBuff,       //  Compressed Buffer
      nCompressedBufferSize,   //  Compressed Buffer size
      &nRealCompressSize);   //  Compressed Data size

    if (!bSuccess)
    {
      return false;
    }

    //保存压缩数据的信息
    m_pCompressDatas[i].m_nSrcSize = nSizeOfSecData;
    m_pCompressDatas[i].m_nComSize = nRealCompressSize;
    m_pCompressDatas[i].m_pComData = pCompressDataBuff;
  }

  return false;
}

bool CMaker::GetDecomcode()
{
  unsigned char data[1824] = {
  0x55, 0x8B, 0xEC, 0x81, 0xEC, 0xB4, 0x00, 0x00, 0x00, 0xE8, 0x32, 0x03, 0x00, 0x00, 0x89, 0x45,
  0xA0, 0xC6, 0x45, 0xD0, 0x4C, 0xC6, 0x45, 0xD1, 0x6F, 0xC6, 0x45, 0xD2, 0x61, 0xC6, 0x45, 0xD3,
  0x64, 0xC6, 0x45, 0xD4, 0x4C, 0xC6, 0x45, 0xD5, 0x69, 0xC6, 0x45, 0xD6, 0x62, 0xC6, 0x45, 0xD7,
  0x72, 0xC6, 0x45, 0xD8, 0x61, 0xC6, 0x45, 0xD9, 0x72, 0xC6, 0x45, 0xDA, 0x79, 0xC6, 0x45, 0xDB,
  0x41, 0xC6, 0x45, 0xDC, 0x00, 0xC6, 0x45, 0xC0, 0x47, 0xC6, 0x45, 0xC1, 0x65, 0xC6, 0x45, 0xC2,
  0x74, 0xC6, 0x45, 0xC3, 0x50, 0xC6, 0x45, 0xC4, 0x72, 0xC6, 0x45, 0xC5, 0x6F, 0xC6, 0x45, 0xC6,
  0x63, 0xC6, 0x45, 0xC7, 0x41, 0xC6, 0x45, 0xC8, 0x64, 0xC6, 0x45, 0xC9, 0x64, 0xC6, 0x45, 0xCA,
  0x72, 0xC6, 0x45, 0xCB, 0x65, 0xC6, 0x45, 0xCC, 0x73, 0xC6, 0x45, 0xCD, 0x73, 0xC6, 0x45, 0xCE,
  0x00, 0xC6, 0x45, 0xEC, 0x43, 0xC6, 0x45, 0xED, 0x61, 0xC6, 0x45, 0xEE, 0x62, 0xC6, 0x45, 0xEF,
  0x69, 0xC6, 0x45, 0xF0, 0x6E, 0xC6, 0x45, 0xF1, 0x65, 0xC6, 0x45, 0xF2, 0x74, 0xC6, 0x45, 0xF3,
  0x00, 0xC6, 0x45, 0xAC, 0x43, 0xC6, 0x45, 0xAD, 0x72, 0xC6, 0x45, 0xAE, 0x65, 0xC6, 0x45, 0xAF,
  0x61, 0xC6, 0x45, 0xB0, 0x74, 0xC6, 0x45, 0xB1, 0x65, 0xC6, 0x45, 0xB2, 0x44, 0xC6, 0x45, 0xB3,
  0x65, 0xC6, 0x45, 0xB4, 0x63, 0xC6, 0x45, 0xB5, 0x6F, 0xC6, 0x45, 0xB6, 0x6D, 0xC6, 0x45, 0xB7,
  0x70, 0xC6, 0x45, 0xB8, 0x72, 0xC6, 0x45, 0xB9, 0x65, 0xC6, 0x45, 0xBA, 0x73, 0xC6, 0x45, 0xBB,
  0x73, 0xC6, 0x45, 0xBC, 0x6F, 0xC6, 0x45, 0xBD, 0x72, 0xC6, 0x45, 0xBE, 0x00, 0xC6, 0x45, 0xE0,
  0x44, 0xC6, 0x45, 0xE1, 0x65, 0xC6, 0x45, 0xE2, 0x63, 0xC6, 0x45, 0xE3, 0x6F, 0xC6, 0x45, 0xE4,
  0x6D, 0xC6, 0x45, 0xE5, 0x70, 0xC6, 0x45, 0xE6, 0x72, 0xC6, 0x45, 0xE7, 0x65, 0xC6, 0x45, 0xE8,
  0x73, 0xC6, 0x45, 0xE9, 0x73, 0xC6, 0x45, 0xEA, 0x00, 0x8D, 0x45, 0xD0, 0x50, 0x8B, 0x4D, 0xA0,
  0x51, 0xE8, 0x4A, 0x02, 0x00, 0x00, 0x89, 0x45, 0x84, 0x8D, 0x55, 0xC0, 0x52, 0x8B, 0x45, 0xA0,
  0x50, 0xE8, 0x3A, 0x02, 0x00, 0x00, 0x89, 0x45, 0x98, 0x8D, 0x4D, 0xEC, 0x51, 0xFF, 0x55, 0x84,
  0x89, 0x45, 0x9C, 0x8D, 0x55, 0xAC, 0x52, 0x8B, 0x45, 0x9C, 0x50, 0xFF, 0x55, 0x98, 0x89, 0x85,
  0x78, 0xFF, 0xFF, 0xFF, 0x8D, 0x4D, 0xE0, 0x51, 0x8B, 0x55, 0x9C, 0x52, 0xFF, 0x55, 0x98, 0x89,
  0x85, 0x60, 0xFF, 0xFF, 0xFF, 0xE8, 0xA6, 0x01, 0x00, 0x00, 0x89, 0x45, 0xF8, 0x8B, 0x45, 0xF8,
  0x89, 0x45, 0x80, 0x8B, 0x4D, 0x80, 0x8B, 0x55, 0xF8, 0x03, 0x51, 0x3C, 0x89, 0x55, 0xA4, 0x8B,
  0x45, 0xA4, 0x0F, 0xB7, 0x48, 0x14, 0x8B, 0x55, 0xA4, 0x8D, 0x44, 0x0A, 0x18, 0x89, 0x85, 0x7C,
  0xFF, 0xFF, 0xFF, 0xB9, 0x28, 0x00, 0x00, 0x00, 0xD1, 0xE1, 0x8B, 0x95, 0x7C, 0xFF, 0xFF, 0xFF,
  0x8B, 0x45, 0xF8, 0x03, 0x44, 0x0A, 0x0C, 0x89, 0x45, 0x94, 0x8B, 0x4D, 0x94, 0x8B, 0x11, 0x89,
  0x55, 0x90, 0x8B, 0x45, 0x94, 0x83, 0xC0, 0x04, 0x89, 0x45, 0xF4, 0x8B, 0x4D, 0x90, 0xC1, 0xE1,
  0x04, 0x03, 0x4D, 0xF4, 0x89, 0x4D, 0x8C, 0xC7, 0x45, 0x88, 0x00, 0x00, 0x00, 0x00, 0x8D, 0x55,
  0x88, 0x52, 0x6A, 0x00, 0x6A, 0x04, 0xFF, 0x95, 0x78, 0xFF, 0xFF, 0xFF, 0x89, 0x85, 0x5C, 0xFF,
  0xFF, 0xFF, 0x8B, 0x45, 0x8C, 0x89, 0x85, 0x4C, 0xFF, 0xFF, 0xFF, 0xC7, 0x45, 0xA8, 0x00, 0x00,
  0x00, 0x00, 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x09, 0x8B, 0x4D, 0xFC, 0x83, 0xC1,
  0x01, 0x89, 0x4D, 0xFC, 0x8B, 0x55, 0xFC, 0x3B, 0x55, 0x90, 0x0F, 0x8D, 0x9C, 0x00, 0x00, 0x00,
  0x8B, 0x45, 0x8C, 0x03, 0x45, 0xA8, 0x89, 0x85, 0x64, 0xFF, 0xFF, 0xFF, 0x8B, 0x4D, 0xFC, 0xC1,
  0xE1, 0x04, 0x8B, 0x55, 0xF4, 0x8B, 0x44, 0x0A, 0x08, 0x89, 0x85, 0x68, 0xFF, 0xFF, 0xFF, 0x8B,
  0x4D, 0xFC, 0xC1, 0xE1, 0x04, 0x8B, 0x55, 0xF4, 0x8B, 0x04, 0x0A, 0x03, 0x45, 0xF8, 0x89, 0x85,
  0x6C, 0xFF, 0xFF, 0xFF, 0x8B, 0x4D, 0xFC, 0xC1, 0xE1, 0x04, 0x8B, 0x55, 0xF4, 0x8B, 0x44, 0x0A,
  0x04, 0x89, 0x85, 0x70, 0xFF, 0xFF, 0xFF, 0xC7, 0x85, 0x74, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
  0x00, 0x8D, 0x8D, 0x74, 0xFF, 0xFF, 0xFF, 0x51, 0x8B, 0x95, 0x70, 0xFF, 0xFF, 0xFF, 0x52, 0x8B,
  0x85, 0x6C, 0xFF, 0xFF, 0xFF, 0x50, 0x8B, 0x8D, 0x68, 0xFF, 0xFF, 0xFF, 0x51, 0x8B, 0x95, 0x64,
  0xFF, 0xFF, 0xFF, 0x52, 0x8B, 0x45, 0x88, 0x50, 0xFF, 0x95, 0x60, 0xFF, 0xFF, 0xFF, 0x89, 0x85,
  0x5C, 0xFF, 0xFF, 0xFF, 0x8B, 0x4D, 0xFC, 0xC1, 0xE1, 0x04, 0x8B, 0x55, 0xF4, 0x8B, 0x45, 0xA8,
  0x03, 0x44, 0x0A, 0x08, 0x89, 0x45, 0xA8, 0xE9, 0x4F, 0xFF, 0xFF, 0xFF, 0xB9, 0x08, 0x00, 0x00,
  0x00, 0xC1, 0xE1, 0x00, 0x8B, 0x55, 0xA4, 0x8D, 0x44, 0x0A, 0x78, 0x89, 0x85, 0x58, 0xFF, 0xFF,
  0xFF, 0x8B, 0x8D, 0x58, 0xFF, 0xFF, 0xFF, 0x8B, 0x11, 0x03, 0x55, 0xF8, 0x89, 0x95, 0x54, 0xFF,
  0xFF, 0xFF, 0x8B, 0x85, 0x54, 0xFF, 0xFF, 0xFF, 0x50, 0x8B, 0x4D, 0xF8, 0x51, 0xE8, 0x2E, 0x02,
  0x00, 0x00, 0x83, 0xC4, 0x08, 0xBA, 0x10, 0x00, 0x00, 0x00, 0x6B, 0xC2, 0x00, 0x8B, 0x4D, 0xF4,
  0x8B, 0x54, 0x01, 0x0C, 0x03, 0x55, 0xF8, 0x89, 0x95, 0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0xA5, 0x50,
  0xFF, 0xFF, 0xFF, 0xB8, 0x08, 0x00, 0x00, 0x00, 0x8B, 0xE5, 0x5D, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC,
  0x55, 0x8B, 0xEC, 0x51, 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x64, 0xA1, 0x18, 0x00, 0x00,
  0x00, 0x8B, 0x40, 0x30, 0x8B, 0x40, 0x08, 0x89, 0x45, 0xFC, 0x8B, 0x45, 0xFC, 0x8B, 0xE5, 0x5D,
  0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
  0x55, 0x8B, 0xEC, 0x51, 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x64, 0xA1, 0x18, 0x00, 0x00,
  0x00, 0x8B, 0x40, 0x30, 0x8B, 0x40, 0x0C, 0x8B, 0x40, 0x0C, 0x8B, 0x00, 0x8B, 0x00, 0x8B, 0x40,
  0x18, 0x89, 0x45, 0xFC, 0x8B, 0x45, 0xFC, 0x8B, 0xE5, 0x5D, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
  0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x38, 0x8B, 0x45, 0x08, 0x89, 0x45, 0xD0, 0x8B, 0x4D, 0xD0, 0x8B,
  0x55, 0x08, 0x03, 0x51, 0x3C, 0x89, 0x55, 0xCC, 0xB8, 0x08, 0x00, 0x00, 0x00, 0x6B, 0xC8, 0x00,
  0x8B, 0x55, 0xCC, 0x8B, 0x44, 0x0A, 0x78, 0x03, 0x45, 0x08, 0x89, 0x45, 0xC8, 0x8B, 0x4D, 0xC8,
  0x89, 0x4D, 0xF8, 0xC7, 0x45, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x81, 0x7D, 0x0C, 0xFF, 0xFF, 0x00,
  0x00, 0x77, 0x3E, 0x0F, 0xB7, 0x55, 0x0C, 0x8B, 0x45, 0xF8, 0x2B, 0x50, 0x10, 0x89, 0x55, 0xD8,
  0x8B, 0x4D, 0xD8, 0x83, 0xC1, 0x01, 0x8B, 0x55, 0xF8, 0x3B, 0x4A, 0x14, 0x76, 0x09, 0xC7, 0x45,
  0xE8, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x15, 0x8B, 0x45, 0xF8, 0x8B, 0x48, 0x1C, 0x03, 0x4D, 0x08,
  0x8B, 0x55, 0xD8, 0x8B, 0x04, 0x91, 0x03, 0x45, 0x08, 0x89, 0x45, 0xE8, 0xE9, 0x13, 0x01, 0x00,
  0x00, 0xC7, 0x45, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x4D, 0x0C, 0x89, 0x4D, 0xE4, 0x8B, 0x55,
  0xE4, 0x0F, 0xBE, 0x02, 0x85, 0xC0, 0x74, 0x14, 0x8B, 0x4D, 0xDC, 0x83, 0xC1, 0x01, 0x89, 0x4D,
  0xDC, 0x8B, 0x55, 0xE4, 0x83, 0xC2, 0x01, 0x89, 0x55, 0xE4, 0xEB, 0xE2, 0xC7, 0x45, 0xF0, 0x00,
  0x00, 0x00, 0x00, 0xEB, 0x09, 0x8B, 0x45, 0xF0, 0x83, 0xC0, 0x01, 0x89, 0x45, 0xF0, 0x8B, 0x4D,
  0xF8, 0x8B, 0x55, 0xF0, 0x3B, 0x51, 0x18, 0x0F, 0x83, 0xB5, 0x00, 0x00, 0x00, 0x8B, 0x45, 0xF8,
  0x8B, 0x48, 0x20, 0x03, 0x4D, 0x08, 0x8B, 0x55, 0xF0, 0x8B, 0x04, 0x91, 0x03, 0x45, 0x08, 0x89,
  0x45, 0xD4, 0x8B, 0x4D, 0xD4, 0x89, 0x4D, 0xE0, 0xC7, 0x45, 0xEC, 0x00, 0x00, 0x00, 0x00, 0x8B,
  0x55, 0xE0, 0x0F, 0xBE, 0x02, 0x85, 0xC0, 0x74, 0x14, 0x8B, 0x4D, 0xEC, 0x83, 0xC1, 0x01, 0x89,
  0x4D, 0xEC, 0x8B, 0x55, 0xE0, 0x83, 0xC2, 0x01, 0x89, 0x55, 0xE0, 0xEB, 0xE2, 0x8B, 0x45, 0xDC,
  0x3B, 0x45, 0xEC, 0x75, 0x68, 0xC7, 0x45, 0xF4, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x09, 0x8B, 0x4D,
  0xF4, 0x83, 0xC1, 0x01, 0x89, 0x4D, 0xF4, 0x8B, 0x55, 0xF4, 0x3B, 0x55, 0xEC, 0x73, 0x1A, 0x8B,
  0x45, 0x0C, 0x03, 0x45, 0xF4, 0x0F, 0xBE, 0x08, 0x8B, 0x55, 0xD4, 0x03, 0x55, 0xF4, 0x0F, 0xBE,
  0x02, 0x3B, 0xC8, 0x74, 0x02, 0xEB, 0x02, 0xEB, 0xD5, 0x8B, 0x4D, 0xF4, 0x3B, 0x4D, 0xEC, 0x75,
  0x2C, 0x8B, 0x55, 0xF8, 0x8B, 0x42, 0x24, 0x03, 0x45, 0x08, 0x8B, 0x4D, 0xF0, 0x66, 0x8B, 0x14,
  0x48, 0x66, 0x89, 0x55, 0xFC, 0x8B, 0x45, 0xF8, 0x8B, 0x48, 0x1C, 0x03, 0x4D, 0x08, 0x0F, 0xB7,
  0x55, 0xFC, 0x8B, 0x04, 0x91, 0x03, 0x45, 0x08, 0x89, 0x45, 0xE8, 0xEB, 0x05, 0xE9, 0x33, 0xFF,
  0xFF, 0xFF, 0x8B, 0x4D, 0xF8, 0x8B, 0x55, 0xF0, 0x3B, 0x51, 0x18, 0x75, 0x07, 0xC7, 0x45, 0xE8,
  0x00, 0x00, 0x00, 0x00, 0x8B, 0x45, 0xE8, 0x8B, 0xE5, 0x5D, 0xC2, 0x08, 0x00, 0xCC, 0xCC, 0xCC,
  0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x60, 0xE8, 0x25, 0xFE, 0xFF, 0xFF, 0x89, 0x45, 0xE4, 0xC6, 0x45,
  0xC4, 0x4C, 0xC6, 0x45, 0xC5, 0x6F, 0xC6, 0x45, 0xC6, 0x61, 0xC6, 0x45, 0xC7, 0x64, 0xC6, 0x45,
  0xC8, 0x4C, 0xC6, 0x45, 0xC9, 0x69, 0xC6, 0x45, 0xCA, 0x62, 0xC6, 0x45, 0xCB, 0x72, 0xC6, 0x45,
  0xCC, 0x61, 0xC6, 0x45, 0xCD, 0x72, 0xC6, 0x45, 0xCE, 0x79, 0xC6, 0x45, 0xCF, 0x41, 0xC6, 0x45,
  0xD0, 0x00, 0xC6, 0x45, 0xB4, 0x47, 0xC6, 0x45, 0xB5, 0x65, 0xC6, 0x45, 0xB6, 0x74, 0xC6, 0x45,
  0xB7, 0x50, 0xC6, 0x45, 0xB8, 0x72, 0xC6, 0x45, 0xB9, 0x6F, 0xC6, 0x45, 0xBA, 0x63, 0xC6, 0x45,
  0xBB, 0x41, 0xC6, 0x45, 0xBC, 0x64, 0xC6, 0x45, 0xBD, 0x64, 0xC6, 0x45, 0xBE, 0x72, 0xC6, 0x45,
  0xBF, 0x65, 0xC6, 0x45, 0xC0, 0x73, 0xC6, 0x45, 0xC1, 0x73, 0xC6, 0x45, 0xC2, 0x00, 0x8D, 0x45,
  0xC4, 0x50, 0x8B, 0x4D, 0xE4, 0x51, 0xE8, 0xD5, 0xFD, 0xFF, 0xFF, 0x89, 0x45, 0xE0, 0x8D, 0x55,
  0xB4, 0x52, 0x8B, 0x45, 0xE4, 0x50, 0xE8, 0xC5, 0xFD, 0xFF, 0xFF, 0x89, 0x45, 0xD8, 0x33, 0xC9,
  0x89, 0x4D, 0xA0, 0x89, 0x4D, 0xA4, 0x89, 0x4D, 0xA8, 0x89, 0x4D, 0xAC, 0x89, 0x4D, 0xB0, 0x6A,
  0x14, 0x8B, 0x55, 0x0C, 0x52, 0x8D, 0x45, 0xA0, 0x50, 0xE8, 0x02, 0x01, 0x00, 0x00, 0x83, 0xC4,
  0x0C, 0x85, 0xC0, 0x0F, 0x84, 0xEA, 0x00, 0x00, 0x00, 0x8B, 0x4D, 0x0C, 0x8B, 0x51, 0x10, 0x89,
  0x55, 0xF8, 0x8B, 0x45, 0xF8, 0x03, 0x45, 0x08, 0x89, 0x45, 0xF8, 0x8B, 0x4D, 0xF8, 0x83, 0x39,
  0x00, 0x75, 0x0B, 0x8B, 0x55, 0x0C, 0x83, 0xC2, 0x14, 0x89, 0x55, 0x0C, 0xEB, 0xC1, 0x8B, 0x45,
  0x0C, 0x8B, 0x08, 0x89, 0x4D, 0xFC, 0x83, 0x7D, 0xFC, 0x00, 0x75, 0x09, 0x8B, 0x55, 0x0C, 0x8B,
  0x42, 0x10, 0x89, 0x45, 0xFC, 0x8B, 0x4D, 0xFC, 0x03, 0x4D, 0x08, 0x89, 0x4D, 0xFC, 0x8B, 0x55,
  0x0C, 0x8B, 0x42, 0x0C, 0x89, 0x45, 0xF4, 0x8B, 0x4D, 0xF4, 0x03, 0x4D, 0x08, 0x89, 0x4D, 0xF4,
  0x8B, 0x55, 0xF4, 0x52, 0xFF, 0x55, 0xE0, 0x89, 0x45, 0xDC, 0xC7, 0x45, 0xE8, 0x00, 0x00, 0x00,
  0x00, 0x8B, 0x45, 0xFC, 0x83, 0x38, 0x00, 0x74, 0x6C, 0xC7, 0x45, 0xEC, 0x00, 0x00, 0x00, 0x00,
  0x8B, 0x4D, 0xFC, 0x8B, 0x11, 0x81, 0xE2, 0x00, 0x00, 0x00, 0x80, 0x74, 0x10, 0x8B, 0x45, 0xFC,
  0x8B, 0x08, 0x81, 0xE1, 0xFF, 0xFF, 0x00, 0x00, 0x89, 0x4D, 0xEC, 0xEB, 0x1A, 0x8B, 0x55, 0xFC,
  0x8B, 0x02, 0x89, 0x45, 0xF0, 0x8B, 0x4D, 0xF0, 0x03, 0x4D, 0x08, 0x89, 0x4D, 0xF0, 0x8B, 0x55,
  0xF0, 0x83, 0xC2, 0x02, 0x89, 0x55, 0xEC, 0x8B, 0x45, 0xEC, 0x50, 0x8B, 0x4D, 0xDC, 0x51, 0xFF,
  0x55, 0xD8, 0x89, 0x45, 0xD4, 0x8B, 0x55, 0xE8, 0x8B, 0x45, 0xF8, 0x8B, 0x4D, 0xD4, 0x89, 0x0C,
  0x90, 0x8B, 0x55, 0xFC, 0x83, 0xC2, 0x04, 0x89, 0x55, 0xFC, 0x8B, 0x45, 0xE8, 0x83, 0xC0, 0x01,
  0x89, 0x45, 0xE8, 0xEB, 0x8C, 0x8B, 0x4D, 0x0C, 0x83, 0xC1, 0x14, 0x89, 0x4D, 0x0C, 0xE9, 0xFC,
  0xFE, 0xFF, 0xFF, 0x33, 0xC0, 0x8B, 0xE5, 0x5D, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
  0x55, 0x8B, 0xEC, 0x83, 0x7D, 0x10, 0x00, 0x75, 0x04, 0x33, 0xC0, 0xEB, 0x3D, 0x8B, 0x45, 0x10,
  0x83, 0xE8, 0x01, 0x89, 0x45, 0x10, 0x74, 0x24, 0x8B, 0x4D, 0x08, 0x0F, 0xBE, 0x11, 0x8B, 0x45,
  0x0C, 0x0F, 0xBE, 0x08, 0x3B, 0xD1, 0x75, 0x14, 0x8B, 0x55, 0x08, 0x83, 0xC2, 0x01, 0x89, 0x55,
  0x08, 0x8B, 0x45, 0x0C, 0x83, 0xC0, 0x01, 0x89, 0x45, 0x0C, 0xEB, 0xD1, 0x8B, 0x4D, 0x08, 0x0F,
  0xB6, 0x01, 0x8B, 0x55, 0x0C, 0x0F, 0xB6, 0x0A, 0x2B, 0xC1, 0x5D, 0xC3, 0x00, 0x00, 0x00, 0x00
  };


  m_nDecompressCodeSize = sizeof(data);
  m_pDecompressCodeBuff = new char[m_nDecompressCodeSize];
  memcpy(m_pDecompressCodeBuff, data, m_nDecompressCodeSize);

  return true;
}

bool CMaker::GetDeCodeSec()
{
  //申请内存
  int nFileAlign = m_pNtHdr->OptionalHeader.FileAlignment;
  m_nsizeOfDecodeSec = GetAlinValue(m_nDecompressCodeSize, nFileAlign);
  m_pDecodeSecData = new char[m_nsizeOfDecodeSec];

  //拷贝解压缩代码到新pe的节区
  memcpy(m_pDecodeSecData, m_pDecompressCodeBuff, m_nDecompressCodeSize);
  
  return true;
}


bool CMaker::GetCompressDataSec()
{
  /*
       -------------
       |  压缩个数 |
       -------------
       | 解压缩大小 |
       | 压缩大小   |
       -------------
       | 解压缩大小 |
       | 压缩大小   |
       -------------
       | ...       |
       | ...       |
       -------------
  */

  //放在压缩数据节头的信息
  struct DataInfo
  {
    int m_nVirtualAddress; //原节数据的内存地址
    int m_nVirtualSize; //解压缩后数据的大小
    int m_nCompressSize; //压缩数据的大小
    int m_nOEP; //原PE的OEP
  };

  //获取节区数据的总大小
  int nSizeAll = 0;
  nSizeAll += sizeof(int);
  nSizeAll += sizeof(DataInfo) * m_pNtHdr->FileHeader.NumberOfSections;
  for (int i = 0; i < m_pNtHdr->FileHeader.NumberOfSections; i++)
  {
    nSizeAll += m_pCompressDatas[i].m_nComSize;
  }
  m_nSizeOfCompressSec = GetAlinValue(nSizeAll, m_pNtHdr->OptionalHeader.FileAlignment);

  //申请内存,存放压缩数据
  m_pCompressSecData = new char[m_nSizeOfCompressSec];

  //拷贝数据
  int nNumberOfSections = m_pNtHdr->FileHeader.NumberOfSections;
  int nOffset = 0;
  memcpy(m_pCompressSecData, &nNumberOfSections, sizeof(nNumberOfSections));
  nOffset += sizeof(nNumberOfSections);

  DataInfo* pDi = new DataInfo[nNumberOfSections];
  for (int i = 0; i < nNumberOfSections; i++)
  {
    pDi[i].m_nVirtualSize = m_pCompressDatas[i].m_nSrcSize;
    pDi[i].m_nCompressSize = m_pCompressDatas[i].m_nComSize;
    pDi[i].m_nVirtualAddress = m_pSecHdrs[i].VirtualAddress;
    pDi[i].m_nOEP = m_pNtHdr->OptionalHeader.AddressOfEntryPoint;
  }
  memcpy(m_pCompressSecData+ nOffset, pDi, sizeof(DataInfo)*nNumberOfSections);
  nOffset += sizeof(DataInfo)*nNumberOfSections;

  for (int i = 0; i < nNumberOfSections; i++)
  {
    memcpy(
      m_pCompressSecData + nOffset, 
      m_pCompressDatas[i].m_pComData, 
      m_pCompressDatas[i].m_nComSize);
    nOffset += m_pCompressDatas[i].m_nComSize;
  }

  return true;
}

bool CMaker::GetNewSectionHeaders()
{
  //构建节表
  m_nNumberOfNewSecs = 3;
  m_pNewSecHdrs = new IMAGE_SECTION_HEADER[m_nNumberOfNewSecs];

  enum 
  {
    SECIDX_SPACE,
    SECIDX_CODE,
    SECIDX_DATA
  };

  //构建空节
  strcpy((char*)m_pNewSecHdrs[SECIDX_SPACE].Name, "cr33");
  m_pNewSecHdrs[SECIDX_SPACE].Misc.VirtualSize = m_pNtHdr->OptionalHeader.SizeOfImage;
  m_pNewSecHdrs[SECIDX_SPACE].VirtualAddress = m_pSecHdrs[0].VirtualAddress; //内存偏移
  m_pNewSecHdrs[SECIDX_SPACE].PointerToRawData = 0; //文件偏移
  m_pNewSecHdrs[SECIDX_SPACE].SizeOfRawData = 0;//文件大小
  m_pNewSecHdrs[SECIDX_SPACE].Characteristics = 
    IMAGE_SCN_MEM_SHARED 
    | IMAGE_SCN_MEM_EXECUTE 
    | IMAGE_SCN_MEM_READ 
    | IMAGE_SCN_MEM_WRITE;

  //构建解压缩代码节  
  strcpy((char*)m_pNewSecHdrs[SECIDX_CODE].Name, "code");
  m_pNewSecHdrs[SECIDX_CODE].Misc.VirtualSize = m_nsizeOfDecodeSec; //内存大小
  m_pNewSecHdrs[SECIDX_CODE].VirtualAddress =
    m_pNewSecHdrs[SECIDX_SPACE].VirtualAddress
    + GetAlinValue(m_pNewSecHdrs[SECIDX_SPACE].Misc.VirtualSize, m_pNtHdr->OptionalHeader.SectionAlignment);
    //内存偏移
  m_pNewSecHdrs[SECIDX_CODE].PointerToRawData = m_pNtHdr->OptionalHeader.SizeOfHeaders; //文件偏移
  m_pNewSecHdrs[SECIDX_CODE].SizeOfRawData = m_nsizeOfDecodeSec;//文件大小
  m_pNewSecHdrs[SECIDX_CODE].Characteristics =
    IMAGE_SCN_MEM_SHARED
    | IMAGE_SCN_MEM_EXECUTE
    | IMAGE_SCN_MEM_READ
    | IMAGE_SCN_MEM_WRITE;

  //解压缩数据节
  strcpy((char*)m_pNewSecHdrs[SECIDX_DATA].Name, "data");
  m_pNewSecHdrs[SECIDX_DATA].Misc.VirtualSize = m_nSizeOfCompressSec; //内存大小
  m_pNewSecHdrs[SECIDX_DATA].VirtualAddress = 
    m_pNewSecHdrs[SECIDX_CODE].VirtualAddress
    + GetAlinValue(m_pNewSecHdrs[SECIDX_CODE].Misc.VirtualSize, m_pNtHdr->OptionalHeader.SectionAlignment);
  //内存偏移
  m_pNewSecHdrs[SECIDX_DATA].PointerToRawData = 
    m_pNewSecHdrs[SECIDX_CODE].PointerToRawData + m_pNewSecHdrs[SECIDX_CODE].SizeOfRawData; //文件偏移
  m_pNewSecHdrs[SECIDX_DATA].SizeOfRawData = m_nSizeOfCompressSec;//文件大小
  m_pNewSecHdrs[SECIDX_DATA].Characteristics = IMAGE_SCN_MEM_READ;

  return true;
}

bool CMaker::GetNewPeHdr()
{
  //申请新PE头内存
  m_nSizeOfNewPeHdr = m_pNtHdr->OptionalHeader.SizeOfHeaders;
  m_pNewPeHdr = new char[m_nSizeOfNewPeHdr];

  //拷贝原来的PE头
  memcpy(m_pNewPeHdr, m_pDosHdr, m_nSizeOfNewPeHdr);

  //修改字段
  PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)m_pNewPeHdr;
  PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((char*)m_pNewPeHdr + pDosHdr->e_lfanew);
  PIMAGE_SECTION_HEADER pSecHdrs = (PIMAGE_SECTION_HEADER)
    ((char*)&pNtHdr->OptionalHeader + pNtHdr->FileHeader.SizeOfOptionalHeader);

  pNtHdr->FileHeader.NumberOfSections = 3;
  pNtHdr->OptionalHeader.AddressOfEntryPoint = m_pNewSecHdrs[1].VirtualAddress;
  pNtHdr->OptionalHeader.SizeOfImage = m_pNewSecHdrs[2].VirtualAddress
    + GetAlinValue(m_pNewSecHdrs[2].Misc.VirtualSize, pNtHdr->OptionalHeader.SectionAlignment);

  //拷贝新构造的节表
  memcpy(
    pSecHdrs, 
    m_pNewSecHdrs, 
    pNtHdr->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));

  return true;
}

bool CMaker::WriteNewPeFile(string strDstPath)
{
  HANDLE hFle = CreateFile(strDstPath.c_str(),
    FILE_GENERIC_READ | FILE_GENERIC_WRITE,
    FILE_SHARE_READ,
    NULL,
    CREATE_ALWAYS,
    FILE_ATTRIBUTE_NORMAL,
    NULL);
  if (hFle == (HANDLE)-1)
  {
    return false;
  }

  WriteFile(hFle, m_pNewPeHdr, m_nSizeOfNewPeHdr, NULL, NULL);
  WriteFile(hFle, m_pDecodeSecData, m_nsizeOfDecodeSec, NULL, NULL);
  WriteFile(hFle, m_pCompressSecData, m_nSizeOfCompressSec, NULL, NULL);

  CloseHandle(hFle);

  return true;
}

int CMaker::GetAlinValue(int nValue, int nAlign)
{
  if (nValue % nAlign == 0)
  {
    return nValue;
  }
  else
  {
    return (nValue / nAlign + 1) * nAlign;
  }
}

shellcode

地址无关代码(shellcode):代码中没有访问绝对地址的指令,也就是上面的解压缩代码
使用VS写Shellcode注意点:

  1. 使用Release版,因为debug会产生多余的调试代码,这些代码都会涉及到绝对地址
  2. 修改连接器的入口点
  3. 禁用安全检查-GS
  4. 随机基址
代码如下
// Shellcode.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <windows.h>
#include <compressapi.h>

FARPROC WINAPI MyGetProcAddress(
  __in  HMODULE hModule,
  __in  LPCSTR lpProcName
);

typedef
HMODULE
(WINAPI *PFN_LoadLibraryA)(
  _In_ LPCSTR lpLibFileName
);

typedef
FARPROC
(WINAPI* PFN_GetProcAddress)(
  _In_ HMODULE hModule,
  _In_ LPCSTR lpProcName
);

typedef
int
(WINAPI*PFN_MessageBoxA)(
  _In_opt_ HWND hWnd,
  _In_opt_ LPCSTR lpText,
  _In_opt_ LPCSTR lpCaption,
  _In_ UINT uType);

typedef 
BOOL
(WINAPI* PFN_DeCreateCompressor)(
  _In_ DWORD Algorithm,
  _In_opt_ PCOMPRESS_ALLOCATION_ROUTINES AllocationRoutines,
  _Out_ PCOMPRESSOR_HANDLE CompressorHandle
);

typedef
BOOL
(WINAPI* PFN_Decompress)(
  _In_ DECOMPRESSOR_HANDLE DecompressorHandle,
  _In_reads_bytes_opt_(CompressedDataSize) LPCVOID CompressedData,
  _In_ SIZE_T CompressedDataSize,
  _Out_writes_bytes_opt_(UncompressedBufferSize) PVOID UncompressedBuffer,
  _In_ SIZE_T UncompressedBufferSize,
  _Out_opt_ PSIZE_T UncompressedDataSize
);

HMODULE GetKernel32Base();
HMODULE GetImageBase();
BOOL ImportProc(HINSTANCE hInstance, PIMAGE_IMPORT_DESCRIPTOR lpImport);
int __cdecl mymemcmp(const void * buf1,const void * buf2,size_t count);

int ShellCodeEntry()
{
#if 0
  HMODULE hKerl32 = GetKernel32Base();

  char szHello[] = { 'h','e','l','l','o','h','e','l','l','h','e','l','l','o','\0' };
  char szLoadLibraryA[] = { 'L','o','a','d','L','i','b','r','a','r','y','A', '\0' };
  char szGetProcAddress[] = { 'G','e','t','P','r','o','c','A','d','d','r','e','s','s', '\0' };

  PFN_LoadLibraryA pfnLoadLibraryA = (PFN_LoadLibraryA)MyGetProcAddress(hKerl32, szLoadLibraryA);
  PFN_GetProcAddress pfnGetProcAddress = (PFN_GetProcAddress)MyGetProcAddress(hKerl32, szGetProcAddress);

  char szUser32[] = { 'u','s','e','r','3','2', '\0' };
  char szMessageBoxA[] = { 'M','e','s','s','a','g','e','B','o','x','A', '\0' };

  HMODULE hUser32 = pfnLoadLibraryA(szUser32);
  PFN_MessageBoxA pfnMessageBoxA = (PFN_MessageBoxA)pfnGetProcAddress(hUser32, szMessageBoxA);
  pfnMessageBoxA(NULL, szHello, NULL, MB_OK);
#endif // 测试shellcode的框架
  HMODULE hKerl32 = GetKernel32Base();

  char szLoadLibraryA[] = { 'L','o','a','d','L','i','b','r','a','r','y','A', '\0' };
  char szGetProcAddress[] = { 'G','e','t','P','r','o','c','A','d','d','r','e','s','s', '\0' };
  char szCabinet[] = {'C','a','b','i','n','e','t', '\0'};
  char szCreateCompressor[] = {'C','r','e','a','t','e','D','e','c','o','m','p','r','e','s','s','o','r', '\0'};
  char szDecompress[] = {'D','e','c','o','m','p','r','e','s','s', '\0'};

  PFN_LoadLibraryA pfnLoadLibraryA = (PFN_LoadLibraryA)MyGetProcAddress(hKerl32, szLoadLibraryA);
  PFN_GetProcAddress pfnGetProcAddress = (PFN_GetProcAddress)MyGetProcAddress(hKerl32, szGetProcAddress);
  
  HMODULE hModCabinet = pfnLoadLibraryA(szCabinet);
  PFN_DeCreateCompressor pfnCreateDecompressor = (PFN_DeCreateCompressor)pfnGetProcAddress(hModCabinet, szCreateCompressor);
  PFN_Decompress pfnDecompress = (PFN_Decompress)pfnGetProcAddress(hModCabinet, szDecompress);

  //1. 定位压缩数据,解压缩
  HMODULE hImageBase = GetImageBase();
  PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hImageBase;
  PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((char*)hImageBase + pDosHdr->e_lfanew);
  PIMAGE_SECTION_HEADER pSecHdrs = (PIMAGE_SECTION_HEADER)
    ((char*)&pNtHdr->OptionalHeader + pNtHdr->FileHeader.SizeOfOptionalHeader);

  //获取压缩数据
  enum
  {
    SECIDX_SPACE,
    SECIDX_CODE,
    SECIDX_DATA
  };
  char* pDataSec = (char*)hImageBase + pSecHdrs[SECIDX_DATA].VirtualAddress;

  //获取压缩数据信息
  struct DataInfo
  {
    int m_nVirtualAddress; //原节数据的内存地址
    int m_nVirtualSize; //解压缩后数据的大小
    int m_nCompressSize; //压缩数据的大小
    int m_nOEP; //原PE的OEP
  };
  int nNumberOfDatas = *(int*)pDataSec;
  DataInfo* pDI = (DataInfo*)(pDataSec + sizeof(nNumberOfDatas));
  char* pCompressData = (char*)(pDI + nNumberOfDatas);//第一个压缩数据块地址

  //2. 还原节区数据
  COMPRESSOR_HANDLE hDecompressor = NULL;
  BOOL bSuccess = pfnCreateDecompressor(
    COMPRESS_ALGORITHM_XPRESS_HUFF, //  Compression Algorithm
    NULL,                           //  Optional allocation routine
    &hDecompressor);                 //  Handle

  char* pSrcAddr = pCompressData;
  int nOffset = 0;
  for (int i = 0; i < nNumberOfDatas; i++)
  {
    //获取压缩数据的地址和大小,以及解压数据的地址和大小
    char* pSrcAddr = pCompressData + nOffset;
    int nSrcSize = pDI[i].m_nCompressSize;
    char* pDstAddr = (char*)pDI[i].m_nVirtualAddress + (int)hImageBase;
    int nDstSize = pDI[i].m_nVirtualSize;

    //解压缩
    DWORD dwDecompressedBufferSize = 0;
    bSuccess = pfnDecompress(
      hDecompressor,                //  Compressor Handle
      pSrcAddr,            //  Compressed data
      nSrcSize,               //  Compressed data size
      pDstAddr,                        //  Buffer set to NULL
      nDstSize,                           //  Buffer size set to 0
      &dwDecompressedBufferSize);    //  Decompressed Data size

    //移动到下一个压缩数据块
    nOffset += pDI[i].m_nCompressSize;
  }

  //3. 修复导入表
  PIMAGE_DATA_DIRECTORY pDataDirectory = &pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
  IMAGE_IMPORT_DESCRIPTOR *lpImport =
    (IMAGE_IMPORT_DESCRIPTOR*)(pDataDirectory->VirtualAddress + (DWORD)hImageBase);
  ImportProc(hImageBase, lpImport);

  //4. 执行原PE的代码
  int nOEP = pDI[0].m_nOEP + (int)hImageBase;
  //jmp [esp-xxx]
  __asm jmp nOEP

  return 8;
}

HMODULE GetImageBase()
{
  HMODULE hImageBase = NULL;
  __asm
  {
    mov eax, fs:[0x18]; //teb
    mov eax, [eax + 0x30]; //peb
    mov eax, [eax + 0x08]; //ImageBaseAddress
    mov hImageBase, eax
  }

  return hImageBase;
}

HMODULE GetKernel32Base()
{
  HMODULE hKer32 = NULL;
  __asm
  {
    mov eax, fs:[0x18]; //teb
    mov eax, [eax + 0x30]; //peb
    mov eax, [eax + 0x0C]; //_PEB_LDR_DATA
    mov eax, [eax + 0x0C]; //_LIST_ENTRY, 主模块
    mov eax, [eax]; //ntdll
    mov eax, [eax]; //kernel32
    mov eax, dword ptr [eax + 0x18]; //kernel32基址
    mov hKer32, eax
  }

  return hKer32;
}

FARPROC WINAPI MyGetProcAddress(
  __in  HMODULE hModule,
  __in  LPCSTR lpProcName
)
{
  //通过hModule找到导出表的位置
  PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER)hModule;
  PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)hModule + pDOSHeader->e_lfanew);
  DWORD dwExportTableAddr = pNTHeader->OptionalHeader.DataDirectory[0].VirtualAddress + (DWORD)hModule;
  PIMAGE_EXPORT_DIRECTORY pExportTable = (PIMAGE_EXPORT_DIRECTORY)dwExportTableAddr;

  FARPROC farRet = 0;
  //因为地址空间低64K不能访问.所以名字小于64K的为序号导出
  if ((DWORD)lpProcName <= 0xFFFF)
  {
    DWORD dwNumberOfFunctions = (WORD)lpProcName - pExportTable->Base;

    //大于NumberOfFunctions
    if (dwNumberOfFunctions + 1 > pExportTable->NumberOfFunctions)
    {
      farRet = 0;
    }
    else
    {
      farRet = (FARPROC)(((DWORD*)(pExportTable->AddressOfFunctions + DWORD(hModule)))[dwNumberOfFunctions] + DWORD(hModule));
    }
  }
  else
  {
    //名称导出

    //获得lpProcName的字符串长度
    DWORD dwlpProcNameCount = 0;
    char* pName = (char*)lpProcName;
    while (*pName != '\0')
    {
      dwlpProcNameCount++;
      pName++;
    }

    //遍历名称表, 找到名称表的下标
    size_t i = 0;
    for (; i < pExportTable->NumberOfNames; i++)
    {
      //获得第i项导出名称长度
      char* pExportName = (char*)(*((DWORD*)(pExportTable->AddressOfNames + DWORD(hModule)) + i) + DWORD(hModule));
      char* pExportNameCMP = pExportName;
      DWORD dwExportNameCount = 0;
      while (*pExportNameCMP != '\0')
      {
        dwExportNameCount++;
        pExportNameCMP++;
      }

      //如果长度相等, 比较每个字符串
      if (dwlpProcNameCount == dwExportNameCount)
      {
        size_t j = 0;
        for (; j < dwExportNameCount; j++)
        {
          if (lpProcName[j] != pExportName[j])
          {
            break;
          }
        }
        if (j == dwExportNameCount)
        {
          //找到了对应函数
          //找到序数表对应下标
          WORD wNameOrdinals = *(WORD*)((pExportTable->AddressOfNameOrdinals + DWORD(hModule)) + i * sizeof(WORD));


          //在地址表中找到函数地址
          farRet = (FARPROC)(((DWORD*)(pExportTable->AddressOfFunctions + DWORD(hModule)))[wNameOrdinals] + DWORD(hModule));
          break;
        }
      }
    }
    if (i == pExportTable->NumberOfNames)
    {
      farRet = 0;
    }
  }
  return farRet;
}

BOOL ImportProc(HINSTANCE hInstance, PIMAGE_IMPORT_DESCRIPTOR lpImport)
{
  HMODULE hKerl32 = GetKernel32Base();
  char szLoadLibraryA[] = { 'L','o','a','d','L','i','b','r','a','r','y','A', '\0' };
  char szGetProcAddress[] = { 'G','e','t','P','r','o','c','A','d','d','r','e','s','s', '\0' };

  PFN_LoadLibraryA pfnLoadLibraryA = (PFN_LoadLibraryA)MyGetProcAddress(hKerl32, szLoadLibraryA);
  PFN_GetProcAddress pfnGetProcAddress = (PFN_GetProcAddress)MyGetProcAddress(hKerl32, szGetProcAddress);


  IMAGE_IMPORT_DESCRIPTOR ZeroImport = { 0 };
  while (mymemcmp(&ZeroImport, lpImport, sizeof ZeroImport) != 0)
  {
    IMAGE_THUNK_DATA *pIAT = (IMAGE_THUNK_DATA *)lpImport->FirstThunk;
    pIAT = (IMAGE_THUNK_DATA*)((int)pIAT + (int)hInstance);
    if (pIAT->u1.Function == NULL)
    {
      lpImport++;
      continue;
    }

    IMAGE_THUNK_DATA *pThunk = (IMAGE_THUNK_DATA *)lpImport->OriginalFirstThunk;
    if (pThunk == NULL)
    {
      pThunk = (IMAGE_THUNK_DATA *)lpImport->FirstThunk;
    }
    pThunk = (IMAGE_THUNK_DATA*)((int)pThunk + (int)hInstance);

    LPSTR lpLibName = (LPSTR)lpImport->Name;
    lpLibName = (LPSTR)((int)lpLibName + (int)hInstance);
    HMODULE hMod = pfnLoadLibraryA(lpLibName);
    // check it

    int i = 0;
    while (pThunk->u1.Ordinal != NULL)
    {
      LPSTR lpApiName = NULL;
      if (IMAGE_SNAP_BY_ORDINAL32(pThunk->u1.Ordinal)) // is name
      {
        lpApiName = (LPSTR)IMAGE_ORDINAL32(pThunk->u1.Ordinal);
      }
      else // is ordinal
      {
        IMAGE_IMPORT_BY_NAME *pName = (IMAGE_IMPORT_BY_NAME*)pThunk->u1.AddressOfData;
        pName = (IMAGE_IMPORT_BY_NAME*)((int)pName + (int)hInstance);
        lpApiName = (LPSTR)pName->Name;
      }

      DWORD pApi = (DWORD)pfnGetProcAddress(hMod, lpApiName);
      // check it

      pIAT[i].u1.Ordinal = pApi;
      pThunk++;
      i++;
    }


    lpImport++;
  }


  return FALSE;
}

int __cdecl mymemcmp(
  const void * buf1,
  const void * buf2,
  size_t count
)
{
  if (!count)
    return(0);

  while (--count && *(char *)buf1 == *(char *)buf2) {
    buf1 = (char *)buf1 + 1;
    buf2 = (char *)buf2 + 1;
  }

  return(*((unsigned char *)buf1) - *((unsigned char *)buf2));
}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值