squaretest逆向記錄


squaretest逆向記錄

單測編寫在程序開發實踐中至關重要,我想每個寫過單測的小伙伴都深有感受。但編寫單測費時費力,極大影響研發的工作效率。憑借拿來主義精神,我熟練地打開百度並在互聯網中搜尋自動化單元測試生成工具,功夫不負有心人,在眾多質量參差不齊的單測生成工具中發現了squareTest,使用過感覺相當不錯,能夠自動生成Mockito測試用例還能兼容多Module工程,但30天的免費試用就讓人不開心了,內外網也沒對應開心版本,但畢竟java能夠輕松反編譯,就嘗試pj,並記錄下

環境:

系統:macos

工具:idea 2021.3;jclasslib

 

問渠那得清如許,為有源頭活水。哪個小伙伴不想知道程序驗證的原理呢?那我們就嘗試反編譯程序看看他是怎么加密的。最佳反編譯實踐可以看我這篇https://www.cnblogs.com/vycz/p/15624996.html

java -cp "/Applications/IntelliJ IDEA.app/Contents/plugins/java-decompiler/lib/java-decompiler.jar" org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -dgs=true TestStarter-1.6.4.jar.jar mysrc

反編譯可以看出其實代碼是有混淆的,但不打緊,關鍵字符串是沒混淆的。咱們可以從ui上的提示文案入手。

校驗按鈕Validate and Save就是咱們的入手點,簡單在代碼中全局搜索下

在com.squaretest.c.l下這個按鈕被引用了。

這里面包含了3個關鍵方法createActions() doOKAction() doValidate()

大致我們可以知道一個是創建組建的方法,一個是點擊ok時的回調,一個是驗證方法

通過DialogWrapper我們能知道doValidate是在doOKAction方法內做校驗邏輯的,校驗成功調用OkActions,失敗返回錯誤提示。

到此咱們主要關心,一個是doValidate中this.a.b(var1)到底做了啥邏輯

第二是doOKAction做了啥

 

咱們看this.a.b(var1)到底在干啥

 absolutely 就是咱們的驗密邏輯,返回var6.verify(var7) 就是var6就是a公鑰+var5簽名消息進行驗密,正確返回true,錯誤返回false。這個咱們先不急先接下里看

既然doValidate已經完成驗密工作,那么我們自然而然會想到是不是要緩存許可證書了!畢竟不能每次啟動idea都得重新驗證吧

咱們可以看到var1被set了,按照業務開發邏輯,只是一個簡單的對象set操作,但實際到代碼中咱們看看

實際是實現了一個idea提供的持久化存儲接口,所以咱們就懂了,在doValidate通過公鑰對文本和簽名就行核驗,核驗通過后太多doActions就行證書的持久化倉儲!

到目前為止原理咱們都知道的了,常規咱們能想到2種破解方法

第一種是通過java agent對代碼就行增強,增強證書校驗方法,令其直接返回true。測試發現在idea中通過custom vm進行java agent進行配置后,idea啟動直接崩潰了!后來發現可能是idea的一種啟動保護措施,防止進行字節碼增強。

 

第二種是直接修改字節碼,通過修改字節碼常量池中的公鑰串,實現生產證書。咱們來實驗下!

通過反編譯代碼我們得知,公鑰串位於com.squaretest.c包的r對象下

將class文件通過jclasslib打開

咱們輕松找到了公鑰的存放地址,現在問題來了,怎么生產公鑰和證書呢

先放生成代碼

 

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");

KeyPair keys = keyPairGenerator.generateKeyPair();

PublicKey publicKey = keys.getPublic();




System.out.printf("pub:"+Base64.getEncoder().encodeToString(publicKey.getEncoded()));

PrivateKey privateKey = keys.getPrivate();




System.out.println("\n");

System.out.println("priv:"+Base64.getEncoder().encodeToString(privateKey.getEncoded()));




Signature sig = Signature.getInstance("SHA256withDSA", "SUN");

sig.initSign(privateKey);

String clearText = "SQT1-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" +

        "SQT1-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" +

        "SQT1-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n";

sig.update(clearText.getBytes(StandardCharsets.UTF_8));

byte[] signature = sig.sign();

System.out.println("sign:"+Base64.getEncoder().encodeToString(signature));




sig.initVerify(publicKey);

sig.update(clearText.getBytes(StandardCharsets.UTF_8));

boolean verify = sig.verify(signature);

System.out.println("verify:"+verify);

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM