能力值:
( LV4,RANK:50 )
|
-
-
2 楼
嘿嘿~~~~~~~~顶一下
你又弄这些高级语言的东西了, 看得头很大的
|
能力值:
(RANK:350 )
|
-
-
3 楼
期待续篇,等全部完成再设精华
|
能力值:
( LV2,RANK:150 )
|
-
-
4 楼
|
能力值:
( LV2,RANK:150 )
|
-
-
5 楼
继续昨天的活。
大概分析了一下DLL的那个导出函数,下面把它成为Load吧。
一开始减esp,创建一块很大的栈区域用于存储本地变量。
然后,把六个参数复制到本地变量中。除了这六个参数外,第一个参数可能是jvm函数表的地址,因为后面可以简单大量的:
mov esi, [esp+688h+jvm_base] ;jvm_base是我重命名后的
mov edx, [esi]
mov eax, [edx+18h] ;18h可能是别的。有点类似于位移
call eax ;动态调试发现,这个eax的值是jvm.dll里面的jvm.6D7355CE,可惜我没有这个库的sig,不知道它名字
为了方便阅读,我在IDA中对这些变量进行了重命名。
往下是是两个jvm的call,不知道干嘛的,不管它。第一个call前面,把那个重写ClassLoader的类的路径压栈。第二call后就是一个长长的跳转,跳到函数尾部的,嗯,这一般是参数检查之类的写法。结合那个类路径,我猜测是检查调用者是否是那个类,如果不是,则返回。工作还挺到位的。
再往下,数百行都是mov指令,把常量一个个拷贝到本地变量中。变量名几乎是递减的。为什么说几乎呢?那是因为,有个别的顺序是乱的,不过在别的地方,肯定能找到“丢失”了的指令。这可真是费尽心思哦,如果我没猜错,这个就应该是一个密码之类的东西。往往破解者习惯搜索字符串常量来获得密码,这种方法,在这里就无效了,它其实已经是相当于把密码写在指令里面了,还故意搞乱了顺序,因而,这个库,很有可能是手工修改过的,甚至可能就是人工写的。因此,可以猜测,这是很重要的字符串(密码?)
往下,就开始不断调用jvm的方法了,我整理了一下字符串参考,如下:
"java/security/spec/X509EncodedKeySpec")
"<init>")
"java/security/KeyFactory")
"(Ljava/lang/String;)Ljava/security/KeyFactory;")
"getInstance")
"(Ljava/security/spec/KeySpec;)Ljava/security/PublicKey;")
"generatePublic")
"java/security/Signature")
"com/要创建的类名以及路径.class")
"(Ljava/lang/String;)Ljava/security/Signature;")
"getInstance")
"(Ljava/security/PublicKey;)V")
"initVerify")
"update")
"verify")
"java/io/FileInputStream")
"(Ljava/lang/String;)V")
"<init>")
"available")
"read")
"close")
"DSA")
"SHA1withDSA")
"java/security/SecureClassLoader")
"(Ljava/lang/String;[BIILjava/security/CodeSource;)Ljava/lang/Class;")
"defineClass")
看字符串参考,或者IDA识别出来的函数名,望文生义,是我在搞逆向中的常用方法。因为我比较熟悉VB,上次逆向一个VB的DLL的时候,几乎等于看VB代码,因为流程不是很复杂,所以,根本不用管本地变量怎么赋值,直接看函数名,就直到它想干嘛了。
言归正传,从上面的字符串参考可以大概看出:先初始化了一个X509编码的实例,然后取得一个密钥工厂,生成一个公钥,接着取得数字签名对象,并用公钥初始化签名对象,取得被签名的数据,验证。
然后声明FileInputStream,呵呵,开始读取文件了,不多说。
DSA,鼎鼎大名的DSA非对称加密算法。
SHA1withDSA,看到这,我只知道SHA1是一种散列算法,一般来说,散列算法和DSA结合起来使用,主要用于数字签名。其实,如果不懂这个是什么东西,只要上百度搜索一遍,马上就会明白了。
综合上面的分析,可以发现,这里主要进行了数字签名,用于判断目标(可能就是那个类)是否被修改过。而上面猜测的那个密码,正是公钥。
在信息安全中,为了确保信息的完整性,可以对信息进行数字签名。签名者持有一对密钥,分别是公钥和私钥,他使用私钥对信息进行签名,然后签名后的信息和公钥一起分发出去。另一方,就可以使用该公钥对信息进行签名验证,判断信息是否被修改过。公钥和私钥是唯一对应的。
在这里,公钥存储与程序中,并且做了很好的保护,就是为了防止被人轻易获取。若第三方(比如我们)获取公钥,并可以修改,那么,他完全可以使用另外的一对密钥中的对信息进行签名,并把这里的公钥也换掉,那么,就算修改了信息,这里也会认为是没有修改过。这正是作者花费那么多心思来保护这个公钥的原因。
回过头来,才发现,我的问题,根本就还没有解决。我猜测这里是解密class的,但并没有明显的痕迹。
从上面的字符串参考可以看到,它已经调用SecureClassLoader的defineClass方法返回类对象了。从网络上的资料来看,调用defineClass前,类的字节码会作为参数传进去的。因此,我们可以修改SecureClassLoader类的defineClass方法拦截这些字节码。可惜,我不会Java,更不知道如何修改这个方法,这方面,我觉得 舵手 可以帮上忙。
上面的字符串参考中间,穿插着一些本地的函数调用,偶然(对于破解工作来说,需要很多偶然)发现其中一个方法,其大无比,在IDA的流程图中,可以看到很多层循环。很遗憾,我没认真研究过各种加密算法的写法,不知道它是什么算法。直觉告诉我,这里是解密用的。因此,有了第二个获取class字节码的方法:把这个方法抽取出来,直接对class文件进行解密,希望除了这个函数外,作者没做过别的处理。
第三种方法:动态调试,直接从内存中抽取解密后的字节码。这个方法对我来说,相对容易很多。但是,到现在为止,我还无法确定它把字节码存放在哪个地方。没有Client/JVM.dll的函数名,看到的全都是数字,想猜都猜不来。对于Java中方法的参数规范又不熟悉……
这几天公司项目要很忙,这个软件的下一步逆向,就暂时压后一点,同时,也留一点时间查资料,已经请求论坛上各位高手的帮助。
|
能力值:
( LV2,RANK:150 )
|
-
-
6 楼
这个软件的逆向,还远远未完成.
这个DLL破解后,我才可以拿到那个jar包的字节码,还不知道能不能正常反编译呢.
要是能正常反编译,应该不用费多少时间,就可以分析里面的注册算法了.
不过,要是里面又是调用DLL来调用注册算法,我可就真晕了.
|
能力值:
( LV2,RANK:150 )
|
-
-
7 楼
早两天,在一个文件中文件了调用这个LoadClass的痕迹,现在是想这么做的:
另外仿造这个文件写一个java程序,任意加载一个被加密的jar包内部的类,使得它调用那个DLL。然后,我就可以用OD跟踪了。如果好运的话,可以从内存中把那些类的字节码抽取出来。反正我只是需要逆向那些字节码,从中得到注册算法,而不需要重新编译。
另外一种办法,就是强行分析DLL,看看它所调用的jvm.dll中的函数究竟干嘛用的。这样或许能得到加密算法。这种办法可能比较完美一点
|
能力值:
( LV3,RANK:30 )
|
-
-
8 楼
这种活还能搞下去,佩服你
|
能力值:
( LV2,RANK:150 )
|
-
-
9 楼
呵呵,都到了这个份上了,没什么好佩服的。
这个系统,安装文件就1G多,我是猜测并反了无数文件后,才把目标定位到这里来的。
同时,这里几乎可以说是它的最后防线了,因为别的文件,我几乎都看完了
它引用了很多别人的开源项目,那些文件我就不看了。
因为它自身就带有编译器,我花了很长时间才摸清这个系统的总体构架。
所以,来之不易。继续干活……
|
能力值:
( LV9,RANK:210 )
|
-
-
10 楼
今天才看到,不好意思,终于找到工作了,干得就是 Java Reverse Enginee,本来想在看雪
发一篇感谢的文章呢,不过真没时间,一天到晚跟 J2me Browser呢,
感觉你的这个 target 应该使用了 JNI,有一些 核心的东西 应该在 dll库中,
看了上面的 ConstantPool String 发现这个软件中至少一部分使用了 DSA算法,
大概是什么软件,如果使用 OD的话只能使用 JVM跟,那么工作量就太大了,我感觉可以使用
某些工具先把软件中的字符串信息找到,即使是英文的,同样也可以先理解以下,
不过最近开始对Java逆向,感觉多了个朋友了,哥们现在靠这个吃饭了。
还是要感谢一下看雪的各位朋友,没有你们,空拍我还在 Study Java呢,现在却是 Reverse Java
再次感谢。
auThOr: vhly[FR]
Date: 2007/05/29
|
能力值:
( LV2,RANK:150 )
|
-
-
11 楼
恭喜恭喜!
的确,DLL中对jar中的类进行解密,然后再调用LoadClass来加载类返回。
这些我知道,字符串参考究上面那些。
最麻烦的就是jvm,这个DLL用了很多jvm的函数,我连猜测都不可能了。就算我想硬来,也都不行……看来,我应该查查PE代码怎么调用jvm函数。
|
能力值:
(RANK:350 )
|
-
-
12 楼
真为你找到工作感到高兴
|
能力值:
( LV2,RANK:150 )
|
-
-
13 楼
谢谢vhly!
对这个软件的分析,在两条路线上,我都有了进展。
1,从注册程序入手。我修改反编译后的注册程序,再编译,调试,终于找出了注册授权文件的格式,前面是一些授权信息,后面似乎是一个校验码。我试过修改前面的授权信息,但是系统马上发现文件被修改过。所以,我肯定后面是校验码。但是,我也纳闷,它是47个字节的,实在想不到哪种校验方式是47字节的。因为是Java的原因,可能要出去三个字节,那就是44了。
2,上面分析的这个DLL,它根本不调用任何C/C++/API函数,调的全部都是JVM没有公开的函数。我在想,它是不是作者用软件把java程序转成DLL,然后手工混淆汇编代码。不过,我已经想办法取得了里面用到的大部分JVM函数的意义,也已经把部分汇编,反写成Java代码了。因为对JVM函数的参数传递搞不清楚,所以,目前还存在一些问题。
真想不到,为了这个,我学会了一点Java
|
能力值:
( LV2,RANK:150 )
|
-
-
14 楼
成功解决那些jvm函数的问题。
经过查找资料,最终确定,那个DLL,就是用JNI编译的。然后我也做了一个JNI的DLL,把可能的函数写进去,编译,用IDA看,对应一下就知道哪个地址是哪个函数了。
此外,我还发现一个更惊人的事情,在IDA中新建一个结构体用于存放JNI方法名的时候,发现,方法的顺序居然和jni.h头文件中方法顺序一致……呵呵,这回不用一个个猜了。
好了,吃饭了,先把jni的idc发上来,希望对大家有用。迟点我再把这些日子做的写上来。
目前一切顺利,已经到了最后一关了,正在破解DSA的私钥中……
|
能力值:
( LV13,RANK:530 )
|
-
-
15 楼
补充一句。 搂主的那个”哪门子“编译器应该就是Visual C++ 的编译模型,而且风格和VC6接近。如果真是自己的编译器或者VM。就不会这么写了哈 绝对不弄一个在堆栈执行代码是过不得哈:)
|
|
|