static bool IsVariableArgumentFormat(AST::Ptr t, AbsRegion &index) { if (t->getID() != AST::V_RoseAST) { return false; } RoseAST::Ptr rt = boost::static_pointer_cast<RoseAST>(t); if (rt->val().op != ROSEOperation::addOp) { return false; } if (rt->child(0)->getID() != AST::V_ConstantAST || rt->child(1)->getID() != AST::V_RoseAST) { return false; } RoseAST::Ptr c1 = boost::static_pointer_cast<RoseAST>(rt->child(1)); if (c1->val().op == ROSEOperation::addOp) { if (c1->child(0)->getID() == AST::V_RoseAST && c1->child(1)->getID() == AST::V_ConstantAST) { RoseAST::Ptr lc = boost::static_pointer_cast<RoseAST>(c1->child(0)); ConstantAST::Ptr rc = boost::static_pointer_cast<ConstantAST>(c1->child(1)); if (lc->val().op == ROSEOperation::invertOp && rc->val().val == 1) { return IsIndexing(lc->child(0), index); } } return false; } return IsIndexing(rt->child(1), index); }
static bool IsIndexing(AST::Ptr node, AbsRegion &index) { RoseAST::Ptr n = boost::static_pointer_cast<RoseAST>(node); if (n->val().op != ROSEOperation::sMultOp && n->val().op != ROSEOperation::uMultOp && n->val().op != ROSEOperation::shiftLOp && n->val().op != ROSEOperation::rotateLOp) return false; if (n->child(0)->getID() != AST::V_VariableAST) return false; if (n->child(1)->getID() != AST::V_ConstantAST) return false; VariableAST::Ptr var = boost::static_pointer_cast<VariableAST>(n->child(0)); index = var->val().reg; return true; }
AST::Ptr ComparisonVisitor::visit(DataflowAPI::RoseAST *ast) { // For cmp type instruction setting zf // Looking like <eqZero?>(<add>(<V([x86_64::rbx])>,<Imm:8>,),) // Assuming ast has been simplified if (ast->val().op == ROSEOperation::equalToZeroOp) { bool minuendIsZero = true; AST::Ptr child = ast->child(0); if (child->getID() == AST::V_RoseAST) { RoseAST::Ptr childRose = boost::static_pointer_cast<RoseAST>(child); if (childRose->val().op == ROSEOperation::addOp) { minuendIsZero = false; subtrahend = childRose->child(0); minuend = childRose->child(1); // If the minuend is a constant, then // the minuend is currently in its two-complement form if (minuend->getID() == AST::V_ConstantAST) { ConstantAST::Ptr constAST = boost::static_pointer_cast<ConstantAST>(minuend); uint64_t val = constAST->val().val; int size = constAST->val().size; if (size < 64) val = ((~val)+ 1) & ((1ULL << size) - 1); else if (size == 64) val = (~val) + 1; else parsing_printf("WARNING: constant bit size %d exceeds 64!\n", size); minuend = ConstantAST::create(Constant(val, size)); } else if (minuend->getID() == AST::V_RoseAST) { RoseAST::Ptr sub = boost::static_pointer_cast<RoseAST>(minuend); minuend = AST::Ptr(); if (sub->val().op == ROSEOperation::addOp && sub->child(0)->getID() == AST::V_RoseAST) { sub = boost::static_pointer_cast<RoseAST>(sub->child(0)); if (sub->val().op == ROSEOperation::invertOp) { // Otherwise, the minuend ast is in the form of add(invert(minuend), 1) // Need to extract the real minuend minuend = sub->child(0); } } } } } if (minuendIsZero) { // The minuend is 0, thus the add operation is subsume. subtrahend = ast->child(0); minuend = ConstantAST::create(Constant(0)); } } return AST::Ptr(); }
AST::Ptr JumpTableFormatVisitor::visit(DataflowAPI::RoseAST *ast) { bool findIncorrectFormat = false; if (ast->val().op == ROSEOperation::derefOp) { // We only check the first memory read if (ast->child(0)->getID() == AST::V_RoseAST) { RoseAST::Ptr roseAST = boost::static_pointer_cast<RoseAST>(ast->child(0)); if (roseAST->val().op == ROSEOperation::derefOp) { // Two directly nested memory accesses cannot be jump tables parsing_printf("Two directly nested memory access, not jump table format\n"); findIncorrectFormat = true; } else if (roseAST->val().op == ROSEOperation::addOp) { Address tableBase = 0; if (roseAST->child(0)->getID() == AST::V_ConstantAST && roseAST->child(1)->getID() == AST::V_VariableAST) { ConstantAST::Ptr constAST = boost::static_pointer_cast<ConstantAST>(roseAST->child(0)); tableBase = (Address)constAST->val().val; } if (roseAST->child(1)->getID() == AST::V_ConstantAST && roseAST->child(0)->getID() == AST::V_VariableAST) { ConstantAST::Ptr constAST = boost::static_pointer_cast<ConstantAST>(roseAST->child(1)); tableBase = (Address)constAST->val().val; } if (tableBase) { Architecture arch = b->obj()->cs()->getArch(); if (arch == Arch_x86) { tableBase &= 0xffffffff; } #if defined(os_windows) tableBase -= b->obj()->cs()->loadAddress(); #endif if (!b->obj()->cs()->isValidAddress(tableBase)) { parsing_printf("\ttableBase 0x%lx invalid, not jump table format\n", tableBase); findIncorrectFormat = true; } if (!b->obj()->cs()->isReadOnly(tableBase)) { parsing_printf("\ttableBase 0x%lx not read only, not jump table format\n", tableBase); findIncorrectFormat = true; } } } } if (findIncorrectFormat) { format = false; } return AST::Ptr(); } if (!findIncorrectFormat) { unsigned totalChildren = ast->numChildren(); for (unsigned i = 0 ; i < totalChildren; ++i) { ast->child(i)->accept(this); } } return AST::Ptr(); }
AST::Ptr SimplifyRoot(AST::Ptr ast, Address addr) { if (ast->getID() == AST::V_RoseAST) { RoseAST::Ptr roseAST = boost::static_pointer_cast<RoseAST>(ast); switch (roseAST->val().op) { case ROSEOperation::invertOp: if (roseAST->child(0)->getID() == AST::V_RoseAST) { RoseAST::Ptr child = boost::static_pointer_cast<RoseAST>(roseAST->child(0)); if (child->val().op == ROSEOperation::invertOp) return child->child(0); } else if (roseAST->child(0)->getID() == AST::V_ConstantAST) { ConstantAST::Ptr child = boost::static_pointer_cast<ConstantAST>(roseAST->child(0)); size_t size = child->val().size; uint64_t val = child->val().val; if (size < 64) { uint64_t mask = (1ULL << size) - 1; val = (~val) & mask; } else val = ~val; return ConstantAST::create(Constant(val, size)); } break; case ROSEOperation::extendMSBOp: case ROSEOperation::extractOp: case ROSEOperation::signExtendOp: case ROSEOperation::concatOp: return roseAST->child(0); case ROSEOperation::addOp: // We simplify the addition as much as we can // Case 1: two constants if (roseAST->child(0)->getID() == AST::V_ConstantAST && roseAST->child(1)->getID() == AST::V_ConstantAST) { ConstantAST::Ptr child0 = boost::static_pointer_cast<ConstantAST>(roseAST->child(0)); ConstantAST::Ptr child1 = boost::static_pointer_cast<ConstantAST>(roseAST->child(1)); uint64_t val = child0->val().val + child1->val().val; size_t size; if (child0->val().size > child1->val().size) size = child0->val().size; else size = child1->val().size; return ConstantAST::create(Constant(val,size)); } // Case 2: anything adding zero stays the same if (roseAST->child(0)->getID() == AST::V_ConstantAST) { ConstantAST::Ptr child = boost::static_pointer_cast<ConstantAST>(roseAST->child(0)); if (child->val().val == 0) return roseAST->child(1); } if (roseAST->child(1)->getID() == AST::V_ConstantAST) { ConstantAST::Ptr child = boost::static_pointer_cast<ConstantAST>(roseAST->child(1)); if (child->val().val == 0) return roseAST->child(0); } // Case 3: if v + v * c = v * (c+1), where v is a variable and c is a constant if (roseAST->child(0)->getID() == AST::V_VariableAST && roseAST->child(1)->getID() == AST::V_RoseAST) { RoseAST::Ptr rOp = boost::static_pointer_cast<RoseAST>(roseAST->child(1)); if (rOp->val().op == ROSEOperation::uMultOp || rOp->val().op == ROSEOperation::sMultOp) { if (rOp->child(0)->getID() == AST::V_VariableAST && rOp->child(1)->getID() == AST::V_ConstantAST) { VariableAST::Ptr varAST1 = boost::static_pointer_cast<VariableAST>(roseAST->child(0)); VariableAST::Ptr varAST2 = boost::static_pointer_cast<VariableAST>(rOp->child(0)); if (varAST1->val().reg == varAST2->val().reg) { ConstantAST::Ptr oldC = boost::static_pointer_cast<ConstantAST>(rOp->child(1)); ConstantAST::Ptr newC = ConstantAST::create(Constant(oldC->val().val + 1, oldC->val().size)); RoseAST::Ptr newRoot = RoseAST::create(ROSEOperation(rOp->val()), varAST1, newC); return newRoot; } } } } break; case ROSEOperation::sMultOp: case ROSEOperation::uMultOp: if (roseAST->child(0)->getID() == AST::V_ConstantAST) { ConstantAST::Ptr child0 = boost::static_pointer_cast<ConstantAST>(roseAST->child(0)); if (child0->val().val == 1) return roseAST->child(1); } if (roseAST->child(1)->getID() == AST::V_ConstantAST) { ConstantAST::Ptr child1 = boost::static_pointer_cast<ConstantAST>(roseAST->child(1)); if (child1->val().val == 1) return roseAST->child(0); } break; case ROSEOperation::xorOp: if (roseAST->child(0)->getID() == AST::V_VariableAST && roseAST->child(1)->getID() == AST::V_VariableAST) { VariableAST::Ptr child0 = boost::static_pointer_cast<VariableAST>(roseAST->child(0)); VariableAST::Ptr child1 = boost::static_pointer_cast<VariableAST>(roseAST->child(1)); if (child0->val() == child1->val()) { return ConstantAST::create(Constant(0 , 32)); } } break; case ROSEOperation::derefOp: // Any 8-bit value is bounded in [0,255]. // Need to keep the length of the dereference if it is 8-bit. // However, dereference longer than 8-bit should be regarded the same. if (roseAST->val().size == 8) return ast; else return RoseAST::create(ROSEOperation(ROSEOperation::derefOp), ast->child(0)); break; case ROSEOperation::shiftLOp: if (roseAST->child(0)->getID() == AST::V_ConstantAST && roseAST->child(1)->getID() == AST::V_ConstantAST) { ConstantAST::Ptr child0 = boost::static_pointer_cast<ConstantAST>(roseAST->child(0)); ConstantAST::Ptr child1 = boost::static_pointer_cast<ConstantAST>(roseAST->child(1)); return ConstantAST::create(Constant(child0->val().val << child1->val().val, 64)); } break; case ROSEOperation::andOp: if (roseAST->child(0)->getID() == AST::V_ConstantAST && roseAST->child(1)->getID() == AST::V_ConstantAST) { ConstantAST::Ptr child0 = boost::static_pointer_cast<ConstantAST>(roseAST->child(0)); ConstantAST::Ptr child1 = boost::static_pointer_cast<ConstantAST>(roseAST->child(1)); return ConstantAST::create(Constant(child0->val().val & child1->val().val, 64)); } break; case ROSEOperation::orOp: if (roseAST->child(0)->getID() == AST::V_ConstantAST && roseAST->child(1)->getID() == AST::V_ConstantAST) { ConstantAST::Ptr child0 = boost::static_pointer_cast<ConstantAST>(roseAST->child(0)); ConstantAST::Ptr child1 = boost::static_pointer_cast<ConstantAST>(roseAST->child(1)); return ConstantAST::create(Constant(child0->val().val | child1->val().val, 64)); } break; default: break; } } else if (ast->getID() == AST::V_VariableAST) { VariableAST::Ptr varAST = boost::static_pointer_cast<VariableAST>(ast); if (varAST->val().reg.absloc().isPC()) { MachRegister pc = varAST->val().reg.absloc().reg(); return ConstantAST::create(Constant(addr, getArchAddressWidth(pc.getArchitecture()) * 8)); } // We do not care about the address of the a-loc // because we will keep tracking the changes of // each a-loc. Also, this brings a benefit that // we can directly use ast->isStrictEqual() to // compare two ast. return VariableAST::create(Variable(varAST->val().reg)); } else if (ast->getID() == AST::V_ConstantAST) { ConstantAST::Ptr constAST = boost::static_pointer_cast<ConstantAST>(ast); size_t size = constAST->val().size; uint64_t val = constAST->val().val; if (size == 32) if (!(val & (1ULL << (size - 1)))) return ConstantAST::create(Constant(val, 64)); } return ast; }