一、題目來源
題目來源:XCTF題庫安卓區easyjava
題目下載鏈接:下載地址
二、解題過程
1、將該apk安裝進夜神模擬器中,發現有一個輸入框和一個按鈕,隨便輸入信息,點擊按鈕,發現彈出信息You are wrong!Bye~
。
2、將該APK拖進AndroidKiller中反編譯,反編譯完成后,搜索字符串You are wrong
,發現該字符串位於MainActivity.java中,如下圖所示:
3、用jeb反編譯該apk,反編譯完成后直接將smali層代碼轉為java代碼,發現在onCreate
函數出現該字符串,發現將輸入框中的字符串作為參數傳入MainActivity的a(string)
函數中,返回的布爾值確認flag是否正確。
4、而該a函數調用了MainActivity的b函數,b函數返回一個布爾值,b函數作用為首先獲取輸入框的字符串截取前5個符flag{
與最后一個字符}
之間的字符串。
然后實例化了一個b類,並且傳入了一個參數2,而b類的構造函數首先為一個整形數組復制,然后左移該整形數組,左移的次數就是傳進來的整數,這里是2。
在然后實例化了一個a類,傳入了一個參數3,而a類的構造函數與b類的構造函數基本相同,就不再說了。
之后遍歷截取下來的字符串的每個字符,然后將調用MainActivity中的a(string,b,a)
函數返回回來的字符串添加到變量v3的尾部,遍歷完后,將得到的字符串與字符串wigwrkaugala
比較,若結果為真,返回True
,否則返回False
。
5、接着來看MainActivity的a(string,b,a)
函數,該函數首先將傳進來的第一個字符串作為調用b類的a函數的參數傳入,然后將返回回來的結果作為調用a類的a函數的參數傳入,最后返回一個字符。
再來看b類的a函數,該函數首先獲取傳進來的字符在字符串b.b中的索引,然后得到在b類中定義的整形數組中與該該索引相等的在數組中的索引,然后調用b類的a()
函數,該函數作用為將b類中數組與字符串左移一位,然后返回該數組索引。
接着再來看a類中的a(int)
函數,該函數首先獲取與傳進來的參數相等的數組中的值的索引,然后獲取在字符串中索引為該數組索引的字符,最后返回該字符,當然,其中也調用a()
函數,但是該函數要求等於25,所以該函數木有任何作用。
6、上面幾步以及詳細講述了該apk的flag加密流程,要獲取flag,逆向解密即可,解密腳本跑出結果如下:
三、附件
解密腳本:(要求python版本3.6或者與上)
cipherText = 'wigwrkaugala'
aArray = [21,4,24,25,20,5,15,9,17,6,13,3,18,12,10,19,0,22,2,11,23,1,8,7,14,16]
aString = 'abcdefghijklmnopqrstuvwxyz'
bArray = [17,23,7,22,1,16,6,9,21,0,15,5,10,18,2,24,4,11,3,14,19,12,20,13,8,25]
bString = 'abcdefghijklmnopqrstuvwxyz'
def changeBArrayandString():
global bString
global bArray
chArray = bArray[0]
chString = bString[0:1]
for i in range(len(bArray) - 1):
bArray[i] = bArray[i + 1]
bArray[len(bArray) - 1] = chArray
bString = bString[1:]
bString += chString
def getBchar(ch):
v2 = bArray[ch]
arg = bString[v2]
changeBArrayandString()
return arg
def getAint(ch):
global aString
global aArray
v1 = aString.index(ch)
arg5 = aArray[v1]
return arg5
print('flag{',end='')
for k in cipherText:
v0 = getAint(k)
print(getBchar(v0),end='')
print('}')