80 lines
3.5 KiB
C++
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;
|
|
}
|