Module: wine Branch: master Commit: f5ebe032b08ba87aaaee35f7bda571eb92c67fda URL: http://source.winehq.org/git/wine.git/?a=commit;h=f5ebe032b08ba87aaaee35f7bd...
Author: Owen Rudge orudge@codeweavers.com Date: Thu Dec 3 13:50:58 2009 -0600
imagehlp: Verify magic numbers and pad certificates to 8 byte boundaries.
Includes checks for 64-bit file structure and avoids repeating header checks.
---
dlls/imagehlp/integrity.c | 143 ++++++++++++++++++++++++++++++++++++-------- 1 files changed, 117 insertions(+), 26 deletions(-)
diff --git a/dlls/imagehlp/integrity.c b/dlls/imagehlp/integrity.c index bbec56b..a46c853 100644 --- a/dlls/imagehlp/integrity.c +++ b/dlls/imagehlp/integrity.c @@ -3,6 +3,7 @@ * * Copyright 1998 Patrik Stridvall * Copyright 2003 Mike McCormack + * Copyright 2009 Owen Rudge for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -36,49 +37,129 @@ WINE_DEFAULT_DEBUG_CHANNEL(imagehlp); * http://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt */
+#define HDR_FAIL -1 +#define HDR_NT32 0 +#define HDR_NT64 1 + /*********************************************************************** - * IMAGEHLP_GetSecurityDirOffset (INTERNAL) + * IMAGEHLP_GetNTHeaders (INTERNAL) * - * Read a file's PE header, and return the offset and size of the - * security directory. + * Return the IMAGE_NT_HEADERS for a PE file, after validating magic + * numbers and distinguishing between 32-bit and 64-bit files. */ -static BOOL IMAGEHLP_GetSecurityDirOffset( HANDLE handle, - DWORD *pdwOfs, DWORD *pdwSize ) +static int IMAGEHLP_GetNTHeaders(HANDLE handle, DWORD *pe_offset, IMAGE_NT_HEADERS32 *nt32, IMAGE_NT_HEADERS64 *nt64) { IMAGE_DOS_HEADER dos_hdr; - IMAGE_NT_HEADERS nt_hdr; DWORD count; BOOL r; - IMAGE_DATA_DIRECTORY *sd;
- TRACE("handle %p\n", handle ); + TRACE("handle %p\n", handle); + + if ((!nt32) || (!nt64)) + return HDR_FAIL;
/* read the DOS header */ - count = SetFilePointer( handle, 0, NULL, FILE_BEGIN ); - if( count == INVALID_SET_FILE_POINTER ) - return FALSE; + count = SetFilePointer(handle, 0, NULL, FILE_BEGIN); + + if (count == INVALID_SET_FILE_POINTER) + return HDR_FAIL; + count = 0; - r = ReadFile( handle, &dos_hdr, sizeof dos_hdr, &count, NULL ); - if( !r ) - return FALSE; - if( count != sizeof dos_hdr ) - return FALSE; + + r = ReadFile(handle, &dos_hdr, sizeof dos_hdr, &count, NULL); + + if (!r) + return HDR_FAIL; + + if (count != sizeof dos_hdr) + return HDR_FAIL; + + /* verify magic number of 'MZ' */ + if (dos_hdr.e_magic != 0x5A4D) + return HDR_FAIL; + + if (pe_offset != NULL) + *pe_offset = dos_hdr.e_lfanew;
/* read the PE header */ - count = SetFilePointer( handle, dos_hdr.e_lfanew, NULL, FILE_BEGIN ); - if( count == INVALID_SET_FILE_POINTER ) - return FALSE; + count = SetFilePointer(handle, dos_hdr.e_lfanew, NULL, FILE_BEGIN); + + if (count == INVALID_SET_FILE_POINTER) + return HDR_FAIL; + count = 0; - r = ReadFile( handle, &nt_hdr, sizeof nt_hdr, &count, NULL ); - if( !r ) - return FALSE; - if( count != sizeof nt_hdr ) + + r = ReadFile(handle, nt32, sizeof(IMAGE_NT_HEADERS32), &count, NULL); + + if (!r) + return HDR_FAIL; + + if (count != sizeof(IMAGE_NT_HEADERS32)) + return HDR_FAIL; + + /* verify NT signature */ + if (nt32->Signature != IMAGE_NT_SIGNATURE) + return HDR_FAIL; + + /* check if we have a 32-bit or 64-bit executable */ + switch (nt32->OptionalHeader.Magic) + { + case IMAGE_NT_OPTIONAL_HDR32_MAGIC: + return HDR_NT32; + + case IMAGE_NT_OPTIONAL_HDR64_MAGIC: + /* Re-read as 64-bit */ + + count = SetFilePointer(handle, dos_hdr.e_lfanew, NULL, FILE_BEGIN); + + if (count == INVALID_SET_FILE_POINTER) + return HDR_FAIL; + + count = 0; + + r = ReadFile(handle, nt64, sizeof(IMAGE_NT_HEADERS64), &count, NULL); + + if (!r) + return HDR_FAIL; + + if (count != sizeof(IMAGE_NT_HEADERS64)) + return HDR_FAIL; + + /* verify NT signature */ + if (nt64->Signature != IMAGE_NT_SIGNATURE) + return HDR_FAIL; + + return HDR_NT64; + } + + return HDR_FAIL; +} + +/*********************************************************************** + * IMAGEHLP_GetSecurityDirOffset (INTERNAL) + * + * Read a file's PE header, and return the offset and size of the + * security directory. + */ +static BOOL IMAGEHLP_GetSecurityDirOffset( HANDLE handle, + DWORD *pdwOfs, DWORD *pdwSize ) +{ + IMAGE_NT_HEADERS32 nt_hdr32; + IMAGE_NT_HEADERS64 nt_hdr64; + IMAGE_DATA_DIRECTORY *sd; + int ret; + + ret = IMAGEHLP_GetNTHeaders(handle, NULL, &nt_hdr32, &nt_hdr64); + + if (ret == HDR_NT32) + sd = &nt_hdr32.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY]; + else if (ret == HDR_NT64) + sd = &nt_hdr64.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY]; + else return FALSE;
- sd = &nt_hdr.OptionalHeader. - DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY]; + TRACE("ret = %d size = %x addr = %x\n", ret, sd->Size, sd->VirtualAddress);
- TRACE("size = %x addr = %x\n", sd->Size, sd->VirtualAddress); *pdwSize = sd->Size; *pdwOfs = sd->VirtualAddress;
@@ -126,6 +207,11 @@ static BOOL IMAGEHLP_GetCertificateOffset( HANDLE handle, DWORD num,
/* calculate the offset of the next certificate */ offset += len; + + /* padded out to the nearest 8-byte boundary */ + if( len % 8 ) + offset += 8 - (len % 8); + if( offset >= size ) return FALSE; } @@ -207,6 +293,11 @@ BOOL WINAPI ImageEnumerateCertificates(
/* next certificate */ offset += hdr.dwLength; + + /* padded out to the nearest 8-byte boundary */ + if (hdr.dwLength % 8) + offset += 8 - (hdr.dwLength % 8); + index++; }