// Describe and parse the command-line static std::vector<std::string> parseCommandLine(int argc, char *argv[], Partitioner2::Engine &engine) { using namespace Sawyer::CommandLine; std::string purpose = "simulate execution using concrete semantics"; std::string description = "Parses and loads the specimen and then executes its instructions in a concrete domain."; // The parser is the same as that created by Engine::commandLineParser except we don't need any partitioning switches since // this tool doesn't partition. Parser parser; parser .purpose(purpose) .version(std::string(ROSE_SCM_VERSION_ID).substr(0, 8), ROSE_CONFIGURE_DATE) .chapter(1, "ROSE Command-line Tools") .doc("Synopsis", "@prop{programName} [@v{switches}] @v{specimen_names}") .doc("Description", description) .doc("Specimens", engine.specimenNameDocumentation()) .with(engine.engineSwitches()) .with(engine.loaderSwitches()) .with(engine.disassemblerSwitches()); SwitchGroup tool("Tool switches"); tool.insert(Switch("start") .argument("address", nonNegativeIntegerParser(settings.startVa)) .doc("Address at which to start executing. If no address is specified then execution starts at the " "lowest address having execute permission.")); return parser.with(tool).parse(argc, argv).apply().unreachedArgs(); }
int main(int argc, char *argv[]) { Diagnostics::initialize(); ::mlog = Diagnostics::Facility("tool", Diagnostics::destination); Diagnostics::mfacilities.insertAndAdjust(::mlog); // Parse the command-line Partitioner2::Engine engine; std::vector<std::string> specimenNames = parseCommandLine(argc, argv, engine); if (specimenNames.empty()) throw std::runtime_error("no specimen specified; see --help"); // Load specimen into memory MemoryMap map = engine.loadSpecimens(specimenNames); // Configure instruction semantics Partitioner2::Partitioner partitioner = engine.createPartitioner(); Disassembler *disassembler = engine.obtainDisassembler(); const RegisterDictionary *regdict = disassembler->get_registers(); if (disassembler->dispatcher() == NULL) throw std::runtime_error("no instruction semantics for this architecture"); BaseSemantics::RiscOperatorsPtr ops = InstructionSemantics2::ConcreteSemantics::RiscOperators::instance(regdict); BaseSemantics::DispatcherPtr cpu = disassembler->dispatcher()->create(ops); ConcreteSemantics::MemoryState::promote(ops->currentState()->memoryState())->memoryMap(map); // Find starting address rose_addr_t va = 0; if (settings.startVa) { va = *settings.startVa; } else if (engine.isaName() == "coldfire") { // Use the interrupt vector to initialize the stack pointer and instruction pointer. uint32_t sp, ip; if (4 != map.at(0).limit(4).read((uint8_t*)&sp).size()) throw std::runtime_error("cannot read stack pointer at address 0x00000000"); ops->writeRegister(disassembler->stackPointerRegister(), ops->number_(32, ByteOrder::be_to_host(sp))); if (4 != map.at(4).limit(4).read((uint8_t*)&ip).size()) throw std::runtime_error("cannot read instruction pointer at address 0x00000004"); va = ByteOrder::be_to_host(ip); } else if (!map.atOrAfter(0).require(MemoryMap::EXECUTABLE).next().assignTo(va)) { throw std::runtime_error("no starting address specified and none marked executable"); } ops->writeRegister(disassembler->instructionPointerRegister(), ops->number_(32, va)); // Execute map.dump(::mlog[INFO]); while (1) { va = ops->readRegister(disassembler->instructionPointerRegister())->get_number(); SgAsmInstruction *insn = partitioner.instructionProvider()[va]; SAWYER_MESG(::mlog[TRACE]) <<unparseInstructionWithAddress(insn, NULL, regdict) <<"\n"; try { cpu->processInstruction(insn); } catch (const BaseSemantics::Exception &e) { ::mlog[WARN] <<e <<"\n"; } } // std::cout <<"Final state:\n"; // std::cout <<*ops->currentState(); }
int main(int argc, char *argv[]) { //! [setup] Partitioner2::Engine engine; std::vector<std::string> specimen = engine.parseCommandLine(argc, argv, purpose, description).unreachedArgs(); if (specimen.empty()) { mlog[FATAL] <<"no binary specimen specified; see --help\n"; exit(1); } //! [setup] //! [partition] Partitioner2::Partitioner partitioner = engine.partition(specimen); //! [partition] //! [function cfg] BOOST_FOREACH (const Partitioner2::Function::Ptr &function, partitioner.functions()) { // global control flow graph Partitioner2::ControlFlowGraph cfg = partitioner.cfg(); // Erase all vertices that don't belong to the function of interest, and their incident edges Partitioner2::ControlFlowGraph::VertexIterator vi = cfg.vertices().begin(); while (vi != cfg.vertices().end()) { if (!vi->value().isOwningFunction(function)) { cfg.eraseVertex(vi++); } else { ++vi; } } // Print the results std::cout <<"CFG for " <<function->printableName() <<"\n" <<" Vertices:\n"; BOOST_FOREACH (const Partitioner2::ControlFlowGraph::Vertex &v, cfg.vertices()) std::cout <<" " <<partitioner.vertexName(v) <<"\n"; std::cout <<" Edges:\n"; BOOST_FOREACH (const Partitioner2::ControlFlowGraph::Edge &e, cfg.edges()) std::cout <<" " <<partitioner.edgeName(e) <<"\n"; } //! [function cfg] }
int main(int argc, char *argv[]) { //! [commandline] ROSE_INITIALIZE; // see rose::initialize std::string purpose = "finds static strings in a binary specimen"; std::string description = "This tool disassembles a binary specimen and then scans the " "read-only parts of memory to find static strings. It looks for " "C-style NUL-termianted printable ASCII strings, zero-terminated " "UTF-16 little-endian strings, two-byte little-endian length-encoded " "ASCII strings, and some other common formats."; Partitioner2::Engine engine; std::vector<std::string> specimen = engine.parseCommandLine(argc, argv, purpose, description).unreachedArgs(); //! [commandline] //! [load] MemoryMap map = engine.loadSpecimens(specimen); ByteOrder::Endianness sex = engine.obtainDisassembler()->get_sex(); //! [load] //! [analysis] Strings::StringFinder finder; // the string analyzer finder.settings().minLength = 5; // no strings shorter than 5 characters finder.settings().maxLength = 8192; // no strings longer than 8k characters finder.insertCommonEncoders(sex); // match common encodings of strings finder.find(map.require(MemoryMap::READABLE).prohibit(MemoryMap::WRITABLE)); //! [analysis] //! [output] // Output, or just do "std::cout <<finder" if you're not picky. BOOST_FOREACH (const Strings::EncodedString &string, finder.strings()) { std::cout <<"string at " <<string.address() <<" for " <<string.size() <<" bytes\n"; std::cout <<"encoding: " <<string.encoder()->name() <<"\n"; std::cout <<"narrow value: \"" <<StringUtility::cEscape(string.narrow()) <<"\"\n"; } //! [output] }