听说1.8.10版本的Squaretest 单元测试插件 neo激活失效了?

起因

我还在摸鱼ing,后宫群有人再喊1.8.10版本的 Squaretest 激活失效
我心想论坛不是有大佬发了激活原理还配合ja实现的
IDEA Squaretest 插件激活原理分析 - 软件开发 - LINUX DO
当我idea一启动果然失效了,好好好开干!

教学开始

看下提示

原来是格式不对

--- BEGIN SQUARETEST LICENSE --- 
Name 
License Type 
SQT1-edfa8aa1-9b85-4b25-8ee8-de3fb9906e6d 
4FmXe7wH0qKOtYhJQpKaKwnV7dA1tMhX1NNK39XLDKXwdny70PpG6dhpPOFL7pAVapDjTi8zEJS0irBFeOndVx0VYkLOZDI7 
--- END SQUARETEST LICENSE ---


写的很清楚了:
Name :用户名
License Type :许可类型
SQT1:这里的SEQ格式和之前做了区别
第四部分:还是签名

jadx-gui启动

这里你问我为什么不远程调试,那我只能说我电脑配置调试虚拟机里面的idea有点卡 :rofl:

直接关键字搜索


就是这个b类的a属性来控制的,显然我们要往上找,看下他的激活码判断真正逻辑。

进入this.a.b(this.c.getText().trim());这个b方法

进来之后,发现他是调用的this.b.a(str),a方法

进入a方法


这可以看到这里就是真正的逻辑处

package com.squaretest.c;

import com.intellij.openapi.diagnostic.Logger;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jetbrains.annotations.NotNull;

/* JADX INFO: Access modifiers changed from: package-private */
/* loaded from: instrumented-TestStarter-1.8.10.jar:com/squaretest/c/q.class */
public class q {
    private static final Logger a = Logger.getInstance("SquaretestLicenseVerifier");
    private static final Pattern b = Pattern.compile("(-{0,3})?(\\s*BEGIN\\s+SQUARETEST\\s+LICENSE\\s*)(-{0,3})?");
    private static final Pattern c = Pattern.compile("(-{0,3})?(\\s*END\\s+SQUARETEST\\s+LICENSE\\s*)(-{0,3})?");
    private static final Pattern d = Pattern.compile("(.*)(\\s+\\d+\\s+User\\s+License|\\s+Single\\s+User\\s+License)\\s*(SQT1-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})\\s*([a-zA-Z0-9\\+\\/\\=\\s]+)", 32);
    private static final PublicKey e;

    private static /* synthetic */ void a(int i) {
        throw new IllegalArgumentException(String.format("Argument for @NotNull parameter '%s' of %s.%s must not be null", "licenseText", "com/squaretest/c/q", "getLicenseParts"));
    }

