x86的VEH HOOK案例:废除某软件注册按钮功能并改成自己的

代码

实战代码,实战场景是:

1.废除某软件的注册按钮里面的代码

2.把原来注册按钮的代码执行逻辑,通过VEH HOOK更改为自己dll的某些代码

3.实现了废除原本程序的注册逻辑,更改为自己的注册逻辑算法

4.注入DLL采用的导入表注入

这个是修改的注册机的机器码生成规则,然后点击按钮会把注册码写入注册表

涉及知识点

1.写入注册表信息

2.枚举窗口控件,获取目标窗口控件(编辑框)内容

3.VEH HOOK

4.获取CPU序列号

5.获取第一个网卡的MAC地址

6.生成机器码

7.使用MinHook库挂钩SetWindowTextA

8.导出重要函数

注册机

#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <wincrypt.h>
#include <string>
#include <stdio.h>

#pragma comment(lib, "advapi32.lib")

// 固定 AES-128 密钥(示例)
static const BYTE AES_KEY[16] = {
    0x32,0x71,0x19,0x88,0xA6,0x55,0xC3,0xD2,
    0x09,0xF1,0xBC,0x44,0xE7,0x6A,0x90,0x1F
};

// 正确导入 AES Key
bool ImportAESKey(HCRYPTPROV hProv, HCRYPTKEY& hKey)
{
    struct {
        BLOBHEADER hdr;
        DWORD keyLen;
        BYTE key[16];
    } blob = {
        { PLAINTEXTKEYBLOB, CUR_BLOB_VERSION, 0, CALG_AES_128 },
        16,
        { 0 }
    };

    memcpy(blob.key, AES_KEY, 16);

    return CryptImportKey(
        hProv,
        (BYTE*)&blob,
        sizeof(blob),
        0,
        0,
        &hKey
    );
}

