Esempio n. 1
0
/**
 * Test the dominator frontier code.
 */
void
CfgTest::testDominators()
{
#define FRONTIER_FOUR     0x08048347
#define FRONTIER_FIVE     0x08048351
#define FRONTIER_TWELVE   0x080483b2
#define FRONTIER_THIRTEEN 0x080483b9

	auto prog = Prog::open(FRONTIER_PENTIUM);
	CPPUNIT_ASSERT(prog);

	auto fe = prog->getFrontEnd();
	Type::clearNamedTypes();
	fe->decode();

	bool gotMain;
	ADDRESS addr = fe->getMainEntryPoint(gotMain);
	CPPUNIT_ASSERT(addr != NO_ADDRESS);

	UserProc *pProc = (UserProc *)prog->getProc(0);
	Cfg *cfg = pProc->getCFG();
	DataFlow *df = pProc->getDataFlow();
	df->dominators(cfg);

	// Find BB "5" (as per Appel, Figure 19.5).
	BasicBlock *bb = nullptr;
	for (const auto &b : *cfg) {
		if (b->getLowAddr() == FRONTIER_FIVE) {
			bb = b;
			break;
		}
	}
	CPPUNIT_ASSERT(bb);

	std::ostringstream expected, actual;
#if 0
	expected << std::hex
	         << FRONTIER_FIVE << " "
	         << FRONTIER_THIRTEEN << " "
	         << FRONTIER_TWELVE << " "
	         << FRONTIER_FOUR << " "
	         << std::dec;
#endif
	expected << std::hex
	         << FRONTIER_THIRTEEN << " "
	         << FRONTIER_FOUR << " "
	         << FRONTIER_TWELVE << " "
	         << FRONTIER_FIVE << " "
	         << std::dec;
	int n5 = df->pbbToNode(bb);
	std::set<int> &DFset = df->getDF(n5);
	for (const auto &ii : DFset)
		actual << std::hex << (unsigned)df->nodeToBB(ii)->getLowAddr() << std::dec << " ";
	CPPUNIT_ASSERT_EQUAL(expected.str(), actual.str());
	delete prog;
}
Esempio n. 2
0
/**
 * Test a case where semi dominators are different to dominators.
 */
