首页
社区
课程
招聘
[求助]Java编写的某行业软件逆向分析(Senxxxxx RXX保护)
2007-8-30 16:25 22513

[求助]Java编写的某行业软件逆向分析(Senxxxxx RXX保护)

2007-8-30 16:25
22513
感谢各位对我的帮助,高手就不要看了,以下内容现在回想起来真是很幼稚,破解思路完全错误,从lic上入手才是正确的方向。

这两天因学习需要,研究起了一款行业软件的逆向。该软件是Java编写的,主要功能就是作为服务器提供网络服务。
    软件的许可方式是发布文件许可,以计算机名+时间为限制,条件全符合方可正常运行服务。因为许可服务那里有几个这样的文件,故确定是 Senxxxxx RxXX保护的:StartSenLM.bat、lservnt.exe、loadls.exe。
    因为有关Java的逆向分析文章简直是太少了,仅找到过一篇像样的,主要是关于如何解包jar,反编译Class文件为java文件,或者根据JVM指令查找相应Class文件中的二进制指令并用HEX修改器修改的教程。没办法,自己就摸索着尝试搞一下。以下是流程,但到后面遇到了问题,不知如何解决,希望高手们帮忙看看。

1.观察软件的log文件得到以下信息:
==============================================
2007-8-30 15:09:47 com.XXX.logging.Logger create
信息: Logger(Service1) is created.
2007-8-30 15:09:48 com.XXX.logging.Logger debug
良好: 开始检查正式许可
2007-8-30 15:09:58 com.XXX.logging.Logger warning
警告: 检查正式许可发生错误,错误码:XXXXXXXXX
2007-8-30 15:09:58 com.XXX.logging.Logger debug
良好: 开始检查临时许可
2007-8-30 15:09:58 com.XXX.logging.Logger severe
严重: 检查临时许可发生错误,错误码:1
2007-8-30 15:09:58 com.XXX.logging.Logger severe
严重: Failed in starting service(Service1):
java.lang.Exception: 检查临时许可发生错误,错误码:1

com.XXX.service.Service.<init>(Service.java:94)
com.XXX.service.ServiceFactory.getLocalService(ServiceFactory.java:421)
com.XXX.server.Server.start(Server.java:77)
com.XXX.server.Server.main(Server.java:180)
2007-8-30 15:09:58 com.XXX.logging.Logger info
信息: Server is to be exited.
================================================
可以看出,该软件的许可有两种:
正式许可:肯定是没有时间限制的,估计与计算机名和硬件绑定。
临时许可:提供给开发人员临时开发用的许可,经验证申请到的临时许可,得知只与计算机名和系统时间有关。
    如果服务启动时在指定目录下找不到许可文件或者找到错误的许可文件,就会:Server is to be exited.

    下面开始动手:
    检查软件安装目录,在Bin目录下发现 Server.jar 以及众多Dll文件,其中 startServer.cmd 中内容如下:
..\thirdparty\jdk\bin\java -Xms128m -Xmx1024m -Djava.library.path=. -cp Server.jar com.XXX.server.Server -start Service1
      说明服务功能基本上都是在 Server.jar 中实现的,当然可能也包含许可的验证。
    关于Jar包,可以用WinRAR解压。解压 Server.jar 后得到一大堆的 class 文件。
    接着上网又一通寻找 class 的反编译工具,经过验证发现 DJ Java Decompiler 几乎能反编译所有的 class。。。。
    对 Server.jar 包中上百个文件的扫视,最后在 Service.class 中找到了重要的代码,反编译后关键内容如下:
