Path: blob/main/contrib/elftoolchain/libpe/libpe_rich.c
39478 views
/*-1* Copyright (c) 2015 Kai Wang2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#include <assert.h>27#include <errno.h>28#include <stdlib.h>29#include <string.h>3031#include "_libpe.h"3233ELFTC_VCSID("$Id: libpe_rich.c 3312 2016-01-10 09:23:51Z kaiwang27 $");3435static char *36memfind(char *s, const char *find, size_t slen, size_t flen)37{38int i;3940if (slen == 0 || flen == 0 || flen > slen)41return (NULL);4243for (i = 0; (size_t) i <= slen - flen; i++) {44if (s[i] != find[0])45continue;46if (flen == 1)47return (&s[i]);48if (memcmp(&s[i + 1], &find[1], flen - 1) == 0)49return (&s[i]);50}5152return (NULL);53}5455int56libpe_parse_rich_header(PE *pe)57{58PE_RichHdr *rh;59char *p, *r, *s;60uint32_t x;61int found, i;6263assert(pe->pe_stub != NULL && pe->pe_stub_ex > 0);6465/* Search for the "Rich" keyword to locate the Rich header. */66s = pe->pe_stub + sizeof(PE_DosHdr);67r = memfind(s, PE_RICH_TEXT, pe->pe_stub_ex, 4);68if (r == NULL || r + 8 > s + pe->pe_stub_ex) {69errno = ENOENT;70return (-1);71}7273if ((rh = calloc(1, sizeof(*rh))) == NULL) {74errno = ENOMEM;75return (-1);76}7778rh->rh_xor = le32dec(r + 4); /* Retrieve the "XOR mask" */7980/*81* Search for the hidden keyword "DanS" by XOR the dwords before82* the "Rich" keyword with the XOR mask.83*/84found = 0;85for (p = r - 4; p >= s; p -= 4) {86x = le32dec(p) ^ rh->rh_xor;87if (x == PE_RICH_HIDDEN) {88found = 1;89break;90}91}92if (!found) {93free(rh);94errno = ENOENT;95return (-1);96}9798/*99* Found the "DanS" keyword, which is the start of the Rich header.100* The next step is to skip the first 16 bytes (DanS, XOR mask,101* XOR mask, XOR mask) and read the (compid,cnt) tuples.102*/103pe->pe_rh_start = p;104p += 16;105rh->rh_total = (r - p) / 8;106if ((rh->rh_compid = malloc(rh->rh_total * sizeof(*rh->rh_compid))) ==107NULL) {108free(rh);109errno = ENOMEM;110return (-1);111}112if ((rh->rh_cnt = malloc(rh->rh_total * sizeof(*rh->rh_cnt))) ==113NULL) {114free(rh->rh_compid);115free(rh);116errno = ENOMEM;117return (-1);118}119for (i = 0; (uint32_t) i < rh->rh_total; i++, p += 8) {120rh->rh_compid[i] = le32dec(p) ^ rh->rh_xor;121rh->rh_cnt[i] = le32dec(p + 4) ^ rh->rh_xor;122}123124pe->pe_rh = rh;125126return (0);127}128129130