PE嵌入式签名检测方法
·
(1)参考wine的代码,微软说的那个方法有些复杂(除非是一些特殊的pe),正常情况下的pe文件,各个节都是紧密排列的有序的,只需跳过checksum security_dir 和security_dir.VA之后的数据就行,当然微软是比较严谨的
/* See https://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt
* for details about the hashing.
*/
static BOOL SOFTPUB_HashPEFile(HANDLE file, HCRYPTHASH hash)
{
DWORD checksum, security_dir;
IMAGE_DOS_HEADER dos_header;
union
{
IMAGE_NT_HEADERS32 nt32;
IMAGE_NT_HEADERS64 nt64;
} nt_header;
IMAGE_DATA_DIRECTORY secdir;
LARGE_INTEGER file_size;
DWORD bytes_read;
BOOL ret;
if (!GetFileSizeEx(file, &file_size))
return FALSE;
SetFilePointer(file, 0, NULL, FILE_BEGIN);
ret = ReadFile(file, &dos_header, sizeof(dos_header), &bytes_read, NULL);
if (!ret || bytes_read != sizeof(dos_header))
return FALSE;
if (dos_header.e_magic != IMAGE_DOS_SIGNATURE)
return FALSE;
if (dos_header.e_lfanew >= 256 * 1024 * 1024) /* see RtlImageNtHeaderEx */
return FALSE;
if (dos_header.e_lfanew + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader.MajorLinkerVersion) > file_size.QuadPart)
return FALSE;
SetFilePointer(file, dos_header.e_lfanew, NULL, FILE_BEGIN);
ret = ReadFile(file, &nt_header, sizeof(nt_header), &bytes_read, NULL);
if (!ret || bytes_read < FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader.Magic) +
sizeof(nt_header.nt32.OptionalHeader.Magic))
return FALSE;
if (nt_header.nt32.Signature != IMAGE_NT_SIGNATURE)
return FALSE;
if (nt_header.nt32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
{
if (bytes_read < sizeof(nt_header.nt32))
return FALSE;
checksum = dos_header.e_lfanew + FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader.CheckSum);
security_dir = dos_header.e_lfanew + FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]);
secdir = nt_header.nt32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];
}
else if (nt_header.nt32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
if (bytes_read < sizeof(nt_header.nt64))
return FALSE;
checksum = dos_header.e_lfanew + FIELD_OFFSET(IMAGE_NT_HEADERS64, OptionalHeader.CheckSum);
security_dir = dos_header.e_lfanew + FIELD_OFFSET(IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]);
secdir = nt_header.nt64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];
}
else
return FALSE;
if (secdir.VirtualAddress < security_dir + sizeof(IMAGE_DATA_DIRECTORY))
return FALSE;
if (secdir.VirtualAddress > file_size.QuadPart)
return FALSE;
if (secdir.VirtualAddress + secdir.Size != file_size.QuadPart)
return FALSE;
if (!hash_file_data( file, 0, checksum, hash )) return FALSE;
if (!hash_file_data( file, checksum + sizeof(DWORD), security_dir, hash )) return FALSE;
if (!hash_file_data( file, security_dir + sizeof(IMAGE_DATA_DIRECTORY), secdir.VirtualAddress, hash ))
return FALSE;
return TRUE;
}
(2)对于签名中的hash 应该提取的oid是 SpcIndirectDataContext的OID应为1.3.6.1.4.1.311.2.1.4,而不是属性中的消息摘要,这个字段如果不好找,那就再签名数据部分搜索hash就行了,只要签名有效并包含hash,可以粗略认为这个PE文件的签名是存在的
更多推荐


所有评论(0)