写壳2

壳2

创建MFC-基于对话框项目。

绘制界面

1566822235721

图片插入,添加工具-picture control-属性

1566822286994

属性-设置

1566822402416

一键加壳按钮实现

void CMFCShellDlg::OnBnClickedButton1()
{
//设置过滤器
TCHAR szFilter[] = _T("文本文件(*.txt)|*.txt|所有文件(*.*)|*.*||");
// 构造打开文件对话框
CFileDialog fileDlg(TRUE, _T("txt"), NULL, 0, szFilter, this);
CString strFilePath, strText;

// 显示打开文件对话框
if (IDOK == fileDlg.DoModal())
{
strFilePath = fileDlg.GetPathName(); //获取文件路径
CMyPack MyPack;

// 读取一个 PE 文件
USES_CONVERSION;
MyPack.LoadFile(W2A(strFilePath.GetBuffer()));

// 读取 stub 文件
MyPack.LoadStub("my_stub.dll");

// 将 stub 中的 .text 拷贝到 pe 文件的 .mypack
MyPack.CopySection(".mypack", ".text");

// 重新设置被加壳程序的 OEP,必须在这个位置,因为需要知道新的RVA
MyPack.SetOep();

// 修复 stub 代码的重定位项
MyPack.FixRealoc();

// 加密代码段
MyPack.XorFileSection(".text");

// 压缩所有的段
MyPack.PackCode(".text");

// 修正压缩后的区段位置
MyPack.FixSection();

// 清除一些表项
MyPack.ClearDataDir();

// 拷贝区段数据
MyPack.CopySectionData(".mypack", ".text");

// 将修改后的PE保存
MyPack.SaveFile("demo_pack.exe");
MessageBoxW(L"加壳成功");
return;
}

CMypack.cpp

#include "stdafx.h"
//#include "pch.h"
#include "CMyPack.h"
#include <time.h>
#include <DbgHelp.h>
#pragma comment(lib, "DbgHelp.lib")
#include "aplib.h"
#pragma comment(lib,"aPlib.lib")


struct TypeOffset
{
WORD Offset : 12;
WORD Type : 4;
};

// 获取各种头的函数
PIMAGE_DOS_HEADER CMyPack::DosHeader(DWORD Base)
{
return (PIMAGE_DOS_HEADER)Base;
}
PIMAGE_NT_HEADERS CMyPack::NTHeader(DWORD Base)
{
return (PIMAGE_NT_HEADERS)(Base + DosHeader(Base)->e_lfanew);
}
PIMAGE_FILE_HEADER CMyPack::FileHeader(DWORD Base)
{
return &NTHeader(Base)->FileHeader;
}
PIMAGE_OPTIONAL_HEADER CMyPack::OptHeader(DWORD Base)
{
return &NTHeader(Base)->OptionalHeader;
}

// 将传入的数值对齐到指定力度的倍数
DWORD CMyPack::Aligment(DWORD Item, DWORD Align)
{
// 35000 % 1000 != 0 -> (3500 / 1000 + 1)*1000
return Item % Align ? (Item / Align + 1)*Align : Item;
}


// 获取指定名称的区段头表地址
PIMAGE_SECTION_HEADER CMyPack::GetSection(DWORD Base, LPCSTR Name)
{
// 获取到区段头表的首地址
auto SectionTable = IMAGE_FIRST_SECTION(NTHeader(Base));

// 获取区段头表的元素个数
WORD Count = FileHeader(Base)->NumberOfSections;

// 遍历区段头表,并比对名称
for (WORD i = 0; i < Count; ++i)
{
// 区段的有效名称长度是8,理论应该单独拷贝出来再比较
if (!strcmp((char*)SectionTable[i].Name, Name))
return &SectionTable[i];
}

return nullptr;
}


// 加载一个 PE 文件
void CMyPack::LoadFile(LPCSTR FileName)
{
// 打开一个文件,理论上应该对文件进行判断,是否是一个 PE 文件,位数是多少
HANDLE FileHandle = CreateFileA(FileName, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

// 获取到文件的大小,并申请相应的堆空间
FileSize = GetFileSize(FileHandle, NULL);
FileBase = (DWORD)malloc(sizeof(BYTE) * FileSize);

// 读取 PE 文件的内容
DWORD BytesRead = 0;
ReadFile(FileHandle, (LPVOID)FileBase, FileSize, &BytesRead, NULL);

// 关闭句柄,防止句柄泄露
CloseHandle(FileHandle);
}


// 加载一个 dll 文件
void CMyPack::LoadStub(LPCSTR FileName)
{
// 以不调用 dllmain 的方式加载 dll 到当前的内存,会展开
StubBase = (DWORD)LoadLibraryExA(FileName, NULL, DONT_RESOLVE_DLL_REFERENCES);

// 获取 start 函数在 .text 的段内偏移
DWORD Start = (DWORD)GetProcAddress((HMODULE)StubBase, "start");
StartOffset = Start - StubBase - GetSection(StubBase, ".text")->VirtualAddress;

// 加载stub数据对象,向其中填充内容
StubData = (ShareData*)GetProcAddress((HMODULE)StubBase, "StubData");
}


// 拷贝区段,从 stub 拷贝 SrcName 区段到 exe 中并命名为 DestName
void CMyPack::CopySection(LPCSTR DestName, LPCSTR SrcName)
{
// 从 dll 中获取到需要拷贝的区段对应的区段头结构
auto SrcSection = GetSection(StubBase, SrcName);

// 获取到最后一个区段的位置,下标从0开始,区段数量-1
auto LastSection = &IMAGE_FIRST_SECTION(NTHeader(FileBase))
[FileHeader(FileBase)->NumberOfSections - 1];

// 将文件头中的区段数量+1
FileHeader(FileBase)->NumberOfSections += 1;

// 获取新添加的区段头表的首地址
auto DestSection = LastSection + 1;

// 将源区段的属性直接拷贝到新的区段
memcpy(DestSection, SrcSection, sizeof(IMAGE_SECTION_HEADER));

// 设置区段的名称,可以是用 memcpy strcpy
memcpy(DestSection->Name, DestName, 7);

// 设置区段起始位置的 RVA = 上一个区段 RVA + 对齐的内存大小
DestSection->VirtualAddress = LastSection->VirtualAddress +
Aligment(LastSection->Misc.VirtualSize, OptHeader(FileBase)->SectionAlignment);

// 设置区段起始位置的 FOA = 上一个区段 FOA + 对齐的文件大小
DestSection->PointerToRawData = LastSection->PointerToRawData +
Aligment(LastSection->SizeOfRawData, OptHeader(FileBase)->FileAlignment);

// 重新的分配空间,大小是 最后一个区段的FOA + 最后一个区段的文件大小
FileSize = DestSection->PointerToRawData + DestSection->SizeOfRawData;
// 使用 realloc 的时候,它新的地址会作为返回值进行返回
FileBase = (DWORD)realloc((LPVOID)FileBase, FileSize);

// 重新设置映像大小 = 最后一个区段的 RVA + 最后一个区段的内存大小
OptHeader(FileBase)->SizeOfImage = DestSection->VirtualAddress + DestSection->Misc.VirtualSize;
}


// 保存修改后的 PE 文件
void CMyPack::SaveFile(LPCSTR NewName)
{
// 打开一个文件,理论上应该对文件进行判断,是否是一个 PE 文件,位数是多少
HANDLE FileHandle = CreateFileA(NewName, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

// 写入 PE 文件的内容
DWORD BytesWrite = 0;
WriteFile(FileHandle, (LPVOID)FileBase, FileSize, &BytesWrite, NULL);

// 关闭句柄,防止句柄泄露
CloseHandle(FileHandle);
}

// 拷贝区段的内容,需要指定区段的名称
void CMyPack::CopySectionData(LPCSTR DestName, LPCSTR SrcName)
{
// 获取到源区段的区段头表结构并计算出偏移(DLL加载到了内存,使用的是内存偏移)
auto SrcSection = GetSection(StubBase, SrcName);
BYTE* SrcData = (BYTE*)(SrcSection->VirtualAddress + StubBase);

// 获取到目标区段的区段头表结构并计算出偏移(PE文件没有对齐,使用的是文件偏移)
auto DestSection = GetSection(FileBase, DestName);
BYTE* DestData = (BYTE*)(DestSection->PointerToRawData + FileBase);

// 以文件大小进行拷贝
memcpy(DestData, SrcData, SrcSection->SizeOfRawData);
}


// 设置入口点为新区段中的 start 的位置(RVA)
void  CMyPack::SetOep()
{
// 保存原始的 OEP
StubData->OldOEP = OptHeader(FileBase)->AddressOfEntryPoint;

// 因为获取到的 start 函数的地址是在dll中的地址,现在这个区段被拷贝到了
// 被加壳程序中,所以需要重新计算 start 的 RVA 并设置为 OEP
OptHeader(FileBase)->AddressOfEntryPoint =
GetSection(FileBase, ".mypack")->VirtualAddress + StartOffset;
}


// 修复壳代码的重定位
void CMyPack::FixRealoc()
{
ULONG Size = 0, OldProtect = 0,OldRelocProtect = 0;

// 获取到程序的重定位表
auto RealocTable = (PIMAGE_BASE_RELOCATION)
ImageDirectoryEntryToData((PVOID)StubBase, TRUE, 5, &Size);

// 遍历重定位表,重定位表以一个空表结尾
while (RealocTable->SizeOfBlock)
{
// 获取重定位项,并依次修复重定位项
auto Item = (TypeOffset*)(RealocTable + 1);

// 获取到重定位项的个数
DWORD Count = (RealocTable->SizeOfBlock - 8) / 2;

// 遍历重定位项并修复
for (DWORD i = 0; i < Count; ++i)
{
// 修改整个分页的属性,使它能够被写入
VirtualProtect((LPVOID)(RealocTable->VirtualAddress + StubBase), 0x1000, PAGE_READWRITE, &OldProtect);

// 只需要关注 type == 3 的类型
if (Item[i].Type == 3)
{
// 需要重定位的数据所在的地址 dll所在的基址Base + 重定位表的RVA + 重定位块所在的Offset
DWORD* ItemAddr = (DWORD*)(StubBase + RealocTable->VirtualAddress + Item[i].Offset);

// 计算出不会改变(会改变的有基址和段的RVA)的偏移
// 不会改变的是重定位块在重定位段里面的相对偏移。
// 重定位块在重定位段里面的相对偏移=重定位块当前所在地址-dll所在的基址Base-在dll内重定位段的RVA
DWORD Offset = *ItemAddr - StubBase - GetSection(StubBase, ".text")->VirtualAddress;

// 要替换掉原本程序的重定位的位置。
// 相对偏移+段地址RVA(在exe内拷到了.mypack段)+exe基址
*ItemAddr = Offset + GetSection(FileBase, ".mypack")->VirtualAddress + OptHeader(FileBase)->ImageBase;
}

// 还原属性
VirtualProtect((LPVOID)(RealocTable->VirtualAddress + StubBase), 0x1000, OldProtect, &OldProtect);
}


// 上面的行为,是因为exe的mypack直接是拷贝的dll的text。
// 直接拷贝的话,dll里面的text里面的重定位存的重定位表的地址是相对于dll基址的地址。
// 所以要先更改成以exe为基址的地址。


// 修改整个分页的属性,使它能够被写入
VirtualProtect((LPVOID)((DWORD)RealocTable&0xFFFFF000), 0x1000, PAGE_READWRITE, &OldProtect);

// dll的重定位表在exe的位置= dll重定位表-dll的text段RVA+exe的mypack段RVA
// RealocTable->VirtualAddress =
// (GetSection(FileBase, ".mypack")->VirtualAddress - GetSection(StubBase, ".text")->VirtualAddress)+RealocTable->VirtualAddress;
RealocTable->VirtualAddress += (GetSection(FileBase, ".mypack")->VirtualAddress - GetSection(StubBase, ".text")->VirtualAddress);

// 找到下一个重定位块
RealocTable = (PIMAGE_BASE_RELOCATION)((DWORD)RealocTable + RealocTable->SizeOfBlock);
}

// 手动的关闭动态基址,否则程序无法运行
//OptHeader(FileBase)->DllCharacteristics = 0;


// 但是现在,程序运行的还是原本exe的重定位表,所以接下来要把原程序的重定位表替换成dll的
// 在exe中重新做一个新的重定位表
// 从stub 拷贝 壳的重定位内容.reloc 到 exe中。
CopySection(".sreloc", ".reloc");
CopySectionData(".sreloc", ".reloc");


// 修改整个分页的属性,使它能够被写入
VirtualProtect((LPVOID)(RealocTable->VirtualAddress + FileBase), 0x1000, PAGE_READWRITE, &OldRelocProtect);
// 让stub的重定位代替exe的。
OptHeader(FileBase)->DataDirectory[5].VirtualAddress = GetSection(FileBase, ".sreloc")->VirtualAddress;
OptHeader(FileBase)->DataDirectory[5].Size = GetSection(FileBase, ".sreloc")->Misc.VirtualSize;
// 恢复整个分页的属性
VirtualProtect((LPVOID)(RealocTable->VirtualAddress + FileBase), 0x1000, OldRelocProtect, &OldRelocProtect);



// 保存被加壳程序的重定位表
StubData->RelocRVA = GetSection(FileBase, ".reloc")->VirtualAddress;
StubData->ImageBase = OptHeader(FileBase)->ImageBase;
StubData->ImportRVA= OptHeader(FileBase)->DataDirectory[1].VirtualAddress;
StubData->TlsRVA= OptHeader(FileBase)->DataDirectory[9].VirtualAddress;
if (StubData->TlsRVA!=0)
{
StubData->HideTLS =false;
}
//StubData->TlsRVA= 1000;
}


// 异或指定区段的数据
void CMyPack::XorFileSection(LPCSTR SectionName)
{
// 获取指定的区段
auto Section = GetSection(FileBase, SectionName);
// 保存区段的 RVA 以及 Size
StubData->XorRVA = Section->VirtualAddress;
StubData->XorSize = Section->SizeOfRawData;

// 计算出区段的位置
BYTE* Buffer = (BYTE*)(FileBase + Section->PointerToRawData);

// 随机生成一个加密的 key
srand((unsigned int)time(0));
StubData->XorKey = rand() % 0x100;

// 根据文件大小对它进行异或
for (DWORD i = 0; i < Section->SizeOfRawData; ++i)
Buffer[i] ^= StubData->XorKey;
}

// 清除一些表项
void CMyPack::ClearDataDir()
{
auto Dir = OptHeader(FileBase)->DataDirectory;
for (int i=0;i<16;++i)
{
if (i!=0&&i!=5)
{
Dir[i].Size = 0;
Dir[i].VirtualAddress = 0;
}

}

}

void CMyPack::PackCode(LPCSTR SectionName)
{
// 获取指定的区段
// auto Section = GetSection(FileBase, SectionName);
// 获取到第一个代码段
auto Section = IMAGE_FIRST_SECTION(NTHeader(FileBase));
// 保存区段的 RVA 以及 Size
StubData->PackRVA = Section->VirtualAddress;
StubData->PackSize = Section->SizeOfRawData;
// 区段数量
DWORD dwScnCount = FileHeader(FileBase)->NumberOfSections;

// 进度条控件
//CMFCShellDlg::m_ProgressCtrl.SetStep(dwScnCount);

for (DWORD i = 0; i < dwScnCount - 2; i++)//mypack,新的reloc段不压缩
{
// 进度条
//CMFCShellDlg::m_ProgressCtrl.StepIt();
// 所在区段大小
DWORD nDataSize = Section->SizeOfRawData;
if (nDataSize)
{
// 计算出区段的位置
char* nSectionByte = (char*)(FileBase + Section->PointerToRawData);
// 要压缩前的准备工作。
char *nWorkMem = (char*)malloc(aP_workmem_size(nDataSize));
char *nPackData = (char*)malloc(aP_max_packed_size(nDataSize));

// 压缩成功返回压缩的大小
size_t nPackSize = aPsafe_pack(nSectionByte, nPackData, nDataSize, nWorkMem, NULL, NULL);

// 将原本位置上的数据清除
memset(nSectionByte, 0, Section->SizeOfRawData);

// 将新压缩完的nPackSize大小的nPackData内容放入原本位置
memcpy_s(nSectionByte, Section->SizeOfRawData, nPackData, nPackSize);

// 将原本文件区段大小更新
Section->SizeOfRawData = nPackSize;

// 释放
free(nPackData);
free(nWorkMem);
}
// 下一个段
Section++;
}
//清除资源表
OptHeader(FileBase)->DataDirectory[2].VirtualAddress = 0;
OptHeader(FileBase)->DataDirectory[2].Size = 0;
}
//获取最后一个区段头
IMAGE_SECTION_HEADER* CMyPack::GetLastSection()// 获取最后一个区段
{
// 获取区段个数
DWORD dwScnCount = FileHeader(FileBase)->NumberOfSections;
// 获取第一个区段
IMAGE_SECTION_HEADER* pScn = IMAGE_FIRST_SECTION(NTHeader(FileBase));
// 得到最后一个有效的区段
return pScn + (dwScnCount - 1);
}
// 修复压缩后的区段
void CMyPack::FixSection()
{
// 获取区段数
DWORD dwScnCount = FileHeader(FileBase)->NumberOfSections;
// 获取区段头
auto pScn = IMAGE_FIRST_SECTION(NTHeader(FileBase));
// 获取文件对其力度
DWORD nFileAligment = OptHeader(FileBase)->FileAlignment;
// 循环
for (DWORD i = 0; i < dwScnCount - 1; i++)
{
// 如果有文件内容
if (pScn->PointerToRawData)
{
// 对其
DWORD nSectionAligment = Aligment(pScn->SizeOfRawData, nFileAligment);
// 下一个区段
IMAGE_SECTION_HEADER* pTempScn = pScn + 1;
// 下一个区段的大小
DWORD nTempDataSize = pTempScn->SizeOfRawData;
// 申请新的空间
CHAR *nTempData = new CHAR[nTempDataSize]{};
// 先保存下一个区段的内容

memcpy_s(nTempData, nTempDataSize,(BYTE*)(FileBase + pTempScn->PointerToRawData), nTempDataSize);
// 根据新的力度重新定位下个区段的位置
pTempScn->PointerToRawData = pScn->PointerToRawData + nSectionAligment;
// 把刚刚保存的下个区段的内容还原
memcpy_s((BYTE*)(FileBase + pTempScn->PointerToRawData), nTempDataSize, nTempData, nTempDataSize);
// 释放
delete[]nTempData;
}
// 下一个段
pScn++;
}
// 获取最后一个区段位置
pScn = GetLastSection();
// 计算出新的文件大小
FileSize = pScn->PointerToRawData + pScn->SizeOfRawData;

}


CMypack.h

#include <windows.h>
#include "MFCShellDlg.h"

struct ShareData
{
DWORD OldOEP = 0;
BYTE XorKey = 0;
DWORD XorRVA = 0;
DWORD XorSize = 0;
DWORD RelocRVA = 0;
DWORD ImageBase = 0;
DWORD ImportRVA = 0;
DWORD TlsRVA = 0;
DWORD PackRVA = 0;
DWORD PackSize = 0;
bool HideTLS = true;
};

class CMyPack
{
private:
// 文件相关的属性
DWORD FileSize = 0;
DWORD FileBase = 0;

// Stub 相关的属性
DWORD StubBase = 0;
DWORD StartOffset = 0;
ShareData* StubData = nullptr;

private:
// 获取各种头的函数
PIMAGE_DOS_HEADER DosHeader(DWORD Base);
PIMAGE_NT_HEADERS NTHeader(DWORD Base);
PIMAGE_FILE_HEADER FileHeader(DWORD Base);
PIMAGE_OPTIONAL_HEADER OptHeader(DWORD Base);

// 将传入的数值对齐到指定力度的倍数
DWORD Aligment(DWORD Item, DWORD Align);

// 获取指定名称的区段头表地址
PIMAGE_SECTION_HEADER GetSection(DWORD Base, LPCSTR Name);

public:
// 加载一个 PE 文件
void LoadFile(LPCSTR FileName);

// 加载一个 PE 文件
void LoadStub(LPCSTR FileName);

// 拷贝区段,从 stub 拷贝 SrcName 区段到 exe 中并命名为 DestName
void CopySection(LPCSTR DestName, LPCSTR SrcName);

// 拷贝区段的内容,需要指定区段的名称
void CopySectionData(LPCSTR DestName, LPCSTR SrcName);

// 保存修改后的 PE 文件
void SaveFile(LPCSTR NewName);

// 设置入口点为新区段中的 start 的位置(RVA)
void  SetOep();

// 修复壳代码的重定位
void FixRealoc();

// 异或指定区段的数据
void XorFileSection(LPCSTR SectionName);

// 清除一些表项
void ClearDataDir();

// 压缩代码
void PackCode(LPCSTR SectionName);


// 修复压缩后的区段
void FixSection();

// 获取最后一个段
IMAGE_SECTION_HEADER * GetLastSection();
};

my_stub

main.cpp

#include <windows.h>
#include "header.h"



// 将 .data 和 .rdata 合并到 .text 区域
#pragma comment(linker, "/merge:.data=.text")
#pragma comment(linker, "/merge:.rdata=.text")
// 并且设置 .text 区属性为壳读壳写壳执行
#pragma comment(linker, "/section:.text,RWE")

#include "aplib.h"
#pragma comment(lib,"aPlib.lib")

DWORD g_Bass = 0;

#define STATIC_TIP 0x999
#define EDIT_PASSWORD 0x1000
#define BUTTON_OK 0x1001

#define Process32First Process32FirstW
#define Process32Next Process32NextW
#define PROCESSENTRY32 PROCESSENTRY32W
#define PPROCESSENTRY32 PPROCESSENTRY32W
#define LPPROCESSENTRY32 LPPROCESSENTRY32W
// 获取各种头的函数
PIMAGE_DOS_HEADER DosHeader(DWORD Base)
{
return (PIMAGE_DOS_HEADER)Base;
}
PIMAGE_NT_HEADERS NTHeader(DWORD Base)
{
return (PIMAGE_NT_HEADERS)(Base + DosHeader(Base)->e_lfanew);
}
PIMAGE_FILE_HEADER FileHeader(DWORD Base)
{
return &NTHeader(Base)->FileHeader;
}
PIMAGE_OPTIONAL_HEADER OptHeader(DWORD Base)
{
return &NTHeader(Base)->OptionalHeader;
}

// 获取函数地址
DWORD MyGetProcAddress(DWORD Module, LPCSTR FunName)
{
// 获取 Dos 头和 Nt 头
auto DosHeader = (PIMAGE_DOS_HEADER)Module;
auto NtHeader = (PIMAGE_NT_HEADERS)(Module + DosHeader->e_lfanew);
// 获取导出表结构
DWORD ExportRva = NtHeader->OptionalHeader.DataDirectory[0].VirtualAddress;
auto ExportTable = (PIMAGE_EXPORT_DIRECTORY)(Module + ExportRva);
// 找到导出名称表、序号表、地址表
auto NameTable = (DWORD*)(ExportTable->AddressOfNames + Module);
auto FuncTable = (DWORD*)(ExportTable->AddressOfFunctions + Module);
auto OrdinalTable = (WORD*)(ExportTable->AddressOfNameOrdinals + Module);
// 遍历找名字
for (DWORD i = 0; i < ExportTable->NumberOfNames; ++i)
{
// 获取名字
char* Name = (char*)(NameTable[i] + Module);
if (!strcmp(Name, FunName))
return FuncTable[OrdinalTable[i]] + Module;
}
return -1;
}

// 跳转到 OEP
_declspec(naked) void JmpOep()
{
__asm
{
mov eax, StubData.OldOEP; 原始 OEP 的RVA
mov ebx, dword ptr FS : [0x30]; PEB
mov ebx, dword ptr[ebx + 0x08]; 当前加载基址
add eax, ebx; 计算出 OEP

// 花指令1
push ebp
mov ebp, esp
push - 1
push 111111
push 222222
mov ebx, fs:[0]
push eax
mov fs : [0], esp
pop ebx
mov fs : [0], eax
pop ebx
pop ebx
pop ebx
pop ebx
mov ebp, eax

// 花指令2
nop
nop
nop
nop
nop
nop
push ebp
mov ebp, esp
inc ecx
push edx
nop
pop edx
dec ecx
pop ebp
inc ecx
mov eax,eax //原入口地址
jmp eax
//jmp eax; 跳转 OEP
}
}


// 获取KernelBase
_declspec(naked) DWORD GetKernelBase()
{
__asm
{
// 按照加载顺序
mov eax, dword ptr fs : [0x30]
mov eax, dword ptr[eax + 0x0C]
mov eax, dword ptr[eax + 0x0C]
mov eax, dword ptr[eax]
mov eax, dword ptr[eax]
mov eax, dword ptr[eax + 0x18]
ret
}
}


// 解密数据
void XorData()
{
DWORD ImageBase = 0, OldProtect = 0;
__asm
{
mov ebx, dword ptr FS : [0x30]; PEB
mov ebx, dword ptr[ebx + 0x08]; 当前加载基址
mov ImageBase, ebx
}

// 获取到被加密区段的起始位置
BYTE* Data = (BYTE*)(ImageBase + StubData.XorRVA);

pVirtualProtect(Data, StubData.XorSize, PAGE_READWRITE, &OldProtect);

// 循环进行解密
for (DWORD i = 0; i < StubData.XorSize; ++i)
Data[i] ^= StubData.XorKey;

pVirtualProtect(Data, StubData.XorSize, OldProtect, &OldProtect);
}

// 获取所有想要使用的函数
void GetApis()
{

pVirtualProtect = (fnVirtualProtect)MyGetProcAddress(GetKernelBase(), "VirtualProtect");
pLoadLibraryExA = (fnLoadLibraryExA)MyGetProcAddress(GetKernelBase(), "LoadLibraryExA");

// 获取User32.dll
HMODULE GetUser32=pLoadLibraryExA("User32.dll", 0, 0);
DWORD dwUser32 = (DWORD)GetUser32;


pCreateWindowExA = (fnCreateWindowExA)MyGetProcAddress(dwUser32, "CreateWindowExA");
pRegisterClassA = (fnRegisterClassA)MyGetProcAddress(dwUser32, "RegisterClassA");
pShowWindow = (fnShowWindow)MyGetProcAddress(dwUser32, "ShowWindow");

pExitProcess = (fnExitProcess)MyGetProcAddress(GetKernelBase(), "ExitProcess");

pDefWindowProcA = (fnDefWindowProcA)MyGetProcAddress(dwUser32, "DefWindowProcA");
pGetStockObject = (fnGetStockObject)MyGetProcAddress(dwUser32, "GetStockObject");
pGetMessageA = (fnGetMessageA)MyGetProcAddress(dwUser32, "GetMessageA");
pTranslateMessage = (fnTranslateMessage)MyGetProcAddress(dwUser32, "TranslateMessage");
pDispatchMessageA = (fnDispatchMessageA)MyGetProcAddress(dwUser32, "DispatchMessageA");
pMessageBoxW = (fnMessageBoxW)MyGetProcAddress(dwUser32, "MessageBoxW");
pGetDlgItem = (fnGetDlgItem)MyGetProcAddress(dwUser32, "GetDlgItem");
pGetWindowTextA = (fnGetWindowTextA)MyGetProcAddress(dwUser32, "GetWindowTextA");
pGetWindowTextW = (fnGetWindowTextW)MyGetProcAddress(dwUser32, "GetWindowTextW");
pMessageBoxA = (fnMessageBoxA)MyGetProcAddress(dwUser32, "MessageBoxA");
pPostQuitMessage = (fnPostQuitMessage)MyGetProcAddress(dwUser32, "PostQuitMessage");
pGetModuleHandleA = (fnGetModuleHandleA)MyGetProcAddress(GetKernelBase(), "GetModuleHandleA");
pGetProcAddress = (fnGetProcAddress)MyGetProcAddress(GetKernelBase(), "GetProcAddress");
pVirtualAlloc = (fnVirtualAlloc)MyGetProcAddress(GetKernelBase(), "VirtualAlloc");
HMODULE GetNtdll = pLoadLibraryExA("ntdll.dll", 0, 0);
DWORD dwNtdll = (DWORD)GetNtdll;

pNtQueryInformationProcess = (fnNtQueryInformationProcess)MyGetProcAddress(dwNtdll, "NtQueryInformationProcess");

pGetCurrentProcess = (fnGetCurrentProcess)MyGetProcAddress(GetKernelBase(), "GetCurrentProcess");
pVirtualFree = (fnVirtualFree)MyGetProcAddress(GetKernelBase(), "VirtualFree");
pRtlZeroMemory = (fnRtlZeroMemory)MyGetProcAddress(GetKernelBase(), "RtlZeroMemory");
pRtlMoveMemory = (fnRtlMoveMemory)MyGetProcAddress(GetKernelBase(), "RtlMoveMemory");
pCreateToolhelp32Snapshot = (fnCreateToolhelp32Snapshot)MyGetProcAddress(GetKernelBase(), "CreateToolhelp32Snapshot");
pProcess32FirstW = (fnProcess32FirstW)MyGetProcAddress(GetKernelBase(), "Process32FirstW");
pProcess32NextW = (fnProcess32NextW)MyGetProcAddress(GetKernelBase(), "Process32NextW");
pCloseHandle = (fnCloseHandle)MyGetProcAddress(GetKernelBase(), "CloseHandle");


}



// 获取当前加载基址
void GetPeModuleHandle()
{
__asm
{
mov eax, FS:[0x30]
mov eax, [eax + 0xc]
mov eax, [eax + 0xc]
mov eax, [eax + 0x18]
mov g_Bass, eax;

}


}

//窗口回调函数
LRESULT CALLBACK WNDMYPROC(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
WORD wHigh = HIWORD(wParam);
WORD wLow = LOWORD(wParam);

// 分配消息
switch (uMsg)
{
case WM_CLOSE:{pExitProcess(0);}break;

case WM_COMMAND:
{
switch (wLow)
{
case BUTTON_OK:{

// 获取输入框内字符串
HWND hEdit=pGetDlgItem(hWnd, EDIT_PASSWORD);
CHAR nBuff[MAX_PATH] = {0};
pGetWindowTextA(hEdit, nBuff, MAX_PATH);


if (!strcmp(nBuff,"1515"))
{
pMessageBoxA(0, "密码正确", "密码正确", 0);
pShowWindow(hWnd, SW_HIDE);
pPostQuitMessage(0);
}
else
{
pMessageBoxA(0, "密码错误,请重新输入", "密码错误", 0);
}


}break;
}
break;
}break;
}
return pDefWindowProcA(hWnd, uMsg, wParam, lParam);

}

// 显示输入密码对话框
void ShowMyDialog()
{
// 注册窗口类
WNDCLASSA wc = { 0 };
wc.lpszClassName = "Password";
wc.lpfnWndProc = &WNDMYPROC;
//wc.hbrBackground = (HBRUSH)pGetStockObject(WHITE_BRUSH);
pRegisterClassA(&wc);

// 创建窗口
HWND hWnd = NULL;
hWnd=pCreateWindowExA(0,"Password","CheckPassWord",WS_OVERLAPPEDWINDOW,600,300,180,200,0,0,(HINSTANCE)g_Bass,0);

// 设置子窗口信息
pCreateWindowExA(0, "Edit", "请输入密码:", SS_CENTER | WS_CHILD | WS_VISIBLE | WS_GROUP,
20, 20, 120, 30, hWnd, (HMENU)STATIC_TIP, (HINSTANCE)g_Bass, NULL);
pCreateWindowExA(WS_EX_CLIENTEDGE, "Edit", "", ES_NUMBER | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
20, 50, 120, 30, hWnd, (HMENU)EDIT_PASSWORD, (HINSTANCE)g_Bass, NULL);
pCreateWindowExA(0, "Button", "确认密码", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE,
20, 100, 120, 30, hWnd, (HMENU)BUTTON_OK, (HINSTANCE)g_Bass, NULL);

// 显示窗口
pShowWindow(hWnd, SW_SHOW);

// 分配消息
MSG msg = { 0 };
while (pGetMessageA(&msg, 0, 0, 0))
{
pTranslateMessage(&msg);
pDispatchMessageA(&msg);

}

}

//修复被加壳重定位
void FixReloc()
{
DWORD ImageBase = (DWORD)pGetModuleHandleA(NULL);
DWORD OldProtect = 0;
auto RealocTable = (PIMAGE_BASE_RELOCATION)(ImageBase+ StubData.RelocRVA);
// 遍历重定位表,重定位表以一个空表结尾
while (RealocTable->SizeOfBlock)
{
// 获取重定位项,并依次修复重定位项
auto Item = (TypeOffset*)(RealocTable + 1);

// 获取到重定位项的个数
DWORD Count = (RealocTable->SizeOfBlock - 8) / 2;

// 遍历重定位项并修复
for (DWORD i = 0; i < Count; ++i)
{
// 修改整个分页的属性,使它能够被写入
pVirtualProtect((LPVOID)(RealocTable->VirtualAddress + ImageBase), 0x1000, PAGE_READWRITE, &OldProtect);

// 只需要关注 type == 3 的类型
if (Item[i].Type == 3)
{
// 需要重定位的数据所在的地址 Base + RVA + Offset
DWORD* ItemAddr = (DWORD*)(ImageBase + RealocTable->VirtualAddress + Item[i].Offset);

// 计算出新的 VA
*ItemAddr = *ItemAddr - 0x400000 + ImageBase;
}

// 还原属性
pVirtualProtect((LPVOID)(RealocTable->VirtualAddress + ImageBase), 0x1000, OldProtect, &OldProtect);
}

// 找到下一个重定位块
RealocTable = (PIMAGE_BASE_RELOCATION)((DWORD)RealocTable + RealocTable->SizeOfBlock);
}

}


// 未加密修复导入表
// void FixImport()
// {
// char shellcode[] = { "\x68\x63\xE9\x8C\xC3\xC3" };
// LPVOID Addr = pVirtualAlloc(NULL, 0X1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
// DWORD ImageBase = (DWORD)pGetModuleHandleA(NULL), OldProtect = 0;
// auto ImportTable = (PIMAGE_IMPORT_DESCRIPTOR)(ImageBase + StubData.ImportRVA);
//
// // 循环,以0结尾
// while (ImportTable->Name)
// {
// // 获取模块名称,根据名称调用loadlibrary
// char* Name = (char*)(ImageBase + ImportTable->Name);
// HMODULE Module = pLoadLibraryExA(Name,0,0);
// // 根据IAT内保存的名字修复IAT
// auto Iat = (PIMAGE_THUNK_DATA)(ImportTable->FirstThunk + ImageBase);
// for (int i=0;Iat[i].u1.Function!=0;++i)
// {
// LPCSTR FuncName = nullptr;
// // 判断当前的函数是否有名称
// if (IMAGE_SNAP_BY_ORDINAL32(Iat[i].u1.Ordinal))
// {
// FuncName = (LPCSTR)IMAGE_ORDINAL32(Iat[i].u1.Ordinal);
//
// }
// else
// {
// FuncName = ((PIMAGE_IMPORT_BY_NAME)(Iat[i].u1.AddressOfData + ImageBase))->Name;
// }
//
// // 获取到函数地址
// DWORD FunAddr = (DWORD)pGetProcAddress(Module, FuncName);
//
// // 生成新的shellcode
// *(DWORD*)& shellcode[1] = FunAddr;
// memcpy(Addr, shellcode, 12);
// pVirtualProtect((LPVOID)((DWORD)&Iat[i]&0xFFFFF000), 0x1000, PAGE_READWRITE, &OldProtect);
//
// // 修复到IAT
// Iat[i].u1.Function = (DWORD)Addr;
// pVirtualProtect((LPVOID)((DWORD)&Iat[i]&0xFFFFF000), 0x1000, OldProtect, &OldProtect);
// Addr = (LPVOID)((DWORD)Addr + 6);
// }
// ImportTable++;
// }
// }

// 将传入的数值对齐到指定力度的倍数
DWORD Aligment(DWORD Item, DWORD Align)
{
// 35000 % 1000 != 0 -> (3500 / 1000 + 1)*1000
return Item % Align ? (Item / Align + 1)*Align : Item;
}


// 加密修复导入表
void FixImport()
{
// char shellcode[] = { "\x68\x63\xE9\x8C\xC3\xC3" };
// LPVOID Addr = pVirtualAlloc(NULL, 0X1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
DWORD ImageBase = (DWORD)pGetModuleHandleA(NULL), OldProtect = 0;
auto ImportTable = (PIMAGE_IMPORT_DESCRIPTOR)(ImageBase + StubData.ImportRVA);

// 循环,以0结尾
while (ImportTable->Name)
{
// 获取模块名称,根据名称调用loadlibrary
char* Name = (char*)(ImageBase + ImportTable->Name);
HMODULE Module = pLoadLibraryExA(Name, 0, 0);
// 根据IAT内保存的名字修复IAT
auto Iat = (PIMAGE_THUNK_DATA)(ImportTable->FirstThunk + ImageBase);
for (int i = 0; Iat[i].u1.Function != 0; ++i)
{
LPCSTR FuncName = nullptr;
// 判断当前的函数是否有名称
if (IMAGE_SNAP_BY_ORDINAL32(Iat[i].u1.Ordinal))
{
FuncName = (LPCSTR)IMAGE_ORDINAL32(Iat[i].u1.Ordinal);

}
else
{
FuncName = ((PIMAGE_IMPORT_BY_NAME)(Iat[i].u1.AddressOfData + ImageBase))->Name;
}

// 获取到函数地址
DWORD dwFunAddr = (DWORD)pGetProcAddress(Module, FuncName);


  // **加密函数地址**
dwFunAddr ^= 0x13973575;
LPVOID Addr = (PDWORD)pVirtualAlloc(NULL, 0x20, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

//构造一段花指令解密的ShellCode
byte shellcode[] = { 0xe8, 0x01, 0x00, 0x00,
   0x00, 0xe9, 0x58, 0xeb,
   0x01, 0xe8, 0xb8, 0x8d,
   0xe4, 0xd8, 0x62, 0xeb,
   0x01, 0x15, 0x35, 0x75,
   0x35, 0x97, 0x13, 0xeb,
   0x01, 0xff, 0x50, 0xeb,
   0x02, 0xff, 0x15, 0xc3 };
//把dwFunAddr写入到解密的ShellCode中
shellcode[11] = dwFunAddr;
shellcode[12] = dwFunAddr >> 0x8;
shellcode[13] = dwFunAddr >> 0x10;
shellcode[14] = dwFunAddr >> 0x18;
//拷贝数据到申请的内存

memcpy(Addr, shellcode, 0x20);
//修改保护属性

pVirtualProtect((LPVOID)((DWORD)&Iat[i] & 0xFFFFF000), 0x1000, PAGE_READWRITE, &OldProtect);
//把获取到的加密函数地址填充在导入地址表里面
Iat[i].u1.Function = (DWORD)Addr;
pVirtualProtect((LPVOID)((DWORD)&Iat[i] & 0xFFFFF000), 0x1000, OldProtect, &OldProtect);

}
ImportTable++;
}
}

// 反调试
bool NQIP_ProcessDebugPort()
{

int nDebugPort = 0;
pNtQueryInformationProcess(
pGetCurrentProcess(),//目标进程句柄
ProcessDebugPort,   //查询信息的类型
&nDebugPort,        //输出查询的信息
sizeof(nDebugPort), //查询类型的大小
NULL);
return nDebugPort == 0xFFFFFFFF ? true : false;
}
// 判断是否被调试
void IsBeingDebug()
{
if (NQIP_ProcessDebugPort())
{
pMessageBoxA(0, "正在被调试", 0, 0);
return ;
}

}

// 调用Tls
void CallTls()
{

DWORD ImageBase = (DWORD)pGetModuleHandleA(NULL), OldProtect = 0;
auto TlsTable = (PIMAGE_TLS_DIRECTORY)(ImageBase + StubData.TlsRVA);
if (StubData.HideTLS==true)
{
pMessageBoxA(0, "未发现", "TLS", 0);
return;
}
DWORD dwTlsCallBack = *(DWORD*)TlsTable->AddressOfCallBacks;
__asm
{
cmp dwTlsCallBack, 0
je ENDCALL
push 0
push 1
push ImageBase
call dwTlsCallBack
ENDCALL:


}
pMessageBoxA(0, "成功调用", "TLS", 0);


}

// 解压
void UpackCode()
{
// 获取到第一个代码段
DWORD ImageBase = (DWORD)pGetModuleHandleA(NULL);
DWORD dwScnCount = FileHeader(ImageBase)->NumberOfSections;
auto pScn = IMAGE_FIRST_SECTION(NTHeader(ImageBase));
for (DWORD i = 0; i < dwScnCount-2 ; i++)
{
// 如果代码段里有数据
if (pScn->SizeOfRawData)
{
// 定位到压缩代码的位置
char *nSectionByte = (char*)(pScn->VirtualAddress + (DWORD)ImageBase);

// 区段的大小
DWORD nPackSize = pScn->SizeOfRawData;

// 获取到被压缩代码的大小
size_t nUPackSize = aPsafe_get_orig_size(nSectionByte);

// 申请被压缩代码大小的空间用来存储数据
char *nUPackData = (char*)pVirtualAlloc(NULL, nUPackSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
// 解压数据,返回解压完大小。(1.源文件地址,区段大小,存放的目的文件地址,压缩代码大小)
nPackSize = aPsafe_depack(nSectionByte, nPackSize, nUPackData, nUPackSize);


DWORD nOldProtect = 0;

// 更改页属性
pVirtualProtect((char*)((DWORD)nSectionByte & 0xfffff000), pScn->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &nOldProtect);

// 清空原本区段内容
memset(nSectionByte, 0, nPackSize);
//pRtlZeroMemory(nSectionByte, nPackSize);
// 拷贝解压完的内容到原本位置
memcpy(nSectionByte, nUPackData, nUPackSize);
//pRtlMoveMemory(nSectionByte, nUPackData, nUPackSize);

pVirtualProtect((char*)((DWORD)nSectionByte & 0xfffff000), pScn->Misc.VirtualSize, nOldProtect, &nOldProtect);
//释放
pVirtualFree(nUPackData, nUPackSize, MEM_RELEASE);


// 更改页属性
pVirtualProtect((LPVOID)ImageBase, 0x1000, PAGE_EXECUTE_READWRITE, &nOldProtect);
//更新代码段大小
pScn->SizeOfRawData = nUPackSize;
// 更改页属性
pVirtualProtect((LPVOID)ImageBase, 0x1000, nOldProtect, &nOldProtect);
}
pScn++;
}



}

// 反虚拟机
void AntiVMare()
{
//保存进程信息
PROCESSENTRY32  ProcInfo;
ProcInfo.dwSize = sizeof(ProcInfo);
//进程快照
HANDLE hProcessSnap = pCreateToolhelp32Snapshot(0x00000002, 0);
//遍历所有快照
BOOL FindFlags = pProcess32FirstW(hProcessSnap, &ProcInfo);
while (FindFlags)
{
WCHAR target[] = L"vmtoolsd.exe";
//虚拟机标志
int flags = 0;
//比较
if (!wcscmp(target, ProcInfo.szExeFile))
{
flags = true;
}


//如果存在指定名称的进程,则结束
if (flags)
{
pMessageBoxA(0, "发现虚拟机", "虚拟机", 0);
pExitProcess(0);
}
else
{
FindFlags = pProcess32NextW(hProcessSnap, &ProcInfo);
}
}
//关闭句柄
pMessageBoxA(0, "未发现虚拟机", "虚拟机", 0);
pCloseHandle(hProcessSnap);
}

// 导出且是一个裸函数,不会自动生成代码
_declspec(dllexport) _declspec(naked) void start()
{
// 获取所需函数
GetApis();

// 是否被调试
IsBeingDebug();

// 反虚拟机
AntiVMare();

// 弹出密码框
ShowMyDialog();


// 解压
UpackCode();

// 开始解密
XorData();

// 修复被加壳重定位
FixReloc();

// 修复导入表
FixImport();

// 调用TLS

CallTls();
// 跳回OEP
JmpOep();
}


header.h

#include <windows.h>

typedef struct tagPROCESSENTRY32W
{
DWORD   dwSize;
DWORD   cntUsage;
DWORD   th32ProcessID;          // this process
ULONG_PTR th32DefaultHeapID;
DWORD   th32ModuleID;           // associated exe
DWORD   cntThreads;
DWORD   th32ParentProcessID;    // this process's parent process
LONG    pcPriClassBase;         // Base priority of process's threads
DWORD   dwFlags;
WCHAR   szExeFile[MAX_PATH];    // Path
} PROCESSENTRY32W;
typedef PROCESSENTRY32W *  PPROCESSENTRY32W;
typedef PROCESSENTRY32W *  LPPROCESSENTRY32W;



// 查询调式用
typedef enum _PROCESSINFOCLASS {
ProcessBasicInformation = 0,
ProcessDebugPort = 7,
ProcessWow64Information = 26,
ProcessImageFileName = 27,
ProcessBreakOnTermination = 29
} PROCESSINFOCLASS;

// 提供一个结构体,这里的数据应该由加壳器填充
struct ShareData
{
DWORD OldOEP = 0;
BYTE XorKey = 0;
DWORD XorRVA = 0;
DWORD XorSize = 0;
DWORD RelocRVA = 0;
DWORD ImageBase = 0;
DWORD ImportRVA = 0;
DWORD TlsRVA = 0;
DWORD PackRVA = 0;
DWORD PackSize = 0;
bool HideTLS = true;
};
struct TypeOffset
{
WORD Offset : 12;
WORD Type : 4;
};

extern "C"
{
// 导出这个结构体的一个变量,提供给加壳器
_declspec(dllexport) ShareData StubData;

// 导出且是一个裸函数,不会自动生成代码
_declspec(dllexport) void start();
}

typedef BOOL(WINAPI* fnVirtualProtect)(
_In_  LPVOID lpAddress,
_In_  SIZE_T dwSize,
_In_  DWORD flNewProtect,
_Out_ PDWORD lpflOldProtect
);
fnVirtualProtect pVirtualProtect;


typedef HWND (WINAPI* fnCreateWindowExA)(
_In_ DWORD dwExStyle,
_In_opt_ LPCSTR lpClassName,
_In_opt_ LPCSTR lpWindowName,
_In_ DWORD dwStyle,
_In_ int X,
_In_ int Y,
_In_ int nWidth,
_In_ int nHeight,
_In_opt_ HWND hWndParent,
_In_opt_ HMENU hMenu,
_In_opt_ HINSTANCE hInstance,
_In_opt_ LPVOID lpParam);
fnCreateWindowExA pCreateWindowExA;


typedef ATOM (WINAPI * fnRegisterClassA)(
_In_ CONST WNDCLASSA *lpWndClass);
fnRegisterClassA pRegisterClassA;

typedef BOOL (WINAPI* fnShowWindow)(
_In_ HWND hWnd,
_In_ int nCmdShow);
fnShowWindow pShowWindow;

typedef VOID (WINAPI* fnExitProcess)(
_In_ UINT uExitCode
);
fnExitProcess pExitProcess;

typedef LRESULT(WINAPI*fnDefWindowProcA)(
_In_ HWND hWnd,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam);
fnDefWindowProcA pDefWindowProcA;

typedef HMODULE (WINAPI*fnLoadLibraryExA)(
_In_ LPCSTR lpLibFileName,
_Reserved_ HANDLE hFile,
_In_ DWORD dwFlags
);
fnLoadLibraryExA pLoadLibraryExA;

typedef HGDIOBJ (WINAPI* fnGetStockObject)(_In_ int i);
fnGetStockObject pGetStockObject;

typedef BOOL (WINAPI* fnGetMessageA)(
_Out_ LPMSG lpMsg,
_In_opt_ HWND hWnd,
_In_ UINT wMsgFilterMin,
_In_ UINT wMsgFilterMax);
fnGetMessageA pGetMessageA;

typedef BOOL(WINAPI* fnTranslateMessage)(
_In_ CONST MSG *lpMsg);
fnTranslateMessage pTranslateMessage;

typedef LRESULT(WINAPI*fnDispatchMessageA)(
_In_ CONST MSG *lpMsg);
fnDispatchMessageA pDispatchMessageA;

typedef int (WINAPI* fnMessageBoxW)(
_In_opt_ HWND hWnd,
_In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption,
_In_ UINT uType);
fnMessageBoxW pMessageBoxW;

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

typedef HWND (WINAPI*fnGetDlgItem)(
_In_opt_ HWND hDlg,
_In_ int nIDDlgItem);
fnGetDlgItem pGetDlgItem;

typedef int(WINAPI* fnGetWindowTextA)(
_In_ HWND hWnd,
_Out_writes_(nMaxCount) LPSTR lpString,
_In_ int nMaxCount);
fnGetWindowTextA pGetWindowTextA;

typedef int (WINAPI*fnGetWindowTextW)(
_In_ HWND hWnd,
_Out_writes_(nMaxCount) LPWSTR lpString,
_In_ int nMaxCount);
fnGetWindowTextW pGetWindowTextW;

typedef VOID (WINAPI* fnPostQuitMessage)(
_In_ int nExitCode);
fnPostQuitMessage pPostQuitMessage;

typedef HMODULE(WINAPI*fnGetModuleHandleA)(
_In_opt_ LPCSTR lpModuleName
);
fnGetModuleHandleA pGetModuleHandleA;

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

typedef LPVOID(WINAPI*fnVirtualAlloc)(
_In_opt_ LPVOID lpAddress,
_In_     SIZE_T dwSize,
_In_     DWORD flAllocationType,
_In_     DWORD flProtect
);
fnVirtualAlloc pVirtualAlloc;

typedef NTSTATUS(NTAPI*fnNtQueryInformationProcess)(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
fnNtQueryInformationProcess pNtQueryInformationProcess;

typedef HANDLE(WINAPI* fnGetCurrentProcess)(
VOID
);
fnGetCurrentProcess pGetCurrentProcess;
typedef LPVOID(WINAPI* fnVirtualFree)(LPVOID, SIZE_T, DWORD);
fnVirtualFree pVirtualFree;

typedef VOID(WINAPI* fnRtlZeroMemory)(LPVOID, SIZE_T);
fnRtlZeroMemory pRtlZeroMemory;

typedef VOID(WINAPI* fnRtlMoveMemory)(LPVOID, LPVOID, SIZE_T);
fnRtlMoveMemory pRtlMoveMemory;

typedef HANDLE (WINAPI* fnCreateToolhelp32Snapshot)(
DWORD dwFlags,
DWORD th32ProcessID
);
fnCreateToolhelp32Snapshot pCreateToolhelp32Snapshot;

typedef BOOL(WINAPI*fnProcess32FirstW)(
HANDLE hSnapshot,
LPPROCESSENTRY32W lppe
);
fnProcess32FirstW pProcess32FirstW;

typedef BOOL(WINAPI*fnProcess32NextW)(
HANDLE hSnapshot,
LPPROCESSENTRY32W lppe
);
fnProcess32NextW pProcess32NextW;

typedef BOOL(WINAPI*fnCloseHandle)(
_In_ HANDLE hObject
);
fnCloseHandle pCloseHandle;

转载于:https://www.cnblogs.com/ltyandy/p/11415880.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值