CLion程序版权为jetBrains所有、注册码授权为jetBrains及其付费用户所有,本篇只从兴趣出发,研究其程序运行原理。
在上篇: CLion注册码算法逆向分析实录
我们通过结合jdb、jd-gui等工具,静态分析被混淆过的CLion的 clion.jar
中的class信息,顺利拿到了CLion的注册码算法.
但是,如果能在动态调试中分析代码路径,拿注册码并推算法不是更愉快么?本篇将从动态调试的角度展开逆向之旅,作为对上篇的一个补充。
本篇用到的关键技术和工具:
因为没有源代码,而CLion的class经过混淆,且有很多运行时生成的class,所以无法直接通过简单地使用类似 jd-gui
之类的工具来得到java文件。
如果仅仅是名称和控制流混淆,其实还是比较简单的情况,不是太变态的情况下, jd-gui
可以拿到java代码,如果混淆的很厉害,一般也有字节码可以看,所以需要我们对字节码或混淆代码的阅读感觉比较熟练即可。
如果是上面的相对简单的情况,我们可以有耐心地 重建 或者 修补 反编译而来的java代码,以达到调试的目的。
CLion的情况不同,它还有一些运行时生成的类,再加上混淆,使得我们很难仅仅通过反编译来完成动态调试的准备。
办法总比困难多,让我们开始准备动态调试吧!
通过上一篇博文的分析,我们已经熟悉了CLion程序启动的一些代码路径,首先要找到程序的入口函数 main
,并重建它。怎么找呢?
可以通过查看 $CLION_HOME/bin
下的 clion.sh
来看启动参数:
133 MAIN_CLASS_NAME="$CL_MAIN_CLASS_NAME" 134 if [ -z "$MAIN_CLASS_NAME" ]; then #注意这里 135 MAIN_CLASS_NAME="com.intellij.idea.Main" 136 fi ... 176 LD_LIBRARY_PATH="$IDE_BIN_HOME:$LD_LIBRARY_PATH" "$JDK/bin/java" / 177 $AGENT / 178 "-Xbootclasspath/a:$IDE_HOME/lib/boot.jar" / 179 -classpath "$CLASSPATH" / 180 $VM_OPTIONS "-Djb.vmOptionsFile=$VM_OPTIONS_FILES_USED" / 181 "-XX:ErrorFile=$HOME/java_error_in_CL_%p.log" / 182 -Djb.restart.code=88 -Didea.paths.selector=clion10 / 183 $IDE_PROPERTIES_PROPERTY / 184 $IDE_JVM_ARGS / 185 $REQUIRED_JVM_ARGS / #以及这里 186 $MAIN_CLASS_NAME / 187 "$@" 188 EC=$?
也可以让CLion先跑起来,通过 jinfo
来获取,首先通过 jps
和 ps -ef | grep clion
来确认CLion的 pid
:
[haoran@localhost Tools]$ jps 27120 Jps 4001 Main 26953 Main 16911 Launcher
接着输入 jinfo pid
,这里是 jinfo 26953
:
[haoran@localhost Tools]$ jinfo 26953 Attaching to process ID 26953, please wait... Error attaching to process: sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versions are 25.45-b02. Target VM is 25.40-b25 sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versions are 25.45-b02. Target VM is 25.40-b25 at sun.jvm.hotspot.HotSpotAgent.setupVM(HotSpotAgent.java:435) at sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:305) at sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:140) at sun.jvm.hotspot.tools.Tool.start(Tool.java:185) at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118) at sun.jvm.hotspot.tools.JInfo.main(JInfo.java:138)
发现因为 jre/jvm
的版本不匹配,出现了异常,怎么解决呢?
从 clion.sh
入手,看看它如何指定 jvm
:
可以发现, $IDE_HOME
意即CLion安装的路径比 $JAVA_HOME
搜索的顺序更靠前,我们调整这个顺序即可避免 jre/jvm
版本不匹配的问题。
调整后,再次利用 jinfo pid
来查看,得到如下信息:
之所以列举jre/jvm版本不匹配的异常问题,以及通过jinfo来获取程序入口函数所在类的方式,是为后续我们通过 SA 来dump运行时的class及修复java文件扫清障碍。
我们已经得到 main
函数所在的类名为 com.intellij.idea.Main
,但是通过分析,发现其不在 clion.jar
中,那么它在哪里?
我们通过在CLion启动参数中加入-verbose,并将结果重定向到文件中,来分析这个类所在的jar。
如下所示:
接下来,通过 jd-gui
来反编译 bootstrap.jar/com/intellij/idea/Main.class
,并将其java代码导入到我们新建的同名java文件中:
这样的java代码是无法通过编译的,而且因为很多缺失的类都是很重要的依赖,所以无法通过简单的屏蔽来让代码跑起来。
那我们开始修复这些缺失的类,怎么修复呢?
我们可以使用 HotSpot™ Serviceability Agent (SA)
提供的能力,获取运行时的class。当然,获取运行时的class不只这一种方式。
说干就干,classFilter:
编译好这个 classFilter
,按下面的步骤来运行:
java -cp $JAVA_HOME/lib/sa-jdi.jar:. / -Dsun.jvm.hotspot.tools.jcore.filter=$filterName / -Dsun.jvm.hotspot.tools.jcore.outputDir=$dumpedClassOutputDir / sun.jvm.hotspot.tools.jcore.ClassDump $clion_pid # $filterName :我们自定义的classFilter # $dumpedClassOutputDir : 存放dump出的class文件的目录 # $clion_pid :CLion进程pid.
看下我们dump出的classes:
到这一步,已经成功了一大半,接下来,按照你喜欢的方式将这些classes加入 classPath
吧!
还在等什么,赶紧点 run
吧:
嗯,果不其然,很多类还是缺失,对于运行中生成的类,按上面的方法来找,对于已经在 jar
中的类,赶紧找找 classPath
还有什么吧。
还记得上面的 jinfo
吧,祭出:
将这些加入 ClassPath
中。
程序已经越来越接近跑起来的状态,还有一些细碎,奔跑吧骚年!
Q. 此刻有没有一种,买来风扇,涂上硅胶,扣定开关的感觉?A. 要的就是这种能够DIY的工程师感觉嘛~^^
你会发现,后续的运行中,还会出现许多异常,没有关系,通过分析,就知道还有一些东西没有修复,包括:
vm options
我们依然通过 jinfo
方式获取: shell -Xss2m -Xms256m -Xmx768m -XX:MaxPermSize=250m / -XX:ReservedCodeCacheSize=96m -XX:+UseConcMarkSweepGC / ... -XX:ErrorFile=/home/haoran/java_error_in_CL_%p.log / -Djb.restart.code=88 -Didea.paths.selector=clion10 / -Didea.platform.prefix=CLion / -Didea.no.jre.check=true
----------
做完了上面细碎的功夫,来看看我们的成果:
华丽丽的注册码算法!
什么?没有动态调试过程?
有意研究 注册码算法 的同学,请参考上篇博文: CLion注册码算法逆向分析实录 .
我觉得上面的几个 华丽丽的东西 已经足够你
羞涩ing : 撰文不易,若觉得对你有帮助或者博你一笑的,点个推荐吧 :]