Beispiel #1
0
def reversed_move_parameters_test():
    print("\nRunning reversed move parameters test")
    print("\ttest/supportActivity_method.smali")

    scd = SmaliClassDef.SmaliClassDef("./test/supportActivity_method.smali")
    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    scd.instrument()
    scd.write_to_file("./test/supportActivity_method_result.smali")

    # the bug here is that v0 was used for the tag propagation on
    # the initial parameter moves, but v0 was used on the second and
    # and therefore did not hold the correct value when it was used
    # later, by the original program

    fh = open("./test/supportActivity_method_result.smali", "r")
    result = fh.readlines()
    fh.close()

    fh = open("./test/supportActivity_method_soln.smali", "r")
    soln = fh.readlines()
    fh.close()

    assert (result == soln)

    print("passed!")
Beispiel #2
0
def on_nested_scrolling_parent_helper():
    print("\nRunning copy1 v0<-v4")
    print("\ttest/onNestedScrollAccepted_method.smali")

    scd = SmaliClassDef.SmaliClassDef(
        "./test/onNestedScrollAccepted_method.smali")

    check_arg_method = scd.methods[0]
    #print("before growing: ", check_arg_method.get_register_meta_data())
    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    #print("after growing: ", check_arg_method.get_register_meta_data())
    scd.instrument()
    scd.write_to_file("./test/onNestedScrollAccepted_method_result.smali")

    fh = open("./test/onNestedScrollAccepted_method_result.smali", "r")
    result = fh.readlines()
    fh.close()

    fh = open("./test/onNestedScrollAccepted_method_soln.smali", "r")
    soln = fh.readlines()
    fh.close()

    assert (result == soln)

    print("passed!")
Beispiel #3
0
def wide_register_has_type_long_string():
    print("\nRunning wide register has type long/string")
    print("\ttest/checkArgumentInRange_method.smali")

    scd = SmaliClassDef.SmaliClassDef(
        "./test/checkArgumentInRange_method.smali")

    check_arg_method = scd.methods[0]
    #print("before growing: ", check_arg_method.get_register_meta_data())
    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    #print("after growing: ", check_arg_method.get_register_meta_data())
    scd.instrument()
    scd.write_to_file("./test/checkArgumentInRange_method_result.smali")

    fh = open("./test/checkArgumentInRange_method_result.smali", "r")
    result = fh.readlines()
    fh.close()

    fh = open("./test/checkArgumentInRange_method_soln.smali", "r")
    soln = fh.readlines()
    fh.close()

    assert (result == soln)

    print("passed!")
Beispiel #4
0
def double_move_result_bug():
    print(
        "\nRunning basic wholistic taint tracking instrumentation tests (double move result bug)..."
    )
    print("\ttest/double_move_result_line.smali")

    scd = SmaliClassDef.SmaliClassDef("./test/double_move_result_line.smali")
    putExtraData_method = scd.methods[0]
    #print(str(putExtraData_method))
    #print(putExtraData_method.get_locals_directive_line())
    assert (str(
        putExtraData_method.get_locals_directive_line()) == ".locals 2")
    #print(putExtraData_method.get_register_meta_data())
    assert (putExtraData_method.get_register_meta_data() ==
            "['v0', 'v1', 'v2/p0', 'v3/p1']")

    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    scd.instrument()
    scd.write_to_file("./test/double_move_result_line_result.smali")

    #print(str(putExtraData_method))
    #print(putExtraData_method.get_locals_directive_line())
    assert (str(
        putExtraData_method.get_locals_directive_line()) == ".locals 6")
    #print(putExtraData_method.get_register_meta_data())
    assert (putExtraData_method.get_register_meta_data() ==
            "['v0', 'v1', 'v2/p0', 'v3/p1', 'v4', 'v5', 'v6', 'v7']")

    result = open("./test/double_move_result_line_result.smali",
                  "r").readlines()
    soln = open("./test/double_move_result_line_soln.smali", "r").readlines()
    assert (result == soln)

    print("passed!")
Beispiel #5
0
def on_start_intent_sender_from_fragment():
    print("\nRunning copy v19<-v0 Imprecise Constant: -128")
    print("\ttest/onStartIntentSenderFromFragment_method.smali")

    scd = SmaliClassDef.SmaliClassDef(
        "./test/onStartIntentSenderFromFragment_method.smali")

    check_arg_method = scd.methods[0]
    #print("before growing: ", check_arg_method.get_register_meta_data())
    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    #print("after growing: ", check_arg_method.get_register_meta_data())
    scd.instrument()
    scd.write_to_file(
        "./test/onStartIntentSenderFromFragment_method_result.smali")

    fh = open("./test/onStartIntentSenderFromFragment_method_result.smali",
              "r")
    result = fh.readlines()
    fh.close()

    fh = open("./test/onStartIntentSenderFromFragment_method_soln.smali", "r")
    soln = fh.readlines()
    fh.close()

    assert (result == soln)

    print("passed!")
