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
This commit is contained in:
Lanyi 2021-12-24 21:16:47 +01:00 committed by GitHub
parent af52e5ee8a
commit f0097d2d9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 18 deletions

View File

@ -24,6 +24,7 @@ THE SOFTWARE.
#include <cstring> #include <cstring>
#include <iomanip> #include <iomanip>
#include <ios>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@ -35,19 +36,34 @@ using namespace peparse;
int printExps(void *N, int printExps(void *N,
const VA &funcAddr, const VA &funcAddr,
std::uint16_t ordinal,
const std::string &mod, const std::string &mod,
const std::string &func) { const std::string &func,
const std::string &fwd) {
static_cast<void>(N); static_cast<void>(N);
auto address = static_cast<std::uint32_t>(funcAddr); auto address = static_cast<std::uint32_t>(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 << mod;
std::cout << "!"; std::cout << "!";
std::cout << func; std::cout << func;
std::cout << ": 0x"; std::cout << ": ";
std::cout << std::hex << address; if (!fwd.empty()) {
std::cout << fwd;
} else {
std::cout << std::showbase << std::hex << address;
}
std::cout << "\n"; std::cout << "\n";
// restore default formatting
std::cout.copyfmt(initial);
return 0; return 0;
} }
@ -440,7 +456,7 @@ int main(int argc, char *argv[]) {
IterSec(p, printSecs, NULL); IterSec(p, printSecs, NULL);
std::cout << "Exports: " std::cout << "Exports: "
<< "\n"; << "\n";
IterExpVA(p, printExps, NULL); IterExpFull(p, printExps, NULL);
// read the first 8 bytes from the entry point and print them // read the first 8 bytes from the entry point and print them
VA entryPoint; VA entryPoint;

View File

@ -222,13 +222,25 @@ typedef int (*iterSymbol)(void *,
const std::uint8_t &); const std::uint8_t &);
void IterSymbols(parsed_pe *pe, iterSymbol cb, void *cbd); void IterSymbols(parsed_pe *pe, iterSymbol cb, void *cbd);
// iterate over the exports // iterate over the exports, except forwarded exports
typedef int (*iterExp)(void *, typedef int (*iterExp)(void *,
const VA &, const VA &,
const std::string &, const std::string &,
const std::string &); const std::string &);
void IterExpVA(parsed_pe *pe, iterExp cb, void *cbd); 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 // iterate over sections
typedef int (*iterSec)(void *, typedef int (*iterSec)(void *,
const VA &, const VA &,

View File

@ -51,8 +51,10 @@ struct importent {
struct exportent { struct exportent {
VA addr; VA addr;
std::uint16_t ordinal;
std::string symbolName; std::string symbolName;
std::string moduleName; std::string moduleName;
std::string forwardName;
}; };
struct reloc { struct reloc {
@ -1670,23 +1672,37 @@ bool getExports(parsed_pe *p) {
((symRVA >= exportDir.VirtualAddress) && ((symRVA >= exportDir.VirtualAddress) &&
(symRVA < exportDir.VirtualAddress + exportDir.Size)); (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) { if (!isForwarded) {
VA symVA; a.addr = symVA;
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) { a.forwardName.clear();
symVA = symRVA + p->peHeader.nt.OptionalHeader.ImageBase; } else {
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) { section fwdSec;
symVA = symRVA + p->peHeader.nt.OptionalHeader64.ImageBase; if (!getSecForVA(p->internal->secs, symVA, fwdSec)) {
} else {
return false; return false;
} }
auto fwdOff = static_cast<std::uint32_t>(symVA - fwdSec.sectionBase);
exportent a; a.addr = 0;
if (!readCString(*fwdSec.sectionData, fwdOff, a.forwardName)) {
a.addr = symVA; return false;
a.symbolName = symName; }
a.moduleName = modName;
p->internal->exports.push_back(a);
} }
p->internal->exports.push_back(a);
} }
} }
} }
@ -2532,6 +2548,9 @@ void IterExpVA(parsed_pe *pe, iterExp cb, void *cbd) {
std::vector<exportent> &l = pe->internal->exports; std::vector<exportent> &l = pe->internal->exports;
for (exportent &i : l) { for (exportent &i : l) {
if (i.addr == 0) {
continue;
}
if (cb(cbd, i.addr, i.moduleName, i.symbolName) != 0) { if (cb(cbd, i.addr, i.moduleName, i.symbolName) != 0) {
break; break;
} }
@ -2540,6 +2559,20 @@ void IterExpVA(parsed_pe *pe, iterExp cb, void *cbd) {
return; return;
} }
// iterate over the exports with full information
void IterExpFull(parsed_pe *pe, iterExpFull cb, void *cbd) {
std::vector<exportent> &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 // iterate over sections
void IterSec(parsed_pe *pe, iterSec cb, void *cbd) { void IterSec(parsed_pe *pe, iterSec cb, void *cbd) {
parsed_pe_internal *pint = pe->internal; parsed_pe_internal *pint = pe->internal;