fold/tools/pcode_scan.cpp

80 lines
3.5 KiB
C++

// Phase-3.5 smoke driver for the dual-stream P-Code router.
// Lifts one function (raw + SSA), encodes both, and prints the merged findings.
//
// pcode_scan <specs_dir> <sla_path> <language_id> <base_vaddr_hex> <raw_bytes_file>
//
#include <cstdint>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include "fold/binary/pcode_router.hpp"
#include "fold/report/finding.hpp"
int main(int argc, char** argv) {
// Whole-binary form: `pcode_scan <binary>` → detect arch, enumerate
// functions via r2, route each through both streams, print merged findings.
if (argc == 2) {
std::string err;
auto findings = fold::binary::scanBinaryWithPcode(argv[1], /*max_functions=*/0, &err);
if (!err.empty())
std::cerr << "note: " << err << '\n';
std::cout << "merged findings: " << findings.size() << '\n';
for (const auto& f : findings) {
const int line = f.locations.empty() ? 0 : f.locations.front().line;
const std::string fn = f.locations.empty() ? "" : f.locations.front().function;
std::cout << " [" << f.evidence.backend << "] kind=" << static_cast<int>(f.kind)
<< " @0x" << std::hex << line << std::dec << " fn=" << fn << " " << f.message
<< '\n';
// Dump any attached exploit context (ROP gadgets + chain scaffold).
if (f.evidence.exploit_context && f.evidence.exploit_context->chain) {
const auto& ec = *f.evidence.exploit_context;
const auto& c = *ec.chain;
std::cout << " exploit: gadgets=" << ec.gadgets.size() << " target=" << c.target
<< " padding_len=" << c.padding_len << '\n';
for (const auto& s : c.steps)
std::cout << " [" << s.role << "] @0x" << std::hex << s.addr << " val=0x"
<< s.value << std::dec << " off=" << s.stack_offset << " " << s.note
<< '\n';
for (const auto& cav : c.caveats)
std::cout << " caveat: " << cav << '\n';
}
}
return 0;
}
if (argc != 6) {
std::cerr << "usage: " << argv[0] << " <binary>\n or: " << argv[0]
<< " <specs_dir> <sla_path> <language_id> <base_vaddr_hex> <raw_bytes_file>\n";
return 2;
}
fold::binary::RouterConfig cfg;
cfg.specs_dir = argv[1];
cfg.sla_path = argv[2];
cfg.language_id = argv[3];
fold::binary::LiftRequest req;
req.language_id = argv[3];
req.base = std::strtoull(argv[4], nullptr, 16);
req.name = "smoke";
std::ifstream bf(argv[5], std::ios::binary);
if (!bf) {
std::cerr << "cannot open bytes file: " << argv[5] << '\n';
return 2;
}
const std::vector<char> raw((std::istreambuf_iterator<char>(bf)),
std::istreambuf_iterator<char>());
req.bytes.assign(raw.begin(), raw.end());
auto findings = fold::binary::routeFunctionToFindings(req, cfg, "smoke.bin");
std::cout << "merged findings: " << findings.size() << '\n';
for (const auto& f : findings) {
const int line = f.locations.empty() ? 0 : f.locations.front().line;
std::cout << " [" << f.evidence.backend << "] kind=" << static_cast<int>(f.kind)
<< " @line=0x" << std::hex << line << std::dec << " " << f.message << '\n';
}
return 0;
}