一、題目來源
題目來源:XCTF的mobile區的easyjni題目。
題目下載地址:題目鏈接地址
二、解題過程
1、下載好題目后,安裝到夜神模擬器中,發現有一個輸入框和一個按鈕,隨便輸入內容,點擊按鈕后發現彈出信息You are wrong!Bye~

2、將該apk拖進AK中反編譯,反編譯完成后搜索字符串You are wrong!,發現該信息位於MainActivity.java中。

3、用jeb反編譯直接查看反編譯后的java代碼,發現zaiMainActivity中首先導入了一個名為native的so文件,然后查看You are wrong!Bye~信息處發現將輸入框得到的字符串與MainActivity的b屬性作為參數調用MainActivity中的a(string,string)方法返回的布爾值作為是否通關條件的。


4、再來看一下a(string,string)方法,該方法返回第一個參數調用的a(string)方法的返回值,傳進去的參數為輸入框中的字符串,而方法a(string)則是調用ncheck方法,返回值也是ncheck函數的返回值,傳進去的參數則是調用實例化了a類的a函數的返回值,a類的a函數傳進去的參數為一個字節數組,再去看一下a類的a函數,很明顯是一個base64加密,只是編碼表變了一下而已。
a(string)函數:
private boolean a(String arg3) {
boolean v0_1;
try {
v0_1 = this.ncheck(new a().a(arg3.getBytes()));
}
catch(Exception v0) {
v0_1 = false;
}
return v0_1;
}

5、用ida打開so文件,找到ncheck函數,發現將傳進來的字符串首先將前16個字符和后16個字符交換位置,然后將這個新字符串兩兩一組互相交換位置,最后和一個字符串比較,相等則返回TRUE。

6、獲取flag思路也很簡單了,首先將字符串兩兩一組交換位置,然后將前16個字符和后16個字符交換位置,然后將這個新的字符串用自定義的basr64編碼表解碼即可得到flag,寫了個腳本,跑出來結果如下:

三、附件
獲取flag的python腳本如下(需要python版本至少為3.6):
def Base64Decode(str_list):
list_base = []
a = str_list[0] << 2
c = str_list[1] & 15
b = str_list[1] >> 4
a = a | b
list_base.append(a)
c = c << 4
a = str_list[2] & 3
b = str_list[2] >> 2
c = c | b
list_base.append(c)
a = a << 6
a = a | str_list[3]
list_base.append(a)
return list_base
CodingTable = 'i5jLW7S0GX6uf1cv3ny4q8es2Q+bdkYgKOIT/tAxUrFlVPzhmow9BHCMDpEaJRZN'
Ciphertext = 'QAoOQMPFks1BsB7cbM3TQsXg30i9g3=='
i = 0
flag = ''
while i <= (len(Ciphertext) - 1):
list1 = []
n = 0
for k in range(4):
if Ciphertext[i + k] == '=':
list1.append(0)
n = n + 1
else:
list1.append(CodingTable.index(Ciphertext[i + k]))
ba = Base64Decode(list1)
for j in range(3 - n):
ch = chr(ba[j])
flag = flag + str(ch)
i = i + 4
print(flag)
