壳的分类
压缩壳:减少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注意点:
- 使用Release版,因为debug会产生多余的调试代码,这些代码都会涉及到绝对地址
- 修改连接器的入口点
- 禁用安全检查-GS
- 随机基址
代码如下
// 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));
}