// 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 // #include #include #include #include #include #include #include #include "fold/binary/pcode_router.hpp" #include "fold/report/finding.hpp" int main(int argc, char** argv) { // Whole-binary form: `pcode_scan ` → 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(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] << " \n or: " << argv[0] << " \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 raw((std::istreambuf_iterator(bf)), std::istreambuf_iterator()); 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(f.kind) << " @line=0x" << std::hex << line << std::dec << " " << f.message << '\n'; } return 0; }