bendera3 (re)
file
was not able to tell what binary type this is:
❯ file bendera3
bendera3: data
So, I inspected the hexdump to see if there are any interesting values:
❯ xxd bendera3 | head
00000000: 7664 6578 3032 3700 0400 0000 0000 0000 vdex027.........
00000010: 3c00 0000 0400 0000 0100 0000 4000 0000 <...........@...
00000020: 702f 1d00 0200 0000 b02f 1d00 ab35 0000 p/......./...5..
00000030: 0300 0000 5c65 1d00 0440 0000 4c50 68a2 ....\e...@..LPh.
00000040: 6465 780a 3033 3700 07df b049 905c a902 dex.037....I.\..
00000050: 6299 7fe2 26a1 804c 9bfc e126 3480 c860 b...&..L...&4..`
Doing an online search, I see that this is related to Android Dex bytecode. There’s an extractor at anestisb/vdexExtractor and in particular this PR vdexExtractor#72 by IgorEisberg contains the patch needed to support vdex027.
So I checked out this branch, built the extractor, and extracted a bendera3_classes.dex.
❯ mkdir out
❯ vdexExtractor/bin/vdexExtractor -i bendera3 -o out
❯ ls out
bendera3_classes.dex
Then, I loaded this file into jadx-gui and got this p004my.wargames.mobile.bendera3.MainActivity
class:
package p004my.wargames.mobile.bendera3;
import android.os.Bundle;
import android.support.p003v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.Toast;
/* renamed from: my.wargames.mobile.bendera3.MainActivity */
/* loaded from: /Users/daniellimws/ctfs/wargames21/bendera/out/bendera3_classes.dex */
public class MainActivity extends AppCompatActivity {
/* renamed from: wx */
private static char[] f32wx = {'t', 'h', '1', 's', '-', 'i', '5', '_', '4', '_', 'k', '3', 'y'};
/* renamed from: eT */
private EditText f33eT;
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.p003v7.app.AppCompatActivity, android.support.p000v4.app.FragmentActivity, android.support.p000v4.app.ComponentActivity, android.app.Activity
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(C0273R.layout.activity_main);
final EditText editText = (EditText) findViewById(C0273R.C0275id.editText);
editText.addTextChangedListener(new TextWatcher() { // from class: my.wargames.mobile.bendera3.MainActivity.1
@Override // android.text.TextWatcher
public void afterTextChanged(Editable editable) {
}
@Override // android.text.TextWatcher
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
@Override // android.text.TextWatcher
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
if (MainActivity.m1cF(editText.getText().toString())) {
Toast.makeText(MainActivity.this, "Correct! Submit it!!", 0).show();
}
}
});
}
public static byte[] hStB(String str) {
int length = str.length();
byte[] bArr = new byte[length / 2];
for (int i = 0; i < length; i += 2) {
bArr[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4) + Character.digit(str.charAt(i + 1), 16));
}
return bArr;
}
/* renamed from: cF */
public static boolean m1cF(String str) {
if (str.length() == 0) {
return false;
}
if ((str.length() > 5 && !str.substring(0, 5).equals("wgmy{")) || str.charAt(str.length() - 1) != '}') {
return false;
}
if (str.substring(5, str.length() - 1).equals(m0xx(f32wx, hStB(new StringBuilder("kxk1x4xxkx11O4TxkOc6xxb64Obxk1613xdxx1F11x9OT6Txd31xcOd1O1OOcO64").reverse().toString().replace("O", "0").replace("T", "7").replace("b", "8").replace("x", "5").replace("F", "f").replace("k", "e"))))) {
return true;
}
return false;
}
/* renamed from: xx */
private static String m0xx(char[] cArr, byte[] bArr) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bArr.length; i++) {
sb.append((char) (bArr[i] ^ cArr[i % cArr.length]));
}
return sb.toString();
}
}
From this snippet, we can tell that m1cF
is used to check the flag:
@Override // android.text.TextWatcher
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
if (MainActivity.m1cF(editText.getText().toString())) {
Toast.makeText(MainActivity.this, "Correct! Submit it!!", 0).show();
}
}
The top part is easy to understand, just making sure the flag is in the correct format:
public static boolean m1cF(String str) {
if (str.length() == 0) {
return false;
}
if ((str.length() > 5 && !str.substring(0, 5).equals("wgmy{")) || str.charAt(str.length() - 1) != '}') {
return false;
}
Then, it compares the contents in the wgmy{...}
burrito with a string that gets reversed and undergoes some replacements.
if (str.substring(5, str.length() - 1).equals(m0xx(f32wx, hStB(new StringBuilder("kxk1x4xxkx11O4TxkOc6xxb64Obxk1613xdxx1F11x9OT6Txd31xcOd1O1OOcO64").reverse().toString().replace("O", "0").replace("T", "7").replace("b", "8").replace("x", "5").replace("F", "f").replace("k", "e"))))) {
return true;
}
}
We can just copy this whole thing into Python and run it to get the expected flag.
from pwn import xor
from binascii import unhexlify
aaa = unhexlify("kxk1x4xxkx11O4TxkOc6xxb64Obxk1613xdxx1F11x9OT6Txd31xcOd1O1OOcO64"[::-1].replace("O", "0").replace("T", "7").replace("b", "8").replace("x", "5").replace("F", "f").replace("k", "e"))
print(b"wgmy{" + xor(aaa, "th1s-i5_4_k3y") + b"}")
# wgmy{2d1c0edbc8bbfa5be3117a3ed9e6d637}