十三. JEB破解三

一.启动环境
JEB 2.0Demo版本启动后出现这样一个界面


当前环境算出的许可证数据
48000000BDEAE192E4CEFC82B34C2AC67F3A85DF5C0E262E421772CF84F18EC0E4A9F41798FD1648BF2794B4545F6315D6AC21C3921172C29FA004FAE1A8127C585A37F27FC478F9187BD35BBD7BA0DE

根据经验来看,肯定是机器码和注册码经过特定的运算,运算通过就注册成功


二. 分析过程
1. 定位关键点
在main函数我们发现启动时会先回去License相关信息,我们跟进这个函数


在跟进的AbstractClientContext类中我们发现

这里比较像注册码比较的地方
上面的this.uomid 点击不进去, 搜索也搜索不到, 一般情况这个成员的值定义可能在父类

我们父类跟踪该值this.uomid,果然找到相关初始化地方


跟踪最终的初始化,发现其在该函数进行初始化过程

看起来很像算机器码的地方, 我们可以高度怀疑上面的过程就是注册码检查校验的过程了

2. 先还原机器码算法
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;
public final class MachineHelper {
    private String GetWinSerialNum() {
        Process locProcess;
        String serial = null;
        Runtime locRuntime = Runtime.getRuntime();
        try {
            locProcess = locRuntime.exec("wmic bios get serialnumber".split(" "));
            Scanner scanner = new Scanner(locProcess.getInputStream());
            while (scanner.hasNext()) {
                if ("SerialNumber".equals(scanner.next())) {
                    serial = scanner.next().trim();
                    break;
                }
            }
            scanner.close();
        } catch (IOException e) {
        }
        return serial;
    }
    @SuppressWarnings("null")
    private String GetMacSerialNum() {
        Process locProcess;
        String serial = null;
        Runtime locRuntime = Runtime.getRuntime();
        try {
            locProcess = locRuntime.exec("/usr/sbin/system_profiler SPHardwareDataType".split(" "));
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(locProcess.getInputStream()));
            String buffer = null;
            while ((buffer = bufferedReader.readLine()) != null) {
                if (buffer.indexOf("Serial Number") >= 0) {
                    String buf1 = buffer.split("Serial Number")[1];
                    int iPoint = buf1.indexOf(":");
                    if (iPoint >= 0) {
                        serial = serial.substring(iPoint + 1).trim();
                    }
                    break;
                }
            }
        } catch (IOException e) {
        }
        return serial;
    }
    private String GetLinuxSerialNum() {
        String serial = null;
        try {
            BufferedReader midFilebuf = new BufferedReader(new InputStreamReader(new FileInputStream("/var/lib/dbus/machine-id")));
            String buffer = midFilebuf.readLine();
            midFilebuf.close();
            if (buffer != null) {
                serial = buffer.trim();
            }
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        }
        return serial;
    }
    private String GetLinuxSerialNum2() {
        String serial = null;
        try {
            BufferedReader fstabFilebuf = new BufferedReader(new InputStreamReader(new FileInputStream("/etc/fstab")));
            String buffer = null;
            while ((buffer = fstabFilebuf.readLine()) != null) {
                buffer = buffer.trim();
                if (buffer.length() == 0) {
                    continue;
                }
                if (buffer.startsWith("#")) {
                    continue;
                }
                String[] Keyvalue = buffer.split("[ \\t]+");
                if (Keyvalue.length < 2) {
                    continue;
                }
                if (!Keyvalue[1].equals("/")) {
                    continue;
                }
                buffer = Keyvalue[0];
                if (buffer.startsWith("UUID=")) {
                    serial = buffer.substring(5);
                } else if (buffer.startsWith("LABEL=")) {
                    serial = buffer.substring(6);
                }
                if (serial != null) {
                    serial.toLowerCase();
                }
            }
            fstabFilebuf.close();
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
            e.printStackTrace();
        }
        return serial;
    }
    public long GetMachineID() {
        String osType = System.getProperty("os.name""");
        String SNKey = null;
        long machineId = 0;
        if (osType.startsWith("Windows")) {
            SNKey = GetWinSerialNum();
        } else if (osType.startsWith("Mac")) {
            SNKey = GetMacSerialNum();
        } else if (osType.startsWith("Linux")) {
            SNKey = GetLinuxSerialNum();
            if (SNKey == null) {
                SNKey = GetLinuxSerialNum2();
            }
        } else {
            SNKey = "LambdaLambda";
        }
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            ByteBuffer buffer = ByteBuffer.wrap(md.digest(SNKey.getBytes()));
            buffer.order(ByteOrder.LITTLE_ENDIAN);
            machineId = buffer.getLong() & 0xFFFFFFFF;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return machineId;
    }
    
    public static void main(String[] args) {
        MachineHelper helper = new MachineHelper();
        System.out.println(helper.GetMachineID());
    }
}

解密后


3. 注册算法分析
当v2_1 != 0时 校验通过


当v6 == v8时校验通过


向上跟踪发现v6 v8是根据licenseKey和machineKey分别计算出来的
那么还原licenseKey的算法即可
import java.nio.ByteBuffer;
public class Test {
    private static int sum(int i)
    {
        int j = 0;
        for(; i > 0i >>= 4)
            j += i & 0xf;
        return j % 10;
    }
    
    public static String getKey(long machineId,long unixTime) {
        int i = (int)(machineId & 0xFFFFFFFF);
        int j = (int)(machineId >> 32 & 0xFFFFFFFF);
        int i1 = i +  0x45F22A12 + 0x11223344 & 0xFFFFFFFF;
        int j1 = j - 0x1B0CB11 + 0x55667788 & 0x7FFFFFFF;
        ByteBuffer bb = ByteBuffer.allocateDirect(8);
        bb.putInt(j1);
        bb.putInt(i1);
        bb.rewind();
        long l = bb.getLong();
        int d = (int)unixTime ^ 0x56739ACD;
        
        return String.format("%dZ%d%d"ldsum(d));
    }
    
    public static void main(String[] args) {
        MachineHelper helper = new MachineHelper();
        long machineID = helper.GetMachineID();
        long unixTime = System.currentTimeMillis() / 1000L + 94608000L - 1123200L;
        
        String key = getKey(machineIDunixTime);
        System.out.println(helper.GetMachineID());
        System.out.println(key);
    }
}

计算出key


成功通过运算










posted @ 2016-08-29 22:06  Bingghost  阅读(3376)  评论(0编辑  收藏  举报