Network?
Points: 1991 [2000]
Description
Just how many times do we have to log in! Web has one, now mobile too?
Please view this Document for download instructions.
Solution
- For this challenge, we will be analyzing the code from
sg.gov.tech.ctf.mobile.Admin.NetworkActivity.java
. From the initial analysis of the page, it appears that they are attempting to send a HTTP request tohttp://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41061/api/login
, and are setting the username and password in the payload somehow.// ... /* renamed from: e reason: collision with root package name */ public String f2943e = "yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg"; /* renamed from: f reason: collision with root package name */ public String f2944f = "41061"; /* renamed from: g reason: collision with root package name */ public String f2945g = ("http://" + this.f2943e + ":" + this.f2944f + "/api/login"); // ... public void onClick(View v) { NetworkActivity networkActivity = NetworkActivity.this; networkActivity.d(networkActivity.f2940b.getText().toString(), NetworkActivity.this.f2941c.getText().toString(), NetworkActivity.this.f2945g); NetworkActivity networkActivity2 = NetworkActivity.this; networkActivity2.c(networkActivity2.f2940b.getText().toString(), NetworkActivity.this.f2941c.getText().toString()); }
- Reading the code further, we see that they called the method
d
, which creates a new objectf.a.a.a.a.a.b
public void d(String username, String password, String url) { try { List<String> response = new f.a.a.a.a.a.b(url, SQLiteDatabase.KEY_ENCODING, username, password).a(); Log.v("rht", "SERVER REPLIED:"); Iterator<String> it = response.iterator(); while (it.hasNext()) { Log.v("rht", "Line : " + it.next()); } } catch (IOException e2) { e2.printStackTrace(); } }
- Opening
f.a.a.a.a.a.b
reveals the true HTTP payload that will be sent to the server. In this case, we just have to set the admin username and password on the request headers to the URL to get some values back.public b(String requestURL, String charset, String username, String password) { HttpURLConnection httpURLConnection = (HttpURLConnection) new URL(requestURL).openConnection(); this.f2863a = httpURLConnection; httpURLConnection.setRequestMethod("POST"); this.f2863a.setUseCaches(false); this.f2863a.setDoOutput(true); this.f2863a.setDoInput(true); this.f2863a.setRequestProperty("Host", "host"); this.f2863a.setRequestProperty("Accept", "application/json, text/plain, */*"); this.f2863a.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); this.f2863a.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Edg/83.0.478.37"); this.f2863a.setRequestProperty("username", username); this.f2863a.setRequestProperty("password", password); this.f2863a.getOutputStream().close(); this.f2865c = new PrintWriter((Writer) new OutputStreamWriter(this.f2864b, charset), true); }
- Opening up Postman, we can then send a POST request to
http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41061/api/login
, and set the admin username and password we found in mobile/True or false?, then sending the payload, which yields us the flag!{ "flagOne": "govtech-csg{m!sS1nG_cR3DeN+!@1s}", "encryptedFlagTwo": "717f4cda287d40c47e7b50cb772b4def5a415387257510d1" }
- But
flagOne
was not the flag… so we have to go back tosg.gov.tech.ctf.mobile.Admin.NetworkActivity.java
to see if there was anything interesting we can use to decryptencryptedFlagTwo
. From the sameonClick
function, it also calls the functionc
, which provides some context to the possible encryption algorithm.public void c(String username, String password) { String hexUserVal = e(username); String hexPassVal = e(password); String hexUserVal2 = b(hexUserVal); b(hexPassVal); int numberOfParts = hexUserVal2.length() / 8; String[] tokens = new String[numberOfParts]; for (int i = 1; i <= numberOfParts; i++) { tokens[i - 1] = hexUserVal2.substring((i - 1) * 8, i * 8); } String fullEnc = BuildConfig.FLAVOR; for (String str : tokens) { fullEnc = fullEnc + bytesToHex(messy(a(Integer.parseInt(str, 16), 8), 8)); } }
- From the code in
c
, we can see that they are converting the username and password into hex, and after which, they took the hex version ofusername
string, and shifted every 4th character to the front. Afterwhich, it calls a native functionmessy
. Decompilingmessy
inlibnative-lib.so
will show that they are taking every integer and XOR-ing it with the value0x051823ac
- Throwing
0x051823ac
into CyberChef with717f4cda287d40c47e7b50cb772b4def5a415387257510d1
yields a rotated flagtgov-ech{csgr3nC_Yp+ m3}
- We can then “unrotate” it with the following and we will get the flag!
>> rotated_flag = "tgov-ech{csgr3nC_Yp+ m3}" >> flag = "" >>> for i in range(len(rotated_flag) // 4): ... flag += rotated_flag[i * 4 + 1: i * 4 + 4] + rotated_flag[i * 4] ... >>> flag 'govtech-csg{3nCrYp+_m3} '
Flag
govtech-csg{3nCrYp+_m3}