You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用WinApi读取经disitool注入的证书附加数据?

读取disitool注入到签名区域的自定义数据方法

核心思路

disitool的--paddata参数会将自定义数据附加到PE文件的证书签名区域末尾,并更新签名哈希。要读取这段数据,需要解析PE文件结构定位到证书区域,再从中查找目标字符串。

具体实现步骤(以C语言为例)

  1. 获取自身可执行文件路径
    通过GetModuleFileName获取当前程序的完整路径,用于打开自身文件。

  2. 解析PE文件头
    依次读取并验证IMAGE_DOS_HEADER和IMAGE_NT_HEADERS,定位到PE文件的核心结构。

  3. 定位证书区域
    从OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]中获取证书区域的文件偏移(VirtualAddress字段,证书区域不属于任何节区,该值直接对应文件偏移)和总大小(Size字段)。

  4. 读取证书区域数据
    根据偏移和大小读取整个证书区域的二进制数据,在其中查找注入的自定义字符串(如super_id=)。

完整代码示例

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

int main() {
    char szPath[MAX_PATH];
    // 获取自身可执行文件路径
    if (!GetModuleFileNameA(NULL, szPath, MAX_PATH)) {
        printf("获取程序路径失败\n");
        return 1;
    }

    // 打开文件
    HANDLE hFile = CreateFileA(szPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        printf("打开文件失败\n");
        return 1;
    }

    // 读取DOS头
    IMAGE_DOS_HEADER dosHeader;
    DWORD dwRead;
    if (!ReadFile(hFile, &dosHeader, sizeof(dosHeader), &dwRead, NULL) || dwRead != sizeof(dosHeader) || dosHeader.e_magic != IMAGE_DOS_SIGNATURE) {
        printf("不是有效的PE文件\n");
        CloseHandle(hFile);
        return 1;
    }

    // 读取NT头
    IMAGE_NT_HEADERS ntHeaders;
    if (SetFilePointer(hFile, dosHeader.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
        printf("定位NT头失败\n");
        CloseHandle(hFile);
        return 1;
    }
    if (!ReadFile(hFile, &ntHeaders, sizeof(ntHeaders), &dwRead, NULL) || dwRead != sizeof(ntHeaders) || ntHeaders.Signature != IMAGE_NT_SIGNATURE) {
        printf("读取NT头失败\n");
        CloseHandle(hFile);
        return 1;
    }

    // 获取证书区域信息
    IMAGE_DATA_DIRECTORY securityDir = ntHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];
    if (securityDir.Size == 0) {
        printf("未找到证书签名区域\n");
        CloseHandle(hFile);
        return 1;
    }

    // 读取证书区域数据
    LPBYTE pCertData = (LPBYTE)malloc(securityDir.Size);
    if (!pCertData) {
        printf("内存分配失败\n");
        CloseHandle(hFile);
        return 1;
    }
    if (SetFilePointer(hFile, securityDir.VirtualAddress, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
        printf("定位证书区域失败\n");
        free(pCertData);
        CloseHandle(hFile);
        return 1;
    }
    if (!ReadFile(hFile, pCertData, securityDir.Size, &dwRead, NULL) || dwRead != securityDir.Size) {
        printf("读取证书区域失败\n");
        free(pCertData);
        CloseHandle(hFile);
        return 1;
    }

    // 查找目标字符串
    char* pFoundData = strstr((char*)pCertData, "super_id=");
    if (pFoundData) {
        printf("读取到注入的数据:%s\n", pFoundData);
    } else {
        printf("未找到注入的数据\n");
    }

    // 清理资源
    free(pCertData);
    CloseHandle(hFile);

    return 0;
}

注意事项

  • 如果是64位程序,需将IMAGE_NT_HEADERS替换为IMAGE_NT_HEADERS64,并调整相关结构体的使用。
  • 证书区域包含签名二进制数据,直接通过字符串匹配(strstr)即可定位到注入的明文数据。
  • 确保程序拥有读取自身文件的权限,常规环境下默认具备该权限。

内容的提问来源于stack exchange,提问作者qloq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 03:01:01