Beispiel #6
0
def returning_uninitialized_object():
    # returning uninitialized object
    # Uninitialized Reference: android.support.v4.app.FragmentManagerImpl$AnimationOrAnimator Allocation PC: 462
    # there was an invoke-direct method dropped during instrumentation
    print("\nRunning returning uninitialized object")
    print("\ttest/loadAnimation.smali")

    # this method was truncated just after the instructions relevant
    # to the bug being fixed
    scd = SmaliClassDef.SmaliClassDef("./test/loadAnimation_method.smali")

    check_arg_method = scd.methods[0]
    #print("before growing: ", check_arg_method.get_register_meta_data())
    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    #print("after growing: ", check_arg_method.get_register_meta_data())
    scd.instrument()
    scd.write_to_file("./test/loadAnimation_method_result.smali")

    fh = open("./test/loadAnimation_method_result.smali", "r")
    result = fh.readlines()
    fh.close()

    fh = open("./test/loadAnimation_method_soln.smali", "r")
    soln = fh.readlines()
    fh.close()

    assert (result == soln)

    print("passed!")
Beispiel #7
0
def tried_to_get_class_from_non_reference_register_v0():
    # tried to get class from non-reference register v0 (type=Float)
    print(
        "\nRunning tried to get class from non-reference register v0 (type=Float)"
    )
    print("\ttest/executeOpsTogether_method.smali")

    # this method was truncated just after the instructions relevant
    # to the bug being fixed
    scd = SmaliClassDef.SmaliClassDef(
        "./test/executeOpsTogether_method_truncated.smali")

    check_arg_method = scd.methods[0]
    #print("before growing: ", check_arg_method.get_register_meta_data())
    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    #print("after growing: ", check_arg_method.get_register_meta_data())
    scd.instrument()
    scd.write_to_file("./test/executeOpsTogether_method_result.smali")

    fh = open("./test/executeOpsTogether_method_result.smali", "r")
    result = fh.readlines()
    fh.close()

    fh = open("./test/executeOpsTogether_method_soln.smali", "r")
    soln = fh.readlines()
    fh.close()

    assert (result == soln)

    print("passed!")
Beispiel #8
0
def goto_tracking_bug():
    # [0xC3] copy1 v16<-v0 type=Reference: android.view.View cat=1
    # something wrong with tracking the type of v0 through some
    # complex goto instructions

    print("\nRunning goto_tracking_bug")
    print("\ttest/findReferenceChild_method_minimal.smali")

    scd = SmaliClassDef.SmaliClassDef(
        "./test/findReferenceChild_method_minimal.smali")
    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    scd.instrument()
    #scd.methods[0].cfg.show()
    scd.write_to_file("./test/findReferenceChild_method_minimal_result.smali")

    fh = open("./test/findReferenceChild_method_minimal_result.smali", "r")
    result = fh.readlines()
    fh.close()

    fh = open("./test/findReferenceChild_method_minimal_soln.smali", "r")
    soln = fh.readlines()
    fh.close()

    assert (result == soln)

    print("passed!")
Beispiel #9
0
def wide_register_index_out_of_range_bug_2():
    print("\nRunning wide register index out of range bug 2")
    print("\ttest/makeOpenCloseAnimation_method.smali")

    scd = SmaliClassDef.SmaliClassDef(
        "./test/makeOpenCloseAnimation_method.smali")
    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    scd.instrument()
    scd.write_to_file("./test/makeOpenCloseAnimation_method_result.smali")

    # the bug here is that v19 was used in the moves_before and moves_after
    # but it was used to store a wide value and the method does not allow
    # the user of v20
    # .locals is 15 and there are 5 parameter registers (counting this)
    # so the method uses 20 registers total: v0 - v19

    fh = open("./test/makeOpenCloseAnimation_method_result.smali", "r")
    result = fh.readlines()
    fh.close()

    fh = open("./test/makeOpenCloseAnimation_method_soln.smali", "r")
    soln = fh.readlines()
    fh.close()

    assert (result == soln)

    print("passed!")
Beispiel #10
0
def grow_locals_test_2():
    print("\nRunning grow locals 2 test")
    print("\ttest/Main.smali")

    scd = SmaliClassDef.SmaliClassDef("./test/Main.smali")
    scd.grow_locals(3)
    scd.write_to_file("./test/Main_After.smali")

    print("passed!")
