0x00

   很久没写文章了,好多朋友问我博客是不是废了。。其实主要是没什么可写的,大部分内容都是大同小异,换汤不换药。BTW HVV躺枪了,希望大家关注过程就可以了,不要过多解读,很多人要吃饭。

0x01

  对某款游戏跟踪了很多年(buwuzhengye),以前基于Unity3d的时候也对源代码分析过。但是后来还是没干做了嘴上的巨人。
最近看某款游戏出了个辅(wai)助(gua)软件。开始以为是基于按键精灵来搞定的。后来真正拿到软件发现并不是和我的想法一致。

0x02

  软件整体布局如下

0x01
0x01

  可以看到很明显是java进行开发同时在使用教程中还给小白写了如何配置TShark到系统环境变量。

  猜测整体运行逻辑如下:

0x02
0x02

0x03

   文件夹排除教程类一共有4个文件:

  • lords.jar ---程序主要逻辑和运行文件

  • ShanHai.lua ---lua脚本(按键精灵)

  • start.bat ---启动java bat

  • 掉盾扫描脚本-ui.mqb ---直观未知

  先看比较清晰的ShanHai.lua以及start.bat

  • ShanHai.lua 通过搜索发现是个按键精灵的库
  • start.bat
java -javaagent:lords.jar -jar -Xms1024m -Xmx1024m -Djava.io.tmpdir=D:\lords\data\Temp lords.jar

java 临时缓存在D:\lords\data\Temp

  • 掉盾扫描脚本-ui.mqb

0x03
0x03

通过查看文件头(504B0304)发现是zip压缩。解压缩后:

0x04
0x04

直接用txt打开发现是lua脚本调用了前面说的ShanHai.lua模块

0x05
0x05

其他两个文件为按键精灵的UI文件。

0x04

   到这我们已经把其他文件都进行了分析只差lords.jar这个核心文件了。
   常规操作把lords.jar放入jad.exe反编译一下看看

0x06
0x06

  浏览了一下org.springframework.boot.loader,并没有发现核心代码,但是注意到net.roseboy.classfinal内部存在JarDecryptor类,猜测是加密。通过查询github发现
ClassFinal-github)

0x07
0x07

ClassFinal是一款java class文件安全加密工具,支持直接加密jar包或war包,无需修改任何项目代码,兼容spring-framework;
可避免源码泄漏或字节码被反编译。

  作者还是对软件做了一些处理,怪不得无法找到一些核心内容。
  继续查看jar文件发现了META-INF下的.classes存在大量加密文件。

0x08
0x08

0x05

  目前我们发现META-INF下的.classes存在大量加密文件,必须通过解密他们才能获得运行逻辑。那么我们在过程中发现net.roseboy.classfinal内部存在JarDecryptor类,只能试试通过此类尝试还原加密文件。
JarDecryptor类中存在下面这些方法

0x09
0x09

我们看到有个doDecrypt

public byte[] doDecrypt(String projectPath, String fileName, char[] password) 

参数需要一个密码才能彻底完成运行。那么继续往下找发现readPassFromJar

  public static char[] readPassFromJar(File workDir) {
    byte[] passbyte = readEncryptedFile(workDir, "org.springframework.config.Pass");
    if (passbyte != null) {
      char[] pass = StrUtils.toChars(passbyte);
      return EncryptUtils.md5(pass);
    } 
    return null;
  }

  如果想知道密码就得调用这个方法。那么我们用最笨的方法,改写这个JarDecryptor类添加main方法,让我们可以用readPassFromJar和doDecrypt。
在JarDecryptor添加如下代码

      public static void main(String[] args) {
          System.out.println(JarDecryptor.readPassFromJar(new File("D:\\lords\\lords\\")));
      }

通过javac生成class文件

    javac -cp lords.jar JarDecryptor.java

替换原有class文件

0x10
0x10

之后我们尝试调用JarDecryptor

    java -javaagent:lords.jar net.roseboy.classfinal.JarDecryptor

0x11
0x11

