奎享雕刻1.7.8大刀阔斧的破解记录

查看 167|回复 12
作者:永恒陌   
奎享雕刻1.7.8大刀阔斧的破解记录

author:永恒陌
date:2021年6月23日
本贴仅用于学习交流,禁止用于商业用途
起因
为什么想起来尝试破解这个呢,这是公司用的写字机的上位机,发现里边的程序时java的,插着加密狗,有点好奇java是怎么读狗的,到最后也没研究明白,只研究到了它是调用dll的某个函数读狗的,dll逆向还看不懂
也是因为它是java的,会写java,有初步的了解,才敢下手尝试的。
前言
破解的过程中也是取巧了,没有对解密函数进行分析(实在看不懂),提取了了已有的一个加密狗的生成的值,硬编码到了程序里边,令读狗函数固定返回这个硬编码。
废话也会很多,很详细的记录了过程
心得
勇于尝试,车到山前必有路。

中途遇到了一些小麻烦,反正是解决了。后边详述
正文
工具
[ol]
  • jar包解包工具:

  • winrar(足够了)

  • jar反编译工具:

  • jd-gui-1.6.6.jar
  • jadx-gui-1.2.0-no-jre-win.exe
  • luyten-0.5.4.exe(没用上)

  • class 字节码浏览器

  • jclasslib_win64_5_8.exe

  • 十六进制编辑器

  • 010Editor v11.0.1 汉化特别版

  • dll查看器

  • IDA_Pro_v7.0_Portable


    [/ol]
    最后,写java代码的idea就不用介绍了吧,各位爱用啥用啥就是了
    下载/安装/分析
    下载安装跳过
    [ol]
  • 打开文件夹看看


    1.png (65.24 KB, 下载次数: 1)
    下载附件
    2021-6-23 12:57 上传

    [/ol]
    由于不会exe的逆向,而且体积这么大的一个jar,很值得打开瞧瞧。
    直接用jar反编译工具打开,先找main函数(java的入口函数)
  • 用jadx打开映入眼帘的就是com了,找吧,熟悉的launcher,很顺利,就在这里,那接下来的工作就比较简单了:
    复制这个class的反编译代码,扔idea里开始做手术。
    肯定提示缺包, 将这个大jar包作为lib引入就行(后边才知道,差点死在这一步,jar包没有混淆。我才能顺利的作为lib引入)
    [/ol]


    2.png (101.05 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传
  • 扔idea里之后就可以进行分析啦,上边无非都是读配置,环境检查
    从这里才是引起我注意的代码。
    i只是读了个配置,觉得有用,输出来看看,最后发现,似乎没啥用
    l就是了,l就是读取的加密狗的函数,追进去看看都做了什么操作。
    [/ol]


    3.png (102.67 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传
  • 追l


    4.png (18.56 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    好家伙,就一行,继续追,一眼望去 一堆return "";
    既然是注册码,return "";的统统干掉!


    5.png (118.35 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    代码瞬间清爽了许多,可以看到  这个outstring一定就是狗里的东西了,而上边的DevicePath,ID1,ID2,就肯定是狗的信息了。
    这就是我在这个函数中间写出outsting到文件之后,硬编码到return里了:


    6.png (135.97 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    [/ol]
    然后我还尝试用IDA查看了这个jsyunew3.dll的NewReadString,嗯,压根看不懂。就更没办法写注册机了(加密狗写注册机有毛用!摔!)
    这个类上边有这个名字,这应该就是java加载dll的方式,但是还没研究明白,知道它加载了dll,调用了dll的函数,研究破解来说知道这些够用了,
    就是这行调用了dll,确信,下边这些肯定就是形如接口一样的东西了。
        static {
            System.load(b.e(String.valueOf(String.valueOf(Platform.is64Bit() ? "x64" : "x86")) + "/jsyunew3.dll").getAbsolutePath());
        }
        public static native int GetVersion(final String p0);
        public static native int GetVersionEx(final String p0);
        public static native long GetID_1(final String p0);
        public static native long GetID_2(final String p0);
        public static native long get_LastError();
        public static native String FindPort(final int p0);
        public static native String NewReadString(final int p0, final int p1, final String p2, final String p3, final String p4);
        public static native int ReSet(final String p0);
    然后我就想到了第二个破解思路:能不能让这个return直接返回这个硬编码的字符串,以及那个FindPort函数能不能直接返回一个正确的值,这样就可以比较小的修改了,然后结果就是,不会!然后当场放弃。


    7.png (97.1 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传
  • 编译
    然后就编译呗!用winrar打开jar,把编译后的这个jsyunew3.class替换掉,运行那个.exe,哦吼!


    8.png (23.51 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    那还能怎么办,搜呗,既然是在窗口里,那很有可能在launcher这个里,用jad搜字符串找呗,然后就发现这个玩意果然在,那么,统统注释掉!


    9.png (69.07 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    然后编译,打开!一路确认,然后又来一个,同样的操作,去jad里搜呗。


    10.png (74.18 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    嗯?没有?


    11.png (112.05 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    那肯定在其他类里,又不是只有一个类可以创建窗口,翻!
    结果翻遍了每一个类,没有!
    事情变得复杂了起来。那只有去分析main函数具体都做了什么了,然后看看为什么没有这一个字符串。
  • 回头继续分析main


    12.png (66.13 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    分析得出: 这个while是不断地弹框,如果没有插加密狗,肯定读不出来l 就会是上边第4里边return的空字符串,因为已经硬编码写死返回值了,所以这个while直接跳过,进入最终的KenjoyDrawLauncher.j.a();
  • 追a();
    哟,这不是刚注释了弹窗的那个方法嘛,接着往下看吧


    13.png (128.56 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    继续往下分析,从上往下,这是根据l创建了个json,然后操作了一番,咱这l肯定没有问题,就不管对l做什么了,没有意义。


    14.png (139.68 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    看最后,this.a(jsonObject);
    不用说,追进去。
    长这样


    15.png (137.85 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    简单解释一下代码吧:
    if这里判断了是否存在,追进去看
    b=D.b() 追进去D.b()发现用了core这个文件。那这个core应该也是个jar,然后WinRar打开试试,发现打不开,010打开看文件头,啥也不是。不是jar,往后继续分析代码
    往下看发现,又用到了l,先看看this.a(b) 看看对文件core做了什么
    看不懂(破解到后边看懂了,实则是解密byte流),但是看得出来输出了一个前缀xxx后缀xxx的临时文件,退出时删除,然后最后返回值就是这个临时文件。那咱就去看看!
    把这个临时文件复制出来之后,尝试用WinRar打开,哎呀,打开了,反编译!
  • 反编译!
    直接碰壁,一个源代码都反编译不出来。会不会是jadx不够强大,换换工具试试看,jd,luyten都试了,哪个都不行!


    17.png (41.48 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    先保存一下进度,把这个临时文件重命名成core,替换掉安装目录里的core,然后让上边那个函数返回this.g的,直接返回file(执行了一堆寂寞)
    然后我就去万能的Q群求助了,经过麦兜指点,忽略了一个问题,class的文件头(魔数)不对,不是class的文件头,也是这个时候知道了,文件头还叫魔数
    既然文件头不对,那肯定就是加密了。继续分析!看看哪里解密class文件了!
  • 寻找解密class的地方
    那就继续找第7步第三个图的C.a(this.a(b),bulabulabula);了
    追进去这个a();瞧瞧看,好家伙,继承了ClassLoader,想必就是传说中的类加载器,又是知识盲区,硬着头皮看吧。研究这个玩意是花费时间比较久的。


    18.png (118.89 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    然后接下来再看a里都做了什么,翻来覆去的读。哪都不是解密class的啊!


    19.png (117.35 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    花了很长时间研究,然后后来脑子开窍了,既然是类加载器,那肯定是用来加载class的,既然加载class,文件头又对不上,那么加载之前一定是解密了,这个a里没有, 那肯定就在其他地方,寻找可疑函数。
    最后定位到了findclass,英文直译:寻找类文件,嗯,满足猜想的一个方法。


    20.png (117.95 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    往里看,又发现了可疑方法DecodeClassFile,英文直译:解密类文件!
    可算找到了,接下来事情就明朗了,跟搞core文件思路类似,还是大刀阔斧的修改,修改后如下,为啥要判断呢,因为要替换core里边的class。所以加上之后调试起来方便点。


    21.png (120.62 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    将这个字节数组a,导出成文件的代码如下
    [/ol]
    导出成文件写的代码也比较水,凑合看,这就是上边图例收起来的代码
    也是通过导出s,判断出来传进来的s就是类的包名+类名,然后就这样输出了所有文件
    //尝试输出byte
    String d = s.replace(".","\\");
    File file3 = new File("testtest\\"+d+"class");
    if (!file3.getParentFile().exists()) {
        file3.getParentFile().mkdirs();
    }else {
        file3.renameTo(new File("testtest\\" + d + ".class1"));
    }
    file3.createNewFile();
    OutputStream out3 = new FileOutputStrea(file3);
    InputStream is3 = new ByteArrayInputStrea(a);
    byte[] buff3 = new byte[1024];
    int len3 = 0;
    while((len3=is3.read(buff3))!=-1){
        out3.write(buff3, 0, len3);
    }
    is3.close();
    out3.close();
    为啥要判断文件是否存在,是因为! core这个jar同路径下有大小写不同的两个同名class(混淆过)! 在windows下不区分大小写!然后我就装了个linux虚拟机,又是一上午。下了个arm64的 咋都装不进vmware,后来发现下错了,然后才下了个x86_x64的。然后问百度找linux替换class的命令,鼓捣jdk之类的,放进去了。
  • 一切ok之后!就到了找“再进行操作”字符串的步骤了!
    找到是在core.jar\com\kenjoy\kenjoycnc\k\a这个类里边
    跟上边一样,大刀阔斧的修改,发现无法编译!


    22.png (173.63 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    然后百度后的结果都指向了是因为混淆的原因。
    然后没招了,祭出010editor,比较小剂量的修改,就是反转这两个if的判定结果,一个一个试。先反转第一个的判定结果
    用jclasslib跟010都打开a.class
    jclasslib:


    24.png (132.82 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:57 上传

    根据jclasslib的指示,在010editor里边找到method[0]的code部分的第137行
    010editor:
    然后在jclasslib里点击ifeq,弹出来的页面搜索ifeq,往下看就能看到0x99对应ifeq,与ifeq相反的ifne的值为0x9A。
    接下来只需要将99改为9A然后放回core里试试。


    26.png (136.69 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:58 上传

    打开exe


    27.png (70.8 KB, 下载次数: 0)
    下载附件
    2021-6-23 12:58 上传

    大功告成
    最后
    一边写一边复盘了整个过程,发现有很多地方确实是运气好,比如一开始,壳都没有查,混淆也没看,结果就是没有混淆没有壳,然后我才能很顺利的将第一个jar给反编译之后修改并编译回去。
    最最后
    提供下载链接
    源文件:
    链接:https://pan.baidu.com/s/1L-eCjF739AQD9BDml6_tCQ
    提取码:gvhz
    侵删
    [/ol]

    下载次数, 下载附件

  • wei5383079   

    链接:https://pan.baidu.com/s/1go0hlcv_EpBERK6V-5E9yA
    提取码:52pj
    复制这段内容后打开百度网盘手机App,操作更方便哦
    永恒陌
    OP
      

    哎呀,图插的有问题。23.png对应jclasslib
    永恒陌
    OP
      


    替我咬一口 发表于 2021-7-26 12:11
    楼主的破解被闲鱼挂上卖了。。。。。。挂30的那个就是

    怕是不只一个。
    替我咬一口   

    楼主的破解被闲鱼挂上卖了。。。。。。挂30的那个就是
    xuxiaoman   

    很厉害收藏一波
    bjxiaoyao   

    图文并茂,内容精彩,感谢分享。下载下来慢慢研究,学习楼主的破解思路
    大大连连   

    收藏一波,感谢分享
    smartfind   

    楼主的思路很清晰,值得学习!
    cheng050231   

    crosoft.com (exe 4883ec 28-48) - no sec. Cab/7z/Zip - ovl : install4j / exe4j  Runtime DATA
    这种java有没有例子
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部