<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    XX客戶端APP簽名分析之bp插件打造篇

    VSole2021-08-02 19:09:58

    前言

    本篇主要思路及方法來自于bit4woo和CC11001100兩位巨佬的成果。


    學習鏈接https://github.com/bit4woo/burp-api-drops
    


    根據大佬的建議,本次插件使用java進行編寫。而且bp插件的編寫對于類名也有嚴格的限制。


    主要的調用邏輯如下所示



    根據該圖,對于插件編寫的流程其實也很清楚了,我們只需要先調用這些之前寫好的類,然后只需要編寫BurpExtender這一個類就好了。


    01 熱編寫流程


    首先因為不同網站對應的Key不同,先創建個字典進行存放。


    public BurpExtender() {  this.signMap = new ConcurrentHashMap<>();    signMap.put("class.mosaic.cn", "ac6190d7dfaa77df726f0a82244d3eda68675ccd4e95de802f5042e91d15edc7bae3026d8f0fb2a8287446bb289563970264");  signMap.put("bbsapi.mosaic.cn", "Wj8BI3VUZ6BuojAkqzBM3HWHNHv08xdZEtaksbRg6snnuLsvivwa8IvR6PvQ76H0IQQsqkIsa5OKJtg6QcBMfCblMMywgZaA8co");    }
    


    然后是IBurpExtender必須實現的方法registerExtenderCallbacks


    @Overridepublic void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {        this.callbacks = callbacks;        callbacks.setExtensionName("xxsign重放輔助滲透");        helpers = callbacks.getHelpers();        stdout = new PrintWriter(callbacks.getStdout(), true);        callbacks.registerHttpListener(this);//如果不注冊,processHttpMessage方法不會生效。    }
    


    接下來就是processHttpMessage方法,首先要確定toolFlag,不同的toolFlag代表不同的burp組件,此處我們只處理repeater發出的消息。


    if (toolFlag != burp.IBurpExtenderCallbacks.TOOL_REPEATER) {            return;        }        // 只處理請求,響應則忽略        if (!messageIsRequest) {            return;        }        byte[] request = messageInfo.getRequest();        if (request == null || request.length == 0) {            return;        }
            // 只有特定的兩個域名才會生效        final IHttpService httpService = messageInfo.getHttpService();        final String host = httpService.getHost();        if (!signMap.containsKey(host)) {            return;        }
    


    接下來是獲取參數,由于上一節中已經分析出了參數組成,key是固定值,noncestr是隨機生成。timestamp是當前時間戳,因此實際上參數的獲取所產生交互是比較少的。只需要生成這些參數的拼接格式,以及SHA1算法。


    long now = System.currentTimeMillis();
    


    private static String randomNoncestr() {        StringBuilder sb = new StringBuilder();        for (int i = 0; i < 8; i++) {            char c = (char) (ThreadLocalRandom.current().nextInt(10) + 48);            sb.append(c);        }        return sb.toString();    }
    


    final String sign = DigestUtils.sha1Hex(sb.toString());
    

    最后每次重放就替換掉參數即可。

    final IParameter newTimestampParam = helpers.buildParameter("timestamp", now + "", IParameter.PARAM_URL);        final IParameter newSignParam = helpers.buildParameter("sign", sign, IParameter.PARAM_URL);        final IParameter newNoncestrParam = helpers.buildParameter("noncestr", noncestr, IParameter.PARAM_URL);        request = helpers.updateParameter(request, newTimestampParam);        request = helpers.updateParameter(request, newSignParam);        request = helpers.updateParameter(request, newNoncestrParam);        messageInfo.setRequest(request);        stdout.println("更新了sign: " + sign);        stdout.println("更新了timestamp: " + now);        stdout.println("更新了noncestr: " + noncestr);        stdout.println("本次處理完畢");
    

    所有的關鍵操作就這樣完成了。

    02 總結

    最終BurpExtender類代碼

    public class BurpExtender implements IBurpExtender, IHttpListener {
        private IBurpExtenderCallbacks callbacks;    private IExtensionHelpers helpers;    private PrintWriter stdout;
        private ConcurrentHashMap signMap;
        public BurpExtender() {        this.signMap = new ConcurrentHashMap<>();        signMap.put("class.mosaic.cn", "ac6190d7dfaa77df726f0a82244d3eda68675ccd4e95de802f5042e91d15edc7bae3026d8f0fb2a8287446bb289563970264");        signMap.put("bbsapi.mosaic.cn", "Wj8BI3VUZ6BuojAkqzBM3HWHNHv08xdZEtaksbRg6snnuLsvivwa8IvR6PvQ76H0IQQsqkIsa5OKJtg6QcBMfCblMMywgZaA8co");    }
        @Override    public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {        this.callbacks = callbacks;        callbacks.setExtensionName("xx客戶端sign重放輔助滲透");        helpers = callbacks.getHelpers();        stdout = new PrintWriter(callbacks.getStdout(), true);        callbacks.registerHttpListener(this);    }
        @Override    public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {        // 只處理repeater發出的消息        if (toolFlag != burp.IBurpExtenderCallbacks.TOOL_REPEATER) {            return;        }        // 只處理請求,響應則忽略        if (!messageIsRequest) {            return;        }        byte[] request = messageInfo.getRequest();        if (request == null || request.length == 0) {            return;        }
            // 只有特定的兩個域名才會生效        final IHttpService httpService = messageInfo.getHttpService();        final String host = httpService.getHost();        if (!signMap.containsKey(host)) {            return;        }
            stdout.println("檢測到,開始處理...");        final IRequestInfo requestInfo = helpers.analyzeRequest(request);        TreeMap signParamsMap = new TreeMap<>();        requestInfo.getParameters().forEach(x -> {            if (IParameter.PARAM_URL != x.getType()) {                return;            }            if ("timestamp".equals(x.getName()) || "sign".equals(x.getName()) || "noncestr".equals(x.getName())) {                return;            }            signParamsMap.put(URLDecoder.decode(x.getName(), UTF_8), URLDecoder.decode(x.getValue(), UTF_8));        });
            String appSignKey = signMap.get(host);        signParamsMap.put("appSignKey", appSignKey);
            long now = System.currentTimeMillis();//        long now = 1626237221383L;        signParamsMap.put("timestamp", now + "");
            String noncestr = randomNoncestr();//        String noncestr = "73699378";        signParamsMap.put("noncestr", noncestr);
            StringBuilder sb = new StringBuilder();        signParamsMap.forEach((key, value) -> {            sb.append(key).append("=").append(value).append("&");        });        if (sb.length() > 0) {            sb.deleteCharAt(sb.length() - 1);        }        stdout.println("用來SHA1加密的字符串: " + sb.toString());        final String sign = DigestUtils.sha1Hex(sb.toString());
            // 替換掉參數        final IParameter newTimestampParam = helpers.buildParameter("timestamp", now + "", IParameter.PARAM_URL);        final IParameter newSignParam = helpers.buildParameter("sign", sign, IParameter.PARAM_URL);        final IParameter newNoncestrParam = helpers.buildParameter("noncestr", noncestr, IParameter.PARAM_URL);        request = helpers.updateParameter(request, newTimestampParam);        request = helpers.updateParameter(request, newSignParam);        request = helpers.updateParameter(request, newNoncestrParam);        messageInfo.setRequest(request);        stdout.println("更新了sign: " + sign);        stdout.println("更新了timestamp: " + now);        stdout.println("更新了noncestr: " + noncestr);        stdout.println("本次處理完畢");
    
    
    
        }
        private static String randomNoncestr() {        StringBuilder sb = new StringBuilder();        for (int i = 0; i < 8; i++) {            char c = (char) (ThreadLocalRandom.current().nextInt(10) + 48);            sb.append(c);        }        return sb.toString();    }
        public static void main(String[] args) {        System.out.println(randomNoncestr());    }
    }
    


    stringsign
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    得益于Unicorn的強大的指令trace能力,可以很容易實現對cpu執行的每一條匯編指令的跟蹤,進而對ollvm保護的函數進行剪枝,去掉虛假塊,大大提高逆向分析效率。
    介紹實戰中由于各種情況,可能會對反序列化Payload的長度有所限制,因此研究反序列化Payload縮小技術是有意義且必要的本文以CommonsBeanutils1鏈為示例,
    本篇主要思路及方法來自于bit4woo和CC11001100兩位巨佬的成果。學習鏈接https://github.com/bit4woo/burp-api-drops
    JSP Webshell的檢測工具
    2021-12-13 12:04:53
    在11月初,我做了一些JSP Webshell的免殺研究,主要參考了三夢師傅開源的代碼。然后加入了一些代碼混淆手段,編寫了一個免殺馬生成器JSPHorse,沒想到在Github上已收獲500+的Star
    它們基于JSON格式,并包含一個令牌簽名以確保令牌的完整性。本文主要討論使用JSON Web令牌的安全隱患,以及攻擊者如何利用它們繞過訪問控制。有效載荷和簽名。
    frida復現某app算法
    2023-01-11 10:44:51
    獲取數據某app的登錄界面抓包,發現參數都加密了查驗一下殼,未加殼,可以進行反編譯使用jadx進行反編譯,嘗試搜索一下參數名”Encrypt”,發現兩個JsonRequest類的方法存在運用frida及其下面的代碼在java層進行hook,發現只調用了addRequestMap方法Java.perform(function (){. 跟進addRequestMap方法,了解其使用des加密,hook該方法可獲取明文及加密結果hook代碼Java.perform(function () {
    首先使用jadx對apk進行逆向。?搜索關鍵字 QDSign,可以直接找到對應的類,可以看到參數經過加密得到。??進一步跟蹤,發現了c類中有如下三個so方法,還有3個loadlibrary,分別進行了hook,發現c-lib動態注冊了sign,sos動態注冊了s,沒有發現crypto有動態注冊。
    買車報價APP sign分析
    2023-01-12 11:14:54
    數字企業殼懂得都懂不可能全部脫下來的只能用哪些類就脫哪些了,略微麻煩點。想著通過url的地址去找對應的發請求的位置是不是可以,于是通過搜索url路徑找到了一個類。這是具體的加密方法,沒啥難度了。
    在火線zone看到利用app歷史版本來進行app的逆向分析,可以降低一下分析難度,比較老版本的安全防護做的不是很到位。正好最近有一個app,嘗試利用一下老版本進行分析登錄簽名,沒想到效果非常好。
    FastJson結合二次反序列化繞過黑名單
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类