pe_rich.c revision 302408
122347Spst/*- 222347Spst * Copyright (c) 2016 Kai Wang 322347Spst * All rights reserved. 429964Sache * 592914Smarkm * Redistribution and use in source and binary forms, with or without 622347Spst * modification, are permitted provided that the following conditions 722347Spst * are met: 822347Spst * 1. Redistributions of source code must retain the above copyright 922347Spst * notice, this list of conditions and the following disclaimer. 1022347Spst * 2. Redistributions in binary form must reproduce the above copyright 1122347Spst * notice, this list of conditions and the following disclaimer in the 1222347Spst * documentation and/or other materials provided with the distribution. 1322347Spst * 1422347Spst * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1522347Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1622347Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1722347Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1822347Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1922347Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2022347Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2122347Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2222347Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2322347Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2422347Spst * SUCH DAMAGE. 2522347Spst */ 2622347Spst 2722347Spst#include <assert.h> 2822347Spst#include <errno.h> 2922347Spst 3022347Spst#include "_libpe.h" 3122347Spst 3278644SacheELFTC_VCSID("$Id: pe_rich.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); 3378644Sache 3478644SachePE_RichHdr * 3522347Spstpe_rich_header(PE *pe) 3622347Spst{ 3722347Spst 3881973Smarkm if (pe == NULL) { 3981973Smarkm errno = EINVAL; 4022347Spst return (NULL); 4181973Smarkm } 4222347Spst 4322347Spst if (pe->pe_rh == NULL && pe->pe_stub_ex > 0 && 4422347Spst (pe->pe_flags & LIBPE_F_LOAD_DOS_STUB) == 0) { 4522347Spst assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0); 4622347Spst (void) libpe_read_msdos_stub(pe); 4722347Spst } 4881973Smarkm 4922347Spst if (pe->pe_rh == NULL) { 5022347Spst errno = ENOENT; 5122347Spst return (NULL); 5278644Sache } 5322347Spst 5478644Sache return (pe->pe_rh); 5578644Sache} 5678644Sache 5778644Sachestatic uint32_t 5878644Sacherol32(uint32_t n, int c) 5978644Sache{ 6022347Spst 6122347Spst c &= 0x1f; 6222347Spst 6322347Spst return ((n << c) | (n >> (0x20 - c))); 6422347Spst} 6522347Spst 6622347Spstint 6722347Spstpe_rich_header_validate(PE *pe) 6822347Spst{ 6922347Spst PE_RichHdr *rh; 7022347Spst uint32_t cksum; 7122347Spst char *p; 7222347Spst int i, off; 7322347Spst 7422347Spst if (pe_rich_header(pe) == NULL) 7522347Spst return (-1); 7622347Spst 7722347Spst assert(pe->pe_rh_start != NULL); 7822347Spst 7978644Sache /* 8078644Sache * Initial value of the checksum is the offset to the begin of 8178644Sache * the Rich header. 8278644Sache */ 8378644Sache cksum = pe->pe_rh_start - pe->pe_stub; 8422347Spst 8578644Sache /* 8622347Spst * Add the bytes before the Rich header to the checksum, rotated 8722347Spst * left by the offset. 8881973Smarkm */ 8981973Smarkm for (p = pe->pe_stub; p < pe->pe_rh_start; p++) { 9081973Smarkm /* Skip dh_lfanew. */ 9181973Smarkm off = p - pe->pe_stub; 9281973Smarkm if (off >= 0x3c && off < 0x40) 9322347Spst continue; 9422347Spst cksum += rol32((unsigned char) *p, off); 9522347Spst } 9622347Spst 9722347Spst /* Add each compid rotated left by its count to the checksum. */ 9822347Spst rh = pe->pe_rh; 9922347Spst for (i = 0; (uint32_t) i < rh->rh_total; i++) 10022347Spst cksum += rol32(rh->rh_compid[i], rh->rh_cnt[i]); 10122347Spst 10222347Spst /* Validate the checksum with the XOR mask stored after "Rich". */ 10322347Spst if (cksum == rh->rh_xor) 10422347Spst return (1); 105 106 return (0); 107} 108