Dalvik字节码检测-寄存器类型合并

时间:2019-05-22 11:55:21

标签: dalvik smali

我正在使用dexlib2做某种dalvik字节码检测。 但是,还有两个问题。 goto指令后似乎发生的寄存器类型合并 并以某种方式准确地在相应的标签上捕获块 派生出意外的寄存器类型,这反过来会破坏所检测的代码。

要插入的说明如下:

move(-wide,-object,/16,/from16) vNew, v0
const-string v0, "some string"
invoke-static, {v0}, LPathToSomeClass;->SomeMethod(Ljava/lang/String;)V
move(..) v0, vNew

因此,v0用于保存静态函数调用的某些参数,而 vNew是一个新的(本地)寄存器,用于存储和还原v0的原始内容。 v0的寄存器类型是预先导出的,以便导出权限 移动指令,即全范围移动,移动或移动对象。但是,当此代码包含在某些try块中时,检测将中断。输出 baksmali(baksmali d -b“” --register-info ALL,FULLMERGE --offsets) 揭示const字符串指令之后的v0类型(即Reference,L / java / lang / String)被视为合并过程的输入,例如在相应的catch-block标签处发生的合并过程。假定插入代码之前的类型是Reference,[I(int array) 现在的类型为Reference,L / java / lang / Object(这会产生验证错误),尽管最后的移动指令将恢复原始的寄存器类型。

现在我的问题是

1)这种合并何时真正发生?

2)为什么合并过程考虑了const-string指令后的v0类型?是否在考虑每条指令修改任何寄存器的类型?

3)此问题仅与try-catch块有关吗?

4)在此情况下,try-catch块有哪些限制?

5)除了为每个不带参数的要注入的代码构造自己的方法之外,是否有解决此问题的方法?那么有可能使用一个额外的寄存器来解决这个问题吗?

6)我可以使用dexlib2 try-catch块进行检测并确定它们包括的指令集吗?

7)是否有任何笔记/文献讨论此问题,例如合并程序及相关技术,例如进一步的限制/限制 用于仪器?

我非常感谢您对此事的帮助。预先感谢!

1 个答案:

答案 0 :(得分:0)

在catch块的开始处合并寄存器时,try块中的每条指令都会有输入边沿抛出。仅某些指令可以抛出-由CAN_THROW操作码标志确定。

在您的特定示例中,const-string指令之后的invoke-static指令可能会抛出,因此从该指令之前到catch块的开始都有一条边缘。

如果您退后一步,则执行可以从try块中可以抛出的所有指令跳转到catch块的开始。因此,必须在catch块中的代码准备好使寄存器处于与寄存器内容一致的状态,就在任何可能抛出的指令之前。

因此,例如,如果存在一个从try块到catch块的可能的“跳转”,其中寄存器包含原始int类型,而另一个可能的跳转是其中包含一个对象的跳转,则该寄存器被视为“冲突” ,因为寄存器此时在代码中可能包含两种类型,并且两种类型彼此不兼容。例如。原始int永远不能传递给期望引用类型的对象,反之亦然。而且字节码中没有用于静态寄存器类型检查的机制。

一种可能的解决方案可能是在插入仪器的位置拆分try块,以使该仪器本身不被try块覆盖,但是原始代码的两面都被覆盖。并且请记住,在字节码中,同一个catch块可以被多个try块使用,因此您可以将原始try块分成两个,并且都引用原始catch块。

否则,您只需要找出某种方法来适当地管理寄存器即可避免此问题。

关于6),请参见MethodImplementation.getTryBlocks(),它将为您提供该方法中的try块列表。每个try块都指定它的开始位置,覆盖的指令数量以及与其关联的所有catch块(针对不同异常的不同catch块)。