From f0097d2d9f32cd329a80e89f01dc2b9918cbe149 Mon Sep 17 00:00:00 2001 From: Lanyi Date: Fri, 24 Dec 2021 21:16:47 +0100 Subject: [PATCH] Expose more export information, like forwarded export and ordinal (#161) * Expose more export information namely, ordinal and forwarded export * ensure IterExpVA's behavior is not changed * Added description in the header file --- dump-pe/main.cpp | 26 ++++++++-- pe-parser-library/include/pe-parse/parse.h | 14 +++++- pe-parser-library/src/parse.cpp | 57 +++++++++++++++++----- 3 files changed, 79 insertions(+), 18 deletions(-) diff --git a/dump-pe/main.cpp b/dump-pe/main.cpp index f945c85..d8b71f8 100644 --- a/dump-pe/main.cpp +++ b/dump-pe/main.cpp @@ -24,6 +24,7 @@ THE SOFTWARE. #include #include +#include #include #include @@ -35,19 +36,34 @@ using namespace peparse; int printExps(void *N, const VA &funcAddr, + std::uint16_t ordinal, const std::string &mod, - const std::string &func) { + const std::string &func, + const std::string &fwd) { static_cast(N); auto address = static_cast(funcAddr); - std::cout << "EXP: "; + // save default formatting + std::ios initial(nullptr); + initial.copyfmt(std::cout); + + std::cout << "EXP #"; + std::cout << ordinal; + std::cout << ": "; std::cout << mod; std::cout << "!"; std::cout << func; - std::cout << ": 0x"; - std::cout << std::hex << address; + std::cout << ": "; + if (!fwd.empty()) { + std::cout << fwd; + } else { + std::cout << std::showbase << std::hex << address; + } std::cout << "\n"; + + // restore default formatting + std::cout.copyfmt(initial); return 0; } @@ -440,7 +456,7 @@ int main(int argc, char *argv[]) { IterSec(p, printSecs, NULL); std::cout << "Exports: " << "\n"; - IterExpVA(p, printExps, NULL); + IterExpFull(p, printExps, NULL); // read the first 8 bytes from the entry point and print them VA entryPoint; diff --git a/pe-parser-library/include/pe-parse/parse.h b/pe-parser-library/include/pe-parse/parse.h index 879f377..c4b0777 100644 --- a/pe-parser-library/include/pe-parse/parse.h +++ b/pe-parser-library/include/pe-parse/parse.h @@ -222,13 +222,25 @@ typedef int (*iterSymbol)(void *, const std::uint8_t &); void IterSymbols(parsed_pe *pe, iterSymbol cb, void *cbd); -// iterate over the exports +// iterate over the exports, except forwarded exports typedef int (*iterExp)(void *, const VA &, const std::string &, const std::string &); void IterExpVA(parsed_pe *pe, iterExp cb, void *cbd); +// iterate over the exports, including forwarded exports +// export ordinal is also provided as the third argument. +// VA will be zero if the current export is forwarded, +// in this case, the last argument (forward string) will be non-empty +typedef int (*iterExpFull)(void *, + const VA &, + std::uint16_t, + const std::string &, + const std::string &, + const std::string &); +void IterExpFull(parsed_pe *pe, iterExpFull cb, void *cbd); + // iterate over sections typedef int (*iterSec)(void *, const VA &, diff --git a/pe-parser-library/src/parse.cpp b/pe-parser-library/src/parse.cpp index 36bfaa4..bb2a8d4 100644 --- a/pe-parser-library/src/parse.cpp +++ b/pe-parser-library/src/parse.cpp @@ -51,8 +51,10 @@ struct importent { struct exportent { VA addr; + std::uint16_t ordinal; std::string symbolName; std::string moduleName; + std::string forwardName; }; struct reloc { @@ -1670,23 +1672,37 @@ bool getExports(parsed_pe *p) { ((symRVA >= exportDir.VirtualAddress) && (symRVA < exportDir.VirtualAddress + exportDir.Size)); + VA symVA; + if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) { + symVA = symRVA + p->peHeader.nt.OptionalHeader.ImageBase; + } else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) { + symVA = symRVA + p->peHeader.nt.OptionalHeader64.ImageBase; + } else { + return false; + } + + exportent a; + a.ordinal = ordinal; + a.symbolName = symName; + a.moduleName = modName; + if (!isForwarded) { - VA symVA; - if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) { - symVA = symRVA + p->peHeader.nt.OptionalHeader.ImageBase; - } else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) { - symVA = symRVA + p->peHeader.nt.OptionalHeader64.ImageBase; - } else { + a.addr = symVA; + a.forwardName.clear(); + } else { + section fwdSec; + if (!getSecForVA(p->internal->secs, symVA, fwdSec)) { return false; } + auto fwdOff = static_cast(symVA - fwdSec.sectionBase); - exportent a; - - a.addr = symVA; - a.symbolName = symName; - a.moduleName = modName; - p->internal->exports.push_back(a); + a.addr = 0; + if (!readCString(*fwdSec.sectionData, fwdOff, a.forwardName)) { + return false; + } } + + p->internal->exports.push_back(a); } } } @@ -2532,6 +2548,9 @@ void IterExpVA(parsed_pe *pe, iterExp cb, void *cbd) { std::vector &l = pe->internal->exports; for (exportent &i : l) { + if (i.addr == 0) { + continue; + } if (cb(cbd, i.addr, i.moduleName, i.symbolName) != 0) { break; } @@ -2540,6 +2559,20 @@ void IterExpVA(parsed_pe *pe, iterExp cb, void *cbd) { return; } +// iterate over the exports with full information +void IterExpFull(parsed_pe *pe, iterExpFull cb, void *cbd) { + std::vector &l = pe->internal->exports; + + for (exportent &i : l) { + if (cb(cbd, i.addr, i.ordinal, i.moduleName, i.symbolName, i.forwardName) != + 0) { + break; + } + } + + return; +} + // iterate over sections void IterSec(parsed_pe *pe, iterSec cb, void *cbd) { parsed_pe_internal *pint = pe->internal;