    static {
        try {
            e = KeyFactory.getInstance("DSA").generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode("MIIExjCCAzkGByqGSM44BAEwggMsAoIBgQDqnNqfX72mbdgwSUYJQFaHq3zzhTjgWNHi9o3qlTZIZuHAW+rN7SQift7ijK2AvOytOZE747cTJns7lsjZ8PagO138kiLVz+SvzJmC8zeE92DDt1muvju+kJimuEyW8f3kTOEcCEwqCCx6dqDvFCkotPMoQGq5vrJPhFd90PRs6G/Y8ISIJpmYv0dC1kJfeg7HXYZgxd1vTjs9O+6BssIa/oyei4S4cZLizCD5YdK82BM6/PNnWrgGgcs3THjzPinRARCD2J+cVyi5Rnb8yxtXvGAojBXYWug4rhlBxaIK4rIEmzWD/jDaRV3bPmrZuZVc2btWgUMWIr6w+S2lM/yrSWzrxEeqG7WoA5Ui8tqY/0FiiTI6ZN9iaraIGHCSfc7jh/E7XJ0k1suh2C7TdaCCUG7oe8euMAZ/SpTi7jY9mSxA8nJbXbSzUl694iu7/Q+hJKWIsPWkrLOoaVGv8J+MgZj7W1PaDJMc7cWYtPg1t3nQTZkCbHugjEsn8RisHj0CIQDE7qwrureb2DGUbXF6Vqbmh1R6qOnFSUpaSy9MoT1sEQKCAYBC5fp4RPj6nYmY2DDQBOexWx0na8vl8Sw17JDBol9YMgGKZyS9nNvoA7Z1UJvtFn89fPhZn8hlxtWg95FYwbyRjwCpRNCtDzj1IPuR2F2CZ00NX4dPql/N/lbNF4wa/cfOh5Vye33ulm7Qs8XO3O+KymKL7+vy0QXHr/jrDanJYQc33WTc4SN7gsGyvIYI1V/9qY1xiUROZYgzFWacBXFr3jbHixMKo98uTWCZFMfI3EcPTjABh8d1+B57GpwNzkBdbqssu52cTvREErpXPdQDxO17wjZHcvVqMMSN549QA/k3HFUmLSyKwiRq3jsC/c/PXL/edPvL/m4OD98xYHZPhNMRwXmkCvZ5qPR6sTyPcGiTJF6xHtzORR+iq5gAGZh/El2NyWYi1Bm6DXHxbGAk3OnTZMOybY7Bo8go9snRSx0DM7ldt3v9vjxrzlM3oaWnrOEBESGUSERxl+KjRMxCO+dou4nie+bL0iCFYUpaM2C+I7G/u25uZHE2PTLIXTEDggGFAAKCAYA3NdE3k0LSjmNgtHl1RiTyxig+sFrjvvhWngG3dCXvexWWOccSKfHGJ5NasB0KEh4gGcDCxayuYM4ZqD28ATswcsMUQpkdXfct7Npnheo8OFIdt46TRbFuGcLhwhCnSmqKbd0jRrLfIC7OPOIBSQN//uDO3qwTFGmnNXq8hbxbW6ux28oEOw4swa0l9sS4naAH5Dh2lqh9jwL8Aaeg2wPEeSjIZqvH93fgTTfzWhPxx2ehYcYS6rkaaqxCyPjau65hdfK3tGX0gg90KYRdK42mtRuuWUnkpprf6lnQDqeFkdY8bCh3fOOsRUzE4mLAbieDsDF3JQgc/6yGQWigAqsp+nnHfpVg1A3r5vMoluAvOPbwh9rUVU8JwFaPC+0q4B+mlmNPzber1VSGXMhiBQdU9c/GgIlvhIFYXoWZTJHrAjmE2hFFnSwnEt8hZeVU6zWE8VmkaT7lFkv42iVOtn1VZLhc4bcgiStVRXlu/T56+f3iug3YCyqhf0/NV8Huqus=".getBytes(StandardCharsets.UTF_8))));
        } catch (Throwable th) {
            a.error("Exception parsing Squaretest public key.", th);
            throw new RuntimeException(th);
        }
    }

    /* JADX INFO: Access modifiers changed from: package-private */
    public r a(String str) {
        if (str == null) {
            a.info("Validation failed. The license text is null.");
            return r.a;
        }
        List<String> b2 = b(str);
        if (!b(b2)) {
            return r.a;
        }
        String str2 = b2.get(1) + "\n" + b2.get(2) + "\n" + b2.get(3) + "\n";
        String str3 = b2.get(4);
        try {
            Signature signature = Signature.getInstance("SHA256withDSA", "SUN");
            signature.initVerify(e);
            signature.update(str2.getBytes(StandardCharsets.UTF_8));
            if (signature.verify(Base64.getDecoder().decode(str3))) {
                a.info("Validation succeeded.");
                return new r(true, a(b2));
            }
            a.info("Validation failed. Signature did not match.");
            return r.a;
        } catch (InvalidKeyException e2) {
            a.info("Validation failed. Received InvalidKeyException: ", e2);
            return r.a;
        } catch (NoSuchAlgorithmException e3) {
            a.info("Validation failed. Received NoSuchAlgorithmException: ", e3);
            return r.a;
        } catch (NoSuchProviderException e4) {
            a.info("Validation failed. Received NoSuchProviderException: ", e4);
            return r.a;
        } catch (SignatureException e5) {
            a.info("Validation failed. Invalid Signature: ", e5);
            return r.a;
        } catch (Throwable th) {
            a.info("Validation failed. Received Exception: ", th);
            return r.a;
        }
    }

    private String a(List<String> list) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            sb.append(list.get(i));
            if (i != list.size() - 1) {
                sb.append("\n");
            }
        }
        return sb.toString();
    }

    private boolean b(List<String> list) {
        if (list.size() != 6) {
            a.info(String.format("Validation failed: Number of lines in corrected license should be: %d, but was: %d", 6, Integer.valueOf(list.size())));
            return false;
        } else if (!"--- BEGIN SQUARETEST LICENSE ---".equals(list.get(0))) {
            a.info(String.format("Validation failed: corrected license first line should be %s, but was %s", "--- BEGIN SQUARETEST LICENSE ---", list.get(0)));
            return false;
        } else if (!"--- END SQUARETEST LICENSE ---".equals(list.get(5))) {
            a.info(String.format("Validation failed: corrected license last line should be %s, but was %s", "--- END SQUARETEST LICENSE ---", list.get(5)));
            return false;
        } else {
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).trim().isEmpty()) {
                    a.info(String.format("Validation failed: corrected license line number %d is empty", Integer.valueOf(i + 1)));
                    return false;
                }
            }
            if (!list.get(3).startsWith("SQT1-")) {
                a.info("Validation failed: License line 4 should start with: SQT1-");
                return false;
            } else if (list.get(3).length() != 41) {
                a.info("Validation failed: License line 4 should be 41 characters long");
                return false;
            } else {
                a.info("License format is valid");
                return true;
            }
        }
    }

    private List<String> b(@NotNull String str) {
        if (str == null) {
            a(0);
        }
        String c2 = c(str);
        ArrayList arrayList = new ArrayList();
        Matcher matcher = d.matcher(c2);
        if (!matcher.matches()) {
            a.info("License did not match expected format");
            return arrayList;
        }
        String replaceAll = ((String) Objects.requireNonNullElse(matcher.group(1), "")).trim().replaceAll("\\R", "");
        String replaceAll2 = ((String) Objects.requireNonNullElse(matcher.group(2), "")).replaceAll("\\R", " ").replaceAll("\\s{2,}", " ");
        String str2 = (String) Objects.requireNonNullElse(matcher.group(3), "");
        String replaceAll3 = ((String) Objects.requireNonNullElse(matcher.group(4), "")).trim().replaceAll("\\s", "");
        arrayList.add("--- BEGIN SQUARETEST LICENSE ---");
        arrayList.add(replaceAll);
        arrayList.add(replaceAll2.trim());
        arrayList.add(str2.trim());
        arrayList.add(replaceAll3);
        arrayList.add("--- END SQUARETEST LICENSE ---");
        return arrayList;
    }

    private String c(String str) {
        String replace = str.trim().replace("\r\n", "\n");
        Matcher matcher = b.matcher(replace);
        int i = 0;
        if (matcher.find()) {
            i = matcher.end();
        }
        int length = replace.length();
        Matcher matcher2 = c.matcher(replace);
        if (matcher2.find()) {
            length = matcher2.start();
        }
        return replace.substring(i, length).trim();
    }
}

