Author:Titan

0x0 引子

Java逆向虽然相比X86/64、ARM等逆向轻松了许多,但是当代码做了混淆后还是很头痛的事。对Java字节码的混淆包括了名称(类、方法、变量)混淆、字符串混淆等。名称混淆好理解,就是把原来有意义的名称替换成无意义的字符组合,更调皮的会替换成如0和o的组合,1和l的组合等,让人看一眼就头皮发麻。字符串的混淆一般会将程序中用到的字符串先用编码函数进行变换,转成看似无意义的字节流,然后在混淆后的程序中使用字符串前调用解码函数将字节流反向变换为原来的字符串。逆向时定位关键代码非常依赖字符串,比如根据日志或窗口中的文字信息回溯程序流程,一般会直接在程序中搜索相关的字符串,然后分析其前后代码。如果字符串被混淆了就必须另寻他法了。

0x1 别人家的刀

Java原生的调试工具可以使用jdb,但缺点是纯命令行操作,显示类名、方法名,设置断点等操作全是敲键盘,浪费生命啊。

eclipse下有个插件Bytecode
Visualizer可以动态可视化调试Java字节码,但非Java源码,效率还是不高。

下一个已知的调试方法是将被逆向的jar包采用jd-gui等工具全部逆向出来,然后导入到eclipse等开发环境中,编译通过后即可实现源代码级的调试。但是,多数情况下这种反编译出来的代码是很难一次性编译通过的,各种错误会搞得你怀疑人生,特别是代码量巨大的项目,debug的工作量直接让你放弃。

另外在网上还找到一个方法也是eclipse中的,基本思路是安装decompiler插件(如jd-eclipse),然后在反编译后的java代码中打断点进行调试。但在实际操作中发现由于eclipse把class文件的关联处理默认为自己的Class
File
Viewer且不方便修改,导致打开class文件时部分文件没法反编译,所以没法进行下一步的动态调试,这种方法也就此打住。

此外,还可以采用IDA等工具进行动态调试,但看到的代码也是字节码,调试界面简陋,能看到的变量信息有限,在此就不再深入了。

0x2 老夫来了

接下来是主角出场了。笔者也是在走投无路、万般无奈的情况下偶尔使用这个工具扒拉扒拉然后奇迹出现了。它其实就是java开发工具的另一巨头:Intellij
IDEA,要实现无源码调试,仅仅使用其开源免费的Community
Edition版本即可。下面详细介绍使用它进行java无源码调试的步骤。使用的调试场景的目的是根据某程序输出的文字信息分析出其背后的程序逻辑。

1.请君入瓮

该程序在不同的输入下输出表现不可预测,大多数情况下会输出正常结果,但在部分情况下会提示错误信息,调试的目的就是要找出程序判断出错的逻辑。

首先我们在IDEA中建立一个空的java工程。

工程里面不需要任何新建的代码,然后把待调试的jar包加入到工程的依赖包中:右键点击工程名,选择Open
Module Setteings。

然后在Libraries中加入待调试的jar文件。

2.抽丝剥茧

下面就可以在工程中进行反编译操作了。在左侧工程中双击想反编译的类,反编译结果会很快出现在右侧窗口中。

IDEA反编译功能依赖其自带的Java Bytecode
Decompiler插件,该插件使用的是Fernflower引擎,目前在github上有1.5k的star,更新活跃,比较靠谱。

由于字符串搜索无果,所以软件作者一定是进行了字符串混淆,我们可以先不管字符串混淆的事,先按名称搜索一遍相关的方法,然后在方法中打上断点,碰碰运气。步骤是选定代码行后在菜单中Run->Toggle
Line Breakpoint。再把待调试的jar包运行起来,运行的时候要加上“-Xdebug
-Xrunjdwp:transport=dt_socket,address=9000,server=y,suspend=n”的选项,保证进程可远程调试。

好了,程序跑起来,在IDEA中Run->Attach to
Process附加到被调试进程。在被调试程序中操作后断点停下来。

是不是很亲切?调用栈,变量值,完全跟有源码调试一样。看上哪个方法,直接断它,回溯调用流程,观察变量值,体验庖丁解牛的快感。

可惜在这一步我并没有发现想要的结果,看来必须和字符串混淆开怼了。

3.蛇打七寸

java中的字符串处理离不开String、StringBuilder这些类,因此,在这些类的处理方法处下断点是对付字符串混淆的利器。闲话休说,在java的rt.jar包中在java.lang.String的构造方法和java.lang.StringBuilder的append方法分别下断点,跑程序,中断太多,咋办?这个时候就需要上条件断点功能了。

在Contition中直接填入判断语句,采用java语法,变量名和反编译中的保持一致。然后再继续跑程序,执行操作,断下来。

这下清晰了,输出特定字符串前的调用栈清清楚楚,剩下的工作就是一步步分析了。

0x3 尾声

IDEA中的反编译界面并不适合做综合分析,还是推荐使用jd-gui、jadx、bytecode-viewer等工具进行分析,然后结合IDEA进行动态调试。上面的功能当然也可以通过hook工具,如网红frida等来实现,但笔者还是偏爱这种easy的gui界面。各位看官,萝卜白菜,各取所需吧。