===============================================
       Logger.debug("\u5F00\u59CB\u68C0\u67E5\u6B63\u5F0F\u8BB8\u53EF");\\开始检查正式许可
        long licValue = chkLic(true);
        if(licValue != 0L)
        {
            String msg = "\u68C0\u67E5\u6B63\u5F0F\u8BB8\u53EF\u53D1\u751F\u9519\u8BEF\uFF0C\u9519\u8BEF\u7801\uFF1A" + licValue;\\检查正式许可发生错误,错误码:
            Logger.warning(msg);
            Logger.debug("\u5F00\u59CB\u68C0\u67E5\u4E34\u65F6\u8BB8\u53EF");\\开始检查临时许可
            licValue = chkTrialLic();
            if(licValue != 0L)
            {
                msg = "\u68C0\u67E5\u4E34\u65F6\u8BB8\u53EF\u53D1\u751F\u9519\u8BEF\uFF0C\u9519\u8BEF\u7801\uFF1A" + licValue;\\检查临时许可发生错误,错误码:
                Logger.severe(msg);
                throw new Exception(msg);
            }
            Logger.info("\u68C0\u67E5\u4E34\u65F6\u8BB8\u53EF\u901A\u8FC7");\\检查临时许可通过
        } else
        {
            Logger.info("\u68C0\u67E5\u8BB8\u53EF\u901A\u8FC7");\\检查正式许可通过
        }
===================================================

    看过这些心里就应该有数了吧,关键代码就是这一句:
        if(licValue != 0L)
   如果能把它改为:
        if(licValue == 0L)
    岂不是大功告成了。

    问题又来了,总不能把反编译的源代码修改后再编译回去吧,没有了最初的开发环境,我想这是不可能的,唯一的办法就是直接修改 class 文件,但这样做首先要找到 JVM 指令对应的二进制代码地址。
    在这里我想到了一个最蠢的办法:编写两段一样的简单的Java代码,然后修改一处指令,编译出只有这一出差异的两个 class 文件,用文件比较工具一看就知道代码差别了,于是开始动手写代码,并将文件Test1.java放于C盘根下:
===================================================
public class Test1 {
        public static void main(String[] args) {
                int a=1;
                if(a==0);
        }
}
===================================================
    执行 c:\javac Terst1.java 得到了 Test1.class
    将 if(a==0); 修改为 if(a!=0);,备份 Test1.java 后再次编译,得到另一个 class 文件,使用 UltraCompar 对照后发现只有一个字节的数据发生了变化,对应关系是:
==  :   9A
!=   :   99
    也就是说,在 Server.class 只要找到 if(licValue != 0L) 这一句对应的 99 改为 9A 就可以完成指令的修改了。从上到下数了一下,这个不等号大概是第三个出现的,于是使用 UE 打开 Server.class 文件,搜索 99 ,的确找到了很多处,将代码区的第三个修改为 9A 后保存。为了验证修改是否到位,运行 DJ Java Decompiler 打开修改后的 Server.class 反编译,发现
if(licValue != 0L) 这一句的确变成了 if(licValue == 0L),呵呵,理论上应该是成功了。
   接下来使用 WinRAR 将修改后的 Server.class 保存到 Server.jar 中,运行程序,查看记录文件,赫然发现变成了如下内容:
===================================================
2007-8-30 16:05:57 com.XXX.logging.Logger create
信息: Logger(Service1) is created.
2007-8-30 16:05:57 com.XXX.logging.Logger debug
良好: 开始检查正式许可
2007-8-30 16:06:07 com.XXX.logging.Logger info
信息: 检查许可通过
===================================================
    看到这些信息后心情无比激动,心里就一个念头:Java 破解原来这么简单啊!!!马上打开网页检查自己的成果,结果一下傻了眼,发现预期的功能并没有实现!到底哪里出了错?为什么检查许可都成功了还不能用?
   带着这些疑问我又开始研究起来了.查看进程时,发现 Java 虚拟机并没有运行,列表中没有 Java.exe 这个进程,于是知道了程序可能还有暗桩,没准在哪里还有许可的判断。于是又开始读起代码来了,经过了数个小时的查找,发现其余的地方并没有与许可有关的指令,希望基本上破灭了。
    正当我郁闷的时候,突然发现 bin 目录下赫然多出来一个文件:hs_err_pid2100.log
上网一查,知道了这是 Java 虚拟机的错误报告,说明 Java 进程发生致命错误,崩溃后留下的日志。难道是我修改的地方有误导致进程崩溃?为了验证这一想法,我又自己编写了大量代码,用同样的方法修改,结果发现我的修改并不会引起程序的崩溃,所以断定不是由于修改错误代码引起的崩溃。
    无奈之下看了看 hs_err_pid2100.log 中的内容:
===================================================
#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x4925f9b0, pid=2100, tid=3176
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_04-b05 mixed mode)
# Problematic frame:
# C  [XxXxxxxxxxxxxx.dll+0xf9b0]
#

---------------  T H R E A D  ---------------

Current thread (0x000362d0):  JavaThread "main" [_thread_in_native, id=3176]

siginfo: ExceptionCode=0xc0000005, reading address 0x00000054

Registers:
EAX=0x00000000, EBX=0x430042e8, ECX=0x0000004c, EDX=0x00000000
ESP=0x0007f914, EBP=0x0007f944, ESI=0x430042e8, EDI=0x000362d0
EIP=0x4925f9b0, EFLAGS=0x00010283

Top of Stack: (sp=0x0007f914)
............................
====================================================
    到此为止已经一头雾水了,难道与 # C  [XxXxxxxxxxxxxx.dll+0xf9b0] 这个dll有关,可是挂上OD检查Dll一通后没有发现问题,真不知道究竟怎么回事。。。。。。

。。。。。。。。。。。。。。。。。。

感谢各位对我的帮助,以上内容现在回想起来真是很幼稚,破解思路完全错误,从lic上入手才是正确的方向。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞0
打赏
分享
最新回复 (41)
雪    币: 244
活跃值: (28)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
shenhaiyu 3 2007-8-31 09:09
2
0
呵呵,没人研究过么?帮帮忙吧,都快沉了
雪    币: 203
活跃值: (73)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
davidhee 2007-8-31 09:36
3
0
菜鸟也来学习一下。



从设计的角度看,不会直接比较这么简单。多数是用注册码或许可文件计算一些数值,验证成功后,再用计算出来的数据进行下一步工作。有时候不用if 直接用 = (汇编是cmp-->mov),运气好的话,或许能有点作用。
雪    币: 244
活跃值: (28)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
shenhaiyu 3 2007-8-31 11:15
4
0
感谢 davidhee 的回复,问题关键不在怎样验证许可,而是为什么修改class文件后JVM会崩溃,难道这也是保护的一部分?
雪    币: 244
活跃值: (28)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
shenhaiyu 3 2007-8-31 18:06
5
0
呵呵,怎么还是少有人回复啊,都等两天了,高手们就帮忙看看吧
雪    币: 134
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
swlepus 2007-9-2 14:28
6
0
这个估计是jar的签名验证出错。
修改文件导致jar签名变化。会引起运行时直接报错。

呵呵,我也在研究。
雪    币: 244
活跃值: (28)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
shenhaiyu 3 2007-9-2 17:40
7
0
呵呵,感谢 swlepus 的回复,至少有点思路了,还有签名验证这回事。。
有结果了一定要和我联系啊,谢谢啦!!
雪    币: 328
活跃值: (39)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
vhly 5 2007-9-3 10:41
8
0
首先 删除 .jar中 META-INF中 除了 MANIFEST.MF 之外的所有文件 可能包含

.DSA .SF 这两种,因为这是数字签名用的,删除 MANIFEST.MF文件中所有为

Name: xxx.class
..SHA...

之类的这些内容, 这些是数字签名内容

之后使用饭编译器生成你的那个类的元文件

在重新编译的时候吧, Server.jar当作 classpath 中的一项,这样就可以重新编译了,
最后就是把生成的类,替换原始的,就可以了

注意 备份

author:vhly[FR]
dAtE: 2007/09/03
雪    币: 331
活跃值: (56)
能力值: ( LV13,RANK:410 )
在线值:
发帖
回帖
粉丝
Isaiah 10 2007-9-3 11:50
9
0
建议逆向一下效验lisence的流程。大型软件爆破可靠性不高的。记得MapGis破解版和正版运算是有误差的。一般大型项目都不敢用D版。出了问题,没人能负责。
雪    币: 257
活跃值: (105)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
舵手 3 2007-9-3 12:08
10
0
同意Isaiah的,这样的软件不可能就这么简单暴破,继续往进跟一下,写出注册机会更可靠一些。
狗里面有多少数据最好能搞出来,不然不完全破解的可能性很大。
雪    币: 244
活跃值: (28)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
shenhaiyu 3 2007-9-3 17:19
11
0
呃,谢谢大家的帮助,首先回复vhly 的答复,META-INF中只有  MANIFEST.MF 一个文件,而且  MANIFEST.MF  中没有一个 *.class 的内容,内容就这样:
Manifest-Version: 1.2.0.2926
UGC-Version: UGC for windows 1.0.0.2925
XXXJava-Version: 1.0.0.2925
Main-Class:
那是不是就不用考虑签名的问题了?

