mac App 破解之路六 studio 3t

 

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

 

 

 

輸入郵箱 名字以後 還有licence信息以後,處理函數是:node

 

 

 this.text.getText() 很明顯是你輸入的licence.   而後交給父類okPress處理了.      licence字符串存放的變量是 this.r.   獲取這個變量的方法是 am()android

 

 查看調用licence信息的地方: 算法

t3.common.lic.a.d.bb(). :   把用戶輸入用this.aT.a()進行處理.   aT對象的類名是:t3.utils.amongodb

 

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

 

licence信息存儲組織方法 t3.common.lic.a.j.a():。    猜想xVar應該是服務器傳過來的.安全

 

 

 

 

核心類: 對用戶輸入的licence進行處理服務器

分析:app

String x = RegisteredLicenseDocumentFormatter.m886x(str);socket

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代碼操做刪除,立馬生效.   

相關文章
相關標籤/搜索