論壇中某鎖機軟件破解及注冊碼計算過程
起因
最開始是今天下午在論壇病毒樣本區發現了這個鎖機軟件,出于學習與助人的目的對該鎖機軟件進行了逆向分析。并編寫了注冊機注冊代碼。原帖的地址貼在下面。
https://www.52pojie.cn/thread-1757174-1-1.html
直入主題
該鎖機軟件,共需要解鎖三次。每次注冊碼的計算都大體上相同,但是有細微的區別。
這里先給出注冊碼計算代碼
復制代碼 隱藏代碼
# "?" - 0
# "★" - 1
# "?" - 2
# "?" - 3
# "?" - 4
# "啊" - 5
# "?" - 6
# "?" - 7
# "ぇ" - 8
# "◎" - 9
import hashlib
import re
def MD5(s):
s += "23543dfggeelysdafaqj23ou89ZXcj@#$@#$#@KJdjklj;D../dSF.,"
md5 = hashlib.md5()
md5.update(s.encode('utf-8'))
return md5.hexdigest().upper()
def SHA1(s):
sha1 = hashlib.sha1()
sha1.update(s[:-1].encode('utf-8'))
return sha1.hexdigest().upper()
register = "1422165"
res = re.sub(r'\D+', '', SHA1(MD5(register)))[:9]
# "6D91290A4382B010643970816C4548D6" 290
# "E48DAFD477C1AE9A01D5555585938D86" 100
# "A7BDC7CED8416DB0E2C6ADA4FEE8007C" 800
print("Your password1 is :", "290" + res)
print("Your password2 is :", "100" + res)
print("Your password3 is :", "800" + res)
對于第一個鎖機頁面,其布局如圖,我們需要點擊大概60+次右下角的需要解鎖加群按鈕,然后藍色按鈕上方就會出現輸入框。對于注冊碼的計算。我們需要先將識別碼按上方代碼中的注釋對照表。按照圖標-數字 一一對應,轉化為注冊碼填入輸入框中,之后點擊藍色按鈕,可以通過第一層鎖機界面來到第二層。如圖中的★???★?啊,將其轉換成與之對應的注冊碼為1422165。我們將該轉換得到的數字填入上方代碼中,運行腳本。緊跟輸出Your password1 is :之后的就是第一層鎖機的注冊碼。
原諒我對圖片打這么多碼,因為我知道不打這么厚的碼,圖片是無法過審核的。同時該鎖機軟件在運行時還會發出令人社會性死亡的聲音。并且自動將你手機音量開至最大無法關閉。
那么對于圖片中的識別碼,我們可以計算出來第一層密碼為 290304753532

來到鎖機第二層,界面變得比上層友好了一些,但仍舊伴有令人羞恥的聲音。計算方法同上,將字符識別碼轉化為數字,填入python腳本中,緊跟著輸出Your password2 is : 之后的就是你的第二層鎖機密碼。
這里我們的解鎖密碼為100841573560

最后一層計算同理,這里我們的解鎖密碼為800948640024

全部解鎖完畢后,聲音依舊不會消失。這時把軟件卸載即可。聲音與鎖機界面再也不會出現。
軟件分析
正如原帖子中提到的。這個鎖機機軟件對smali代碼進行了混淆。這里的混淆實際上比較簡單,做的就是在調用類的方法時,將其轉換為一個函數調用的過程。幾乎所有java中的方法都進行了這樣的轉換。其主要表現形式如下方的代碼,并且對于java中的變量名使用了一些unicode字符作為變量名。這些unicode 字符不僅長得相似還難以區分。如下方這個代碼中,你調用bb這個函數,實際上就是在執行一個判斷兩個字符串是否相等的方法而已。當這樣的混淆很多,并且結合unicode變量名的時候。代碼看起來就很混亂。
復制代碼 隱藏代碼
public static boolean bb(String arg2, Object arg3) {
return arg2.equals(arg3);
}
對于如何反混淆這個問題,經過一番搜索后,我搜索到一個android通用反混淆工具 simplify。不過我在使用之后,發現它對于這個樣本中的混淆并不能很好的去除,反混淆得到的dex文件,在jeb中看與原dex基本沒有區別。所有這里我還是選擇通過JEB去調試與分析apk中的注冊碼的計算過程。在逆向過程中我也考慮過是否可以使用frida框架來hook獲取某些函數的返回值。但最后并沒有使用,第一點是我本身對于frida并不是很熟悉,第二點則是這里java中的關鍵部分類名都是unicode字符,幾乎復制不出來。如果編寫frida hook腳本我不知道能不能正常hook。
對于smali中的變量名混淆,我選擇的是使用JEB的變量重命名功能來批量對自己所關心的變量進行重命名。而將方法轉換為函數調用的混淆。我則是去硬閱讀代碼與結合調試分析。畢竟將方法與函數進行一一映射這個邏輯還是比較容易去理解。同時也可以通過對函數一些名稱進行重命名,這樣看見函數名就可以知道它調用的是什么方法。
下面給出一些我逆向過程中的關鍵分析。
所有逆向中最關鍵的是在 com.mycompany.myapp7.chengnan 這個類,這個里實現的加鹽的md5算法,與去掉最后一個字符進行sha1哈希計算的算法。
在chengnan這個類中
對于md5 我們的鹽是儲存在類的一開始。進行md5計算時會將鹽一起附在需要計算的字符串后面。