然后回答 Isaiah  的,简单看了一下,整个服务器核心代码中似乎没有什么额外的加密了,许可算法部分是Sen的。

最后是 舵手 的,这个软件没有狗,就是一个许可文件,格式是 2003010120081231XXXXXXXXXXXXXXXX 这样的一串,前十六位为两个日期,后十六位为加密的字串,个人感觉爆破起来很简单,软件连壳都没加(我是指其余的Dll文件,JAR就更不用说了)!!!!

最后不知道哪位了解Sen*软狗的保护机制,是不是在同目录的那些Dll中还有文件的校验导致JVM崩溃呢?谢谢大家了
雪    币: 257
活跃值: (105)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
舵手 3 2007-9-4 11:22
12
0
没狗分析起来就容易多了,不行把软件放出来大家试试:)
雪    币: 244
活跃值: (28)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
shenhaiyu 3 2007-9-4 13:26
13
0
呃,再次感谢大家的帮助,关于软件已经通过短信息发给大家了,有兴趣的人请帮忙分析一下吧,不过请不要公开该软件,谢谢啦
雪    币: 244
活跃值: (28)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
shenhaiyu 3 2007-9-7 09:22
14
0
呃,帖子沉了,难道对Java感兴趣的人这么少么?呵呵,已经关注的老大们给点信息吧,焦急地等待中。。。
雪    币: 244
活跃值: (28)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
shenhaiyu 3 2007-9-11 14:23
15
0
呵呵,停了几天,突然发现自己的脑子很是笨,怎么就没看看文件的属性信息呢,现在可以肯定了,该软件是 Senxxxxx RXX 保护的,DD们看看吧,如何搞定这个 Senxxxxx RXX 呢?
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
imacbook 2007-9-12 13:18
16
0
编译其实很简单的,用winrar把这个类删除,在classpath加入这个jar
然后就可以编译成class,然后把你的class放到jar里(同样用winrar)
打狗觉得不会这么简单,按道理还有自校验(自装载用Loadclass)
雪    币: 244
活跃值: (28)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
shenhaiyu 3 2007-9-13 09:14
17
0
呃,感谢楼上的提示,现在关进问题就在于自校验在哪里,这个让我是在摸不到头绪
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hanzi 2007-9-17 12:35
18
0
Sentinel RMS 保护的软件可以通过跟踪求出VendorID和Ver、Feature,作出Keygen,来制作可用的LIC。
雪    币: 244
活跃值: (28)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
shenhaiyu 3 2007-9-18 09:12
19
0
呃,楼上的兄弟可以说的具体点吗?软件已经PM给你了,可以的话麻烦帮忙看看吧
雪    币: 204
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
whyIII 2007-11-7 21:14
20
0
java的程序调试起来还是挺麻烦的,不过正如hanzi说的,应该可以制作keygen的。
雪    币: 244
活跃值: (28)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
shenhaiyu 3 2007-11-8 08:31
21
0
兄弟有兴趣看看吗?可否帮忙弄一弄?
雪    币: 204
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
whyIII 2007-11-8 08:38
22
0
可以试试,呵呵
雪    币: 200
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jules 2007-11-8 17:16
23
0
这是可能的, 把所有jar都放在你开发环境的classpath里(先删掉你要编辑源代码的那个class)
雪    币: 255
活跃值: (207)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
peaceclub 6 2007-11-8 20:57
24
0
利用jni吧,软模拟狗。
雪    币: 244
活跃值: (28)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
shenhaiyu 3 2007-11-9 09:06
25
0
好吧,决定从 gen lic 入手了
游客
登录 | 注册 方可回帖
返回