Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenintegrity.c
Go to the documentation of this file.
00001 /* 00002 * IMAGEHLP library 00003 * 00004 * Copyright 1998 Patrik Stridvall 00005 * Copyright 2003 Mike McCormack 00006 * Copyright 2009 Owen Rudge for CodeWeavers 00007 * Copyright 2010 Juan Lang 00008 * Copyright 2010 Andrey Turkin 00009 * 00010 * This library is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU Lesser General Public 00012 * License as published by the Free Software Foundation; either 00013 * version 2.1 of the License, or (at your option) any later version. 00014 * 00015 * This library is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * Lesser General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU Lesser General Public 00021 * License along with this library; if not, write to the Free Software 00022 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00023 */ 00024 00025 #include <stdarg.h> 00026 00027 #include "windef.h" 00028 #include "winbase.h" 00029 #include "winerror.h" 00030 #include "winternl.h" 00031 #include "winnt.h" 00032 #include "imagehlp.h" 00033 #include "wine/debug.h" 00034 00035 WINE_DEFAULT_DEBUG_CHANNEL(imagehlp); 00036 00037 /* 00038 * These functions are partially documented at: 00039 * http://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt 00040 */ 00041 00042 #define HDR_FAIL -1 00043 #define HDR_NT32 0 00044 #define HDR_NT64 1 00045 00046 /*********************************************************************** 00047 * IMAGEHLP_GetNTHeaders (INTERNAL) 00048 * 00049 * Return the IMAGE_NT_HEADERS for a PE file, after validating magic 00050 * numbers and distinguishing between 32-bit and 64-bit files. 00051 */ 00052 static int IMAGEHLP_GetNTHeaders(HANDLE handle, DWORD *pe_offset, IMAGE_NT_HEADERS32 *nt32, IMAGE_NT_HEADERS64 *nt64) 00053 { 00054 IMAGE_DOS_HEADER dos_hdr; 00055 DWORD count; 00056 BOOL r; 00057 00058 TRACE("handle %p\n", handle); 00059 00060 if ((!nt32) || (!nt64)) 00061 return HDR_FAIL; 00062 00063 /* read the DOS header */ 00064 count = SetFilePointer(handle, 0, NULL, FILE_BEGIN); 00065 00066 if (count == INVALID_SET_FILE_POINTER) 00067 return HDR_FAIL; 00068 00069 count = 0; 00070 00071 r = ReadFile(handle, &dos_hdr, sizeof dos_hdr, &count, NULL); 00072 00073 if (!r) 00074 return HDR_FAIL; 00075 00076 if (count != sizeof dos_hdr) 00077 return HDR_FAIL; 00078 00079 /* verify magic number of 'MZ' */ 00080 if (dos_hdr.e_magic != IMAGE_DOS_SIGNATURE) 00081 return HDR_FAIL; 00082 00083 if (pe_offset != NULL) 00084 *pe_offset = dos_hdr.e_lfanew; 00085 00086 /* read the PE header */ 00087 count = SetFilePointer(handle, dos_hdr.e_lfanew, NULL, FILE_BEGIN); 00088 00089 if (count == INVALID_SET_FILE_POINTER) 00090 return HDR_FAIL; 00091 00092 count = 0; 00093 00094 r = ReadFile(handle, nt32, sizeof(IMAGE_NT_HEADERS32), &count, NULL); 00095 00096 if (!r) 00097 return HDR_FAIL; 00098 00099 if (count != sizeof(IMAGE_NT_HEADERS32)) 00100 return HDR_FAIL; 00101 00102 /* verify NT signature */ 00103 if (nt32->Signature != IMAGE_NT_SIGNATURE) 00104 return HDR_FAIL; 00105 00106 /* check if we have a 32-bit or 64-bit executable */ 00107 switch (nt32->OptionalHeader.Magic) 00108 { 00109 case IMAGE_NT_OPTIONAL_HDR32_MAGIC: 00110 return HDR_NT32; 00111 00112 case IMAGE_NT_OPTIONAL_HDR64_MAGIC: 00113 /* Re-read as 64-bit */ 00114 00115 count = SetFilePointer(handle, dos_hdr.e_lfanew, NULL, FILE_BEGIN); 00116 00117 if (count == INVALID_SET_FILE_POINTER) 00118 return HDR_FAIL; 00119 00120 count = 0; 00121 00122 r = ReadFile(handle, nt64, sizeof(IMAGE_NT_HEADERS64), &count, NULL); 00123 00124 if (!r) 00125 return HDR_FAIL; 00126 00127 if (count != sizeof(IMAGE_NT_HEADERS64)) 00128 return HDR_FAIL; 00129 00130 /* verify NT signature */ 00131 if (nt64->Signature != IMAGE_NT_SIGNATURE) 00132 return HDR_FAIL; 00133 00134 return HDR_NT64; 00135 } 00136 00137 return HDR_FAIL; 00138 } 00139 00140 /*********************************************************************** 00141 * IMAGEHLP_GetSecurityDirOffset (INTERNAL) 00142 * 00143 * Read a file's PE header, and return the offset and size of the 00144 * security directory. 00145 */ 00146 static BOOL IMAGEHLP_GetSecurityDirOffset( HANDLE handle, 00147 DWORD *pdwOfs, DWORD *pdwSize ) 00148 { 00149 IMAGE_NT_HEADERS32 nt_hdr32; 00150 IMAGE_NT_HEADERS64 nt_hdr64; 00151 IMAGE_DATA_DIRECTORY *sd; 00152 int ret; 00153 00154 ret = IMAGEHLP_GetNTHeaders(handle, NULL, &nt_hdr32, &nt_hdr64); 00155 00156 if (ret == HDR_NT32) 00157 sd = &nt_hdr32.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY]; 00158 else if (ret == HDR_NT64) 00159 sd = &nt_hdr64.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY]; 00160 else 00161 return FALSE; 00162 00163 TRACE("ret = %d size = %x addr = %x\n", ret, sd->Size, sd->VirtualAddress); 00164 00165 *pdwSize = sd->Size; 00166 *pdwOfs = sd->VirtualAddress; 00167 00168 return TRUE; 00169 } 00170 00171 /*********************************************************************** 00172 * IMAGEHLP_SetSecurityDirOffset (INTERNAL) 00173 * 00174 * Read a file's PE header, and update the offset and size of the 00175 * security directory. 00176 */ 00177 static BOOL IMAGEHLP_SetSecurityDirOffset(HANDLE handle, 00178 DWORD dwOfs, DWORD dwSize) 00179 { 00180 IMAGE_NT_HEADERS32 nt_hdr32; 00181 IMAGE_NT_HEADERS64 nt_hdr64; 00182 IMAGE_DATA_DIRECTORY *sd; 00183 int ret, nt_hdr_size = 0; 00184 DWORD pe_offset; 00185 void *nt_hdr; 00186 DWORD count; 00187 BOOL r; 00188 00189 ret = IMAGEHLP_GetNTHeaders(handle, &pe_offset, &nt_hdr32, &nt_hdr64); 00190 00191 if (ret == HDR_NT32) 00192 { 00193 sd = &nt_hdr32.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY]; 00194 00195 nt_hdr = &nt_hdr32; 00196 nt_hdr_size = sizeof(IMAGE_NT_HEADERS32); 00197 } 00198 else if (ret == HDR_NT64) 00199 { 00200 sd = &nt_hdr64.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY]; 00201 00202 nt_hdr = &nt_hdr64; 00203 nt_hdr_size = sizeof(IMAGE_NT_HEADERS64); 00204 } 00205 else 00206 return FALSE; 00207 00208 sd->Size = dwSize; 00209 sd->VirtualAddress = dwOfs; 00210 00211 TRACE("size = %x addr = %x\n", sd->Size, sd->VirtualAddress); 00212 00213 /* write the header back again */ 00214 count = SetFilePointer(handle, pe_offset, NULL, FILE_BEGIN); 00215 00216 if (count == INVALID_SET_FILE_POINTER) 00217 return FALSE; 00218 00219 count = 0; 00220 00221 r = WriteFile(handle, nt_hdr, nt_hdr_size, &count, NULL); 00222 00223 if (!r) 00224 return FALSE; 00225 00226 if (count != nt_hdr_size) 00227 return FALSE; 00228 00229 return TRUE; 00230 } 00231 00232 /*********************************************************************** 00233 * IMAGEHLP_GetCertificateOffset (INTERNAL) 00234 * 00235 * Read a file's PE header, and return the offset and size of the 00236 * security directory. 00237 */ 00238 static BOOL IMAGEHLP_GetCertificateOffset( HANDLE handle, DWORD num, 00239 DWORD *pdwOfs, DWORD *pdwSize ) 00240 { 00241 DWORD size, count, offset, len, sd_VirtualAddr; 00242 BOOL r; 00243 00244 r = IMAGEHLP_GetSecurityDirOffset( handle, &sd_VirtualAddr, &size ); 00245 if( !r ) 00246 return FALSE; 00247 00248 offset = 0; 00249 /* take the n'th certificate */ 00250 while( 1 ) 00251 { 00252 /* read the length of the current certificate */ 00253 count = SetFilePointer( handle, sd_VirtualAddr + offset, 00254 NULL, FILE_BEGIN ); 00255 if( count == INVALID_SET_FILE_POINTER ) 00256 return FALSE; 00257 r = ReadFile( handle, &len, sizeof len, &count, NULL ); 00258 if( !r ) 00259 return FALSE; 00260 if( count != sizeof len ) 00261 return FALSE; 00262 00263 /* check the certificate is not too big or too small */ 00264 if( len < sizeof len ) 00265 return FALSE; 00266 if( len > (size-offset) ) 00267 return FALSE; 00268 if( !num-- ) 00269 break; 00270 00271 /* calculate the offset of the next certificate */ 00272 offset += len; 00273 00274 /* padded out to the nearest 8-byte boundary */ 00275 if( len % 8 ) 00276 offset += 8 - (len % 8); 00277 00278 if( offset >= size ) 00279 return FALSE; 00280 } 00281 00282 *pdwOfs = sd_VirtualAddr + offset; 00283 *pdwSize = len; 00284 00285 TRACE("len = %x addr = %x\n", len, sd_VirtualAddr + offset); 00286 00287 return TRUE; 00288 } 00289 00290 /*********************************************************************** 00291 * IMAGEHLP_RecalculateChecksum (INTERNAL) 00292 * 00293 * Update the NT header checksum for the specified file. 00294 */ 00295 static BOOL IMAGEHLP_RecalculateChecksum(HANDLE handle) 00296 { 00297 DWORD FileLength, count, HeaderSum, pe_offset, nt_hdr_size; 00298 IMAGE_NT_HEADERS32 nt_hdr32; 00299 IMAGE_NT_HEADERS64 nt_hdr64; 00300 LPVOID BaseAddress; 00301 HANDLE hMapping; 00302 DWORD *CheckSum; 00303 void *nt_hdr; 00304 int ret; 00305 BOOL r; 00306 00307 TRACE("handle %p\n", handle); 00308 00309 ret = IMAGEHLP_GetNTHeaders(handle, &pe_offset, &nt_hdr32, &nt_hdr64); 00310 00311 if (ret == HDR_NT32) 00312 { 00313 CheckSum = &nt_hdr32.OptionalHeader.CheckSum; 00314 00315 nt_hdr = &nt_hdr32; 00316 nt_hdr_size = sizeof(IMAGE_NT_HEADERS32); 00317 } 00318 else if (ret == HDR_NT64) 00319 { 00320 CheckSum = &nt_hdr64.OptionalHeader.CheckSum; 00321 00322 nt_hdr = &nt_hdr64; 00323 nt_hdr_size = sizeof(IMAGE_NT_HEADERS64); 00324 } 00325 else 00326 return FALSE; 00327 00328 hMapping = CreateFileMappingW(handle, NULL, PAGE_READONLY, 0, 0, NULL); 00329 00330 if (!hMapping) 00331 return FALSE; 00332 00333 BaseAddress = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); 00334 00335 if (!BaseAddress) 00336 { 00337 CloseHandle(hMapping); 00338 return FALSE; 00339 } 00340 00341 FileLength = GetFileSize(handle, NULL); 00342 00343 *CheckSum = 0; 00344 CheckSumMappedFile(BaseAddress, FileLength, &HeaderSum, CheckSum); 00345 00346 UnmapViewOfFile(BaseAddress); 00347 CloseHandle(hMapping); 00348 00349 if (*CheckSum) 00350 { 00351 /* write the header back again */ 00352 count = SetFilePointer(handle, pe_offset, NULL, FILE_BEGIN); 00353 00354 if (count == INVALID_SET_FILE_POINTER) 00355 return FALSE; 00356 00357 count = 0; 00358 00359 r = WriteFile(handle, nt_hdr, nt_hdr_size, &count, NULL); 00360 00361 if (!r) 00362 return FALSE; 00363 00364 if (count != nt_hdr_size) 00365 return FALSE; 00366 00367 return TRUE; 00368 } 00369 00370 return FALSE; 00371 } 00372 00373 /*********************************************************************** 00374 * ImageAddCertificate (IMAGEHLP.@) 00375 * 00376 * Adds the specified certificate to the security directory of 00377 * open PE file. 00378 */ 00379 00380 BOOL WINAPI ImageAddCertificate( 00381 HANDLE FileHandle, LPWIN_CERTIFICATE Certificate, PDWORD Index) 00382 { 00383 DWORD size = 0, count = 0, offset = 0, sd_VirtualAddr = 0, index = 0; 00384 WIN_CERTIFICATE hdr; 00385 const size_t cert_hdr_size = sizeof hdr - sizeof hdr.bCertificate; 00386 BOOL r; 00387 00388 TRACE("(%p, %p, %p)\n", FileHandle, Certificate, Index); 00389 00390 r = IMAGEHLP_GetSecurityDirOffset(FileHandle, &sd_VirtualAddr, &size); 00391 00392 /* If we've already got a security directory, find the end of it */ 00393 if ((r) && (sd_VirtualAddr != 0)) 00394 { 00395 /* Check if the security directory is at the end of the file. 00396 If not, we should probably relocate it. */ 00397 if (GetFileSize(FileHandle, NULL) != sd_VirtualAddr + size) 00398 { 00399 FIXME("Security directory already present but not located at EOF, not adding certificate\n"); 00400 00401 SetLastError(ERROR_NOT_SUPPORTED); 00402 return FALSE; 00403 } 00404 00405 while (offset < size) 00406 { 00407 /* read the length of the current certificate */ 00408 count = SetFilePointer (FileHandle, sd_VirtualAddr + offset, 00409 NULL, FILE_BEGIN); 00410 00411 if (count == INVALID_SET_FILE_POINTER) 00412 return FALSE; 00413 00414 r = ReadFile(FileHandle, &hdr, cert_hdr_size, &count, NULL); 00415 00416 if (!r) 00417 return FALSE; 00418 00419 if (count != cert_hdr_size) 00420 return FALSE; 00421 00422 /* check the certificate is not too big or too small */ 00423 if (hdr.dwLength < cert_hdr_size) 00424 return FALSE; 00425 00426 if (hdr.dwLength > (size-offset)) 00427 return FALSE; 00428 00429 /* next certificate */ 00430 offset += hdr.dwLength; 00431 00432 /* padded out to the nearest 8-byte boundary */ 00433 if (hdr.dwLength % 8) 00434 offset += 8 - (hdr.dwLength % 8); 00435 00436 index++; 00437 } 00438 00439 count = SetFilePointer (FileHandle, sd_VirtualAddr + offset, NULL, FILE_BEGIN); 00440 00441 if (count == INVALID_SET_FILE_POINTER) 00442 return FALSE; 00443 } 00444 else 00445 { 00446 sd_VirtualAddr = SetFilePointer(FileHandle, 0, NULL, FILE_END); 00447 00448 if (sd_VirtualAddr == INVALID_SET_FILE_POINTER) 00449 return FALSE; 00450 } 00451 00452 /* Write the certificate to the file */ 00453 r = WriteFile(FileHandle, Certificate, Certificate->dwLength, &count, NULL); 00454 00455 if (!r) 00456 return FALSE; 00457 00458 /* Pad out if necessary */ 00459 if (Certificate->dwLength % 8) 00460 { 00461 char null[8]; 00462 00463 ZeroMemory(null, 8); 00464 WriteFile(FileHandle, null, 8 - (Certificate->dwLength % 8), &count, NULL); 00465 00466 size += 8 - (Certificate->dwLength % 8); 00467 } 00468 00469 size += Certificate->dwLength; 00470 00471 /* Update the security directory offset and size */ 00472 if (!IMAGEHLP_SetSecurityDirOffset(FileHandle, sd_VirtualAddr, size)) 00473 return FALSE; 00474 00475 if (!IMAGEHLP_RecalculateChecksum(FileHandle)) 00476 return FALSE; 00477 00478 if(Index) 00479 *Index = index; 00480 return TRUE; 00481 } 00482 00483 /*********************************************************************** 00484 * ImageEnumerateCertificates (IMAGEHLP.@) 00485 */ 00486 BOOL WINAPI ImageEnumerateCertificates( 00487 HANDLE handle, WORD TypeFilter, PDWORD CertificateCount, 00488 PDWORD Indices, DWORD IndexCount) 00489 { 00490 DWORD size, count, offset, sd_VirtualAddr, index; 00491 WIN_CERTIFICATE hdr; 00492 const size_t cert_hdr_size = sizeof hdr - sizeof hdr.bCertificate; 00493 BOOL r; 00494 00495 TRACE("%p %hd %p %p %d\n", 00496 handle, TypeFilter, CertificateCount, Indices, IndexCount); 00497 00498 r = IMAGEHLP_GetSecurityDirOffset( handle, &sd_VirtualAddr, &size ); 00499 if( !r ) 00500 return FALSE; 00501 00502 offset = 0; 00503 index = 0; 00504 *CertificateCount = 0; 00505 while( offset < size ) 00506 { 00507 /* read the length of the current certificate */ 00508 count = SetFilePointer( handle, sd_VirtualAddr + offset, 00509 NULL, FILE_BEGIN ); 00510 if( count == INVALID_SET_FILE_POINTER ) 00511 return FALSE; 00512 r = ReadFile( handle, &hdr, cert_hdr_size, &count, NULL ); 00513 if( !r ) 00514 return FALSE; 00515 if( count != cert_hdr_size ) 00516 return FALSE; 00517 00518 TRACE("Size = %08x id = %08hx\n", 00519 hdr.dwLength, hdr.wCertificateType ); 00520 00521 /* check the certificate is not too big or too small */ 00522 if( hdr.dwLength < cert_hdr_size ) 00523 return FALSE; 00524 if( hdr.dwLength > (size-offset) ) 00525 return FALSE; 00526 00527 if( (TypeFilter == CERT_SECTION_TYPE_ANY) || 00528 (TypeFilter == hdr.wCertificateType) ) 00529 { 00530 (*CertificateCount)++; 00531 if(Indices && *CertificateCount <= IndexCount) 00532 *Indices++ = index; 00533 } 00534 00535 /* next certificate */ 00536 offset += hdr.dwLength; 00537 00538 /* padded out to the nearest 8-byte boundary */ 00539 if (hdr.dwLength % 8) 00540 offset += 8 - (hdr.dwLength % 8); 00541 00542 index++; 00543 } 00544 00545 return TRUE; 00546 } 00547 00548 /*********************************************************************** 00549 * ImageGetCertificateData (IMAGEHLP.@) 00550 * 00551 * FIXME: not sure that I'm dealing with the Index the right way 00552 */ 00553 BOOL WINAPI ImageGetCertificateData( 00554 HANDLE handle, DWORD Index, 00555 LPWIN_CERTIFICATE Certificate, PDWORD RequiredLength) 00556 { 00557 DWORD r, offset, ofs, size, count; 00558 00559 TRACE("%p %d %p %p\n", handle, Index, Certificate, RequiredLength); 00560 00561 if( !RequiredLength) 00562 { 00563 SetLastError( ERROR_INVALID_PARAMETER ); 00564 return FALSE; 00565 } 00566 00567 if( !IMAGEHLP_GetCertificateOffset( handle, Index, &ofs, &size ) ) 00568 return FALSE; 00569 00570 if( *RequiredLength < size ) 00571 { 00572 *RequiredLength = size; 00573 SetLastError( ERROR_INSUFFICIENT_BUFFER ); 00574 return FALSE; 00575 } 00576 00577 if( !Certificate ) 00578 { 00579 SetLastError( ERROR_INVALID_PARAMETER ); 00580 return FALSE; 00581 } 00582 00583 *RequiredLength = size; 00584 00585 offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN ); 00586 if( offset == INVALID_SET_FILE_POINTER ) 00587 return FALSE; 00588 00589 r = ReadFile( handle, Certificate, size, &count, NULL ); 00590 if( !r ) 00591 return FALSE; 00592 if( count != size ) 00593 return FALSE; 00594 00595 TRACE("OK\n"); 00596 SetLastError( NO_ERROR ); 00597 00598 return TRUE; 00599 } 00600 00601 /*********************************************************************** 00602 * ImageGetCertificateHeader (IMAGEHLP.@) 00603 */ 00604 BOOL WINAPI ImageGetCertificateHeader( 00605 HANDLE handle, DWORD index, LPWIN_CERTIFICATE pCert) 00606 { 00607 DWORD r, offset, ofs, size, count; 00608 const size_t cert_hdr_size = sizeof *pCert - sizeof pCert->bCertificate; 00609 00610 TRACE("%p %d %p\n", handle, index, pCert); 00611 00612 if( !IMAGEHLP_GetCertificateOffset( handle, index, &ofs, &size ) ) 00613 return FALSE; 00614 00615 if( size < cert_hdr_size ) 00616 return FALSE; 00617 00618 offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN ); 00619 if( offset == INVALID_SET_FILE_POINTER ) 00620 return FALSE; 00621 00622 r = ReadFile( handle, pCert, cert_hdr_size, &count, NULL ); 00623 if( !r ) 00624 return FALSE; 00625 if( count != cert_hdr_size ) 00626 return FALSE; 00627 00628 TRACE("OK\n"); 00629 00630 return TRUE; 00631 } 00632 00633 /* Finds the section named section in the array of IMAGE_SECTION_HEADERs hdr. If 00634 * found, returns the offset to the section. Otherwise returns 0. If the section 00635 * is found, optionally returns the size of the section (in size) and the base 00636 * address of the section (in base.) 00637 */ 00638 static DWORD IMAGEHLP_GetSectionOffset( IMAGE_SECTION_HEADER *hdr, 00639 DWORD num_sections, LPCSTR section, PDWORD size, PDWORD base ) 00640 { 00641 DWORD i, offset = 0; 00642 00643 for( i = 0; !offset && i < num_sections; i++, hdr++ ) 00644 { 00645 if( !memcmp( hdr->Name, section, strlen(section) ) ) 00646 { 00647 offset = hdr->PointerToRawData; 00648 if( size ) 00649 *size = hdr->SizeOfRawData; 00650 if( base ) 00651 *base = hdr->VirtualAddress; 00652 } 00653 } 00654 return offset; 00655 } 00656 00657 /* Calls DigestFunction e bytes at offset offset from the file mapped at map. 00658 * Returns the return value of DigestFunction, or FALSE if the data is not available. 00659 */ 00660 static BOOL IMAGEHLP_ReportSectionFromOffset( DWORD offset, DWORD size, 00661 BYTE *map, DWORD fileSize, DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle ) 00662 { 00663 if( offset + size > fileSize ) 00664 { 00665 SetLastError(ERROR_INVALID_PARAMETER); 00666 return FALSE; 00667 } 00668 return DigestFunction( DigestHandle, map + offset, size ); 00669 } 00670 00671 /* Finds the section named section among the IMAGE_SECTION_HEADERs in 00672 * section_headers and calls DigestFunction for this section. Returns 00673 * the return value from DigestFunction, or FALSE if the data could not be read. 00674 */ 00675 static BOOL IMAGEHLP_ReportSection( IMAGE_SECTION_HEADER *section_headers, 00676 DWORD num_sections, LPCSTR section, BYTE *map, DWORD fileSize, 00677 DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle ) 00678 { 00679 DWORD offset, size = 0; 00680 00681 offset = IMAGEHLP_GetSectionOffset( section_headers, num_sections, section, 00682 &size, NULL ); 00683 if( !offset ) 00684 return FALSE; 00685 return IMAGEHLP_ReportSectionFromOffset( offset, size, map, fileSize, 00686 DigestFunction, DigestHandle ); 00687 } 00688 00689 /* Calls DigestFunction for all sections with the IMAGE_SCN_CNT_CODE flag set. 00690 * Returns the return value from * DigestFunction, or FALSE if a section could not be read. 00691 */ 00692 static BOOL IMAGEHLP_ReportCodeSections( IMAGE_SECTION_HEADER *hdr, DWORD num_sections, 00693 BYTE *map, DWORD fileSize, DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle ) 00694 { 00695 DWORD i; 00696 BOOL ret = TRUE; 00697 00698 for( i = 0; ret && i < num_sections; i++, hdr++ ) 00699 { 00700 if( hdr->Characteristics & IMAGE_SCN_CNT_CODE ) 00701 ret = IMAGEHLP_ReportSectionFromOffset( hdr->PointerToRawData, 00702 hdr->SizeOfRawData, map, fileSize, DigestFunction, DigestHandle ); 00703 } 00704 return ret; 00705 } 00706 00707 /* Reports the import section from the file FileHandle. If 00708 * CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO is set in DigestLevel, reports the entire 00709 * import section. 00710 * FIXME: if it's not set, the function currently fails. 00711 */ 00712 static BOOL IMAGEHLP_ReportImportSection( IMAGE_SECTION_HEADER *hdr, 00713 DWORD num_sections, BYTE *map, DWORD fileSize, DWORD DigestLevel, 00714 DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle ) 00715 { 00716 BOOL ret = FALSE; 00717 DWORD offset, size, base; 00718 00719 /* Get import data */ 00720 offset = IMAGEHLP_GetSectionOffset( hdr, num_sections, ".idata", &size, 00721 &base ); 00722 if( !offset ) 00723 return FALSE; 00724 00725 /* If CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO is set, the entire 00726 * section is reported. Otherwise, the debug info section is 00727 * decoded and reported piecemeal. See tests. However, I haven't been 00728 * able to figure out how the native implementation decides which values 00729 * to report. Either it's buggy or my understanding is flawed. 00730 */ 00731 if( DigestLevel & CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO ) 00732 ret = IMAGEHLP_ReportSectionFromOffset( offset, size, map, fileSize, 00733 DigestFunction, DigestHandle ); 00734 else 00735 { 00736 FIXME("not supported except for CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO\n"); 00737 SetLastError(ERROR_INVALID_PARAMETER); 00738 ret = FALSE; 00739 } 00740 00741 return ret; 00742 } 00743 00744 /*********************************************************************** 00745 * ImageGetDigestStream (IMAGEHLP.@) 00746 * 00747 * Gets a stream of bytes from a PE file over which a hash might be computed to 00748 * verify that the image has not changed. Useful for creating a certificate to 00749 * be added to the file with ImageAddCertificate. 00750 * 00751 * PARAMS 00752 * FileHandle [In] File for which to return a stream. 00753 * DigestLevel [In] Flags to control which portions of the file to return. 00754 * 0 is allowed, as is any combination of: 00755 * CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO: reports the entire 00756 * import section rather than selected portions of it. 00757 * CERT_PE_IMAGE_DIGEST_DEBUG_INFO: reports the debug section. 00758 * CERT_PE_IMAGE_DIGEST_RESOURCES: reports the resources 00759 section. 00760 * DigestFunction [In] Callback function. 00761 * DigestHandle [In] Handle passed as first parameter to DigestFunction. 00762 * 00763 * RETURNS 00764 * TRUE if successful. 00765 * FALSE if unsuccessful. GetLastError returns more about the error. 00766 * 00767 * NOTES 00768 * Only supports 32-bit PE files, not tested with any other format. 00769 * Reports data in the following order: 00770 * 1. The file headers are reported first 00771 * 2. Any code sections are reported next. 00772 * 3. The data (".data" and ".rdata") sections are reported next. 00773 * 4. The import section is reported next. 00774 * 5. If CERT_PE_IMAGE_DIGEST_DEBUG_INFO is set in DigestLevel, the debug section is 00775 * reported next. 00776 * 6. If CERT_PE_IMAGE_DIGEST_RESOURCES is set in DigestLevel, the resources section 00777 * is reported next. 00778 * 00779 * BUGS 00780 * CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO must be specified, returns an error if not. 00781 */ 00782 BOOL WINAPI ImageGetDigestStream( 00783 HANDLE FileHandle, DWORD DigestLevel, 00784 DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle) 00785 { 00786 DWORD error = 0; 00787 BOOL ret = FALSE; 00788 DWORD offset, size, num_sections, fileSize; 00789 HANDLE hMap = INVALID_HANDLE_VALUE; 00790 BYTE *map = NULL; 00791 IMAGE_DOS_HEADER *dos_hdr; 00792 IMAGE_NT_HEADERS *nt_hdr; 00793 IMAGE_SECTION_HEADER *section_headers; 00794 00795 TRACE("(%p, %d, %p, %p)\n", FileHandle, DigestLevel, DigestFunction, 00796 DigestHandle); 00797 00798 /* Get the file size */ 00799 if( !FileHandle ) 00800 goto invalid_parameter; 00801 fileSize = GetFileSize( FileHandle, NULL ); 00802 if(fileSize == INVALID_FILE_SIZE ) 00803 goto invalid_parameter; 00804 00805 /* map file */ 00806 hMap = CreateFileMappingW( FileHandle, NULL, PAGE_READONLY, 0, 0, NULL ); 00807 if( hMap == INVALID_HANDLE_VALUE ) 00808 goto invalid_parameter; 00809 map = MapViewOfFile( hMap, FILE_MAP_COPY, 0, 0, 0 ); 00810 if( !map ) 00811 goto invalid_parameter; 00812 00813 /* Read the file header */ 00814 if( fileSize < sizeof(IMAGE_DOS_HEADER) ) 00815 goto invalid_parameter; 00816 dos_hdr = (IMAGE_DOS_HEADER *)map; 00817 00818 if( dos_hdr->e_magic != IMAGE_DOS_SIGNATURE ) 00819 goto invalid_parameter; 00820 offset = dos_hdr->e_lfanew; 00821 if( !offset || offset > fileSize ) 00822 goto invalid_parameter; 00823 ret = DigestFunction( DigestHandle, map, offset ); 00824 if( !ret ) 00825 goto end; 00826 00827 /* Read the NT header */ 00828 if( offset + sizeof(IMAGE_NT_HEADERS) > fileSize ) 00829 goto invalid_parameter; 00830 nt_hdr = (IMAGE_NT_HEADERS *)(map + offset); 00831 if( nt_hdr->Signature != IMAGE_NT_SIGNATURE ) 00832 goto invalid_parameter; 00833 /* It's clear why the checksum is cleared, but why only these size headers? 00834 */ 00835 nt_hdr->OptionalHeader.SizeOfInitializedData = 0; 00836 nt_hdr->OptionalHeader.SizeOfImage = 0; 00837 nt_hdr->OptionalHeader.CheckSum = 0; 00838 size = sizeof(nt_hdr->Signature) + sizeof(nt_hdr->FileHeader) + 00839 nt_hdr->FileHeader.SizeOfOptionalHeader; 00840 ret = DigestFunction( DigestHandle, map + offset, size ); 00841 if( !ret ) 00842 goto end; 00843 00844 /* Read the section headers */ 00845 offset += size; 00846 num_sections = nt_hdr->FileHeader.NumberOfSections; 00847 size = num_sections * sizeof(IMAGE_SECTION_HEADER); 00848 if( offset + size > fileSize ) 00849 goto invalid_parameter; 00850 ret = DigestFunction( DigestHandle, map + offset, size ); 00851 if( !ret ) 00852 goto end; 00853 00854 section_headers = (IMAGE_SECTION_HEADER *)(map + offset); 00855 IMAGEHLP_ReportCodeSections( section_headers, num_sections, 00856 map, fileSize, DigestFunction, DigestHandle ); 00857 IMAGEHLP_ReportSection( section_headers, num_sections, ".data", 00858 map, fileSize, DigestFunction, DigestHandle ); 00859 IMAGEHLP_ReportSection( section_headers, num_sections, ".rdata", 00860 map, fileSize, DigestFunction, DigestHandle ); 00861 IMAGEHLP_ReportImportSection( section_headers, num_sections, 00862 map, fileSize, DigestLevel, DigestFunction, DigestHandle ); 00863 if( DigestLevel & CERT_PE_IMAGE_DIGEST_DEBUG_INFO ) 00864 IMAGEHLP_ReportSection( section_headers, num_sections, ".debug", 00865 map, fileSize, DigestFunction, DigestHandle ); 00866 if( DigestLevel & CERT_PE_IMAGE_DIGEST_RESOURCES ) 00867 IMAGEHLP_ReportSection( section_headers, num_sections, ".rsrc", 00868 map, fileSize, DigestFunction, DigestHandle ); 00869 00870 end: 00871 if( map ) 00872 UnmapViewOfFile( map ); 00873 if( hMap != INVALID_HANDLE_VALUE ) 00874 CloseHandle( hMap ); 00875 if( error ) 00876 SetLastError(error); 00877 return ret; 00878 00879 invalid_parameter: 00880 error = ERROR_INVALID_PARAMETER; 00881 goto end; 00882 } 00883 00884 /*********************************************************************** 00885 * ImageRemoveCertificate (IMAGEHLP.@) 00886 */ 00887 BOOL WINAPI ImageRemoveCertificate(HANDLE FileHandle, DWORD Index) 00888 { 00889 DWORD size = 0, count = 0, sd_VirtualAddr = 0, offset = 0; 00890 DWORD data_size = 0, cert_size = 0, cert_size_padded = 0, ret = 0; 00891 LPVOID cert_data; 00892 BOOL r; 00893 00894 TRACE("(%p, %d)\n", FileHandle, Index); 00895 00896 r = ImageEnumerateCertificates(FileHandle, CERT_SECTION_TYPE_ANY, &count, NULL, 0); 00897 00898 if ((!r) || (count == 0)) 00899 return FALSE; 00900 00901 if ((!IMAGEHLP_GetSecurityDirOffset(FileHandle, &sd_VirtualAddr, &size)) || 00902 (!IMAGEHLP_GetCertificateOffset(FileHandle, Index, &offset, &cert_size))) 00903 return FALSE; 00904 00905 /* Ignore any padding we have, too */ 00906 if (cert_size % 8) 00907 cert_size_padded = cert_size + (8 - (cert_size % 8)); 00908 else 00909 cert_size_padded = cert_size; 00910 00911 data_size = size - (offset - sd_VirtualAddr) - cert_size_padded; 00912 00913 if (data_size == 0) 00914 { 00915 ret = SetFilePointer(FileHandle, sd_VirtualAddr, NULL, FILE_BEGIN); 00916 00917 if (ret == INVALID_SET_FILE_POINTER) 00918 return FALSE; 00919 } 00920 else 00921 { 00922 cert_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, data_size); 00923 00924 if (!cert_data) 00925 return FALSE; 00926 00927 ret = SetFilePointer(FileHandle, offset + cert_size_padded, NULL, FILE_BEGIN); 00928 00929 if (ret == INVALID_SET_FILE_POINTER) 00930 goto error; 00931 00932 /* Read any subsequent certificates */ 00933 r = ReadFile(FileHandle, cert_data, data_size, &count, NULL); 00934 00935 if ((!r) || (count != data_size)) 00936 goto error; 00937 00938 SetFilePointer(FileHandle, offset, NULL, FILE_BEGIN); 00939 00940 /* Write them one index back */ 00941 r = WriteFile(FileHandle, cert_data, data_size, &count, NULL); 00942 00943 if ((!r) || (count != data_size)) 00944 goto error; 00945 00946 HeapFree(GetProcessHeap(), 0, cert_data); 00947 } 00948 00949 /* If security directory is at end of file, trim the file */ 00950 if (GetFileSize(FileHandle, NULL) == sd_VirtualAddr + size) 00951 SetEndOfFile(FileHandle); 00952 00953 if (count == 1) 00954 r = IMAGEHLP_SetSecurityDirOffset(FileHandle, 0, 0); 00955 else 00956 r = IMAGEHLP_SetSecurityDirOffset(FileHandle, sd_VirtualAddr, size - cert_size_padded); 00957 00958 if (!r) 00959 return FALSE; 00960 00961 if (!IMAGEHLP_RecalculateChecksum(FileHandle)) 00962 return FALSE; 00963 00964 return TRUE; 00965 00966 error: 00967 HeapFree(GetProcessHeap(), 0, cert_data); 00968 return FALSE; 00969 } Generated on Fri May 25 2012 04:22:06 for ReactOS by
1.7.6.1
|