From 2bf8ad917e32ff4abba555fe78bea74c09f6c178 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Mon, 30 Mar 2020 10:04:57 -0400 Subject: [PATCH] parse: Fix DIR_SECURITY data directory retrieval (#122) * parse: Fix DIR_SECURITY data directory retrieval Fixes #121. * parse: Fix variables * parse: Add MSDN link for DIR_SECURITY special case --- pe-parser-library/src/parse.cpp | 41 +++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/pe-parser-library/src/parse.cpp b/pe-parser-library/src/parse.cpp index fb450af..d6e4d16 100644 --- a/pe-parser-library/src/parse.cpp +++ b/pe-parser-library/src/parse.cpp @@ -2655,20 +2655,37 @@ bool GetDataDirectoryEntry(parsed_pe *pe, return false; } - section sec; - if (!getSecForVA(pe->internal->secs, addr, sec)) { - PE_ERR(PEERR_SECTVA); - return false; - } + /* NOTE(ww): DIR_SECURITY is an annoying special case: its contents + * are never mapped into memory, so its "RVA" is actually a direct + * file offset. + * See: + * https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-attribute-certificate-table-image-only + */ + if (dirnum == DIR_SECURITY) { + auto *buf = splitBuffer( + pe->fileBuffer, dir.VirtualAddress, dir.VirtualAddress + dir.Size); + if (buf == nullptr) { + PE_ERR(PEERR_SIZE); + return false; + } - auto off = static_cast(addr - sec.sectionBase); - if (off + dir.Size >= sec.sectionData->bufLen) { - PE_ERR(PEERR_SIZE); - return false; - } + raw_entry.assign(buf->buf, buf->buf + buf->bufLen); + } else { + section sec; + if (!getSecForVA(pe->internal->secs, addr, sec)) { + PE_ERR(PEERR_SECTVA); + return false; + } - raw_entry.assign(sec.sectionData->buf + off, - sec.sectionData->buf + off + dir.Size); + auto off = static_cast(addr - sec.sectionBase); + if (off + dir.Size >= sec.sectionData->bufLen) { + PE_ERR(PEERR_SIZE); + return false; + } + + raw_entry.assign(sec.sectionData->buf + off, + sec.sectionData->buf + off + dir.Size); + } return true; }