首页
社区
课程
招聘
java 程序 spket ide 1.6.5 的两种破解方法
发表于: 2008-1-21 16:37 18481

java 程序 spket ide 1.6.5 的两种破解方法

2008-1-21 16:37
18481
spket ide 是一个eclipse 的插件,对于javascript的调试还是不错的。

前两天看到 microcao 发了一个关于java程序的破解,很有感触。也来kanxue很久了,一直没怎么发过帖,刚好最近拿了几个java程序,练了一下手。原来是想发 intall4j 的破解的,但是od里面不小心清空了。昨天看到有人谈spket 1.6.5, 想起来以前破过,在2007-08的时候。原来是用的简单的爆破的方法,现在仔细看了一下代码。用了替换rsa密钥的方法。

在这里首先要感谢 vhly, 舵手 两位,在论坛发了一些关于java的破解教程。多我受益非浅。

下面就把两种方法,写一下。

spket 的注册程序在 com.spket.ui_1.6.5.jar 包里的 com.spket.ui.internal.License.class

这个文件,没有经过混淆,用jad反编译,代码还是非常清楚的。
其中的验证在 check(byte[] abyte0) 这个method中。

===========================================
   private boolean check(byte abyte0[])
    {
        if(abyte0 != null)
        {
            BigInteger biginteger = new BigInteger(abyte0);
            abyte0 = new byte[bpn.length + bpd.length];
            System.arraycopy(bpn, 0, abyte0, 0, bpn.length);
            System.arraycopy(bpd, 0, abyte0, bpn.length, bpd.length);
            BigInteger biginteger1 = new BigInteger(new String(abyte0), 16);
            BigInteger biginteger2 = BigInteger.valueOf(51419L);
            BigInteger biginteger3 = biginteger.modPow(biginteger2, biginteger1);
            if(biginteger3 != null)
            {
                byte abyte1[] = biginteger3.toByteArray();
                if(abyte1 != null && abyte1.length >= 39)
                {
                    String s = new String(abyte1);
                    if(s.length() >= 39 && s.charAt(0) == '1')
                    {
                        for(int i = 1; i < 39; i++)
                        {
                            char c = s.charAt(i);
                            if(i == 17 || i == 20)
                            {
                                if(c != '/')
                                    return false;
                                continue;
                            }
                            if(c < '0' || c > '9')
                                return false;
                        }

                        return true;
                    }
                }
            }
        }
        return false;
    }
==================================================

第一种方法 直接爆破,用javassist找到这个方法,把里面修改掉。
-------------------------------------------------------------------------------------------
//        CtMethod[] cm = cc.getDeclaredMethods();
//
//                cm[4].insertBefore("{return true;}");
-------------------------------------------------------------------------------------------
这个是javassist 修改代码的方法。具体写的话还要在前面把代码补全。

这个方法很简单。我在8月份的时候,就是这么干的。当时好像是1.6.1。

第二种方法 这个是重点拉。就是修改rsa的密钥。

经过分析
---------------------------------------------------------------------------------------------
  private byte[] getKeyFromText(String s)
    {
        if(s == null)
            return null;
        if(s.length() != 172)
        {
            s = s.trim();
            if(s.length() != 172)
                return null;
        }
        return decode(s.getBytes());
    }
-----------------------
   static int decodeDigit(byte byte0)
    {
        char c = (char)byte0;
        if(c <= 'Z' && c >= 'A')
            return c - 65;
        if(c <= 'z' && c >= 'a')
            return (c - 97) + 26;
        if(c <= '9' && c >= '0')
            return (c - 48) + 52;
        switch(c)
        {
        case 43: // '+'
            return 62;

        case 47: // '/'
            return 63;
        }
        throw new IllegalArgumentException("Invalid char to decode: " + byte0);
    }
