1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
| #include <windows.h>
#include <wintrust.h>
#include <stdio.h>
// 获取安全目录项(兼容 x86 和 x64)
BOOL GetSecurityDirectoryEntry(
LPBYTE map,
PIMAGE_DATA_DIRECTORY* securityDir,
PDWORD securitySize)
{
*securityDir = nullptr;
*securitySize = 0;
auto dosHeader = (PIMAGE_DOS_HEADER)map;
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
return FALSE;
auto headers = (PIMAGE_NT_HEADERS)(map + dosHeader->e_lfanew);
if (headers->Signature != IMAGE_NT_SIGNATURE)
return FALSE;
// 判断是 x86 还是 x64
WORD magic = headers->OptionalHeader.Magic;
if (magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
{
// x86 架构
auto headers32 = (PIMAGE_NT_HEADERS32)(map + dosHeader->e_lfanew);
if (headers32->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_SECURITY)
{
*securityDir = &headers32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];
*securitySize = headers32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
}
}
else if (magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
// x64 架构
auto headers64 = (PIMAGE_NT_HEADERS64)(map + dosHeader->e_lfanew);
if (headers64->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_SECURITY)
{
*securityDir = &headers64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];
*securitySize = headers64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
}
}
else
{
return FALSE;
}
// 验证安全目录是否有效
if (*securityDir && (*securityDir)->VirtualAddress != 0 && (*securityDir)->Size != 0)
{
return TRUE;
}
return FALSE;
}
// 读取附加在签名后的数据
void ReadAuthenticodeTail(PCWSTR path, LPBYTE* tailData, LPDWORD tailSize)
{
*tailData = nullptr;
*tailSize = 0;
PIMAGE_DATA_DIRECTORY securityDir = nullptr;
DWORD securitySize = 0;
// 打开文件并映射到内存
auto file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
if (file == INVALID_HANDLE_VALUE) return;
auto mapping = CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr);
if (!mapping) {
CloseHandle(file);
return;
}
auto map = (LPBYTE)MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
if (!map) {
CloseHandle(mapping);
CloseHandle(file);
return;
}
// 获取安全目录项
if (GetSecurityDirectoryEntry(map, &securityDir, &securitySize))
{
// 注意:Certificate Table Entry 的 VirtualAddress 实际是文件偏移,不是 RVA
auto va = securityDir->VirtualAddress;
// 验证偏移是否在文件范围内
if (va + securitySize > GetFileSize(file, nullptr))
{
wprintf(L"Security Directory extends beyond file size.\n");
}
else
{
auto cert = (LPWIN_CERTIFICATE)(map + va);
wprintf(L"Revision: %u\n", cert->wRevision);
wprintf(L"Certificate Type: %u\n", cert->wCertificateType);
wprintf(L"Certificate Length: %u\n", cert->dwLength);
wprintf(L"Size of Directory Entry: %u\n", securitySize);
// 检查是否为 Authenticode 签名,且有附加数据
if (cert->wRevision == WIN_CERT_REVISION_2_0 &&
cert->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA &&
cert->dwLength < securitySize)
{
// 读取签名后的附加数据
*tailSize = securitySize - cert->dwLength;
*tailData = new BYTE[*tailSize];
if (*tailData)
{
CopyMemory(*tailData, map + va + cert->dwLength, *tailSize);
}
else
{
*tailSize = 0;
wprintf(L"Error: Memory allocation failed.\n");
}
}
}
}
UnmapViewOfFile(map);
CloseHandle(mapping);
CloseHandle(file);
}
int main()
{
LPBYTE tail;
DWORD size;
wchar_t path[MAX_PATH];
GetModuleFileName(NULL, path, MAX_PATH);
ReadAuthenticodeTail(path, &tail, &size);
if (tail)
{
wprintf(L"Successfully read %u bytes of tail data.\n", size);
// 在此处理读取的数据
// ...
delete[] tail;
}
else
{
wprintf(L"Did not find valid Authenticode tail data.\n");
}
return 0;
}
|