逻辑分析

仔细看了下和之前的逻辑没啥变化
只不过是加了几个正则进行格式校验罢了
License Type :许可类型—>Single User License
SQT1:这里的SEQ格式和之前做了区别—>SQT1-edfa8aa1-9b85-4b25-8ee8-de3fb9906e6d
主要是上面加粗的两块内容,我这里直接用了它提示的SEQ1的内容

激活

这里提供一下可用的key吧

key:

--- BEGIN SQUARETEST LICENSE ---
https://linux.do
Single User License
SQT1-edfa8aa1-9b85-4b25-8ee8-de3fb9906e6d
MDwCHGOnsKyPJvhi+HOb1EENURBPvw/5yfksBDkzNcUCHDfe4PPw4g9m/Mx1La4FWwjeRdaWoKnH20GFgdc=
--- END SQUARETEST LICENSE ---

url.conf配置

[URL]
PREFIX,https://check-license.squaretest.com

power.conf配置

[Result]
; Crazer SquareTest 
EQUAL,1252928305935930364188836654659539783763354651514198834128474741636901358829591442663268321671447608434672557647654801256695706070390121140997016469299368451878473113176777251052200009896564134479303743386755118832927434621830777556477074692675327555783609023024851522833373208826677805143105704112974100331739660907854283923924846742821567052844564621514845949921927799272821933188023401491391856056178941231077880676157504936206091183929630012090341931726625217028590077151486105984357616693362609622392317788438463684098662383986299250882427800101029658387556883853400183602494493465486360184481856042579198871985642574324903511410852066537444728969819596257384821950203108952633327306239412132356286049996355528115746307723239894344967717017920042238511760861496721482855081711835037980132531066453041155574506158872071720887550549121487096473537646851478896832376289204709176929353782013339691638648706855400626264648427,63799485412468807255359920224075322029909048824336987224426287048077868021164,5324247702829575071675584424464753650392218653107256019844446848108111137442099610337859570555455698143292150721782644697379277011685799642486182126710157502727956703128754514558486334553566476108025376826305819777935803921489384958010396430272101680552342430895462908688531090113078723031928708629285229107140479737510796870634897049041653191187544146563185291995965490522694028755541591759570587784405584216735755028849094405105671910720507385847271205241745578838830570550531235832876196211389164931037470928703345364680618501202641532416176455579713697193616545908678078972847152998443205107778301587260990431581862325745419348472349271905582726545048997572791977411367331277268569955840556518571577037301445271741754306939038630660523878719644605078896473581519115501492972021349181081855817320631731169233237224542755144713990566794971663813152912381666786370580420476874050235609676577291970102822965121019243318222397->346302616994562686354828530212247863540670804209378964601650390240950279272814538723349008837975170834686682767309210719832654920608140532729926116017429875698746238687324099477739726636505214839650235223517803240024058366671228096972265269446102085984558558827927050498027924959390647089036272839794572804270067355257666941389182644150576059725292205985056895465786978165356544330796327645991555476831588133616731413107989259704316553112327979356533140997830603588425049792823605892550897759569276843656950384912753440400198996847985594853186029276570974934887542134987211057883298730914072818540962805139177209073802129570493403945126401844181759243759902539100932296962090990240812090470804229205271359684991016491788354232899346354354762303531440961681243389972692081419090594179220408411441492003686273757093784137568353252663216623391651153420455742073053201186770934788471505846088069915584865307717417353765452100700555952985862144368320422133165694373118641697395272967651566029484291172203986