// 生成注册码
std::string GenerateLicense(const std::string& plain)
{
    HCRYPTPROV hProv = 0;
    HCRYPTKEY hKey = 0;

    CryptAcquireContextA(&hProv, NULL, NULL,
        PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
    ImportAESKey(hProv, hKey);

    BYTE buf[64] = {};
    DWORD len = (DWORD)plain.size();
    memcpy(buf, plain.data(), len);

    // AES 加密(自动 padding)
    CryptEncrypt(hKey, 0, TRUE, 0, buf, &len, sizeof(buf));

    // 二进制 → 4 位数字分组(不丢信息)
    char out[128] = {};
    int pos = 0;
    for (DWORD i = 0; i < len; i += 2)
    {
        WORD v = (buf[i] << 8) | buf[i + 1];
        pos += sprintf(out + pos, "%04u", v);
        if (i + 2 < len) out[pos++] = '-';
    }

    CryptDestroyKey(hKey);
    CryptReleaseContext(hProv, 0);
    return out;
}

int main()
{
    char machineCode[32];
    char expiry[16];

    printf("输入机器码: ");
    scanf("%31s", machineCode);

    printf("输入到期日 (YYYYMMDD): ");
    scanf("%15s", expiry);

    std::string plain = std::string(machineCode) + "|" + expiry;
    std::string license = GenerateLicense(plain);

    printf("\n生成的注册码:\n%s\n", license.c_str());
    return 0;
}

注册码解密器

这个只是用来临时测试的,具体的代码都封装在那个DLL中了

#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <wincrypt.h>
#include <string>
#include <stdio.h>

#pragma comment(lib, "advapi32.lib")

static const BYTE AES_KEY[16] = {
    0x32,0x71,0x19,0x88,0xA6,0x55,0xC3,0xD2,
    0x09,0xF1,0xBC,0x44,0xE7,0x6A,0x90,0x1F
};

bool ImportAESKey(HCRYPTPROV hProv, HCRYPTKEY& hKey)
{
    struct {
        BLOBHEADER hdr;
        DWORD keyLen;
        BYTE key[16];
    } blob = {
        { PLAINTEXTKEYBLOB, CUR_BLOB_VERSION, 0, CALG_AES_128 },
        16,
        { 0 }
    };

    memcpy(blob.key, AES_KEY, 16);

    return CryptImportKey(
        hProv,
        (BYTE*)&blob,
        sizeof(blob),
        0,
        0,
        &hKey
    );
}

// 解密注册码
std::string DecodeLicense(const char* license)
{
    BYTE buf[64] = {};
    int idx = 0;

    char tmp[128];
    strcpy(tmp, license);

    // 数字分组 → 二进制
    for (char* p = strtok(tmp, "-"); p; p = strtok(NULL, "-"))
    {
        WORD v = (WORD)atoi(p);
        buf[idx++] = (BYTE)(v >> 8);
        buf[idx++] = (BYTE)(v & 0xFF);
    }

    HCRYPTPROV hProv = 0;
    HCRYPTKEY hKey = 0;
    CryptAcquireContextA(&hProv, NULL, NULL,
        PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
    ImportAESKey(hProv, hKey);

    DWORD len = idx;
    CryptDecrypt(hKey, 0, TRUE, 0, buf, &len);

    CryptDestroyKey(hKey);
    CryptReleaseContext(hProv, 0);

    return std::string((char*)buf, len);
}

int main()
{
    char license[128];

    printf("输入注册码: ");
    scanf("%127s", license);

    std::string plain = DecodeLicense(license);

    size_t pos = plain.find('|');
    if (pos == std::string::npos)
    {
        printf("注册码无效\n");
        return 0;
    }

    std::string machineCode = plain.substr(0, pos);
    std::string expiry = plain.substr(pos + 1);

    printf("\n解密成功\n");
    printf("机器码: %s\n", machineCode.c_str());
    printf("到期日: %s-%s-%s\n",
        expiry.substr(0, 4).c_str(),
        expiry.substr(4, 2).c_str(),
        expiry.substr(6, 2).c_str());

    return 0;
}

判断程序是否到期

这个是判断注册机写入注册表的注册码是否符合标准与到期

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"

#include <windows.h>
#include <stdio.h>
#include <string>
#include <wincrypt.h>

#pragma comment(lib, "advapi32.lib")

static const BYTE AES_KEY[16] = {
    0x32,0x71,0x19,0x88,0xA6,0x55,0xC3,0xD2,
    0x09,0xF1,0xBC,0x44,0xE7,0x6A,0x90,0x1F
};

bool ImportAESKey(HCRYPTPROV hProv, HCRYPTKEY& hKey)
{
    struct {
        BLOBHEADER hdr;
        DWORD keyLen;
        BYTE key[16];
    } blob = {
        { PLAINTEXTKEYBLOB, CUR_BLOB_VERSION, 0, CALG_AES_128 },
        16,
        { 0 }
    };

    memcpy(blob.key, AES_KEY, 16);

    return CryptImportKey(
        hProv,
        (BYTE*)&blob,
        sizeof(blob),
        0,
        0,
        &hKey
    );
}

// 解密注册码
std::string DecodeLicense(const char* license)
{
    BYTE buf[64] = {};
    int idx = 0;

    char tmp[128];
    strcpy(tmp, license);

    // 数字分组 → 二进制
    for (char* p = strtok(tmp, "-"); p; p = strtok(NULL, "-"))
    {
        WORD v = (WORD)atoi(p);
        buf[idx++] = (BYTE)(v >> 8);
        buf[idx++] = (BYTE)(v & 0xFF);
    }

    HCRYPTPROV hProv = 0;
    HCRYPTKEY hKey = 0;
    CryptAcquireContextA(&hProv, NULL, NULL,
        PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
    ImportAESKey(hProv, hKey);

    DWORD len = idx;
    CryptDecrypt(hKey, 0, TRUE, 0, buf, &len);

    CryptDestroyKey(hKey);
    CryptReleaseContext(hProv, 0);

    return std::string((char*)buf, len);
}





bool ReadLicenseFromRegistry(char* outBuf, DWORD bufSize)
{
    HKEY hKey;
    const char* subKey = "Software\\YourCompany\\YourProduct";

    if (RegOpenKeyExA(
        HKEY_CURRENT_USER,
        subKey,
        0,
        KEY_READ,
        &hKey) != ERROR_SUCCESS)
    {
        return false;
    }

    DWORD type = REG_SZ;
    DWORD size = bufSize;

    LONG ret = RegQueryValueExA(
        hKey,
        "License",
        NULL,
        &type,
        (BYTE*)outBuf,
        &size
    );

    RegCloseKey(hKey);
    return ret == ERROR_SUCCESS;
}


//int Mymain()
//{
//
//
//    char license[128];
//
//
//    if (!ReadLicenseFromRegistry(license, sizeof(license)))
//    {
//        MessageBoxA(0, "注册码无效!", "提示", MB_OK);
//        return 0;
//    }
//
//    MessageBoxA(0, license, "注册码", MB_OK);
//    std::string plain = DecodeLicense(license);
//
//    size_t pos = plain.find('|');
//    if (pos == std::string::npos)
//    {
//        MessageBoxA(0, "注册码无效!", "提示", MB_OK);
//        return 0;
//    }
//
//    std::string machineCode = plain.substr(0, pos);
//    std::string expiry = plain.substr(pos + 1);
//
//    printf("\n解密成功\n");
//    printf("机器码: %s\n", machineCode.c_str());
//    printf("到期日: %s-%s-%s\n",
//        expiry.substr(0, 4).c_str(),
//        expiry.substr(4, 2).c_str(),
//        expiry.substr(6, 2).c_str());
//
//    return 0;
//}

int Mymain()
{
    char license[128];

    if (!ReadLicenseFromRegistry(license, sizeof(license)))
    {
        MessageBoxA(NULL, "注册码无效!", "提示", MB_OK | MB_ICONERROR);
        ExitProcess(0);
        return 0;
    }

    std::string plain = DecodeLicense(license);

    size_t pos = plain.find('|');
    if (pos == std::string::npos)
    {
        MessageBoxA(NULL, "注册码无效!", "提示", MB_OK | MB_ICONERROR);
        ExitProcess(0);
        return 0;
    }

    std::string machineCode = plain.substr(0, pos);
    std::string expiry = plain.substr(pos + 1); // YYYYMMDD

    // 解析到期日
    int expYear = atoi(expiry.substr(0, 4).c_str());
    int expMonth = atoi(expiry.substr(4, 2).c_str());
    int expDay = atoi(expiry.substr(6, 2).c_str());

    // 获取本地日期
    SYSTEMTIME st;
    GetLocalTime(&st);

    int today = st.wYear * 10000 + st.wMonth * 100 + st.wDay;
    int expireDay = expYear * 10000 + expMonth * 100 + expDay;

    char msg[256];

    if (today > expireDay)
    {
        sprintf(msg,
            "授权已过期!\n\n到期时间:%04d-%02d-%02d",
            expYear, expMonth, expDay);

        MessageBoxA(NULL, msg, "授权过期", MB_OK | MB_ICONERROR);
        ExitProcess(0);
        return 0;
    }
    else
    {
        sprintf(msg,
            "授权有效 \n\n到期时间:%04d-%02d-%02d",
            expYear, expMonth, expDay);

        MessageBoxA(NULL, msg, "授权信息", MB_OK | MB_ICONINFORMATION);
    }

    return 1;
}


// 导出函数供外部调用
extern "C" __declspec(dllexport) void EnableHook()
{
    MessageBoxA(NULL, "11", "22", MB_OK);
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        Mymain();
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
请登录后发表评论

    没有回复内容