/**************************************************** * traverse the binary AST ****************************************************/ void RoseBin_FlowAnalysis::visit(SgNode* node) { // cerr << " traversing node " << node->class_name() << endl; if (isSgAsmFunction(node) ) { SgAsmFunction* binDecl = isSgAsmFunction(node); string name = binDecl->get_name(); ostringstream addrhex; addrhex << hex << setw(8) << binDecl->get_address() ; if (name=="") { name=addrhex.str(); binDecl->set_name(name); } SgAsmStatement* stat = NULL; // SgAsmStatementPtrList& list = binDecl->get_statementList(); vector<SgAsmInstruction*> list; FindInstructionsVisitor vis; AstQueryNamespace::querySubTree(binDecl, std::bind2nd( vis, &list )); int sizeList = list.size(); if (sizeList==0) { //cerr << " this function is empty!! " << endl; return; } //if ((func_nr % 1)==0) // if (RoseBin_support::DEBUG_MODE()) // cout << analysisName << " Func Nr: " << (++func_nr) << " blocks:" << // sizeList << " ***************** checking function : " << name << endl; if (forward_analysis) { stat = list.front(); } else { // get the last instruction in a function (backward control flow) stat = list.back(); } ROSE_ASSERT(stat); // if (RoseBin_support::DEBUG_MODE()) //cout << ">>>>>>>>>>>>>. checking statement in function : " << name << " .. " << stat->class_name() << endl; if (isSgAsmInstruction(stat)) { SgAsmInstruction* inst = isSgAsmInstruction(stat); ROSE_ASSERT(inst); // check the control flow of the first instruction in a function string typeFunction ="function"; SgGraphNode* src=NULL; if (analysisName=="callgraph") { // src = vizzGraph->createNode (name, typeFunction, binDecl->get_address(), vizzGraph->graph->get_graph_id(), false, binDecl); src = addCFNode (name, typeFunction, binDecl->get_address(), false, binDecl); } else { //src = vizzGraph->createNode (name, typeFunction, binDecl->get_address(), vizzGraph->graph->get_graph_id(), true, binDecl); //cerr << ">> adding node (f) src: " << RoseBin_support::HexToString(binDecl->get_address()) << endl; src = addCFNode (name, typeFunction, binDecl->get_address(), true, binDecl); string mnemonic=inst->get_mnemonic(); //SgGraphNode* trg = vizzGraph->createNode (mnemonic, typeNode, inst->get_address(), vizzGraph->graph->get_graph_id(),false, inst); //cerr << ">> adding node (first) trg: " << RoseBin_support::HexToString(inst->get_address()) << endl; SgGraphNode* trg = addCFNode (mnemonic, typeNode, inst->get_address(), false, inst); string unp_name = unparseInstructionWithAddress(inst); trg->append_properties(SgGraph::name,unp_name); if (analysisName=="dfa") trg->append_properties(SgGraph::dfa_standard,unp_name); //cerr << "Create edge " << endl; // SgDirectedGraphEdge* edge = vizzGraph->createEdge ( typeFunction, vizzGraph->graph->get_graph_id(), src, binDecl->get_address(), trg, inst->get_address()); SgDirectedGraphEdge* edge = vizzGraph->addDirectedEdge ( src, trg, typeFunction); vizzGraph->setProperty(SgGraph::type, edge, RoseBin_support::ToString(SgGraph::cfg)); } local_visited.clear(); worklist_forthisfunction.push(inst); funcDecl = binDecl; funcDeclNode = src; checkControlFlow(inst, sizeList, sizeList, name, func_nr); } else { if (RoseBin_support::DEBUG_MODE()) cerr << "This is not an Instruction " << endl; } } }
/**************************************************** * process all functions in the DB ****************************************************/ void RoseBin_DB_IDAPRO::process_functions_query(MYSQL* conn, MYSQL_RES* res_set, SgAsmBlock* globalBlock, list<string> functionFilter) { // get the functions rememberFunctions.clear(); //int counter=0; char* q = (char*)"SELECT * FROM functions_1 order by address"; if (RoseBin_support::DEBUG_MODE()) cout << "\n>> QUERY:: " << q << "\n" << endl; res_set = process_query(conn,q); if (res_set == NULL) { print_problemWithResults(conn); } else { MYSQL_ROW row; long address=0; string name = (char*)""; int type=-1; string name_md5 =(char*)""; while ((row = mysql_fetch_row(res_set))!=NULL) { for (unsigned int i=0; i<mysql_num_fields(res_set);i++) { char* ret=(char*)""; if (row[i] ==NULL) { ret = (char*)"<NULL>"; if (i==0) address = -1; if (i==1) name = ret; if (i==2) type= -1; if (i==3) name_md5= ret; } else { ret= row[i]; if (i==0) address = atoi(ret); if (i==1) name = ret; if (i==2) type= atoi(ret); if (i==3) name_md5= ret; } } // demangling ***************************************************** // we need to demangle this function name, so // we can correspond it with the source name char *newName;// = new char[size*2]; int status; size_t length; newName = abi::__cxa_demangle(name.c_str(), 0, &length,&status); // cerr << "converting name : " << name << " status: " << status <<endl; if (status==0) { name =(char*)""; bool found_bracket=false; for (unsigned int i=0; i<length;i++) { if (newName[i]=='(') found_bracket=true; if (found_bracket==false) name += newName[i]; } if (RoseBin_support::DEBUG_MODE()) cout << " demangling name to " << name << endl; } name = getName(name); RoseBin_support::checkText(name); //cerr << " checking for function : " << name << endl; // demangling ***************************************************** // filter : we filter away all kind of functions that are not // relevant == slicing of binaries, relevant = source AST functions // if (functionFilter.size()>0) { // list<string>::iterator filterMe = functionFilter.begin(); // bool skip=true; if (!functionFilter.empty() && std::find(functionFilter.begin(), functionFilter.end(), name) == functionFilter.end()) { continue; } #if 0 for (filterMe;filterMe!=functionFilter.end();++filterMe) { string name_list = *filterMe; // cerr << " comparing strings : " << name_list << " and " << name << endl; if (name_list==name) { // if (name.find(name_list)!=string::npos) skip=false; } } if (skip) continue; #endif // } //make sure we dont get too many nodes, so the visualization works for testing // find me : counter //counter++; //if (counter>50) // break; // -------------------------------------------------------------------------- if (RoseBin_support::DEBUG_MODE()) { ostringstream addrhex; addrhex << hex << setw(8) << address ; cout << ">> creating function : " << address << " " << addrhex.str() << " - " << name << " - " << type << endl; } SgAsmFunction* fd = new SgAsmFunction(); fd->set_address(address); fd->set_name(name); globalBlock->append_statement(fd); fd->set_parent(globalBlock); // added a block between function and instruction to conform to jeremiahs code //SgAsmBlock* block = new SgAsmBlock(); //fd->append_statement(block); //block->set_parent(fd); rememberFunctions[address]= fd ; } // while } // if (res_set==NULL) checkError(conn,res_set); }
SgAsmInstruction* RoseBin_FlowAnalysis::process_jumps_get_target(SgAsmx86Instruction* inst) { if (inst && x86InstructionIsControlTransfer(inst)) { //cerr << " ..................... processing jmp " << endl; ostringstream addrhex3; int addrsource = inst->get_address(); addrhex3 << hex << setw(8) << addrsource ; string funcName =""; // get the operand and the destination address SgAsmOperandList* opList = inst->get_operandList(); ROSE_ASSERT(opList); SgAsmExpressionPtrList ptrList = opList->get_operands(); std::vector<SgAsmExpression*>::iterator itList= ptrList.begin(); for (;itList!=ptrList.end();++itList) { SgAsmExpression* exp = *itList; ROSE_ASSERT(exp); SgAsmRegisterReferenceExpression* regRef = isSgAsmRegisterReferenceExpression(exp); //if (RoseBin_support::DEBUG_MODE()) // cout << " inst (jmp):: " << inst->get_mnemonic() << " addr : " << addrhex3.str() << endl; SgAsmValueExpression* valExpr = isSgAsmValueExpression(exp); SgAsmMemoryReferenceExpression* memExpr = isSgAsmMemoryReferenceExpression(exp); string valStr = ""; if (valExpr) { uint8_t byte_val=0xF; uint16_t word_val=0xFF; uint32_t double_word_val=0xFFFF; uint64_t quad_word_val=0xFFFFFFFFU; valStr = RoseBin_support::resolveValue(valExpr, true, byte_val, word_val, double_word_val, quad_word_val); //if (RoseBin_support::DEBUG_MODE()) //cout << " found value ....... :: " << valStr << endl; funcName = valExpr->get_replacement(); //if (funcName=="") // funcName="noName"; } if (memExpr) { continue; // this is a jump to data ... do not handle right now!! } // convert val string to long uint64_t val=0; if(from_string<uint64_t>(val, valStr, std::hex)) { ostringstream addrhex2; addrhex2 << hex << setw(8) << val ; //if (RoseBin_support::DEBUG_MODE()) //cerr << " looking for value ("<<valStr << " ) in InstrSet: " // << val << " " << addrhex2.str() << endl; rose_hash::unordered_map <uint64_t, SgAsmInstruction* >::const_iterator itc = rememberInstructions.find(val); if (itc!=rememberInstructions.end()) { SgAsmInstruction* target = itc->second; // we set the target (jump to for each control instruction) ROSE_ASSERT(target); //if (RoseBin_support::DEBUG_MODE()) //cout << " >>> target found! " << target << " funcName " << funcName << endl; if (funcName!="") { SgAsmNode* block = target; if (!db) block = isSgAsmNode(target->get_parent()); ROSE_ASSERT(block); SgAsmFunction* func = isSgAsmFunction(block->get_parent()); if (func) { string fname = func->get_name(); uint64_t val_f=0; if(from_string<uint64_t>(val_f, fname, std::hex)) { // func name is a hex number func->set_name(funcName); // inst->set_comment(funcName); } else { // its a name } } } return target; } else { //if (RoseBin_support::DEBUG_MODE()) // cerr << " >>>>>>>>>>>>>>> !!! OPS :: Target not found ... \n" << endl; } } else{ // std::cerr << "FlowAnalysis :: from_string failed .. " << std::endl; if (valStr!="") if (RoseBin_support::DEBUG_MODE()) cerr << " WARNING: Cant convert string to long - in process_jump :: " << regRef->class_name() << " inst :: " << inst->get_mnemonic() << " addr : " << addrhex3.str() << " target : " << valStr << endl; } } } return NULL; }