void
CfgTest::testSemiDominators()
{
#define SEMI_L  0x80483b0
#define SEMI_M  0x80483e2
#define SEMI_B  0x8048345
#define SEMI_D  0x8048354
#define SEMI_M  0x80483e2

	auto prog = Prog::open(SEMI_PENTIUM);
	CPPUNIT_ASSERT(prog);

	auto fe = prog->getFrontEnd();
	Type::clearNamedTypes();
	fe->decode();

	bool gotMain;
	ADDRESS addr = fe->getMainEntryPoint(gotMain);
	CPPUNIT_ASSERT(addr != NO_ADDRESS);

	UserProc *pProc = (UserProc *)prog->getProc(0);
	Cfg *cfg = pProc->getCFG();

	DataFlow *df = pProc->getDataFlow();
	df->dominators(cfg);

	// Find BB "L (6)" (as per Appel, Figure 19.8).
	BasicBlock *bb = nullptr;
	for (const auto &b : *cfg) {
		if (b->getLowAddr() == SEMI_L) {
			bb = b;
			break;
		}
	}
	CPPUNIT_ASSERT(bb);
	int nL = df->pbbToNode(bb);

	// The dominator for L should be B, where the semi dominator is D
	// (book says F)
	unsigned actual_dom  = (unsigned)df->nodeToBB(df->getIdom(nL))->getLowAddr();
	unsigned actual_semi = (unsigned)df->nodeToBB(df->getSemi(nL))->getLowAddr();
	CPPUNIT_ASSERT_EQUAL((unsigned)SEMI_B, actual_dom);
	CPPUNIT_ASSERT_EQUAL((unsigned)SEMI_D, actual_semi);
	// Check the final dominator frontier as well; should be M and B
	std::ostringstream expected, actual;
#if 0
	expected << std::hex << SEMI_M << " " << SEMI_B << " " << std::dec;
#endif
	expected << std::hex << SEMI_B << " " << SEMI_M << " " << std::dec;
	std::set<int> &DFset = df->getDF(nL);
	for (const auto &ii : DFset)
		actual << std::hex << (unsigned)df->nodeToBB(ii)->getLowAddr() << std::dec << " ";
	CPPUNIT_ASSERT_EQUAL(expected.str(), actual.str());
	delete prog;
}
Esempio n. 3
0
bool PalmBinaryLoader::loadFromMemory(QByteArray &img)
{
    const int size = img.size();
    m_image        = reinterpret_cast<uint8_t *>(img.data());

    if (static_cast<unsigned long>(size) < sizeof(PRCHeader) + sizeof(PRCRecordList)) {
        LOG_ERROR("This is not a standard .prc file");
        return false;
    }

    PRCHeader *prcHeader = reinterpret_cast<PRCHeader *>(img.data());

    // Check type at offset 0x3C; should be "appl" (or "palm"; ugh!)
    if ((strncmp(prcHeader->type, "appl", 4) != 0) && (strncmp(prcHeader->type, "panl", 4) != 0) &&
        (strncmp(prcHeader->type, "libr", 4) != 0)) {
        LOG_ERROR("This is not a standard .prc file");
        return false;
    }

    addTrapSymbols();

    // Get the number of resource headers (one section per resource)
    PRCRecordList *records = reinterpret_cast<PRCRecordList *>(m_image + sizeof(PRCHeader));
    if (records->nextRecordListOffset != 0) {
        LOG_ERROR("Reading PRC files with multiple record lists is not supported!");
        return false;
    }

    const SWord numSections = Util::readWord(&records->resourceCount, Endian::Big);

    // Iterate through the resource headers (generating section info structs)
    PRCResource *resource = reinterpret_cast<PRCResource *>(m_image + sizeof(PRCHeader) +
                                                            sizeof(PRCRecordList));

    std::vector<SectionProperties> sectionProperties;

    for (unsigned i = 0; i < numSections; i++) {
        char buf[5];
        strncpy(buf, reinterpret_cast<char *>(&resource[i].type), 4);
        buf[4] = 0;

        SWord id         = Util::readWord(&resource[i].id, Endian::Big);
        QString name     = QString("%1%2").arg(buf).arg(id);
        DWord dataOffset = Util::readDWord(&resource[i].dataOffset, Endian::Big);

        Address startAddr(dataOffset);

        if (i > 0) {
            sectionProperties[i - 1].to = startAddr;
        }

        sectionProperties.push_back(
            { name, startAddr, Address::INVALID, HostAddress(m_image + dataOffset) });
    }

    // last section extends until eof
    sectionProperties[numSections - 1].to = Address(size);

    for (SectionProperties props : sectionProperties) {
        assert(props.to != Address::INVALID);
        BinarySection *sect = m_binaryImage->createSection(props.name, props.from, props.to);

        if (sect) {
            // Decide if code or data; note that code0 is a special case (not code)
            sect->setHostAddr(props.hostAddr);
            sect->setCode((props.name != "code0") && (props.name.startsWith("code")));
            sect->setData(props.name.startsWith("data"));
            sect->setEndian(Endian::Little);            // little endian
            sect->setEntrySize(1);                      // No info available
            sect->addDefinedArea(props.from, props.to); // no BSS
        }
    }

    // Create a separate, uncompressed, initialised data section
    BinarySection *dataSection = m_binaryImage->getSectionByName("data0");

    if (dataSection == nullptr) {
        LOG_ERROR("No data section found!");
        return false;
    }

    const BinarySection *code0Section = m_binaryImage->getSectionByName("code0");

    if (code0Section == nullptr) {
        LOG_ERROR("No code 0 section found!");
        return false;
    }

    // When the info is all boiled down, the two things we need from the
    // code 0 section are at offset 0, the size of data above a5, and at
    // offset 4, the size below. Save the size below as a member variable
    m_sizeBelowA5 = UINT4ADDR(code0Section->getHostAddr() + 4);

    // Total size is this plus the amount above (>=) a5
    unsigned sizeData = m_sizeBelowA5 + UINT4ADDR(code0Section->getHostAddr());

    // Allocate a new data section
    m_data = new unsigned char[sizeData];

    if (m_data == nullptr) {
        LOG_FATAL("Could not allocate %1 bytes for data section", sizeData);
    }

    // Uncompress the data. Skip first long (offset of CODE1 "xrefs")
    Byte *p   = reinterpret_cast<Byte *>((dataSection->getHostAddr() + 4).value());
    int start = static_cast<int>(UINT4(p));
    p += 4;
    unsigned char *q = (m_data + m_sizeBelowA5 + start);
    bool done        = false;

    while (!done && (p < reinterpret_cast<unsigned char *>(
                             (dataSection->getHostAddr() + dataSection->getSize()).value()))) {
        unsigned char rle = *p++;

        if (rle == 0) {
            done = true;
            break;
        }
        else if (rle == 1) {
            // 0x01 b_0 b_1
            // => 0x00 0x00 0x00 0x00 0xFF 0xFF b_0 b_1
            *q++ = 0x00;
            *q++ = 0x00;
            *q++ = 0x00;
            *q++ = 0x00;
            *q++ = 0xFF;
            *q++ = 0xFF;
            *q++ = *p++;
            *q++ = *p++;
        }
        else if (rle == 2) {
            // 0x02 b_0 b_1 b_2
            // => 0x00 0x00 0x00 0x00 0xFF b_0 b_1 b_2
            *q++ = 0x00;
            *q++ = 0x00;
            *q++ = 0x00;
            *q++ = 0x00;
            *q++ = 0xFF;
            *q++ = *p++;
            *q++ = *p++;
            *q++ = *p++;
        }
        else if (rle == 3) {
            // 0x03 b_0 b_1 b_2
            // => 0xA9 0xF0 0x00 0x00 b_0 b_1 0x00 b_2
            *q++ = 0xA9;
            *q++ = 0xF0;
            *q++ = 0x00;
            *q++ = 0x00;
            *q++ = *p++;
            *q++ = *p++;
            *q++ = 0x00;
            *q++ = *p++;
        }
        else if (rle == 4) {
            // 0x04 b_0 b_1 b_2 b_3
            // => 0xA9 axF0 0x00 b_0 b_1 b_3 0x00 b_3
            *q++ = 0xA9;
            *q++ = 0xF0;
            *q++ = 0x00;
            *q++ = *p++;
            *q++ = *p++;
            *q++ = *p++;
            *q++ = 0x00;
            *q++ = *p++;
        }
        else if (rle < 0x10) {
            // 5-0xF are invalid.
            assert(false);
        }
        else if (rle >= 0x80) {
            // n+1 bytes of literal data
            for (int k = 0; k <= (rle - 0x80); k++) {
                *q++ = *p++;
            }
        }
        else if (rle >= 40) {
            // n+1 repetitions of 0
            for (int k = 0; k <= (rle - 0x40); k++) {
                *q++ = 0x00;
            }
        }
        else if (rle >= 20) {
            // n+2 repetitions of b
            unsigned char b = *p++;

            for (int k = 0; k < (rle - 0x20 + 2); k++) {
                *q++ = b;
            }
        }
        else {
            // 0x10: n+1 repetitions of 0xFF
            for (int k = 0; k <= (rle - 0x10); k++) {
                *q++ = 0xFF;
            }
        }
    }

    if (!done) {
        LOG_WARN("Compressed data section premature end");
    }

    LOG_VERBOSE("Used %1 bytes of %2 in decompressing data section",
                p - reinterpret_cast<unsigned char *>(dataSection->getHostAddr().value()),
                dataSection->getSize());

    // Replace the data pointer and size with the uncompressed versions

    dataSection->setHostAddr(HostAddress(m_data));
    dataSection->resize(sizeData);

    m_symbols->createSymbol(getMainEntryPoint(), "PilotMain")->setAttribute("EntryPoint", true);
    return true;
}
void FrontEnd::decode(Prog* prog, bool decodeMain, const char *pname) {
	if (pname)
		{prog->setName(pname);
	std::cout<<"decode pname == "<<pname<<"\n";	
}
	else {std::cout<<"decode pname==null\n";}
	if (!decodeMain)
		return;
	
	Boomerang::get()->alert_start_decode(pBF->getLimitTextLow(), pBF->getLimitTextHigh() - pBF->getLimitTextLow());

	bool gotMain;
	ADDRESS a;
	a = getMainEntryPoint(gotMain);
	
	std::cout<< "start: " << a << " gotmain: " << (gotMain ? "true" : "false") << "\n";
	if (VERBOSE)
		LOG << "start: " << a << " gotmain: " << (gotMain ? "true" : "false") << "\n";
	if (a == NO_ADDRESS) {
		std::vector<ADDRESS> entrypoints = getEntryPoints();
		for (std::vector<ADDRESS>::iterator it = entrypoints.begin(); it != entrypoints.end(); it++)
			decode(prog, *it);
		return;
	}

	decode(prog, a);
	
		
	prog->setEntryPoint(a);
			

	if (gotMain) {
		static const char *mainName[] = { "main", "WinMain", "DriverEntry" };
		const char *name = pBF->SymbolByAddress(a);
		std::cout<<"Proc name "<<name<<"\n";
        if (name == NULL)
			name = mainName[0];
		for (size_t i = 0; i < sizeof(mainName)/sizeof(char*); i++) {
			if (!strcmp(name, mainName[i])) {
				Proc *proc = prog->findProc(a);
				if (proc == NULL) {
					if (VERBOSE)
						LOG << "no proc found for address " << a << "\n";
					return;
				}
				FuncType *fty = dynamic_cast<FuncType*>(Type::getNamedType(name));
				if (fty == NULL)
					LOG << "unable to find signature for known entrypoint " << name << "\n";
				else {

					std::cout<<"Sig type:"<<fty->getSignature()->getReturns()[0]->type->prints();
					proc->setSignature(fty->getSignature()->clone());
					proc->getSignature()->setName(name);
					//proc->getSignature()->setFullSig(true);		// Don't add or remove parameters
					proc->getSignature()->setForced(true);			// Don't add or remove parameters
				}
				break;
			}
		}
	}
	return;
}
std::vector<ADDRESS> FrontEnd::getEntryPoints()
{
	std::vector<ADDRESS> entrypoints;
	bool gotMain = false;
	ADDRESS a = getMainEntryPoint(gotMain);
	if (a != NO_ADDRESS)
		entrypoints.push_back(a);
	else {  // try some other tricks
		const char *fname = pBF->getFilename();
		// X11 Module
		if (!strcmp(fname + strlen(fname) - 6, "_drv.o")) {
			const char *p = fname + strlen(fname) - 6;
			while (*p != '/' && *p != '\\' && p != fname)
				p--;
			if (p != fname) {
				p++;
				char *name = (char*)malloc(strlen(p) + 30);
				strcpy(name, p);
				name[strlen(name)-6] = 0;
				strcat(name, "ModuleData");
				ADDRESS a = pBF->GetAddressByName(name, true);
				if (a != NO_ADDRESS) {
					ADDRESS vers, setup, teardown;
					vers = pBF->readNative4(a);
					setup = pBF->readNative4(a+4);
					teardown = pBF->readNative4(a+8);
					if (setup) {
						Type *ty = NamedType::getNamedType("ModuleSetupProc");
						assert(ty->isFunc());
						UserProc *proc = (UserProc*)prog->setNewProc(setup);
						assert(proc);
						Signature *sig = ty->asFunc()->getSignature()->clone();
						const char *sym = pBF->SymbolByAddress(setup);
						if (sym)
							sig->setName(sym);
						sig->setForced(true);
						proc->setSignature(sig);
						entrypoints.push_back(setup);
					}
					if (teardown) {
						Type *ty = NamedType::getNamedType("ModuleTearDownProc");
						assert(ty->isFunc());
						UserProc *proc = (UserProc*)prog->setNewProc(teardown);
						assert(proc);
						Signature *sig = ty->asFunc()->getSignature()->clone();
						const char *sym = pBF->SymbolByAddress(teardown);
						if (sym)
							sig->setName(sym);
						sig->setForced(true);
						proc->setSignature(sig);						
						entrypoints.push_back(teardown);
					}
				}
			}
		}
		// Linux kernel module
		if (!strcmp(fname + strlen(fname) - 3, ".ko")) {
			a = pBF->GetAddressByName("init_module");
			if (a != NO_ADDRESS)
				entrypoints.push_back(a);
			a = pBF->GetAddressByName("cleanup_module");
			if (a != NO_ADDRESS)
				entrypoints.push_back(a);
		}
	}
	return entrypoints;
}