網易遊戲登入密碼加密破解小試

羅小黑的黑發表於2020-10-18

最近實在太忙,更新速度也慢了,今天得空網上衝浪一會,心血來潮開啟了童年遊戲大話西遊官網,本想看看有什麼變化,發個帖抱怨一下為啥還不開懷舊服,就在登入之際又忍不住按下了F12,跟我想的一樣,的確是把密碼加密了,那好吧,等我把JS程式碼扣完再去發帖吧,覺得有幫助關注一下知識圖譜與大資料公眾號吧,當然不關注也無所謂。

前言

依然有完整JS程式碼,原文連結,點選文末閱讀更多即可,還是熟悉的rsa加密,有興趣的可以跟著東扣扣西扣扣,鍛鍊一下,整個過程不難。登入地址請跳到執行章節,在python程式碼裡有。。

直入正題

開啟登入介面,輸入錯誤的賬號密碼(圖中的賬號均為虛構)。
在這裡插入圖片描述
目的當然是檢視提交的資料裡有沒有加密的,找到其提交url,如下所示:
在這裡插入圖片描述
右側往下拉一點即可看到提交的引數,這次有點不一樣,提交的引數並不是FormData形式,不過也不影響,如下:
在這裡插入圖片描述
仔細看一下,大概可以知道pw是密碼加密結果,un是賬號,其它幾個引數暫時可以看成是固定的(一樣也可以通過除錯得到),今天主要是pw即密碼解密,接下來可以通過呼叫棧進去,呼叫棧進去也可以稍微利用一點技巧,比如可以檢視方法名,我們現在是在解密登入,那我們就可以通過方法名裡有類似login的進去。如下圖所示:
在這裡插入圖片描述
進去以後你可能會迫不及待的像往常一樣查詢pw關鍵字,其實通過關鍵字也能猜到這樣查詢是能找到,當時要耗費不少精力,畢竟pw只有兩個字母太容易與其它單詞匹配了:
在這裡插入圖片描述
是不是,一下子匹配了113個地方,你當然可以一下一下點了,這樣細心點也能找到,只不過費點時間而已,還有一個方法,現在我們已經知道密碼是被加密了,那我們就搜尋關於加密的單詞,類似encrypt,這是一個經驗,大家可以掌握,試著搜一下encrypt
在這裡插入圖片描述
一共搜到16處,這可比113少多了吧,手再也不酸了,,因為以後還會遇到很多引數名只有一個字母或者兩個的情況,這算是一個比較有意思的方法吧。接下來我們在幾個比較懷疑的encrypt打上斷點,一共有三處,為什麼這麼說,看下面程式碼,是不是都很像要找的(截圖麻煩,我直接把程式碼放下面了):

n.pw = MP.encrypt2(this.__password);//第一處
t.pw = MP.encrypt2(this.$refs.mpinput._$getValue() || "0");//第二處
 t.pw = MP.encrypt2(n);//第三處

進入除錯

在前面我們已經在幾個可以點打上了斷點,接下來就可以除錯了,啟用斷點(即輸入賬號密碼,點選登入),果不其然,跳到了其中一個斷點:
在這裡插入圖片描述
那就是這裡嘍,單步執行下去,進入加密函式encrypt2
在這裡插入圖片描述
其中encrypt2的引數e為你輸入的密碼,除錯了幾次發現這裡getPublicKey引數p其實也是個固定值,一共需要摳的主函式也就兩個,一個encryptgetPublicKeyp值請看下圖:
在這裡插入圖片描述
繼續執行,進入設定getPublicKey函式:

  getPublicKey: function(e) {
        if (e.length < 50)
            return !1;
        if ("-----BEGIN PUBLIC KEY-----" != e.substr(0, 26))
            return !1;
        e = e.substr(26);
        if ("-----END PUBLIC KEY-----" != e.substr(e.length - 24))
            return !1;
        e = e.substr(0, e.length - 24);
        e = new ASN1Data(Base64.decode(e));
        if (e.error)
            return !1;
        e = e.data;
        if ("1.2.840.113549.1.1.1" == e[0][0][0])
            return new RSAPublicKey(e[0][1][0][0],e[0][1][0][1]);
        else
            return !1
    }

encrypt函式:

   encrypt: function(e, t) {
        if (!t)
            return !1;
        var i = t.modulus.bitLength() + 7 >> 3;
        e = this.pkcs1pad2(e, i);
        if (!e)
            return !1;
        e = e.modPowInt(t.encryptionExponent, t.modulus);
        if (!e)
            return !1;
        e = e.toString(16);
        for (; e.length < 2 * i; )
            e = "0" + e;
        return Base64.encode(Hex.decode(e))
    }

到這裡大家應該都知道要扣哪些了吧,對,就是getPublicKeyencrypt裡面使用到的一些小函式,比如Base64.decode(e)Hex.decode(e)等等這些,難點是這些方法裡面還巢狀了其它方法,容易的地方是這些方法基本都在一起,再提一個摳程式碼的小技巧,摳的時候可以找到你想要的函式,點一下函式的大括號,括號下面會有橫線,這時候你就可以確定摳到哪裡了,因為結尾的大括號下面也會有橫線,聽不明白沒關係,看一下下圖就理解了:
在這裡插入圖片描述

我這裡就不列出所有程式碼了,大家有興趣的可以關注知識圖譜與大資料公眾號,找到這篇文章,點選文末的閱讀原文即可看到完整JS程式碼。

執行

相信大家都能摳出來,摳完就可以通過python執行,上盤古時期程式碼:

import execjs
#url = http://xy2.netease.com/member.php?mod=logging&action=login
with open('..//js//dahuaxiyou.js', encoding='utf-8') as f:
    dahuaxiyou = f.read()
js = execjs.compile(dahuaxiyou)
logid = js.call('get_pwd', "qwerqwrqrq")
print(logid)

執行結果如下:
在這裡插入圖片描述

結束

rsa的程式碼的確要比md5要費點時間,不過只要細心都能摳出來,摳不出來的點即文末閱讀原文即可。覺得有幫助關注一下知識圖譜與大資料公眾號吧,有大量摳JS程式碼的文章,當然不關注也無所謂。
在這裡插入圖片描述

相關文章