We are given an Android app with a login screen.
[http://www.javadecompilers.com/](http://www.javadecompilers.com/) is a good
website for decompiling the apk (without going through the trouble of
installing all the tools).

After decompiling you can see the code in `LoginActivity.java`:

```  
public void onClick(View view) {  
Toast.makeText(LoginActivity.this.getApplicationContext(),
C0046o.m117a(LoginActivity.this.getApplicationContext(), (int) R.raw.prod,
this.f1785b.getText().toString(), this.f1786c.getText().toString(), false),
1).show();  
}  
```

No way to get the username and password from here. Looking around you'll see
another interesting file named `TestActivity.java`:

```  
public void onClick(View view) {  
String str;  
try {  
MessageDigest instance = MessageDigest.getInstance("SHA-256");  
Signature signature =
TestActivity.this.getApplicationContext().getPackageManager().getPackageInfo(TestActivity.this.getApplicationContext().getPackageName(),
64).signatures[0];  
str = C0046o.m117a(TestActivity.this.getApplicationContext(), (int) R.raw.qa,
"token", signature == null ? "" :
Base64.getEncoder().encodeToString(instance.digest(signature.toByteArray())),
true);  
} catch (NameNotFoundException | NoSuchAlgorithmException e) {  
e.printStackTrace();  
str = null;  
}  
Toast.makeText(TestActivity.this.getApplicationContext(), str, 1).show();  
}  
```

Basically, this code uses `token` as username and the SHA256 of the first APK
signature (encoded in Base64) as the password. This signature can be extracted
from `CERT.RSA` using `keytool`:

```  
$ keytool -printcert -file CERT.RSA  
Owner: CN=RealGam3, OU=RealGam3, O=RealGam3, L=NA  
Issuer: CN=RealGam3, OU=RealGam3, O=RealGam3, L=NA  
Serial number: 19e19e40  
Valid from: Sun Jun 21 16:27:18 ICT 2020 until: Thu Jun 15 16:27:18 ICT 2045  
Certificate fingerprints:  
SHA1: 02:32:1C:57:42:D4:68:DC:45:37:25:11:7D:79:1B:2B:A3:C0:C7:1A  
SHA256:
A7:DF:C1:5E:06:E9:E9:DD:6F:46:D1:C8:70:26:E2:E9:59:BA:7D:A3:40:2D:02:21:63:34:3A:8D:70:A9:52:F9  
Signature algorithm name: SHA256withRSA  
Subject Public Key Algorithm: 2048-bit RSA key  
Version: 3  
```

Encoded Base64: `p9/BXgbp6d1vRtHIcCbi6Vm6faNALQIhYzQ6jXCpUvk=`

Now we need to see how the username and passwords are sent to the server. This
is done in `C0046o.m117a` method. Although the code is not fully decompiled,
we can still have an idea of what is going on:

\- The code sends a basic authentication request with username and password to
[https://certifiedapp.ctf.bsidestlv.com:8003/authenticate](https://certifiedapp.ctf.bsidestlv.com:8003/authenticate)  
\- Client certificate is used to encrypt the SSL/TLS traffic. Certificate is
stored in `res/raw/qa.p12`. Certificate password is `thecakeisalie` (obtained
from key `clientCertPassword` in `res/values/strings.xml`)

Full solver code:

```  
package bsidesltv;

import java.io.*;  
import java.net.ProtocolException;  
import java.nio.charset.StandardCharsets;  
import java.security.MessageDigest;  
import java.security.cert.X509Certificate;  
import java.util.Base64;

import javax.net.ssl.*;

public class CertAppSolver {  
  
public static void m125a(HttpsURLConnection httpsURLConnection, String str,
String str2) {  
StringBuilder sb = new StringBuilder();  
sb.append(str);  
sb.append(":");  
sb.append(str2);  
String sb2 = sb.toString();  
System.out.println(sb2);  
try {  
httpsURLConnection.setRequestMethod("POST");  
httpsURLConnection.setConnectTimeout(1500);  
httpsURLConnection.setReadTimeout(1500);  
byte[] encode =
java.util.Base64.getEncoder().encode(sb2.getBytes(StandardCharsets.UTF_8));  
StringBuilder sb3 = new StringBuilder();  
sb3.append("Basic ");  
sb3.append(new String(encode));  
System.out.println(sb3);  
httpsURLConnection.setRequestProperty("Authorization", sb3.toString());  
} catch (ProtocolException e) {  
e.printStackTrace();  
}  
}  
  
public static String m118a(InputStream inputStream) throws Exception {  
char[] cArr = new char[4096];  
InputStreamReader inputStreamReader = new InputStreamReader(inputStream,
"UTF8");  
StringWriter stringWriter = new StringWriter();  
while (true) {  
int read = inputStreamReader.read(cArr);  
if (-1 == read) {  
return stringWriter.toString();  
}  
stringWriter.write(cArr, 0, read);  
}  
}  
  
public static java.lang.String m117a(java.lang.String r7, java.lang.String r8)
throws Exception {  
TrustManager[] trustAllCerts = new TrustManager[] {  
new X509TrustManager() {  
public java.security.cert.X509Certificate[] getAcceptedIssuers() {  
return null;  
}  
public void checkClientTrusted(X509Certificate[] certs, String authType) { }  
public void checkServerTrusted(X509Certificate[] certs, String authType) { }  
}  
};  
// Create all-trusting host name verifier  
HostnameVerifier allHostsValid = new HostnameVerifier() {  
public boolean verify(String hostname, SSLSession session) {  
return true;  
}  
};  
// Install the all-trusting host verifier  
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);  
  
java.lang.String clientCertPassword = "thecakeisalie";  
java.lang.String certPath = "bsidesltv\\\qa.p12";  
InputStream stream = new DataInputStream(new FileInputStream(certPath));  
java.security.KeyStore r4 = java.security.KeyStore.getInstance("PKCS12");  
r4.load(stream, clientCertPassword.toCharArray());  
javax.net.ssl.KeyManagerFactory r5 =
javax.net.ssl.KeyManagerFactory.getInstance("SunX509");  
r5.init(r4, clientCertPassword.toCharArray());  
javax.net.ssl.KeyManager[] r50 = r5.getKeyManagers();  
javax.net.ssl.SSLContext r6 = javax.net.ssl.SSLContext.getInstance("TLS");  
java.security.SecureRandom r9 = new java.security.SecureRandom();  
r6.init(r50, trustAllCerts, r9);  
java.lang.String r2 =
"https://certifiedapp.ctf.bsidestlv.com:8003/authenticate";  
java.net.URL r51 = new java.net.URL(r2);  
java.net.URLConnection r52 = r51.openConnection();  
javax.net.ssl.HttpsURLConnection r53 = (javax.net.ssl.HttpsURLConnection)r52;  
javax.net.ssl.SSLSocketFactory r61 = r6.getSocketFactory();  
r53.setSSLSocketFactory(r61);  
m125a(r53, r7, r8);  
int r62 = r53.getResponseCode();  
System.out.println(r62);  
java.io.InputStream r71 = r53.getInputStream();  
java.lang.String r63 = m118a(r71);  
r53.disconnect();  
return r63;  
}  
  
public static void main(String[] args) throws Exception {  
String s = m117a("token", "p9/BXgbp6d1vRtHIcCbi6Vm6faNALQIhYzQ6jXCpUvk=");  
System.out.println(s);  
}  
}  
```

Flag: `BSidesTLV2020{I_L1k3_B1g_Apps_And_I_cannot_l13}`