예제 #1
0
void
detectVirtualTableLoad( SgProject* project )
{
    // This function detects the case of a virtual table address load at "address":
    //    mov edx, <address>
    // In the process of detecting the virtual table loads is adds attributes
    // to the section where the virtual tables are put and builds a list of
    // virtual tables.

    // This is a pointer to the ".rodata" section.
    // What happens if we process multiple DLL's where each has it's own ".rodata" section?
    // This case would suggest that we really do need to fram this as a top-down and bottom-up traversal.
    SgAsmElfSection* vTableSection = getVirtualTableSection(project);
    ROSE_ASSERT(vTableSection != NULL);

#if 0
    // This will return NULL (or generate NULL internally).
    SgAsmInterpretation* asmInterpretation = getAsmInterpretation(vTableSection);
    ROSE_ASSERT(asmInterpretation != NULL);
#endif

    // This is the base and bound of the mapped memory representing the ".rodata" section.
    // NOTE: Now that we compute the ".rodata" section, we should refactor this to be a
    // way to get the bounding addresses of the mapped memory section (and use the
    // vTableSection as a function argument).
    pair<size_t,size_t> readOnlyDataSectionAddressBoundary = getVirtualTableSectionBoundaries(project);
    printf ("Section .rodata boundary: address_base = %p address_bound = %p \n",(void*)readOnlyDataSectionAddressBoundary.first,(void*)readOnlyDataSectionAddressBoundary.second);

    // SgAsmElfSection* textSection = getSection(project,".text");
    // ROSE_ASSERT(textSection != NULL);

    // Pass the project so that we can provide for more analysis capability within the VirtualTableSection abstraction.
    VirtualTableSection* virtualTableSectionAttribute = new VirtualTableSection(vTableSection,project);
    ROSE_ASSERT(virtualTableSectionAttribute != NULL);

    // Add it to the AST (so it can be found later in another pass over the AST)
    vTableSection->addNewAttribute("VirtualFunctionTableSectionAttribute",virtualTableSectionAttribute);

    // Alternative approach using a example and searching the AST for a match against the example.
    // printf ("Alternative approach using a example and searching the AST for a match against the example. \n");

    // General template to use in matching against project.
    // Build a specific instruction to match a specific address (in .rodata, where the vitual function tables are located)
#ifdef USE_NEW_ISA_INDEPENDENT_REGISTER_HANDLING
    SgAsmInstruction* target = SageBuilderAsm::buildx86Instruction(x86_mov,
                               SageBuilderAsm::buildAsmx86RegisterReferenceExpression(x86_regclass_gpr,SgAsmx86RegisterReferenceExpression::e_edx),
                               // Note that the address value is ignored in our "equivalenceTest()" function.
                               SageBuilderAsm::buildAsmDWordValue(0x0));
    printf ("Target instruction = %s \n",unparseInstructionWithAddress(target).c_str());
#else
    // DQ (9/2/2013): This allows us to get the existing code compiled and then move to update the code seperately.
    printf ("This code needs to be updated to handle the new register handling (ISA independence) \n");
    ROSE_ASSERT(false);

    SgAsmInstruction* target = NULL;
#endif

    ROSE_ASSERT(target != NULL);

    // General function to find matching target AST in larger AST.
    std::vector<SgNode*> matchingSubtreeList = find ( project, target, equivalenceTest );

    // Use a set so that after processing all instructions we have the collection of unique entries.
    set<size_t> setOfVirtualFunctionTables;

    for (size_t i = 0; i < matchingSubtreeList.size(); i++)
    {
        // Get the SgAsmInstruction
        SgAsmInstruction* instruction = isSgAsmInstruction(matchingSubtreeList[i]);
        ROSE_ASSERT(instruction != NULL);
        ROSE_ASSERT(instruction != target);

        printf ("Processing instruction %s \n",unparseInstructionWithAddress(target).c_str());

        // Build an attribute (on the heap)
        // AstAttribute* newAttribute = new VirtualTableLoad(instruction);
        VirtualTableLoad* newAttribute = new VirtualTableLoad(instruction);
        ROSE_ASSERT(newAttribute != NULL);

        // Accumulate the set of virtual function table addresses.
        size_t virtualFunctionTableAddress = get_value(newAttribute->virtualTableAddress);
        printf ("virtualFunctionTableAddress = %p \n",(void*)virtualFunctionTableAddress);
        printf ("readOnlyDataSectionAddressBoundary.first = %p second = %p \n",(void*)readOnlyDataSectionAddressBoundary.first,(void*)readOnlyDataSectionAddressBoundary.second);

        // This absolutely needs the extra "()" around both of the inner predicates.
        bool inRange = ((virtualFunctionTableAddress > readOnlyDataSectionAddressBoundary.first) &&
                        (virtualFunctionTableAddress < readOnlyDataSectionAddressBoundary.second));

        printf ("inRange = %s \n",inRange ? "true" : "false");

        // If this is ever false then we will need to introduce a conditional to only handle the true cases.
        // ROSE_ASSERT(inRange == true); // can be false for GNU g++ 4.1.x compilers
        if (inRange == true)
        {
            // Add it to the AST (so it can be found later in another pass over the AST)
            instruction->addNewAttribute("VirtualTableLoad",newAttribute);

            // Collect the virtual table addresses into the set.
            setOfVirtualFunctionTables.insert(virtualFunctionTableAddress);
        }
        else
        {
            // If it is not used then delete the analysis attribute
            delete newAttribute;
            newAttribute = NULL;
        }

#if 0
        string comment = "Virtual Table Load: " + get_valueString(newAttribute->virtualTableAddress);

        printf ("Attaching comment = %s \n",comment.c_str());
        addComment(instruction,comment);
#endif
    }

    printf ("Number of unique virtual function tables = %zu \n",setOfVirtualFunctionTables.size());

    int counter = 0;
    for (set<size_t>::iterator i = setOfVirtualFunctionTables.begin(); i != setOfVirtualFunctionTables.end(); i++)
    {
        // This is the address of each virtual function table.
        size_t virtualFunctionTableAddress = *i;

        // These are the separate virtual function tables objects used to summarize analysis.
        ROSE_ASSERT(virtualTableSectionAttribute->tableExists(virtualFunctionTableAddress) == false);
        if (virtualTableSectionAttribute->tableExists(virtualFunctionTableAddress) == false)
        {
            VirtualFunctionTable* vt = new VirtualFunctionTable(project,vTableSection,virtualFunctionTableAddress);
            ROSE_ASSERT(vt != NULL);

            vt->name = "Class_From_vTable_" + StringUtility::numberToString(counter);

            printf ("vt->name = %s \n",vt->name.c_str());

            // This might be depricated in favor of putting the virtual function table list into globalScopeAttribute.
            virtualTableSectionAttribute->virtualFunctionTableList.push_back(vt);

            // This is the more appropriate place for the list of virtual function tables.
            ROSE_ASSERT(globalScopeAttribute != NULL);
            globalScopeAttribute->virtualFunctionTableList.push_back(vt);

            for (size_t i = 0; i < matchingSubtreeList.size(); i++)
            {
                // Get the SgAsmInstruction
                SgAsmInstruction* instruction = isSgAsmInstruction(matchingSubtreeList[i]);
                ROSE_ASSERT(instruction != NULL);

                VirtualTableLoad* attribute = dynamic_cast<VirtualTableLoad*>(instruction->getAttribute("VirtualTableLoad"));

                // This can be false for GNU g++ 4.1.x compilers
                // ROSE_ASSERT(attribute != NULL);

                if (attribute != NULL)
                {
                    size_t local_virtualFunctionTableAddress = get_value(attribute->virtualTableAddress);
                    if (local_virtualFunctionTableAddress == virtualFunctionTableAddress)
                    {
                        attribute->associatedVirtualTable = vt;
                    }
                    else
                    {
                        attribute->associatedVirtualTable = NULL;
                    }
                }
            }

            counter++;
        }

        // These are the separate virtual function tables.
        // virtualTableSectionAttribute->printOutVirtualFunctionTableInformation(virtualFunctionTableAddress);
    }

    printf ("Adding comments to the instructions \n");

    // Add comments
    for (size_t i = 0; i < matchingSubtreeList.size(); i++)
    {
        printf ("matchingSubtreeList -- i = %zu \n",i);

        // Get the SgAsmInstruction
        SgAsmInstruction* instruction = isSgAsmInstruction(matchingSubtreeList[i]);
        ROSE_ASSERT(instruction != NULL);

        printf ("Getting the VirtualTableLoad attribute \n");

        VirtualTableLoad* attribute = dynamic_cast<VirtualTableLoad*>(instruction->getAttribute("VirtualTableLoad"));

        // This can be false for GNU g++ 4.1.x compilers
        // ROSE_ASSERT(attribute != NULL);

        if (attribute != NULL)
        {
            // This can be false for GNU g++ 4.1.x compilers
            // ROSE_ASSERT(attribute->associatedVirtualTable != NULL);

            if (attribute->associatedVirtualTable != NULL)
            {
                printf ("Building a comment \n");
                printf ("attribute->virtualTableAddress = %p \n",(void*)attribute->virtualTableAddress);
                printf ("attribute->associatedVirtualTable->name = %s \n",attribute->associatedVirtualTable->name.c_str());

                string comment = "Virtual Table Load: name = " + attribute->associatedVirtualTable->name + " " + get_valueString(attribute->virtualTableAddress);

                printf ("Attaching comment = %s \n",comment.c_str());
                addComment(instruction,comment);
            }
        }
    }

    printf ("Leaving detectVirtualTableLoad() \n");
}
예제 #2
0
void
setupVariableDeclartionAttributes ( SgProject* project, vector<SgNode*> instructionList )
   {
  // Refactored code to setup DataMemberInitializationAttribute objects.

     ROSE_ASSERT(project != NULL);

     printf ("dataMemberInitializationWithoutOffsetInMemberFunction(): instructionList.size() = %zu \n",instructionList.size());

  // Keep track of previously referenced variables to avoid redeclaring them in code generation.
  // set<size_t> usedGlobalOffsets;

     for (size_t i = 0; i < instructionList.size(); i++)
        {
       // Add another comment.
          string comment = "This is a reference to variable: ";

       // Get the SgAsmInstruction
          SgAsmInstruction* instruction = isSgAsmInstruction(instructionList[i]);
          ROSE_ASSERT(instruction != NULL);

          DataMemberInitializationAttribute* variableAttribute = dynamic_cast<DataMemberInitializationAttribute*>(instruction->getAttribute("DataMemberInitializationAttribute"));
          ROSE_ASSERT(variableAttribute != NULL);

       // Now add the analysis attribute that represents variables referenced in the binary.
          if (variableAttribute->isStackVariable == true)
             {
            // This is a stack variable reference defined in a function.

            // DQ (9/2/2013): Modified to reflect name change in SgAsmFunctionDeclaration to SgAsmFunction.
            // SgAsmFunctionDeclaration* functionDeclaration = getAsmFunctionDeclaration(instruction);
               SgAsmFunction* functionDeclaration = getAsmFunction(instruction);
               ROSE_ASSERT(functionDeclaration != NULL);

            // This can be either a FunctionAnalysisAttribute or MemberFunctionAnalysisAttribute pointer.
               FunctionAnalysisAttribute* functionAnalysisAttribute = dynamic_cast<FunctionAnalysisAttribute*>(functionDeclaration->getAttribute("FunctionAnalysisAttribute"));
               ROSE_ASSERT(functionAnalysisAttribute != NULL);

            // Add it to the AST (so it can be found later in another pass over the AST)
            // functionDeclaration->addNewAttribute("FunctionAnalysisAttribute",functionAnalysisAttribute);

            // Build an analysis attribute specific to the type of each stack variable reference.
               TypeAnalysisAttribute* asmTypeAttribute = new TypeAnalysisAttribute(variableAttribute->offset,variableAttribute->type);
               ROSE_ASSERT(asmTypeAttribute != NULL);

            // Make up a name for the variable.
            // asmTypeAttribute->name = "stackVar_" + StringUtility::numberToString(i);
               asmTypeAttribute->name = "stackVar_" + generateUniqueName ( variableAttribute->offset, functionAnalysisAttribute->usedScopeOffsets, functionAnalysisAttribute->variableCounter );

            // Improve the comments by adding the stack variable name.
               comment += " variable: " + asmTypeAttribute->name;

            // Add this variable's type to the list of variable types with addresses on the stack.
               functionAnalysisAttribute->stackTypeList.push_back(asmTypeAttribute);
             }
            else
             {
            // This is a global variable reference (used from anywhere in the program).

            // Verify we have a valid pointer (global variable).
               ROSE_ASSERT(globalScopeAttribute != NULL);

               size_t offset = variableAttribute->offset;

            // if (usedGlobalOffsets.find(offset) == usedGlobalOffsets.end())
                  {
                 // Add this entry so that it will not be reused.
                 // usedGlobalOffsets.insert(offset);

                    TypeAnalysisAttribute* asmTypeAttribute = new TypeAnalysisAttribute(offset,variableAttribute->type);
                    ROSE_ASSERT(asmTypeAttribute != NULL);

                 // Make up a name for the variable.
                 // asmTypeAttribute->name = "globalVar_" + StringUtility::numberToString(i);
                    asmTypeAttribute->name = "globalVar_" + generateUniqueName ( variableAttribute->offset, globalScopeAttribute->usedScopeOffsets, globalScopeAttribute->variableCounter );

                 // Improve the comments by adding the globald variable name.
                    comment += " variable: " + asmTypeAttribute->name;

                 // Add this variable's type to the list of variable types with addresses on the stack.
                    globalScopeAttribute->stackTypeList.push_back(asmTypeAttribute);
                  }
             }

       // string comment = "Data member initialization in member function: ";
       // printf ("Attaching comment = %s \n",comment.c_str());
          addComment(instruction,comment);
        }
   }