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