目前我们得到了密码,那么下一步就是要调用doDecrypt。继续修改JarDecryptor的main方法。

      public static void main(String[] args) {
          String names = "application.properties";
          JarDecryptor jarde = new JarDecryptor();
          byte[] resu1 = jarde.doDecrypt("D:\\lords\\lords\\",names,JarDecryptor.readPassFromJar(new File("D:\\lords\\lords\\")));
          IoUtils.writeFile(new File("D:\\lords\\lords\\" + names + ".class"),resu1);
          System.out.println(resu1);
      }

继续替换以及运行

0x12
0x12

发现在文件夹已经完成了解密。

0x13
0x13

0x14
0x14

包含了明文的密码以及服务ip等。

0x06

  这样太麻烦了,每次都要去覆盖,既然我们知道了密码以及方法。有没有更简单的方法?如果我们把lords.jar当成lib去调用是否也可以完成解密?
  说干就干!
我们写一个detest类调用JarDecryptor
detest.java

import net.roseboy.classfinal.JarDecryptor;
import java.io.File;
import net.roseboy.classfinal.util.IoUtils;


public class detest {
    public static void main(String[] args) {
        File file = new File("D:\\lords\\lords\\META-INF\\.classes\\");
        File[] array = file.listFiles();
        for(int i=0;i<array.length;i++){
            if(array[i].isFile()){
                JarDecryptor jarde = new JarDecryptor();
                byte[] result = jarde.doDecrypt("D:\\lords\\lords\\",array[i].getName(),"41082bc542a1703e00123401154771be".toCharArray());
                IoUtils.writeFile(new File("D:\\lords\\lords\\decodes\\" + array[i].getName() + ".class"),result);
                System.out.println(array[i].getName());
            }
        }
    }
}

尝试运行:

    java -cp lords.jar detest.java

0x15
0x15

0x16
0x16

后面发现

  • org.springframework.config.Pass
  • org.springframework.config.PassHash

有报错,原因是本身就是明文。。。。
不管了去看看解密后的文件

0x17
0x17

扔到jad

0x18
0x18

到这里基本就是结束了,已经完全还原了源代码))

0x07

  通过分析,发现他是通过WireShark的TShark对本地互联网网卡进行抓包后经过数据包分析上传到云端服务器通过 Redis 与RabbitMQ 来实现消息以及存储。通过不知名开源Web改装成Web前端去完成页面。
  作者能拿到游戏厂商或者说能分析数据包?猜测是由于前期游戏厂商对游戏的逻辑进行简单的异或处理并没有做其他的加密导致拿到了源代码,毕竟游戏厂不能因为这个把源代码逻辑全部重写(参见)。目前由于Unity3d进行了版本升级无法看见源代码了只能看到一些函数的名称。
  作者提供了很好的思路来解决某些情况下可以使用类似这种方法对某种通信方式进行分析。同时厂商也没有做到最基础的通信加密)

Comments
Write a Comment
  • Watermankao reply

    不错的文章,用文中方法解开了一个加密的jar,稍有差别的是,我这jar加了密码不是jar默认的密码文件里存的,文件名也有点差别是PassHash.比较费解的是运行这个jar需要用密码也就是用于解密class的密码,这密码必须告诉使用者,才能使用jar,那这密加的还有啥意义

    • Root reply

      @Watermankao 防君子不防小人。可能对安全还处于初级阶段。

  • 哦哦哦 reply

    解密后的代码 进行修改了,还能够编译回到员jar里面去运行吗?

    • MythHack reply

      @哦哦哦 能。另外改代码不一定需要编译回去,有其他方法也可以。不局限于编译回去。。

  • 哦哦哦 reply

    我只是会需要对很小部分功能做一些简单的调整,有什么方法吗?可以简单说一下吗,我去研究研究。最近在对这方面进行一些学习,但是感觉很困难,哈哈!!谢谢~~

    • MythHack reply

      @哦哦哦 如果没有做混淆,完全可以把整个工程编译回去。如果有,还得看具体要改动的地方。逻辑上javac -cp 应该就可以满足你的要求(可以参考文章上写的部分,举一反三),然后把出来的class替换回去(记得备份)。还有就是通过反射、javaagent等形式。