APKrypt
2 minutos de lectura
Se nos proporciona un archivo APK (APKrypt.apk
). Tenemos que encontrar un código VIP en el archivo APK. Por tanto, utilizaremos d2j-dex2jar
para conseguir un archivo JAR:
$ d2j-dex2jar APKrypt.apk
dex2jar APKrypt.apk -> ./APKrypt-dex2jar.jar
Análisis del código fuente
Ahora podemos subir el archivo JAR a www.javadecompilers.com y seleccionar Jadx como descompilador.
El archivo principal es sources/com/example/apkrypt/MainActivity.java
:
package com.example.apkrypt;
import android.app.Activity;
import android.os.Bundle;
import android.util.Base64;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class MainActivity extends Activity {
/* renamed from: b1 */
Button f77b1;
EditText ed1;
public static String decrypt(String str) throws Exception {
Key generateKey = generateKey();
Cipher instance = Cipher.getInstance("AES");
instance.init(2, generateKey);
return new String(instance.doFinal(Base64.decode(str, 0)), "utf-8");
}
public static String encrypt(String str) throws Exception {
Key generateKey = generateKey();
Cipher instance = Cipher.getInstance("AES");
instance.init(1, generateKey);
return Base64.encodeToString(instance.doFinal(str.getBytes("utf-8")), 0);
}
private static Key generateKey() throws Exception {
return new SecretKeySpec("Dgu8Trf6Ge4Ki9Lb".getBytes(), "AES");
}
public static String md5(String str) {
try {
MessageDigest instance = MessageDigest.getInstance("MD5");
instance.update(str.getBytes());
byte[] digest = instance.digest();
StringBuffer stringBuffer = new StringBuffer();
for (byte b : digest) {
stringBuffer.append(Integer.toHexString(b & 255));
}
return stringBuffer.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return "";
}
}
/* access modifiers changed from: protected */
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(C0535R.layout.activity_main);
this.f77b1 = (Button) findViewById(C0535R.C0538id.button);
this.ed1 = (EditText) findViewById(C0535R.C0538id.editTextVipCode);
this.f77b1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
try {
if (MainActivity.md5(MainActivity.this.ed1.getText().toString()).equals("735c3628699822c4c1c09219f317a8e9")) {
Toast.makeText(MainActivity.this.getApplicationContext(), MainActivity.decrypt("k+RLD5J86JRYnluaZLF3Zs/yJrVdVfGo1CQy5k0+tCZDJZTozBWPn2lExQYDHH1l"), 1).show();
} else {
Toast.makeText(MainActivity.this.getApplicationContext(), "Wrong VIP code!", 0).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
Lo primero que hace es preguntar por el código VIP en onCreate
y mira si su hash MD5 coincide con 735c3628699822c4c1c09219f317a8e9
. Si usamos crackstation.net no encontraremos ninguna coincidencia:
Flag
Aún así, no nos interesa el código VIP, sino lo que viene después. En caso de que tuviéramos el código VIP, se descifraría un texto cifrado codificado en Base64 (k+RLD5J86JRYnluaZLF3Zs/yJrVdVfGo1CQy5k0+tCZDJZTozBWPn2lExQYDHH1l
). El cifrado es AES, y tenemos la clave (Dgu8Trf6Ge4Ki9Lb
). Entonces, vamos a descifrarlo usando Python:
$ python3 -q
>>> from base64 import b64decode
>>> from Crypto.Cipher import AES
>>> from Crypto.Util.Padding import unpad
>>> key = b'Dgu8Trf6Ge4Ki9Lb'
>>> ct = b64decode('k+RLD5J86JRYnluaZLF3Zs/yJrVdVfGo1CQy5k0+tCZDJZTozBWPn2lExQYDHH1l')
>>> cipher = AES.new(key, AES.MODE_ECB)
>>> unpad(cipher.decrypt(ct), AES.block_size)
b'HTB{3nj0y_y0ur_v1p_subscr1pt1on}'