如何利用WinApi读取经disitool注入的证书附加数据?
读取disitool注入到签名区域的自定义数据方法
核心思路
disitool的--paddata参数会将自定义数据附加到PE文件的证书签名区域末尾,并更新签名哈希。要读取这段数据,需要解析PE文件结构定位到证书区域,再从中查找目标字符串。
具体实现步骤(以C语言为例)
获取自身可执行文件路径
通过GetModuleFileName获取当前程序的完整路径,用于打开自身文件。解析PE文件头
依次读取并验证IMAGE_DOS_HEADER和IMAGE_NT_HEADERS,定位到PE文件的核心结构。定位证书区域
从OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]中获取证书区域的文件偏移(VirtualAddress字段,证书区域不属于任何节区,该值直接对应文件偏移)和总大小(Size字段)。读取证书区域数据
根据偏移和大小读取整个证书区域的二进制数据,在其中查找注入的自定义字符串(如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
相关产品推荐
相关产品推荐