Beispiel #11
0
def type_safety_checker_leaks_test():
    print("\nRunning type safety checker leaks test")

    method_text = open("./test/edge_case_method1.smali", "r").readlines()
    mock_class = SmaliClassDef.MockSmaliClassDef()
    smd = SmaliMethodDef.SmaliMethodDef(method_text, mock_class)
    #print(smd.get_num_registers())
    assert (smd.get_num_registers() == 20)
    #print(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    assert (Instrumenter.MAX_DESIRED_NUM_REGISTERS == 4)
    smd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    smd.instrument()

    print("passed!")
Beispiel #12
0
def strange_insert_lines_at_beginning_placement():
    print("\nRunning strange insert line placement test")
    print("\ttest/constructor_truncated.smali")

    # for some reason the IFT instructions added by stigma for method start
    # were displacing the .locals line?  very strange

    scd = SmaliClassDef.SmaliClassDef("./test/constructor_truncated.smali")
    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    scd.instrument()

    assert (scd.methods[0].get_locals_directive_num() == 20)

    print("passed!")
Beispiel #13
0
def runStigma():
    print("Running Stigma")
    start_time = time.time()
    relevantFilePaths = getFiles()

    # getting list of all classes in this project
    class_names = []
    for path in relevantFilePaths:
        class_names.append(
            SmaliClassDef.SmaliClassDef.extract_class_name(path))

    print("...Instrumenting class files")
    counter = 1
    comparison_instruction_count = 0
    not_enough_registers_count = 0
    total_files = len(class_names)
    for path in relevantFilePaths:
        #print("cur file path: " + str(name))
        # parse file
        scd = SmaliClassDef.SmaliClassDef(path)
        scd.internal_class_names.extend(class_names)

        # analytics stuff
        comparison_instruction_count = comparison_instruction_count + scd.get_num_comparison_instructions(
        )
        for every_method in scd.methods:
            not_enough_registers_count += every_method.not_enough_free_registers_count

        #Progress bar
        print(f'...{str(counter)}/{str(total_files)}', end='\r')
        counter += 1

        # actual instrumentation
        scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
        scd.instrument()
        scd.overwrite_to_file()

    analytics_path = os.path.join(temp_file.name,
                                  getNewAPKName() + "_analytics.dat")
    fh = open(analytics_path, "w")
    fh.write("Number of Comparisons: " + str(comparison_instruction_count) +
             "\n")
    fh.write(
        "Number of instructions in which there were not enough registers to properly instrument: "
        + str(comparison_instruction_count))
    fh.close()

    print("Stigma ran in %.1f seconds" % (time.time() - start_time))
Beispiel #14
0
def type_safety_checker_aget2_test():
    print("\nRunning aget2 test")

    fh = open("test/diffPartial_method.smali", "r")
    method_list = fh.readlines()
    fh.close()
    #print("Building SMD")
    mock_class = SmaliClassDef.MockSmaliClassDef()
    smd = SmaliMethodDef.SmaliMethodDef(method_list, mock_class)
    mock_class.methods.append(smd)
    #print(smd)
    #print("Instrumenting")
    assert (Instrumenter.MAX_DESIRED_NUM_REGISTERS == 4)
    smd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    mock_class.write_to_file("test/diffPartial_method_grown.smali")
    smd.instrument()

    print("passed!")
Beispiel #15
0
def register_listeners():
    print("\nRunning missing move-result bug")
    print("\ttest/register_listeners_method.smali")
    # a move-result was dropped

    scd = SmaliClassDef.SmaliClassDef("./test/register_listeners_method.smali")

    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    scd.instrument()
    scd.write_to_file("./test/register_listeners_method_result.smali")

    fh = open("./test/register_listeners_method_result.smali", "r")
    result = fh.readlines()
    fh.close()

    fh = open("./test/register_listeners_method_soln.smali", "r")
    soln = fh.readlines()
    fh.close()

    assert (result == soln)

    print("passed!")
