bool operator()(const MemoryMap::Super &map, const AddressInterval &interval) { rose_addr_t va = interval.least(); while (va <= interval.greatest()) { uint8_t byte; map.at(va).limit(1).read(&byte); if (!self->isAsciiCharacter(byte)) return false; ++nBytes; if (va == interval.greatest()) return true; // prevent overflow ++va; } return true; }
/** Returns a list of parts of a single section that have been referenced. The offsets are relative to the start of the * section. */ AddressIntervalSet SgAsmGenericSection::get_referenced_extents() const { if (0==get_size()) return AddressIntervalSet(); AddressIntervalSet retval; AddressInterval segment = AddressInterval::baseSize(get_offset(), get_size()); const AddressIntervalSet &fileExtents = get_file()->get_referenced_extents(); BOOST_FOREACH (const AddressInterval &interval, fileExtents.intervals()) { if (segment.isContaining(interval)) { retval.insert(AddressInterval::baseSize(interval.least()-get_offset(), interval.size())); } else if (interval.isLeftOf(segment) || interval.isRightOf(segment)) { // no overlap } else if (interval.isContaining(segment)) { retval.insert(AddressInterval::baseSize(0, get_size())); break; // no point in continuing since we've referenced whole segment now } else if (interval.least() < segment.least()) { retval.insert(AddressInterval::baseSize(0, interval.least()+interval.size()-get_offset())); } else if (interval.greatest() > segment.greatest()) { retval.insert(AddressInterval::baseSize(interval.least()-get_offset(), get_offset()+get_size()-interval.least())); } else { ASSERT_not_reachable("invalid extent overlap category"); } } return retval; }
Sawyer::Optional<rose_addr_t> MemoryMap::findAny(const AddressInterval &limits, const std::vector<uint8_t> &bytesToFind, unsigned requiredPerms, unsigned prohibitedPerms) const { if (!limits || bytesToFind.empty()) return Sawyer::Nothing(); // Read a bunch of bytes at a time. If the buffer size is large then we'll have fewer read calls before finding a match, // which is good if a match is unlikely. But if a match is likely, then it's better to use a smaller buffer so we don't // ready more than necessary to find a match. We'll compromise by starting with a small buffer that grows up to some // limit. size_t nremaining = limits.size(); // bytes remaining to search (could be zero if limits is universe) size_t bufsize = 8; // initial buffer size uint8_t buffer[4096]; // full buffer Sawyer::Optional<rose_addr_t> atVa = this->at(limits.least()).require(requiredPerms).prohibit(prohibitedPerms).next(); while (atVa && *atVa <= limits.greatest()) { if (nremaining > 0) // zero implies entire address space bufsize = std::min(bufsize, nremaining); size_t nread = at(*atVa).limit(bufsize).require(requiredPerms).prohibit(prohibitedPerms).read(buffer).size(); assert(nread > 0); // because of the next() calls for (size_t offset=0; offset<nread; ++offset) { if (std::find(bytesToFind.begin(), bytesToFind.end(), buffer[offset]) != bytesToFind.end()) return *atVa + offset; // found } atVa = at(*atVa+nread).require(requiredPerms).prohibit(prohibitedPerms).next(); bufsize = std::min(2*bufsize, sizeof buffer); // use a larger buffer next time if possible nremaining -= nread; // ok if nremaining is already zero } return Sawyer::Nothing(); }
bool operator()(const MemoryMap::Super &map, const AddressInterval &interval) { rose_addr_t va = interval.least(); if (startVa + nChars != va) nChars = 0; while (va <= interval.greatest()) { uint8_t byte; map.at(va).limit(1).read(&byte); if (self->isAsciiCharacter(byte)) { if (1 == ++nChars) startVa = va; if (nChars >= minChars) return false; } else { nChars = 0; } if (va == interval.greatest()) return true; // prevent overflow ++va; } return true; }
int main(int argc, char *argv[]) { ROSE_INITIALIZE; BinaryAnalysis::Partitioner2::Engine engine; Settings settings; std::vector<std::string> specimenNames = parseCommandLine(argc, argv, engine, settings /*in,out*/); BinaryAnalysis::MagicNumber analyzer; analyzer.maxBytesToCheck(settings.maxBytes); MemoryMap::Ptr map = engine.loadSpecimens(specimenNames); map->dump(mlog[INFO]); size_t step = std::max(size_t(1), settings.step); AddressInterval limits = settings.limits.isEmpty() ? map->hull() : (settings.limits & map->hull()); Sawyer::Container::IntervalSet<AddressInterval> addresses(*map); addresses.intersect(limits); size_t nPositions = addresses.size() / step; mlog[INFO] <<"approximately " <<StringUtility::plural(nPositions, "positions") <<" to check\n"; { Sawyer::ProgressBar<size_t> progress(nPositions, mlog[INFO], "positions"); for (rose_addr_t va=limits.least(); va<=limits.greatest() && map->atOrAfter(va).next().assignTo(va); va+=step, ++progress) { std::string magicString = analyzer.identify(map, va); if (magicString!="data") { // runs home to Momma when it gets confused uint8_t buf[8]; size_t nBytes = map->at(va).limit(sizeof buf).read(buf).size(); std::cout <<StringUtility::addrToString(va) <<" |" <<leadingBytes(buf, nBytes) <<" | " <<magicString <<"\n"; } if (va==limits.greatest()) break; // prevent overflow at top of address space } } }
void MemoryMap::eraseZeros(size_t minsize) { if (isEmpty()) return; unsigned permissions = READABLE | EXECUTABLE; // access permissions that must be present AddressIntervalSet toRemove; // to save up intervals until we're done iterating AddressInterval zeroInterval; uint8_t buf[8192]; rose_addr_t va = hull().least(); while (AddressInterval accessed = atOrAfter(va).require(permissions).limit(sizeof buf).read(buf)) { for (size_t offset=0; offset<accessed.size(); ++offset) { if (0 == buf[offset]) { if (zeroInterval.isEmpty()) { zeroInterval = AddressInterval(accessed.least()+offset); } else if (zeroInterval.greatest()+1 < offset) { if (zeroInterval.size() >= minsize) toRemove.insert(zeroInterval); zeroInterval = AddressInterval(accessed.least()+offset); } else { zeroInterval = AddressInterval::hull(zeroInterval.least(), zeroInterval.greatest()+1); } } else if (!zeroInterval.isEmpty()) { if (zeroInterval.size() >= minsize) toRemove.insert(zeroInterval); zeroInterval = AddressInterval(); } } if (accessed.greatest() == hull().greatest()) break; // prevent overflow in next statement va += accessed.size(); } if (zeroInterval.size() >= minsize) toRemove.insert(zeroInterval); BOOST_FOREACH (const AddressInterval &interval, toRemove.intervals()) erase(interval); }
Extent toExtent(const AddressInterval &x) { return x.isEmpty() ? Extent() : Extent::inin(x.least(), x.greatest()); }