通過函數中的一些字符串信息,我們可以去猜測這里使用的是md5加密算法。并且調試去驗證這里是一個標準的md5加密算法。且返回結果為大寫的md5結果。

sha1 加密算法也可以從圖中找到。這里需要注意的是。紅框中的這個函數調用做的一件事是將傳入的字符串,截掉最后一位然后返回。所以其實v1 的值是 arg7[:-1] 這樣的字符串。

然后是我們需要關心的第一個鎖機界面的,驗證密碼的類。它原本的名字是一個unicode字符,如紅框中。在這里我將他重命名了一下,箭頭指向的。

這個類的特征是一開始有這樣一個數組的定義

對于第一個鎖機頁面我們需要關心的代碼如下。
首先第一個紅框是獲取我們的輸入,也就是密碼。并判斷它的長度。
第二個紅框里的小框就是獲取我們的識別碼,在這里它是每一次都會隨機生成的一個隨機數。
然后大紅框里所做的事就是對轉換成數字的識別碼先進行加鹽的md5加密,然后進行截斷掉最后一位的sha1加密。sha1之后得到的結果我們還要通過正則匹配將其中的所有非數字字符替換為空。只保留下數字字符。并且最后得到的純數字字符串,它的長度要大于9。
下面的if 條件判斷就是在判斷我們輸入的密碼經過加密后與識別碼計算得到的結果是否相同。計算過程如下。
首先將我們上方通過識別碼得到的純數字字符串。將其截取前9位并憑借在"6D91290A4382B010643970816C4548D6" 字符串后得到我們的字符串一。
而我們的輸入的密碼進行了哪些計算呢。我們輸入的密碼被分隔成了兩份,前三個字節作為第一份。后面作為第二份。前3個字節先進行sha1計算再進行md5計算。后面的部分直接與三個字節計算得到的結果拼接起來得到字符串二。

這個時候我們就發現了,"6D91290A4382B010643970816C4548D6"字符串實際上是與我們md5哈希計算后得到的結果長度是相同的,所以我們輸入的密碼的前三個數字一定是固定不變的。并且由于是先進行的sha1計算再計算md5。這個樣本的sha1計算會截斷最后一位。所以我們只需要爆破前兩個字節即可得到前三個數字是什么數字。爆破代碼如下
復制代碼 隱藏代碼
def MD5(s):
s += "23543dfggeelysdafaqj23ou89ZXcj@#$@#$#@KJdjklj;D../dSF.,"
md5 = hashlib.md5()
md5.update(s.encode('utf-8'))
return md5.hexdigest().upper()
def SHA1(s):
sha1 = hashlib.sha1()
sha1.update(s[:-1].encode('utf-8'))
return sha1.hexdigest().upper()
l = [chr(i) for i in range(0x21, 0x7f)]
for c1 in l:
for c2 in l:
for c3 in ["0"]:
if MD5(SHA1(c1 + c2 + c3)) == "6D91290A4382B010643970816C4548D6":
print(c1 + c2 + c3)
# 290
所以對于第一層鎖機密碼的前三個數字我們已經得到。而后面9個數字實際上就是通過識別碼計算得到的了。計算方法在上面已經解釋了。先md5再sha1。去除掉非數字字符,截取前9位就是我們的最后9個數字。拼接在一起就是我們第一層鎖機的密碼。
第2 3層鎖機密碼計算過程相同,只不過對于前3個數字的加密結果做了更改。分別為"E48DAFD477C1AE9A01D5555585938D86" 與 "A7BDC7CED8416DB0E2C6ADA4FEE8007C" 我們同樣可以用上方代碼進行爆破。
得到結果如下
復制代碼 隱藏代碼 # "6D91290A4382B010643970816C4548D6" 290 # "E48DAFD477C1AE9A01D5555585938D86" 100 # "A7BDC7CED8416DB0E2C6ADA4FEE8007C" 800
這也就是我們上方計算密碼的python腳本中的注釋。
結束語
至此這個鎖機軟件已經分析完畢。作為潛水論壇多年的底層人員,這次也終于對論壇有了貢獻,如文章中有不足之處,也希望各位大佬能夠指出并包涵我的錯誤。同時最后也要提醒大家對于不明軟件不要亂安裝,同時不要亂給權限即可保證安全。下面我還會打包一份我修改過的鎖機樣本。將其中令人會社會性死亡的音頻給替換掉了以供大家學習。不然在你分析鎖機軟件時,手機一直發出奇怪的聲音,那么也不能安心分析軟件了。
壓縮包的解壓密碼為 52pojie
鏈接:https://pan.baidu.com/s/1ZMGPGf2PM8F3FOcCdqpdXw?pwd=541r
提取碼:541r
信息安全與通信保密雜志社
一顆小胡椒
嘶吼專業版
關鍵基礎設施安全應急響應中心
一顆小胡椒
安全圈
關鍵基礎設施安全應急響應中心
看雪學苑
D1Net
看雪學苑
雷石安全實驗室
看雪學苑