配置好后记得保存文件并重启idea哦 :stuck_out_tongue_closed_eyes:

最后

再次声明哥们真不会破解,群里各位大佬别再at我了

30 个赞

你还说你不会破解!

3 个赞

明文代码总看的懂吧?加密了哥们就无能为力 :thinking:

1 个赞

那你能帮我破解一下支付宝或者微信吗,修改余额为999999999的那种

2 个赞

潇哥就是潇哥,小鹏算个

1 个赞

我一进来就看见潇哥在破解

1 个赞

潇总教我技术

1 个赞

:index_pointing_at_the_viewer:打开 jadx-gui直接把instrumented-TestStarter-1.8.10.jar往里拖,你也会

1 个赞

太厉害了,佬

1 个赞

不错不错, 很快啊

2 个赞

我先写测试再写业务代码怎么办? :pleading_face:

1 个赞

Squaretest大意了,没有闪 :rofl:

2 个赞

牛蛙牛蛙

1 个赞

牛啊

1 个赞

字我都认识,但是看不懂你在说什么。和哥哥比起来,我简直是新世纪文盲

1 个赞

潇总教我破解技术~:dog:

1 个赞

666

1 个赞

前排看看

1 个赞

真棒!
我刚拖进去发现格式变了,来找生成 key 的方法,一搜就有佬搞定了,我直接拿着用了 :kissing_heart:

1 个赞

水一帖