test_results_t mov_size_details_Mutator::executeTest() { const unsigned char buffer[] = { 0x66, 0x8c, 0xe8 }; unsigned int size = 3; unsigned int expectedInsns = 2; InstructionDecoder d(buffer, size, Dyninst::Arch_x86); std::deque<Instruction::Ptr> decodedInsns; Instruction::Ptr i; do { i = d.decode(); decodedInsns.push_back(i); } while(i && i->isValid()); if(decodedInsns.size() != expectedInsns) { logerror("FAILED: Expected %d instructions, decoded %d\n", expectedInsns, decodedInsns.size()); for(std::deque<Instruction::Ptr>::iterator curInsn = decodedInsns.begin(); curInsn != decodedInsns.end(); ++curInsn) { logerror("\t%s\n", (*curInsn)->format().c_str()); } return FAILED; } if(decodedInsns.back() && decodedInsns.back()->isValid()) { logerror("FAILED: Expected instructions to end with an invalid instruction, but they didn't"); return FAILED; } Architecture curArch = Arch_x86; Instruction::Ptr mov = decodedInsns.front(); Expression::Ptr lhs, rhs; lhs = mov->getOperand(0).getValue(); rhs = mov->getOperand(1).getValue(); if(lhs->size() != 2) { logerror("LHS expected 16-bit, actual %d-bit (%s)\n", lhs->size() * 8, lhs->format().c_str()); return FAILED; } if(rhs->size() != 2) { logerror("RHS expected 16-bit, actual %d-bit (%s)\n", rhs->size() * 8, rhs->format().c_str()); return FAILED; } return PASSED; }
func_instance *mapped_object::findGlobalDestructorFunc(const std::string &dtorHandler) { using namespace Dyninst::InstructionAPI; const pdvector<func_instance *> *funcs = findFuncVectorByMangled(dtorHandler); if( funcs != NULL ) { return funcs->at(0); } /* * If the symbol isn't found, try looking for it in a call in the * .fini section. It is the last call in .fini. * * The pattern is: * * _fini: * * ... some code ... * * call dtor_handler * * ... prologue ... */ Symtab *linkedFile = parse_img()->getObject(); Region *finiRegion = NULL; if( !linkedFile->findRegion(finiRegion, ".fini") ) { vector<Dyninst::SymtabAPI::Function *> symFuncs; if( linkedFile->findFunctionsByName(symFuncs, "_fini") ) { finiRegion = symFuncs[0]->getRegion(); }else{ logLine("failed to locate .fini Region or _fini function\n"); return NULL; } } if( finiRegion == NULL ) { logLine("failed to locate .fini Region or _fini function\n"); return NULL; } // Search for last call in the function Address dtorAddress = 0; unsigned bytesSeen = 0; const unsigned char *p = reinterpret_cast<const unsigned char *>(finiRegion->getPtrToRawData()); InstructionDecoder decoder(p, finiRegion->getDiskSize(), parse_img()->codeObject()->cs()->getArch()); Instruction::Ptr lastCall; Instruction::Ptr curInsn = decoder.decode(); while(curInsn && curInsn->isValid() && bytesSeen < finiRegion->getDiskSize()) { InsnCategory category = curInsn->getCategory(); if( category == c_CallInsn ) { lastCall = curInsn; break; } bytesSeen += curInsn->size(); curInsn = decoder.decode(); } if( !lastCall.get() || !lastCall->isValid() ) { logLine("heuristic for finding global destructor function failed\n"); return NULL; } Address callAddress = finiRegion->getMemOffset() + bytesSeen; RegisterAST thePC = RegisterAST( Dyninst::MachRegister::getPC(parse_img()->codeObject()->cs()->getArch())); Expression::Ptr callTarget = lastCall->getControlFlowTarget(); if( !callTarget.get() ) { logLine("failed to find global destructor function\n"); return NULL; } callTarget->bind(&thePC, Result(s64, callAddress)); Result actualTarget = callTarget->eval(); if( actualTarget.defined ) { dtorAddress = actualTarget.convert<Address>(); }else{ logLine("failed to find global destructor function\n"); return NULL; } if( !dtorAddress || !parse_img()->codeObject()->cs()->isValidAddress(dtorAddress) ) { logLine("invalid address for global destructor function\n"); return NULL; } // A targ stub should have been created at the address func_instance *ret = NULL; if( (ret = findFuncByEntry(dtorAddress)) == NULL ) { logLine("unable to find global destructor function\n"); return NULL; } inst_printf("%s[%d]: set global destructor address to 0x%lx\n", FILE__, __LINE__, dtorAddress); return ret; }
test_results_t test_instruction_farcall_Mutator::executeTest() { const unsigned char buffer[] = { 0x9A, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF, 0xFE // CALL 0504030201, with FF/FE as fenceposts }; unsigned int size = 7; unsigned int expectedInsns = 2; #if defined(arch_x86_64_test) Architecture curArch = Arch_x86_64; #elif defined(arch_x86_test) Architecture curArch = Arch_x86; #else Architecture curArch = Arch_none; #endif InstructionDecoder d(buffer, size, curArch); std::vector<Instruction::Ptr> decodedInsns; Instruction::Ptr i; do { i = d.decode(); decodedInsns.push_back(i); } while(i && i->isValid()); #if defined(arch_x86_64_test) if(decodedInsns.empty() || !decodedInsns[0] || !decodedInsns[0]->isValid() || decodedInsns[0]->isLegalInsn()) { logerror("FAILED: %s\n", decodedInsns.empty() ? "no instructions decoded" : "first instruction was valid"); return FAILED; } else { logerror("PASSED: far call invalid on AMD64\n"); return PASSED; } #else if(decodedInsns.size() != expectedInsns) // six valid, one invalid { logerror("FAILED: Expected %d instructions, decoded %d\n", expectedInsns, decodedInsns.size()); for(std::vector<Instruction::Ptr>::iterator curInsn = decodedInsns.begin(); curInsn != decodedInsns.end(); ++curInsn) { logerror("\t%s\t", (*curInsn)->format().c_str()); for(unsigned j = 0; j < (*curInsn)->size(); ++j) { logerror("%x ", (*curInsn)->rawByte(j)); } logerror("\n"); } return FAILED; } if(decodedInsns.back() && decodedInsns.back()->isValid()) { logerror("FAILED: Expected instructions to end with an invalid instruction, but they didn't"); return FAILED; } return PASSED; #endif }
func_instance *mapped_object::findGlobalConstructorFunc(const std::string &ctorHandler) { using namespace Dyninst::InstructionAPI; const pdvector<func_instance *> *funcs = findFuncVectorByMangled(ctorHandler); if( funcs != NULL ) { return funcs->at(0); } /* If the symbol isn't found, try looking for it in a call instruction in * the .init section * * On Linux, the instruction sequence is: * ... * some instructions * ... * call call_gmon_start * call frame_dummy * call ctor_handler * * On FreeBSD, the instruction sequence is: * ... * some instructions * ... * call frame_dummy * call ctor_handler */ Symtab *linkedFile = parse_img()->getObject(); Region *initRegion = NULL; if( !linkedFile->findRegion(initRegion, ".init") ) { vector<Dyninst::SymtabAPI::Function *> symFuncs; if( linkedFile->findFunctionsByName(symFuncs, "_init") ) { initRegion = symFuncs[0]->getRegion(); }else{ logLine("failed to locate .init Region or _init function\n"); return NULL; } } if( initRegion == NULL ) { logLine("failed to locate .init Region or _init function\n"); return NULL; } // Search for last of a fixed number of calls #if defined(os_freebsd) const unsigned CTOR_NUM_CALLS = 2; #else const unsigned CTOR_NUM_CALLS = 3; #endif Address ctorAddress = 0; unsigned bytesSeen = 0; unsigned numCalls = 0; const unsigned char *p = reinterpret_cast<const unsigned char *>(initRegion->getPtrToRawData()); InstructionDecoder decoder(p, initRegion->getDiskSize(), parse_img()->codeObject()->cs()->getArch()); Instruction::Ptr curInsn = decoder.decode(); while(numCalls < CTOR_NUM_CALLS && curInsn && curInsn->isValid() && bytesSeen < initRegion->getDiskSize()) { InsnCategory category = curInsn->getCategory(); if( category == c_CallInsn ) { numCalls++; } if( numCalls < CTOR_NUM_CALLS ) { bytesSeen += curInsn->size(); curInsn = decoder.decode(); } } if( numCalls != CTOR_NUM_CALLS ) { logLine("heuristic for finding global constructor function failed\n"); return NULL; } Address callAddress = initRegion->getMemOffset() + bytesSeen; RegisterAST thePC = RegisterAST( Dyninst::MachRegister::getPC(parse_img()->codeObject()->cs()->getArch())); Expression::Ptr callTarget = curInsn->getControlFlowTarget(); if( !callTarget.get() ) { logLine("failed to find global constructor function\n"); return NULL; } callTarget->bind(&thePC, Result(s64, callAddress)); Result actualTarget = callTarget->eval(); if( actualTarget.defined ) { ctorAddress = actualTarget.convert<Address>(); }else{ logLine("failed to find global constructor function\n"); return NULL; } if( !ctorAddress || !parse_img()->codeObject()->cs()->isValidAddress(ctorAddress) ) { logLine("invalid address for global constructor function\n"); return NULL; } func_instance *ret; if( (ret = findFuncByEntry(ctorAddress)) == NULL ) { logLine("unable to create representation for global constructor function\n"); return NULL; } inst_printf("%s[%d]: set global constructor address to 0x%lx\n", FILE__, __LINE__, ctorAddress); return ret; }