写壳2

≡放荡痞女 提交于 2019-11-28 16:40:32

壳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 中并命名为 DestNamevoid 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;​​
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!