Example #1
0
File: simulate.C Project: 8l/rose
// 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();
}
Example #2
0
File: simulate.C Project: 8l/rose
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();
}
Example #3
0
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]
}
Example #4
0
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]
}