zoukankan      html  css  js  c++  java
  • mac App 破解之路六 studio 3t

     不想无限使用,直接破解到正版:

    输入邮箱 名字之后 还有licence信息之后,处理函数是:

     this.text.getText() 很明显是你输入的licence.   然后交给父类okPress处理了.      licence字符串存放的变量是 this.r.   获取这个变量的方法是 am()

     查看调用licence信息的地方: 

    t3.common.lic.a.d.bb(). :   把用户输入用this.aT.a()进行处理.   aT对象的类名是:t3.utils.a

     

    展示licence信息的地方: t3.common.lic.j.a():

    licence信息存储组织方法 t3.common.lic.a.j.a():。    猜测xVar应该是服务器传过来的.

    核心类: 对用户输入的licence进行处理

    分析:

    String x = RegisteredLicenseDocumentFormatter.m886x(str);

    License f = this.f711aX.mo903f(x);

    if (!f.getStatus().isActive()) {
    this.f710aW.mo720O(f.getStatus().getDescription());
    return;
    }

    随便输入licence信息得到如下信息.  .f710aW.mo720O 是显示错误的对话框.     

    Your license key seems to be corrupted. Make sure you have copied all text between and including the --- markers at the start and end of the license key.

    这个信息的显示意味着走了异常的代码, 这个异常处有一个打印具体的信息. 等会看这个异常原因.   因为不知道是哪一步异常的.

    先找到输出日志的文件: 

    错误详细: 

    从错误信息中可以看到 是  执行License f = this.f711aX.mo903f(x); 这个语句就异常了.   [ at t3.common.lic.a.i.a(ManagerController.java:61)]

    .method private z(Ljava/lang/String;)Lt3/common/lic/h;
        .registers 9
    
        .prologue
        const/4 v1, 0x0
    
        const/4 v3, 0x1
    
        const/4 v4, 0x0
    
        .line 154
        .line 156
        :try_start_3
        const-string v0, "X.509"
    
        invoke-static {v0}, Ljava/security/cert/CertificateFactory;->getInstance(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;
    
        move-result-object v0
    
        .line 157
        const-class v2, Lt3/common/lic/ae;
    
        const-string v5, "/t3/common/lic/licensing_public.cer"
    
        invoke-virtual {v2, v5}, Ljava/lang/Class;->getResourceAsStream(Ljava/lang/String;)Ljava/io/InputStream;
        :try_end_10
        .catch Ljava/security/cert/CertificateException; {:try_start_3 .. :try_end_10} :catch_49
    
        move-result-object v2
    
        .line 160
        if-eqz v2, :cond_aa
    
        .line 163
        :try_start_13
        invoke-virtual {v0, v2}, Ljava/security/cert/CertificateFactory;->generateCertificate(Ljava/io/InputStream;)Ljava/security/cert/Certificate;
    
        move-result-object v0
    
        check-cast v0, Ljava/security/cert/X509Certificate;
        :try_end_19
        .catchall {:try_start_13 .. :try_end_19} :catchall_63
    
        .line 167
        :try_start_19
        invoke-virtual {v2}, Ljava/io/InputStream;->close()V
        :try_end_1c
        .catch Ljava/io/IOException; {:try_start_19 .. :try_end_1c} :catch_59
        .catch Ljava/security/cert/CertificateException; {:try_start_19 .. :try_end_1c} :catch_49
    
        .line 177
        :goto_1c
        :try_start_1c
        const-string v2, "SHA-1"
    
        invoke-static {v2}, Ljava/security/MessageDigest;->getInstance(Ljava/lang/String;)Ljava/security/MessageDigest;
    
        move-result-object v2
    
        .line 178
        invoke-virtual {v0}, Ljava/security/cert/X509Certificate;->getEncoded()[B
    
        move-result-object v5
    
        invoke-virtual {v2, v5}, Ljava/security/MessageDigest;->update([B)V
    
        .line 179
        invoke-virtual {v2}, Ljava/security/MessageDigest;->digest()[B
        :try_end_2c
        .catch Ljava/security/cert/CertificateEncodingException; {:try_start_1c .. :try_end_2c} :catch_72
        .catch Ljava/security/NoSuchAlgorithmException; {:try_start_1c .. :try_end_2c} :catch_a8
        .catch Ljava/security/cert/CertificateException; {:try_start_1c .. :try_end_2c} :catch_49
    
        move-result-object v1
    
        .line 185
        :goto_2d
        if-nez v1, :cond_7c
    
        move v2, v3
    
        :goto_30
        :try_start_30
        sget-object v5, Lt3/common/lic/ae;->am:[B
    
        invoke-static {v1, v5}, Ljava/util/Arrays;->equals([B[B)Z
    
        move-result v1
    
        if-nez v1, :cond_7e
    
        move v1, v3
    
        :goto_39
        or-int/2addr v1, v2
    
        if-eqz v1, :cond_80
    
        .line 186
        const-string v0, "Failed to verify the integrity of the certificate."
    
        invoke-static {v0}, Lorg/pmw/tinylog/Logger;->error(Ljava/lang/String;)V
    
        .line 187
        new-instance v0, Ljava/lang/SecurityException;
    
        const-string v1, "License verification has failed."
    
        invoke-direct {v0, v1}, Ljava/lang/SecurityException;-><init>(Ljava/lang/String;)V
    
        throw v0
        :try_end_49
        .catch Ljava/security/cert/CertificateException; {:try_start_30 .. :try_end_49} :catch_49
    
        .line 193
        :catch_49
        move-exception v0
    
        .line 194
        const-string v1, "Failed to access the 3t certificate."
    
        new-array v2, v4, [Ljava/lang/Object;
    
        invoke-static {v0, v1, v2}, Lorg/pmw/tinylog/Logger;->error(Ljava/lang/Throwable;Ljava/lang/String;[Ljava/lang/Object;)V
    
        .line 195
        new-instance v0, Ljava/lang/SecurityException;
    
        const-string v1, "License verification has failed."
    
        invoke-direct {v0, v1}, Ljava/lang/SecurityException;-><init>(Ljava/lang/String;)V
    
        throw v0
    
        .line 169
        :catch_59
        move-exception v2
    
        .line 170
        :try_start_5a
        const-string v5, "Failed to find or load 3t certificate."
    
        const/4 v6, 0x0
    
        new-array v6, v6, [Ljava/lang/Object;
    
        invoke-static {v2, v5, v6}, Lorg/pmw/tinylog/Logger;->error(Ljava/lang/Throwable;Ljava/lang/String;[Ljava/lang/Object;)V
        :try_end_62
        .catch Ljava/security/cert/CertificateException; {:try_start_5a .. :try_end_62} :catch_49
    
        goto :goto_1c
    
        .line 166
        :catchall_63
        move-exception v0
    
        .line 167
        :try_start_64
        invoke-virtual {v2}, Ljava/io/InputStream;->close()V
        :try_end_67
        .catch Ljava/io/IOException; {:try_start_64 .. :try_end_67} :catch_68
        .catch Ljava/security/cert/CertificateException; {:try_start_64 .. :try_end_67} :catch_49
    
        .line 172
        :goto_67
        :try_start_67
        throw v0
    
        .line 169
        :catch_68
        move-exception v1
    
        .line 170
        const-string v2, "Failed to find or load 3t certificate."
    
        const/4 v3, 0x0
    
        new-array v3, v3, [Ljava/lang/Object;
    
        invoke-static {v1, v2, v3}, Lorg/pmw/tinylog/Logger;->error(Ljava/lang/Throwable;Ljava/lang/String;[Ljava/lang/Object;)V
    
        goto :goto_67
    
        .line 181
        :catch_72
        move-exception v2
    
        .line 182
        :goto_73
        const-string v5, "Failed to hash the certificate."
    
        const/4 v6, 0x0
    
        new-array v6, v6, [Ljava/lang/Object;
    
        invoke-static {v2, v5, v6}, Lorg/pmw/tinylog/Logger;->error(Ljava/lang/Throwable;Ljava/lang/String;[Ljava/lang/Object;)V
    
        goto :goto_2d
    
        :cond_7c
        move v2, v4
    
        .line 185
        goto :goto_30
    
        :cond_7e
        move v1, v4
    
        goto :goto_39
    
        .line 190
        :cond_80
        invoke-virtual {v0}, Ljava/security/cert/X509Certificate;->getPublicKey()Ljava/security/PublicKey;
        :try_end_83
        .catch Ljava/security/cert/CertificateException; {:try_start_67 .. :try_end_83} :catch_49
    
        move-result-object v0
    
        .line 198
        :goto_84
        if-nez v0, :cond_8e
    
        .line 199
        new-instance v0, Ljava/lang/SecurityException;
    
        const-string v1, "Failed to load the 3T certificate."
    
        invoke-direct {v0, v1}, Ljava/lang/SecurityException;-><init>(Ljava/lang/String;)V
    
        throw v0
    
        .line 203
        :cond_8e
        new-instance v1, Lt3/common/lic/h;
    
        invoke-direct {v1}, Lt3/common/lic/h;-><init>()V
    
        .line 204
        invoke-virtual {v1, p1}, Lt3/common/lic/h;->d(Ljava/lang/String;)V
    
        .line 205
        invoke-virtual {v1, v0}, Lt3/common/lic/h;->verify(Ljava/security/PublicKey;)Z
    
        .line 208
        invoke-virtual {v1}, Lt3/common/lic/h;->E()Z
    
        move-result v0
    
        if-nez v0, :cond_a7
    
        .line 209
        new-instance v0, Ljava/lang/SecurityException;
    
        const-string v1, "License verification failed."
    
        invoke-direct {v0, v1}, Ljava/lang/SecurityException;-><init>(Ljava/lang/String;)V
    
        throw v0
    
        .line 211
        :cond_a7
        return-object v1
    
        .line 181
        :catch_a8
        move-exception v2
    
        goto :goto_73
    
        :cond_aa
        move-object v0, v1
    
        goto :goto_84
    .end method

    贴出来的代码就是校验用户输入的licence关键代码, 可以这个方法反编译失败了,有时间再大力研究这段代码吧.

     把这个jar包放在android studio中 居然完全可以看到源码, 不可思议

    看了一下这个方法,  他的思路是:

    获取licensing_public.cer文件, 然后用sha-1算法验证这个文件对不对, 如果不对就跑异常.   这样可以防止有人修改cer文件.

    之后创建 t3.common.lic.h 对象,  然后把这个返回.      var1 是用户输入.   他是用#在分割.    用户完全完全可以输入  xxx#xxxx 这样的格式数据.

    破解思路方法就可多了:

    方案一:  

    自己生成X.509 公私密钥key.    计算公有key的sha-1

    用自己生成的公钥替换licensing_public.cer。 然后替换代码中 sha-1的值.     就OK了.   

    然后用注册机:

    调用 public static af a(String var0, PrivateKey var1)这个方法生成lincese就可以.
    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package t3.common.lic;
    
    import com.google.common.io.BaseEncoding;
    import java.io.UnsupportedEncodingException;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.Signature;
    import java.security.SignatureException;
    import org.pmw.tinylog.Logger;
    
    public class af {
        private String aq = null;
        private String content = null;
        private boolean ar = false;
    
        public String aL() {
            return this.aq;
        }
    
        public String getContent() {
            return this.content;
        }
    
        public boolean E() {
            return this.ar;
        }
    
        private af() {
        }
    
        public static af a(String var0, PublicKey var1) throws IllegalArgumentException {
            af var2 = new af();
            var2.aq = var0;
            var2.ar = false;
            if (null != var0 && null != var1) {
                String[] var3 = w(var0).split("\\");
                if (var3.length != 3) {
                    throw new IllegalArgumentException("signedString is not readable.");
                } else {
                    byte[] var4;
                    byte[] var5;
                    byte[] var6;
                    BaseEncoding var7;
                    IllegalArgumentException var8;
                    try {
                        var7 = BaseEncoding.base64();
                        var4 = var7.decode(var3[0]);
                        if (var4.length == 0) {
                            return var2;
                        }
    
                        var5 = var7.decode(var3[1]);
                        var6 = var7.decode(var3[2]);
                    } catch (IllegalArgumentException var10) {
                        var8 = new IllegalArgumentException("signedString is not readable.");
                        var8.initCause(var10);
                        throw var8;
                    }
    
                    if (var4[0] != 3) {
                        throw new IllegalArgumentException("signedString is not readable (version mismatch).");
                    } else {
                        try {
                            var7 = null;
                            Signature var11 = Signature.getInstance("SHA256withRSA");
                            var11.initVerify(var1);
                            var11.update(var5);
                            if (var11.verify(var6)) {
                                var2.content = new String(var5, "UTF-8");
                                var2.ar = true;
                                return var2;
                            } else {
                                return var2;
                            }
                        } catch (InvalidKeyException | SignatureException | UnsupportedEncodingException | NoSuchAlgorithmException var9) {
                            var8 = new IllegalArgumentException("signedString is not readable.");
                            var8.initCause(var9);
                            throw var8;
                        }
                    }
                }
            } else {
                throw new IllegalArgumentException("One of the arguments is null.");
            }
        }
    
        public static af a(String var0, PrivateKey var1) {
            af var2 = new af();
            var2.content = var0;
            var2.ar = false;
            byte[] var3 = new byte[]{3};
    
            byte[] var4;
            try {
                var4 = var0.getBytes("UTF-8");
            } catch (UnsupportedEncodingException var12) {
                var12.printStackTrace();
                Logger.error(var12, "Encoding failure", new Object[0]);
                return null;
            }
    
            Object var5 = null;
    
            byte[] var13;
            try {
                Signature var6 = Signature.getInstance("SHA256withRSA");
                var6.initSign(var1);
                var6.update(var4);
                var13 = var6.sign();
            } catch (InvalidKeyException | SignatureException | NoSuchAlgorithmException var11) {
                Logger.error(var11, "Encryption failure", new Object[0]);
                return var2;
            }
    
            BaseEncoding var14 = BaseEncoding.base64();
    
            try {
                var14.encode(var3);
                var14.encode(var4);
                var14.encode(var13);
            } catch (IllegalArgumentException var10) {
                Logger.error(var10, "Encryption failure", new Object[0]);
                return var2;
            }
    
            String var7 = String.format("%s\%s\%s", var14.encode(var3), var14.encode(var4), var14.encode(var13));
            var2.aq = w(var7);
            var2.ar = true;
            return var2;
        }
    
        private static String B(String var0) {
            String[] var1 = var0.split("#");
            String var2 = var0;
            if (var1.length > 2) {
                var2 = var1[var1.length - 2];
            } else if (var1.length == 2) {
                var2 = var1[1];
            }
    
            return var2;
        }
    
        private static String w(String var0) {
            return var0.replaceAll("[^0-9a-zA-Z/=+\\]", "");
        }
    }

    方案二:

    直接修改代码此处代码, 然后随便输入:

    =========

    开始动态调试之旅:

    查看安装时间: 

    var1 是记录了安装时间.  看是什么赋值的?

     

     var1和var2记录是在本地:  ~/.3T/studio-3t/soduz3vqhnnja46uvu3szq--

     调试得知: ~/.3T/studio-3t/soduz3vqhnnja46uvu3szq--/settings.dat 文件里的内容就是记录安装时间的.     只不过加密了.   

    理论上删除这个文件,就可以无限试用了, 但是实际情况不是: 

    本人删除这个文件之后,  又重新生成了一个一摸一样的数据, 这个setting.data不是最终源头.  继续调试之旅,

    开始从加密的地方断点调试.

    t3.common.lic.b.j 类中是数据源头, 因为是这个类的 this.bj.get("soduz3vqhnnja46uvu3szq--") 之后得到了数据.

    继续追踪,发现安装时间的数据存放在5个类中: 

    是一个List 这个 list类的信息分别是: 

    如果把这5个地方的安装数据都删除,  那就达到无限试用了. 接下来找到5个地方.

    第一个地方: t3.common.lic.b.j 

    this.bj = Preferences.userRoot().node("/3t/mongochef/" + var2);  var2 = "enterprise"

    // Preferences.userRoot() 目录在: ~/Library/Preferences/com.apple.java.util.prefs.plist

    第二到五地方分别是:

    /Users/dengzhongqiang/.3T/studio-3t/Lwm3TdTxgYJkXBgVk4s3/settings.dat

    /Users/dengzhongqiang/.cache/ftuwWNWoJl-STeZhVGHKkQ--/5rpyYIZGkVBXle1pseFY2g

    /var/folders/x4/xwpchqcd1m9539py__22l0ww0000gn/T/t3/dataman/mongodb/app/AppRunner/soduz3vqhnnja46uvu3szq--

    /var/folders/x4/xwpchqcd1m9539py__22l0ww0000gn/T/ftuwWNWoJl-STeZhVGHKkQ--/5rpyYIZGkVBXle1pseFY2g--.log

    说明:

    第一个地方比较特别 com.apple.java.util.prefs.plist。  这个是所有Java软件共享的,  直接删除可能会影响其他应用.   

    其他第二到五地方随意删.    

    写了一个脚本:

    rm -f ~/Library/Preferences/3t.*
    rm -rf ~/.3T
    rm -rf ~/.cache/ftuwWNWoJl-STeZhVGHKkQ--
    rm -rf /var/folders/x4/xwpchqcd1m9539py__22l0ww0000gn/T/t3
    rm -rf /var/folders/x4/xwpchqcd1m9539py__22l0ww0000gn/T/ftuwWNWoJl-STeZhVGHKkQ--

    发现了一个奇怪现象,执行了之后并没有效果, 时间没有重置.  不得不佩服这个软件安全措施做的很到位.

    没办法,继续挖掘. 

     查找到原因了: t3.common.lic.b.j 没有存放在com.apple.java.util.prefs.plist文件中.  在跟踪就到JVM虚拟机了.  osx库在处理这个数据, 具体怎么处理的就不清楚了.

    只能写代码删除了.

    package com.company.dzqCrack;
    
    import java.util.prefs.Preferences;
    
    public class Main {
    
        public static void main(String[] args) {
        // write your code here
            Preferences  bt = Preferences.userRoot().node("/3t/mongochef/enterprise");
            bt.remove("soduz3vqhnnja46uvu3szq--");
        }
    }

    到此之际,破解完成.  又有30天了 

    关于动态调试别人的jar包总结:

    修改info.plist文件: 圈出来的就是新增的

    <string>-Xdebug</string>
    <string>-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=50064</string>

    然后在 idea编辑器中创建一个remote debug

     =======================

    虽然可以无限试用了,  但是心里有一个结,就是

    为什么删了com.apple.java.util.prefs.plist  3t.mongochef.enterprise.plist 等plist文件,为什么还有存有安装信息.  跟踪的时候 发现它是加载了 osx库.

    一定打破砂锅探到底

    进入jre.bundle目录。 

    将osx库拖入hopper 

    可以看到Java层面的东西,最终调用是这些方法. 

    发现 _getStringsForNode调用了两次 _toCF:

    查了一下苹果开发文档:

    也就是这个_toCF核心是把 c语言的字符串 转换为 CFString .   

    转换之后,有一个方法被调用了: 

    (*(*r15 + 0x530))(r15, r14, rax);  // r15 = arg0.   其实这个就是JNIEnv *env      查看jni.h 中的定义 是struct JNINativeInterface类型

    0x530是这个结构体的偏移,  暂且放一放. 

      

    通过跟踪发现: 一切数据来源都是调用 CFPreferencesCopyValue, 

    上面英文的大概意思。

    CFPreferences 不能直接转 NSUserDefault.      是线程安全的.  和应用程序还有用户ID,host有关.    没有发现特别之处.  之所以删除plist文件不生效是因为数据已经加载到内存中了.

     至此大完结,   删除~/Library/Preferences 目录下 t3* 3t*文件是有用的,  删除plist文件之后重启电脑就好了, 也就是上面的shell脚本是OK的.

    如果不想重启电脑, 就执行一段Java代码, 用Java代码操作删除,立马生效.   

    ====== 

    截止到2020年04月30日,我发现之前的shell脚本对所有studio3T的版本都是有效的,studio3t可以随意升级版本。

    但是之前的shell脚本不具有普适性,只对本人的电脑有效。  鉴于此,为了让所有人都可以无限试用,我改造了一下之前的脚本。   如果发现以下脚本无法使用,请留言。

    #!/bin/sh 
    
    rm -f ~/Library/Preferences/3t.*
    rm -rf ~/.3T
    rm -rf ~/.cache/ftuwWNWoJl-STeZhVGHKkQ--
    
    ftPath=`find /var/folders -name "ftuwWNWoJl-STeZhVGHKkQ--" -print 2>&1 | fgrep -v "Permission denied" | fgrep -v "Operation not permitted"`
    t3Path=`dirname ${ftPath}`/t3
    
    if [ -e ${ftPath} ];then 
        rm -rf ${ftPath}
    fi
    
    if [ -e ${t3Path} ];then 
        rm -rf ${t3Path}
    fi
    
    echo "删除文件成功,请立即重启电脑生效"
    echo "如果不想立刻重启,那么请在重启电脑前,都不要重新运行studio3T, 否则执行脚本将不起作用"
    
  • 相关阅读:
    Fedora/centos Linux如何设置网卡自动获取网络地址
    Django virtualenv Apache2 mod_wsgi
    virtualbox在装centos5.6时自协把virtualbox addon 装上了
    Spring中的事务属性介绍以及声明式事务管理
    Fedora Linux如何设置网卡自动获取网络地址
    Linux vi/vim 编辑命令总结
    about reviewboard stack information
    Installing Python 2.7.2 on Centos 5.2
    Linux Deepin 下载
    Can't open file for writing
  • 原文地址:https://www.cnblogs.com/dzqdzq/p/11261419.html
Copyright © 2011-2022 走看看