Beispiel #16
0
def get_class_from_non_reference_register_bug():

    print("\nRunning get class from non reference register bug")
    print("\ttest/endAnimatingAwayFragments_method.smali")

    scd = SmaliClassDef.SmaliClassDef(
        "./test/endAnimatingAwayFragments_method.smali")
    endAnimatingMethod = scd.methods[0]
    #print("before growth")
    #print(endAnimatingMethod)
    #print(endAnimatingMethod.get_register_meta_data())
    #print("\n\n")

    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)

    #print("after growth")
    #print(endAnimatingMethod)
    #print(endAnimatingMethod.get_register_meta_data())

    scd.instrument()
    scd.write_to_file("./test/endAnimatingAwayFragments_method_result.smali")

    # there was a bug demonstrated by this method.  The system was using
    # the registers as "free_regs" even if they were used on a subsequent
    # move-result-* instruction (re: invoke-* and filled-new-array operations)

    fh = open("./test/endAnimatingAwayFragments_method_result.smali", "r")
    result = fh.readlines()
    fh.close()

    fh = open("./test/endAnimatingAwayFragments_method_soln.smali", "r")
    soln = fh.readlines()
    fh.close()

    #print(soln)

    assert (result == soln)

    print("passed!")
Beispiel #17
0
def register_shuffling_test():
    print("\nRunning register shuffling test")
    print("\ttest/custom_class.smali")

    scd = SmaliClassDef.SmaliClassDef("./test/custom_class.smali")
    made_up_method = scd.methods[0]
    #print(made_up_method.get_register_meta_data())
    assert (made_up_method.get_register_meta_data() == str([
        'v0', 'v1', 'v2', 'v3', 'v4', 'v5', 'v6', 'v7', 'v8', 'v9', 'v10',
        'v11', 'v12', 'v13', 'v14', 'v15', 'v16/p0', 'v17/p1', 'v18/p2',
        'v19/p3'
    ]))

    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)

    #print(made_up_method.get_register_meta_data())
    assert (made_up_method.get_register_meta_data() == str([
        'v0', 'v1', 'v2', 'v3', 'v4', 'v5', 'v6', 'v7', 'v8', 'v9', 'v10',
        'v11', 'v12', 'v13', 'v14', 'v15', 'v16/p0', 'v17/p1', 'v18/p2',
        'v19/p3', 'v20', 'v21', 'v22', 'v23'
    ]))

    scd.instrument()
    scd.write_to_file("./test/custom_class_result.smali")

    fh = open("./test/custom_class_result.smali", "r")
    result = fh.readlines()
    fh.close()

    fh = open("./test/custom_class_soln.smali", "r")
    soln = fh.readlines()
    fh.close()

    assert (result == soln)

    print("passed!")
Beispiel #18
0
def stigma_leaks_crash_SupportActivity():
    print("\nTesting grow() functionality...")

    scd = SmaliClassDef.SmaliClassDef("./test/SupportActivity.smali")

    scd.grow_locals(4)
    scd.write_to_file("./test/SupportActivity_After.smali")

    # Make sure locals cannot be grown twice
    smd = scd.methods[0]
    try:
        smd.grow_locals(4)
        assert (False)
    except ValueError:
        pass

    arbitrary_method = scd.methods[0]
    assert (arbitrary_method.has_grown == 4)
    #print(arbitrary_method.top_regs)
    assert (arbitrary_method.top_regs == ['v2', 'v3', 'v4', 'v5'])
    #print(arbitrary_method.first_new_free_reg_num)
    assert (arbitrary_method.first_new_free_reg_num == 2)

    print("passed!")
Beispiel #19
0
def wide_register_index_out_of_range_bug():
    print("\nRunning wide register index out of range bug")
    print("\t(no instrumentation in this test)")

    # I think the bug is related to the move-wide for p3 (the second part of the last (wide) parameter)
    scd = SmaliClassDef.SmaliClassDef("./test/binarySearch_method.smali")
    binarySearchMethod = scd.methods[0]
    #print(binarySearchMethod.get_register_meta_data())
    scd.grow_locals(Instrumenter.MAX_DESIRED_NUM_REGISTERS)
    #print(binarySearchMethod.get_register_meta_data())

    scd.write_to_file("./test/binarySearch_method_result.smali")

    result_fh = open("./test/binarySearch_method_result.smali")
    result = result_fh.readlines()
    result_fh.close()

    solution_fh = open("./test/binarySearch_method_soln.smali")
    solution = solution_fh.readlines()
    solution_fh.close()

    assert (result == solution)

    print("passed!")
Beispiel #20
0
def type_saftey_checker_test3():

    # there is a couple weird strings declared at the start of the A00 method
    scd = SmaliClassDef.SmaliClassDef("./test/0wH.smali")
