zoukankan      html  css  js  c++  java
  • 写壳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[] = { "x68x63xE9x8CxC3xC3" };
    // 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[] = { "x68x63xE9x8CxC3xC3" };
    // 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;

  • 相关阅读:
    delphi point数据类型
    Sql Server 2008 R2链接服务器Oracle数据库
    ORA-28000 账号被锁定的解决办法
    [Oracle] sqlplus / as sysdba ora-01031 insufficient privileges
    Oracle的操作系统认证(/ as sydba 登录方式)
    Delphi使用线程TThread查询数据库
    oracle
    统计字符串中字符出现的次数-Python
    Jmeter保存下载的文件
    如何在Microsoft Store上免费获得 HEIF、HEVC 编码支持
  • 原文地址:https://www.cnblogs.com/ltyandy/p/11415880.html
Copyright © 2011-2022 走看看