--------------------------------------------------
    private static byte[] decode(byte abyte0[])
    {
        if(abyte0.length == 0)
            return abyte0;
        int i;
        for(i = abyte0.length - 1; abyte0[i] == 61; i--);
        int j = abyte0.length - 1 - i;
        int k = (abyte0.length * 6) / 8 - j;
        byte abyte1[] = new byte[k];
        int l = 0;
        int i1 = 0;
        boolean flag = false;
        int i2 = (i + 1) / 4;
        for(int j2 = 0; j2 < i2; j2++)
        {
            int j1 = 0;
            for(int j3 = 0; j3 < 4; j3++)
                j1 = j1 << 6 | decodeDigit(abyte0[l++]);

            for(int k3 = i1 + 2; k3 >= i1; k3--)
            {
                abyte1[k3] = (byte)(j1 & 0xff);
                j1 >>>= 8;
            }

            i1 += 3;
        }

        switch(j)
        {
        default:
            break;

        case 1: // '\001'
            int k1 = 0;
            for(int k2 = 0; k2 < 3; k2++)
                k1 = k1 << 6 | decodeDigit(abyte0[l++]);

            k1 <<= 6;
            k1 >>>= 8;
            for(int l2 = i1 + 1; l2 >= i1; l2--)
            {
                abyte1[l2] = (byte)(k1 & 0xff);
                k1 >>>= 8;
            }

            break;

        case 2: // '\002'
            int l1 = 0;
            for(int i3 = 0; i3 < 2; i3++)
                l1 = l1 << 6 | decodeDigit(abyte0[l++]);

            l1 <<= 6;
            l1 <<= 6;
            l1 >>>= 8;
            l1 >>>= 8;
            abyte1[i1] = (byte)(l1 & 0xff);
            break;
        }
        return abyte1;
    }
--------------------------------------------------------------------------------------
从上面可以看出注册码要172长,从decode 方法可以看出用了base64编码处理。

再仔细看check的方法,发现是rsa加密的方法。其中的e=(51419L),N是一个1024的大数。
一看到1024就可以说,只有用替换密钥的方法了。想分解是不可能的了。自己伪造一个rsa1024的密钥。
解码后的数据是一个最少39位的字符串,第一位为1,第17和20位为'/'斜杠。

这个时候看到N,发现竟然是两个数组组成。看了看javassist的手册,没有发现修改数组的方法。或者是我不知道。

卡住了,吐血中。。。  google了一下,也没有看到方法。

这个时候想到 microcao 的破文,进来又仔细看了一下。决定用winhex直接修改。
用javap 了一下。又查了vmspec。 发现数组的结构是一样的。自己写个class,然后找到 newarray (0xbc)把整个段用winhex复制,再粘贴一下。

大功告成。

把破解好的文件,打包。覆盖原来的文件。重起eclipse。用自己写的注册机算出的注册码,注册,提示有效。

最后
有一点想法,把N用两个数组保存,的确比用string保存要好一点。如果没有想到方法,的确比较棘手。

[课程]Linux pwn 探索篇!

收藏
免费 7
支持
分享
最新回复 (11)
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
2
路过,看过,java接触过一点点
2008-1-21 23:03
0
雪    币: 257
活跃值: (105)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
3
数组一样可以用javassist修改,和普通变量没什么区别。
2008-1-22 09:21
0
雪    币: 328
活跃值: (39)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
4
其实只要是 private boolean check(byte[] buf) 返回true就可以了,但是对于解密而言,确实RSA如果密钥长度太大就要暴力了
2008-1-22 09:41
0
雪    币: 257
活跃值: (105)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
5
不是吧vhly兄,
你试过暴破RSA的密钥?
记得那本书上这样写过:
就算你拥世界最好的计算机,
要破解RSA密钥恐怕也要终其一生。
2008-1-22 09:59
0
雪    币: 328
活跃值: (39)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
6
暴力的意思,可能描述的不清楚,是通过修改关键点或者其他的方式 突破限制,不是爆破RSA的,
让舵手兄见笑了,嘿嘿
2008-1-22 13:33
0
雪    币: 220
活跃值: (117)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
7
我不知道方法,不知道可不可以,据个例子.!!!!!!!!!!
2008-1-22 21:54
0
雪    币: 220
活跃值: (117)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
8
第一种方法,就是private boolean check(byte[] buf) 直接返回true。
2008-1-22 21:55
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
看看
对java不了解
2008-1-22 22:13
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
看看,对java一知半解。
2008-1-23 18:21
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
我也用这个插件..呵呵..不过我是改isValidLicense()那个函数.直接删掉其他的再return true,不用什么注册机
2008-1-25 10:16
0
雪    币: 220
活跃值: (117)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
12
你这个和我的第一个方法是一样的,第二种主要是对进一步要求不对程序结构作大的修改,而破解。
顺便练练手。
2008-1-25 10:23
0
游客
登录 | 注册 方可回帖
返回
//