/************************************************************ * gets the value of the right (bool=true) hand side * or left hand side of the instruction ***********************************************************/ uint64_t RoseBin_DataFlowAbstract::getValueOfInstr( SgAsmx86Instruction* inst, bool rightSide ) { // bool rightSide specifies // true = checking the right side (of instruction operands) for a registerReference // false = checking the left side (of instruction operands) for a registerReference SgAsmOperandList* opList = inst->get_operandList(); ROSE_ASSERT(opList); uint64_t val = 0xffffffff; int counter=0; int endCounter=0; if (rightSide) endCounter=1; // iterate through the operands (for x86 = 2 operands) SgAsmExpressionPtrList ptrList = opList->get_operands(); for (SgAsmExpressionPtrList::iterator it=ptrList.begin(); it!=ptrList.end(); ++it) { SgAsmExpression* expr = *it; ROSE_ASSERT(expr); // skip the iteration if we do not evaluate the correct side // counter ==0 (left side) counter==1 (right side) if (counter!=endCounter) { counter++; continue; } else counter++; SgAsmValueExpression* valExpr = isSgAsmValueExpression(expr); if (valExpr) { val = getValueInExpression(valExpr); } } return val; }
/************************************************************ * checks if an instruction has a RegisterReference on the * right (bool) or left side. * Return value is meaningless if registerReference return value is false. ***********************************************************/ std::pair<X86RegisterClass, int> RoseBin_DataFlowAbstract::check_isRegister(SgGraphNode* node, SgAsmx86Instruction* inst, bool rightSide, bool& memoryReference, bool& registerReference ) { // bool rightSide specifies // true = checking the right side (of instruction operands) for a registerReference // false = checking the left side (of instruction operands) for a registerReference registerReference = false; SgAsmOperandList* opList = inst->get_operandList(); ROSE_ASSERT(opList); SgAsmx86RegisterReferenceExpression* refExpr =NULL; std::pair<X86RegisterClass, int> code = std::make_pair(x86_regclass_gpr, 0); // meaningless int counter=0; int endCounter=0; if (rightSide) endCounter=1; string operands=""; // iterate through the operands (for x86 = 2 operands) SgAsmExpressionPtrList ptrList = opList->get_operands(); for (SgAsmExpressionPtrList::iterator it=ptrList.begin(); it!=ptrList.end(); ++it) { SgAsmExpression* expr = *it; ROSE_ASSERT(expr); // skip the iteration if we do not evaluate the correct side // counter ==0 (left side) counter==1 (right side) if (counter!=endCounter) { counter++; continue; } else counter++; SgAsmMemoryReferenceExpression* mem = isSgAsmMemoryReferenceExpression(expr); if (mem) { memoryReference = true; SgAsmExpression* memOff = mem->get_address(); if (isSgAsmx86RegisterReferenceExpression(memOff)) { SgAsmx86RegisterReferenceExpression* memRegRef = isSgAsmx86RegisterReferenceExpression(memOff); code = std::make_pair((X86RegisterClass)memRegRef->get_descriptor().get_major(), memRegRef->get_descriptor().get_minor()); registerReference = true; } } refExpr = isSgAsmx86RegisterReferenceExpression(expr); if (refExpr) { code = std::make_pair((X86RegisterClass)refExpr->get_descriptor().get_major(), refExpr->get_descriptor().get_minor()); registerReference = true; } } #if 0 refExpr = isSgAsmx86RegisterReferenceExpression(expr); if (refExpr) { // check if it could be a memory reference // changed by tps on 16Jan08 SgAsmExpression* offset = refExpr->get_offset(); if (isSgAsmMemoryReferenceExpression(offset)) { // is a memory reference memoryReference = true; SgAsmMemoryReferenceExpression* mem = isSgAsmMemoryReferenceExpression(offset); SgAsmExpression* memOff = mem->get_address(); if (isSgAsmx86RegisterReferenceExpression(memOff)) { SgAsmx86RegisterReferenceExpression* memRegRef = isSgAsmx86RegisterReferenceExpression(memOff); code = memRegRef->get_identifier(); registerReference = true; } } else { // is a register reference code = refExpr->get_identifier(); registerReference = true; // } } } #endif return code; }
bool RoseBin_Emulate::evaluateInstruction( SgAsmx86Instruction* binInst, string& operands) { SgAsmOperandList* opList = binInst->get_operandList(); ROSE_ASSERT(opList); //string operands = ""; bool success = true; // *************************************************************** // handle special cases // handle function calls to cpuid and int if (binInst->get_kind() == x86_cpuid) { operands += " :: specialOp cpuid"; //clearRegisters(); rbx = getRandomValue(100); // example return value rcx = getRandomValue(100); // example return value rdx = getRandomValue(100); // example return value return success; } else if (binInst->get_kind() == x86_int) { operands += " :: specialOp Int"; //clearRegisters(); getRegister_val(std::make_pair(x86_regclass_gpr, x86_gpr_ax), RoseBin_support::x86_regpos_qword, rax); // should get the values from memory! string values = ""; rose_hash::unordered_map <uint64_t, uint64_t>::iterator it = memory.begin(); for (;it!=memory.end();++it) { uint64_t loc = it->first; uint64_t val = it->second; string loc_s = RoseBin_support::HexToString(loc); string val_s = RoseBin_support::HexToString(val); values+= "("+loc_s+":"+val_s+")-"; } //uint64_t rbx_v = getMemory(0x1c); //uint64_t rcx_v = getMemory(0x20); //uint64_t rdx_v = getMemory(0x24); if (rax==4) { // sys_write //string values = "" + RoseBin_support::HexToString(rbx_v); //values += "-" + RoseBin_support::HexToString(rcx_v); //values += "-" + RoseBin_support::HexToString(rdx_v); operands += " :: syswrite : "+values; } else { success = false; } return success; } // handle call to rdtsc else if (binInst->get_kind() == x86_rdtsc) { // simulate timer function operands += " :: specialOp rdtsc"; rdx = 0x0ULL; rax = getRandomValue(10); return success; } // ************************************************************** int counter=0; SgAsmx86RegisterReferenceExpression* refExpr =NULL; std::pair<X86RegisterClass, int> code ; RoseBin_support::X86PositionInRegister pos ; // iterate through the operands (for x86 = 2 operands) SgAsmExpressionPtrList ptrList = opList->get_operands(); SgAsmMemoryReferenceExpression* memRef = NULL; for (SgAsmExpressionPtrList::iterator it=ptrList.begin(); it!=ptrList.end(); ++it) { SgAsmExpression* expr = *it; ROSE_ASSERT(expr); //string type = "DWORD"; //string result = unparser->resolveOperand(expr,&type); if (counter==0) { // left hand side ************************************************************* refExpr = isSgAsmx86RegisterReferenceExpression(expr); // check what it could be // ******** 1. its a RegisterReferenceExpression on the left side if (refExpr) { code = std::make_pair((X86RegisterClass)refExpr->get_descriptor().get_major(), refExpr->get_descriptor().get_minor()); pos = get_position_in_register(refExpr->get_descriptor()); operands = "\\nleft :: refExpr "; //SgAsmExpression* expression = refExpr->get_offset(); //memRef = isSgAsmMemoryReferenceExpression(expression); //if (memRef) // operands += " :: memoryRefExp "; operands += "\\n"; } // ******** 2. Its a BitAndByteInstruction else { switch (binInst->get_kind()) { case x86_sete: { // if the instruction is a sete, then we want to check ZF and set the // proper register to 1 if (ZF) { uint64_t qw_val=1; assignRegister(code, qw_val); ZF=false; } break; } case x86_dec: { uint64_t left = getRegister(code); assignRegister(code, --left); break; } default: { success = false; } } } } else { // right hand side ************************************************************ SgAsmValueExpression* valExp = isSgAsmValueExpression(expr); SgAsmx86RegisterReferenceExpression* refExprR = isSgAsmx86RegisterReferenceExpression(expr); uint8_t b_val=0xF; uint16_t w_val=0xFF; uint32_t dw_val=0xFFFF; uint64_t qw_val=0xFFFFFFFF; // check what it could be // ****** 1. valueExpression if (valExp) { // value expr operands += "right :: valExp "; RoseBin_support::resolveValue(valExp, false, b_val, w_val, dw_val, qw_val); uint64_t val = 0xFFFFFFFF; if (b_val!=0xF) val = uint64_t(b_val); else if (w_val!=0xFF) val = uint64_t(w_val); else if (dw_val!=0xFFFF) val = uint64_t(dw_val); else if (qw_val!=0xFFFFFFFF) val = uint64_t(qw_val); if (refExpr) { switch (binInst->get_kind()) { // mov instruction case x86_mov: { operands += " :: DataTrans :: Mov "; assignRegister(code, pos, b_val, w_val, dw_val, qw_val); uint64_t addr_value=0; getRegister_val(code, RoseBin_support::x86_regpos_qword, addr_value); //string str=""; //string var = createVariable(addr_value, str, type, description, length); //string varHex = RoseBin_support::HexToString(addr_value) ; //operands += "\\nVariable : " + var + "("+varHex+")"; break; } case x86_and: { operands += " :: Logical :: And"; uint64_t reg = getRegister(code); operands+=printRegister("reg",reg); operands+=printRegister("val",val); reg &= val; assignRegister(code, reg); if (reg==0) ZF = true; else ZF=false; break; } case x86_add: { operands += " :: Arithm :: Add"; uint64_t left = getRegister(code); uint64_t sum = left+val; assignRegister(code, sum); break; } default: success = false; } } // refExp else { success = false;} } // valExp else if (refExprR) { // ****** 2. referenceExpression // the right hand side is also a register or memory location std::pair<X86RegisterClass, int> codeR ; RoseBin_support::X86PositionInRegister posR ; codeR = std::make_pair((X86RegisterClass)refExprR->get_descriptor().get_major(), refExprR->get_descriptor().get_minor()); posR = get_position_in_register(refExprR->get_descriptor()); operands += "right :: refExpr "; switch (binInst->get_kind()) { case x86_mov: { operands += " :: DataTrans :: Mov"; if (memRef) { operands += " :: MemRef "; SgAsmExpression* mem_loc = memRef->get_address(); string res = unparseExpression(mem_loc); uint64_t pos = 0; RoseBin_support::from_string<uint64_t>(pos, res, std::hex); uint64_t value = getRegister(codeR); assignMemory(pos, value); operands += "["+res+"] "+" ("+RoseBin_support::HexToString(pos)+":"+RoseBin_support::HexToString(value)+")"; } else { operands += " :: RegRef "; // copy value in right register to left register getRegister_val(codeR, posR, b_val, w_val, dw_val, qw_val); assignRegister(code, pos, b_val, w_val, dw_val, qw_val); } break; } //mov instruction case x86_cmp: { operands += " :: Arith :: Cmp"; uint64_t left = getRegister(code); uint64_t right = getRegister(codeR); if (left==right) ZF=true; break; } default: { success =false; } } } //refExprR else { success =false;} } counter++; } operands += "\\n"; return success; }
/************************************************************ * checks if an instruction has a RegisterReference on the * right (bool) or left side ***********************************************************/ int64_t RoseBin_DataFlowAbstract::check_isRegister(SgGraphNode* node, SgAsmx86Instruction* inst, std::pair<X86RegisterClass, int> codeSearch, bool rightSide, vector<std::pair<X86RegisterClass, int> >& regsOfInterest, bool& cantTrack ) { // bool rightSide specifies // true = checking the right side (of instruction operands) for a registerReference // false = checking the left side (of instruction operands) for a registerReference int64_t res = 0xFFFFFFFF; SgAsmOperandList* opList = inst->get_operandList(); ROSE_ASSERT(opList); SgAsmx86RegisterReferenceExpression* refExpr =NULL; std::pair<X86RegisterClass, int> code ; //SgAsmx86RegisterReferenceExpression::x86_position_in_register_enum pos ; //SgAsmMemoryReferenceExpression* memRef = NULL; int counter=0; if (rightSide) counter =-1; else counter = 2; string operands=""; bool foundECX = false; int64_t newVal = 0xFFFFFFFF; // iterate through the operands (for x86 = 2 operands) SgAsmExpressionPtrList ptrList = opList->get_operands(); for (SgAsmExpressionPtrList::iterator it=ptrList.begin(); it!=ptrList.end(); ++it) { SgAsmExpression* expr = *it; ROSE_ASSERT(expr); if (rightSide) counter++; else counter--; if (counter==0) { // left hand side if rightSide=true ************************************************************* // right hand side if rightSide=false ************************************************************* SgAsmValueExpression* valExp = isSgAsmValueExpression(expr); refExpr = isSgAsmx86RegisterReferenceExpression(expr); // ****** 1. valueExpression if (valExp) { // value expr newVal = getValueInExpression(valExp); operands += " <<left :: value " +RoseBin_support::HexToString(newVal)+">>"; } // ****** 2. referenceExpression else if (refExpr) { // ****** 2. referenceExpression // the right hand side is also a register or memory location code = std::make_pair((X86RegisterClass)refExpr->get_descriptor().get_major(), refExpr->get_descriptor().get_minor()); operands += " << left :: refExpr >> "; // we need to track the value of the register in order to find out its value vector<std::pair<X86RegisterClass, int> >::iterator it = regsOfInterest.begin(); for (;it!=regsOfInterest.end();++it) { std::pair<X86RegisterClass, int> codeI = *it; if (codeI==codeSearch) { newVal = trackValueForRegister(node, codeSearch, cantTrack, refExpr); break; } } } else { cerr << " unhandled case in checkVariables " << expr->class_name() << endl; exit(0); } } else { // right hand side if rightSide=true ************************************************************ // left hand side if rightSide=false ************************************************************ SgAsmx86RegisterReferenceExpression* refExprR = isSgAsmx86RegisterReferenceExpression(expr); if (refExprR) { code = std::make_pair((X86RegisterClass)refExprR->get_descriptor().get_major(), refExprR->get_descriptor().get_minor()); operands += " <<right :: refExpr>> "; if (code==codeSearch) foundECX=true; } } } if (foundECX) res = newVal; /* if (RoseBin_support::DEBUG_MODE()) cout << " >> checkRegister : " << RoseBin_support::HexToString(res) << " -- " << operands << " foundReg: " << RoseBin_support::resBool(foundECX) << endl; */ return res; }
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; }