Smali注入代码的最佳位置

时间:2015-06-25 16:31:00

标签: android dalvik smali

我正在创建一个python脚本,为每个方法添加一个跟踪,以便能够在logcat中获取运行时方法调用。

我的应用程序一直崩溃,请不要让我复制错误日志,因为这不是我的问题。 实际上我尝试在注册声明后立即注入我的代码:.locals

我第一次使用.registers指令但由于本地和参数寄存器的别名而出错。

我当时认为我可以使用.locals指令,但它完全相同。

我做的不同测试如下:

  • 如果本地和参数寄存器之间的差异大于2,我使用v0v1
  • 否则我将.locals指令增加了2,我使用了v0v1

但我一直收到VFY错误。

为什么有时候.locals等于0,但有像p0之类的参数。 p0应该为v0设置别名,但.locals为0,那么为什么我要.locals 2更改此设置,只需使用v0v1我仍然得到VFY?

我想在return指令之前添加我的代码,至少只要它不是返回变量我改变一个局部变量就无所谓了

编辑: @JesusFreke感谢您的好评。

我目前正在尝试使用您的建议来改进我的python脚本。所以我创建了一个我在根文件夹中复制的CustomClass,但事实是我循环遍历根文件夹中的所有方法,我得到了存储到变量中的类和方法名称然后我更改了这个参数的值函数,我在每个方法中调用它。

但事实是它无法工作,因为每次输入新方法时静态函数的参数值都会改变,最后它只保留我输入的最后一个方法的值。

在这种情况下,我需要生成尽可能多的静态函数,因为我在smali文件夹中的方法大约是40.000 ...

这是我的代码的一部分:

def edit_custom_class(custom_class_path, my_tag, my_message):
with open(custom_class_path, "r+") as file: 
    for line in file:
        if ('const-string p0' in line):
            file.write('\tconst-string p0, "{0}" \n' .format(my_tag))

        elif ('const-string p1' in line):
            file.write('\tconst-string p1, "{0}" \n' .format(my_message))

        else:
            file.write(line + '\n')


def process_file(file_path, custom_class_path, my_tag, file_metadata):
is_inside = False
valid_registers = []

with open(file_path, "r+") as file: 
    for line in file:
        # we get the data concerning the method and mark it as a treated method
        if (('.method' in line) and (helper.is_valid_class_or_method_directive(line)) and (is_inside == False)):
            is_inside = True
            method_data = get_method_data(helper.get_class_or_method_name(line), file_metadata)
            my_message= (method_data[0] + '->' + method_data[1])
            file.write(line + '\n')

        elif (('return' in line) and (is_inside == True) and (method_data[4] == False)):    
            edit_custom_class(custom_class_path, my_tag, my_message)
            file.write('\t# has been edited by smali-rmc-interceptor on {0} \n' .format(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())))
            file.write('\t# start editing \n')
            file.write('\tinvoke-static, {0};->e(Ljava/lang/String;Ljava/lang/String;)I \n' .format(custom_class_path))
            file.write('\t# end editing \n')
            file.write(line + '\n') 

        elif (('.end method' in line) and (is_inside == True) and (method_data[4] == False)):
            is_inside = False
            method_data = []
            file.write(line + '\n')

        else:
            file.write(line + '\n') 

我的CustomClass内容:

.class public LCustomClass;
.source "CustomClass.java"

.method public static add_trace()V
    .locals 0
    .parameter "tag"
    .parameter "message"

    .prologue   
    .line 10
    const-string p0, "my_tag"

    const-string p1, "my_message"

    .line 15
    invoke-static {p0, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

    .line 18
    return-void
.end method

1 个答案:

答案 0 :(得分:1)

In general, it's easiest to avoid having to allocate new registers in an existing method. This introduces a whole slew of problems due to the register limitations of many instructions. Your best bet is to create a separate static helper method that accepts some values and prints them out or whatever it is you're wanting to do, and then simply inject a static method call in the method that you want to instrument, without allocating any new registers.