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 <iomanip>
#include <ios>
#include <iostream>
#include <sstream>
@ -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<void>(N);
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 << "!";
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;

View File

@ -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 &,

View File

@ -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,7 +1672,6 @@ bool getExports(parsed_pe *p) {
((symRVA >= exportDir.VirtualAddress) &&
(symRVA < exportDir.VirtualAddress + exportDir.Size));
if (!isForwarded) {
VA symVA;
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
symVA = symRVA + p->peHeader.nt.OptionalHeader.ImageBase;
@ -1681,12 +1682,27 @@ bool getExports(parsed_pe *p) {
}
exportent a;
a.addr = symVA;
a.ordinal = ordinal;
a.symbolName = symName;
a.moduleName = modName;
p->internal->exports.push_back(a);
if (!isForwarded) {
a.addr = symVA;
a.forwardName.clear();
} else {
section fwdSec;
if (!getSecForVA(p->internal->secs, symVA, fwdSec)) {
return false;
}
auto fwdOff = static_cast<std::uint32_t>(symVA - fwdSec.sectionBase);
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<exportent> &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<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
void IterSec(parsed_pe *pe, iterSec cb, void *cbd) {
parsed_pe_internal *pint = pe->internal;