本物のAndroidマルウェアの解析訓練にもなる良問なので, ksnctf Jewel の writeup を残そうと思う。
ノーヒントで Jewel.apk が与えられるので JADX でデコンパイルする
AndroidManifest.xmlからエントリーポイントをさがす
<activity android:label="@string/app_name" android:name=".JewelActivity">
JewelActivityから動きそう
JewelActivity の OnCreate() を見るとすぐに AES とわかる
Cipher instance2 = Cipher.getInstance("AES/CBC/PKCS5Padding");
AES鍵は?
String deviceId = ((TelephonyManager) getSystemService("phone")).getDeviceId();
try {
MessageDigest instance = MessageDigest.getInstance("SHA-256");
instance.update(deviceId.getBytes("ASCII"));
String bigInteger = new BigInteger(instance.digest()).toString(16);
if (!deviceId.substring(0, 8).equals("99999991")) {
new AlertDialog.Builder(this).setMessage("Your device is not supported").setCancelable(false).setPositiveButton("OK", new C0001b(this)).show();
} else if (!bigInteger.equals("356280a58d3c437a45268a0b226d8cccad7b5dd28f5d1b37abf1873cc426a8a5")) {
new AlertDialog.Builder(this).setMessage("You are not a valid user").setCancelable(false).setPositiveButton("OK", new C0000a(this)).show();
} else {
InputStream openRawResource = getResources().openRawResource(R.raw.jewel_c);
byte[] bArr = new byte[openRawResource.available()];
openRawResource.read(bArr);
SecretKeySpec secretKeySpec = new SecretKeySpec(("!" + deviceId).getBytes("ASCII"), "AES");
getDeviceId()でIMEIを取得している
!+IMEIがAES鍵だ!
ただし,動作に条件があり,
IMEIの先頭8文字 = 99999991
IMEIのSHA-256ハッシュ = 356280a58d3c437a45268a0b226d8cccad7b5dd28f5d1b37abf1873cc426a8a5
IMEIは15文字なので
999999910000000~999999919999999まで総当たりでハッシュ計算してターゲットのIMEIを計算する
IVは?
IvParameterSpec ivParameterSpec = new IvParameterSpec("kLwC29iMc4nRMuE5".getBytes());
ペイロードは?
InputStream openRawResource = getResources().openRawResource(R.raw.jewel_c);
問題データ Jewel.apk の拡張子を zip にして ペイロードを取り出す
※なお,もしこれが本物の Android マルウェアならば,ここからが本番。