XCTF-easyjni
阿新 • • 發佈:2020-07-28
前期工作
查殼無殼
逆向分析
檔案結構
MainActivity程式碼
public class MainActivity extends c { static { System.loadLibrary("native"); } /* access modifiers changed from: private */ public boolean a(String str) { try { return ncheck(new a().a(str.getBytes())); } catch (Exception e) { return false; } } private native boolean ncheck(String str); /* access modifiers changed from: protected */ public void onCreate(Bundle bundle) { super.onCreate(bundle); setContentView((int) R.layout.activity_main); findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if (MainActivity.this.a(((EditText) ((MainActivity) this).findViewById(R.id.edit)).getText().toString())) { Toast.makeText(this, "You are right!", 1).show(); } else { Toast.makeText(this, "You are wrong! Bye~", 1).show(); } } }); } }
可以看到點選觸發MainActivity的a方法,呼叫了a類的a方法對輸入的字串處理再對結果用native方法ncheck處理。
來看看a類的a方法
public class a { private static final char[] a = {'i', '5', 'j', 'L', 'W', '7', 'S', '0', 'G', 'X', '6', 'u', 'f', '1', 'c', 'v', '3', 'n', 'y', '4', 'q', '8', 'e', 's', '2', 'Q', '+', 'b', 'd', 'k', 'Y', 'g', 'K', 'O', 'I', 'T', '/', 't', 'A', 'x', 'U', 'r', 'F', 'l', 'V', 'P', 'z', 'h', 'm', 'o', 'w', '9', 'B', 'H', 'C', 'M', 'D', 'p', 'E', 'a', 'J', 'R', 'Z', 'N'}; public String a(byte[] bArr) { StringBuilder sb = new StringBuilder(); for (int i = 0; i <= bArr.length - 1; i += 3) { byte[] bArr2 = new byte[4]; byte b = 0; for (int i2 = 0; i2 <= 2; i2++) { if (i + i2 <= bArr.length - 1) { bArr2[i2] = (byte) (b | ((bArr[i + i2] & 255) >>> ((i2 * 2) + 2))); b = (byte) ((((bArr[i + i2] & 255) << (((2 - i2) * 2) + 2)) & 255) >>> 2); } else { bArr2[i2] = b; b = 64; } } bArr2[3] = b; for (int i3 = 0; i3 <= 3; i3++) { if (bArr2[i3] <= 63) { sb.append(a[bArr2[i3]]); } else { sb.append('='); } } } return sb.toString(); } }
又是一個換表的Base64
使用IDA檢視so層的ncheck方法,先看看字串
在最下面看到了個可以的字串,上面也看到了ncheck的方法名,跟進這個字串
在IDA匯入jni.h的過程中出了點問題,匯入後還是無法顯示JNI介面函式,參考了https://www.52pojie.cn/thread-503009-1-1.html中的方法解決
選中env變數,按一下“y”鍵,將_JNIEnv 改成JNIEnv*,即可解決
ncheck程式碼
第一個dowhile作用為將字串前後兩半互換。
第二個dowhile中__ OFSUB __ 功能是產生(v10-30)的溢位標誌位,__ OFSUB __功能參考了
https://blog.csdn.net/youyou519/article/details/103782264
https://jingyan.baidu.com/article/5d6edee23100a3d8eadeecf0.html
因為正數減正數是不會溢位的,所以溢位標誌位為0,v12為0。當v10大於或等於30時v11也為0,二者異或為0,所以第二個dowhile的條件其實相當於v10 <= 30。這個迴圈的功能為將字串兩兩互換。
之後和MbT3sQgX039i3g==AQOoMQFPskB1Bsc7比較,相等則返回1。
指令碼編寫
a = [
'i', '5', 'j', 'L', 'W', '7', 'S', '0', 'G', 'X', '6', 'u', 'f', '1', 'c',
'v', '3', 'n', 'y', '4', 'q', '8', 'e', 's', '2', 'Q', '+', 'b', 'd', 'k',
'Y', 'g', 'K', 'O', 'I', 'T', '/', 't', 'A', 'x', 'U', 'r', 'F', 'l', 'V',
'P', 'z', 'h', 'm', 'o', 'w', '9', 'B', 'H', 'C', 'M', 'D', 'p', 'E', 'a',
'J', 'R', 'Z', 'N'
]
s = ''.join(a)
def My_base64_decode(inputs):
# 將字串轉化為2進位制
bin_str = []
for i in inputs:
if i != '=':
x = str(bin(s.index(i))).replace('0b', '')
bin_str.append('{:0>6}'.format(x))
#print(bin_str)
# 輸出的字串
outputs = ""
nums = inputs.count('=')
while bin_str:
temp_list = bin_str[:4]
temp_str = "".join(temp_list)
#print(temp_str)
# 補足8位位元組
if (len(temp_str) % 8 != 0):
temp_str = temp_str[0:-1 * nums * 2]
# 將四個6位元組的二進位制轉換為三個字元
for i in range(0, int(len(temp_str) / 8)):
outputs += chr(int(temp_str[i * 8:(i + 1) * 8], 2))
bin_str = bin_str[4:]
print("Decrypted String:\n%s " % outputs)
raw = list('MbT3sQgX039i3g==AQOoMQFPskB1Bsc7')
for i in range(0, len(raw), 2):
raw[i], raw[i + 1] = raw[i + 1], raw[i]
raw[:16], raw[16:] = raw[16:], raw[:16]
My_base64_decode(''.join(raw))
flag
flag{just_ANot#er_@p3}