Beispiel #21
0
def splitSmali():
    print("Accounting For Constant Pool Limits")
    # There are separately enumerated and indexed constant pools for references to strings, types, fields, and methods.
    # https://source.android.com/devices/tech/dalvik/dalvik-bytecode

    # Our stigma instrumentation will add many fields and many classes
    # unfortunately, for a single smali_classesX folder there can only be
    # so many classes, so many fields in all the classes combined,
    # and so many methods in all classes combined .  We typically break
    # those limits.  So, we can resolve the issue by simply moving
    # some files to smali_classesX+1

    # basic algorithm is to place all smali files into a list
    # regardless of existing folder location (smali_classesX)
    # go through the list linearly and count the number of fields
    # in the classes, methods in the classes, and total number of
    # classes.  If any of those goes above THRESH
    # break the list at this point and designate all the files
    # until this point to be in smali_classesY (where Y increments)
    # each time the list is split up
    #
    # resultsLists = [file1, file2, file3] [file4, file5, file6, ...]
    #                                     ^
    #                                     |
    #                                split point
    # (number of fields in file1, 2, 3, and 4 combined is > THRESH)
    #

    THRESH = 32768  # probably isn't the correct threshold
    # max unsigned short: 65535
    # middle-ground: 16384 probably not relevant
    # max signed short: 32767
    # max unsigned byte: 255
    # max signed byte: 127

    smaliFiles = getFiles()

    # see the instructions that correspond to the 4 different
    # countable things: type_id, string_id, field_id,
    # http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html
    # method_id does not exist in that file.  BUT, the
    totalFieldCount = 0
    totalMethodCount = 0

    # missing: strings, classes

    resultLists = []
    s = 0
    e = 0
    for idx, smaliFile in enumerate(smaliFiles):
        #print("file: " + str(smaliFile))
        scd = SmaliClassDef.SmaliClassDef(smaliFile)
        field_num = scd.get_num_field_declarations(
        ) + scd.get_num_field_references()
        method_num = scd.get_num_method_declarations(
        ) + scd.get_num_method_references()

        if (method_num > THRESH):
            # https://github.com/JesusFreke/smali/issues/301
            raise RuntimeError("methods in " + str(smaliFile) +
                               " is greater than threshold. " +
                               str(method_num) + ">" + str(THRESH))

        if (field_num > THRESH):
            # https://github.com/JesusFreke/smali/issues/301
            raise RuntimeError("methods in " + str(smaliFile) +
                               " is greater than threshold. " +
                               str(method_num) + ">" + str(THRESH))

        if ((totalFieldCount + field_num >= THRESH)
                or ((totalMethodCount + method_num) >= THRESH)):

            if ((totalMethodCount + method_num >= THRESH)):
                print(
                    "  ...adjusting to avoid method threshold..."
                )  #at:" + str(scd) + ":   " + str(totalMethodCount) + "->" + str(totalMethodCount + method_num))

            if ((totalFieldCount + field_num >= THRESH)):
                print(
                    "  ...adjusting to avoid field threshold..."
                )  #at:" + str(scd) + ":   " + str(totalFieldCount) + "->" + str(totalFieldCount + field_num))

            # do a break
            e = idx
            resultLists.append(smaliFiles[s:e])
            s = e

            # technical detail that's easy to miss / confuse
            # the file that broke the threshold
            # goes into the NEXT list
            totalFieldCount = field_num
            totalMethodCount = method_num

        else:
            totalFieldCount += field_num
            totalMethodCount += method_num

    print("...Re-arranging files")
    #print(str(len(resultLists)) + " groups")
    for idx, group in enumerate(resultLists):
        path = os.path.join(temp_file.name, "smali/")
        if (idx > 0):
            path = os.path.join(temp_file.name,
                                "smali_classes" + str(idx + 1) + "/")
            os.makedirs(path, exist_ok=True)

        for smaliFile in group:
            newFolderPath = path + extractPathParts(smaliFile, 4, -1)
            #print("newFolderPath: " + str(newFolderPath))
            #print("newFolderPath: " + newFolderPath)
            os.makedirs(newFolderPath, exist_ok=True)

            newFileAbsPath = os.path.join(newFolderPath,
                                          os.path.basename(smaliFile))

            # Some characters need to be
            # escaped in bash shell.  For example
            # smali_classes2/edu/fandm/enovak/leaks/Main$1.smali
            # the $1 will be treated like a variable in bash unless
            # it is escaped or wrapped in quotes
            # refactored according to https://docs.python.org/3/library/subprocess.html
            # shell = true means things like "*" and "~" will be expanded in the shell
            # I DID NOT include shell=true, which means that shell=false.
            # This means that single-quotes or escaping $ is unnecessary.

            # sometimes the system determines that a file should result
            # in the place in which it already resides (smali_classes2 -> smali_classes2)
            # in those cases we don't want to do any mv at all.  Even with -n
            # mv will exit with an error, status 1
            if (smaliFile != newFileAbsPath):
                os.rename(smaliFile, newFileAbsPath)