我记得IDA(交互式反汇编程序)具有功能签名的真正巧妙的功能,您不必对标准库中发现的工程代码进行反向操作。
Java字节代码是否具有类似的功能,尤其是对于混淆代码?

评论

IDA功能正在使用实际的二进制签名。因为没有二进制签名,所以这种方法对混淆的代码不起作用。

JEB Decompiler具有Java字节码的签名功能。

@ExtremeCoders,但我认为这不适用于混淆函数。

@ LucaD'Amico Ofcourse。签名不适用于混淆的功能。

#1 楼

Java字节码没有类似的功能。

当您编译C程序并将其静态链接到标准库时,该库代码将或多或少未经修改地存在于二进制文件(除了会更改的地址外),但不会暗示任何特定函数在编译之前具有特定名称(除非在编译/链接时启用了调试)。但是,任何给定的函数都具有或多或少固定的字节模式,通过识别这些字节,IDA可以为该函数分配原始名称。

在Java字节码中,无需这样做。无论如何,函数名称,变量名称和类似信息始终存在于已编译的字节码中。 “标准库” rt.jar也不嵌入到字节码中,因此,如果类使用ArrayList,则即使经过混淆处理,该类也将引用java.util.ArrayList。因此,这里不需要进行签名分析器。

如果应用程序也选择混淆标准库,则需要将该混淆后的库包含到其自己的jar文件中。这可能会引起一些许可问题,但除此之外,由于混淆器将重命名方法和字段,因此该混淆的库的字节代码将与原始字节代码相差太大,无法通过IDA的FLIRT之类的功能来识别。此外,您不能只在IDA中重命名该方法,因为您还必须修改所有引用。

但是,至少有一个开源项目存在类似的问题,例如您的,他们似乎已经很好地解决了问题。 《我的世界》是一款受欢迎的游戏,其中包含用Java编写(且经过混淆)的服务器; Spigot项目对该服务器进行反编译,更改某些内容,添加API,然后分发结果。具体来说,为避免许可问题,他们分发了一个构建系统,该系统可以在用户计算机上下载,反编译,修补和重新编译Minecraft服务器。

他们使用fernflower反编译器,该反编译器具有在反编译时重命名符号的选项,并包含混淆到可读的符号名称的详尽映射。例如:

AttributeInstance a ()LIAttribute; getAttribute
AttributeInstance a (D)V setValue
AttributeInstance e ()D getValue
AttributeMapServer b ()Ljava/util/Set; getAttributes
AxisAlignedBB b (DDD)LAxisAlignedBB; grow


使用这些映射生成的源代码显然比原始代码更具可读性。而且,至少对于spigot项目,重新编译此源代码(在添加了一些补丁程序以创建API之后)会产生可正常使用的Minecraft服务器。使用fernflower来反编译您的类,将它们加载到编辑器中以查找一些有用的代码,并分配可读的类名称,编写映射文件,然后重复几次。然后,当您想进行一些动态分析时,请重新编译反编译的Java代码并将其加载到IDA中。

当然,这种方法仍然存在一些问题: />您仍然必须手动识别每个函数-但正如我所说,您可能始终在代码中找不到任何标准库函数。而且,对于您使用的任何方法,都没有现有的签名库,因此可能无法解决。
由于Java反编译器本身的错误/缺点,反编译/重新编译的代码可能无法工作。由于混淆器,反编译/重新编译的代码可能无法正常工作;例如,混淆器可能将所有字符串常量替换为Obfuscator::decode("some_crypted_stuff"),其中decode函数使用调用类的名称作为其解密密钥,这意味着当该类重命名时解密失败。
混淆器可能会自带类加载器,它在加载类名称之前对其进行修饰;例如,它可能知道将com.obfuscate.SOME_BASE_64_STRING类转换为解码的base64字符串,因此com.obfuscate.amF2YS51dGlsLkFycmF5TGlzdAo.something()将调用java.util.ArrayList.something()。这断开了呼叫者和被呼叫者之间的可见连接(但是名称映射可以很好地解决此问题,并且可以实现很多自动化)

即使您无法获得二进制的反编译的,可重新编译的版本,也可以使用一些启发式方法,编写一些可在反编译的源代码上运行的代码,以通过功能识别功能,然后让代码编写一个映射表,并编写一个python插件以将该映射表作为注释导入到您的代码中。

这些方法是否在IDA中击败了手动逆向工程,但存在疑问,因为IDA没有此功能,并且没有通用的签名库(它们无论如何都无法使用,请参见上文),这是我所提供的最好的。

编辑2016-04-17

有一个小项目,我可以自己使用一些模糊化映射,然后进一步检查Minecraft反编译步骤的模糊化过程。

结果,他们甚至不使用fernflowers重新映射功能。相反,他们有自己的一套工具。可悲的是,这些文档的文献不足,但是似乎有一个GitHub Repository。第一个,SpecialSource.jar,将混淆的jar与未混淆的版本进行比较,并生成映射表。当出现混淆后的原始文件的新版本时,这似乎可以快速构建新表。但是,没有关于确切比较的文档。

第二个文件SpecialSource-2.jar直接在jar文件中重新映射类和方法引用以及名称,而无需进行反编译/编译步骤,因此可以避免随之而来的所有问题。因此,一旦有了映射文件,就可以将其应用到jar中,以获取输出jar,然后将其输入IDA或您选择的反编译器中。
用法是

java -jar /path/to/SpecialSource-2.jar map -m mapping.csrg \
-i obfuscated.jar -o readable.jar


映射文件如下所示

# This renames a class, given the obfuscated name and the readable one
com/example/ab/a MyNiceClassName
# This renames a method, given the class, method, signature, and readable name.
MyNiceClassName a (D)I doubleToInt


#2 楼

如果尚未模糊控制流程图,则可以使用那些流程图进行匹配。最大的障碍是建立图书馆签名数据库。

控制流程图是基本块在作为有向图时的结构。 [1]这些代表方法中可能的执行路径。它们相对容易解析并从已编译的应用程序中恢复。大多数Android和Java混淆都侧重于方法名称而不是控制流。同样,如果修改或移动了方法,则Java / Dalvik字节码可以在编译之间更改。在那里比较结构很方便,除非进行重大更改,否则控制流可能保持不变。

我在Android应用程序中对控制流图匹配做了一些工作。 [2] [3]该项目的真正强项是恶意软件应变集群。它会匹配结构相似的方法,并且您会看到某些应用程序与其他应用程序共享方法,以及应变的演变方式。

如果您要创建Java函数签名,请在结构之间进行组合和基于字节的匹配将非常强大。


https://en.wikipedia.org/wiki/Control_flow_graph
https://github.com/douggard/CFGScanDroid
http://www.irongeek.com/i.php?page=videos/derbycon4/t420-control-flow-graph-based-virus-scanning-douglas-goddard


评论


从我花了3分钟浏览回购代码开始,这听起来很有趣,特别是为了将模糊化的可读映射“更新”到更新版本的模糊化二进制文件。您的项目也可以使用.jar文件,还是仅使用dex文件?

–贡特拉姆·布洛姆(Guntram Blohm)
16年4月19日在21:35

尽管只有dex文件,但是大部分代码都可以重用,这只是从类文件中获取字节码并解析出方法的问题。我敢肯定有一个Java库。从Dalvik到Java,CFG提取可能有所不同,但可能没什么大的。

–道加德
16年4月19日在23:58