ransomware
Description
CTF: STACK the Flags 2022
[don’t remember what the challenge description was]
challenge2.apk
Solution
Pwned by @skytect
Finding the encryption script
Let’s run the APK.
Initially, we’re presented with a page asking for permission to display over other apps.

If we follow the instructions, we’re presented with a dialog overlay the next time we launch the app.

As with any APK challenge, let’s open JADX.
jadx-gui challenge2.apk
We find a key!

Let’s try using the key with the dialog. After we successfully enter 16 characters within 5 seconds on an Android emulator, the dialog is dismissed.
If we dig further in JADX, we find code that suggests a decrypted file in /data/data/com.jaga.app/flag_decrypt.txt
.

Let’s check out the file with adb
.
❯ adb shellemu64a:/ $ suemu64a:/ # cat /data/data/com.jaga.app/flag_decrypt.txtimport java.util.Arrays;
public class Main { public static void main(String args[]) { String pt = "??????????????????????????????"; String ct = "yu1gpulonjtqxn3ct6gkjxph"; String ring1 = "abcdefghijklmnopqrstuvwxyz{}1234567890"; String ring2 = "qw1234567890ertyuiopasdf{}ghjklzxcvbnm"; int initial_shift = 3; int periodic_increment = 7; int periodic_length = 4;
char[] ch = ring1.toCharArray(); char[] ch_pt = pt.toCharArray();
ring2 = shift(ring2, initial_shift);
int temp_period = periodic_length; for (int i = 0; i < pt.length(); i++) { temp_period--;
int index = new String(ch).indexOf(ch_pt[i]); ct = ct + ring2.charAt(index); if (temp_period == 0) { ring2 = shift(ring2, periodic_increment); temp_period = periodic_length; } } }
public static String shift(String text, int shift) { for (int i = 0; i < shift; i++) { text = text.charAt(text.length() - 1) + text.substring(0, text.length() - 1); } return text; }emu64a:/ #
It looks like we found some Java code we have to reverse engineer.
import java.util.Arrays;
public class Main { public static void main(String args[]) { String pt = "??????????????????????????????"; String ct = "yu1gpulonjtqxn3ct6gkjxph"; String ring1 = "abcdefghijklmnopqrstuvwxyz{}1234567890"; String ring2 = "qw1234567890ertyuiopasdf{}ghjklzxcvbnm"; int initial_shift = 3; int periodic_increment = 7; int periodic_length = 4;
char[] ch = ring1.toCharArray(); char[] ch_pt = pt.toCharArray();
ring2 = shift(ring2, initial_shift);
int temp_period = periodic_length; for (int i = 0; i < pt.length(); i++) { temp_period--;
int index = new String(ch).indexOf(ch_pt[i]); ct = ct + ring2.charAt(index); if (temp_period == 0) { ring2 = shift(ring2, periodic_increment); temp_period = periodic_length; } } }
public static String shift(String text, int shift) { for (int i = 0; i < shift; i++) { text = text.charAt(text.length() - 1) + text.substring(0, text.length() - 1); } return text; }}
Reversing the encryption script
First, I rewrite and simplify the script in Python with some help from Copilot.
def shift(text: str, shift: int) -> str: for _ in range(shift): text = text[-1] + text[:-1] return text
pt = "??????????????????????????????"ct = "yu1gpulonjtqxn3ct6gkjxph"ring1 = "abcdefghijklmnopqrstuvwxyz{}1234567890"ring2 = "bnmqw1234567890ertyuiopasdf{}ghjklzxcv"
temp_period = 0for c in pt: temp_period += 1
index = ring1.index(c) ct += ring2[index]
if temp_period == 4: ring2 = shift(ring2, 7) temp_period = 0
After staring at the script for some time, I came up with the following solve script.
ct = "yu1gpulonjtqxn3ct6gkjxph"pt = ""
for i, c in enumerate(ct): lookup = {a: b for a, b in zip(shift(ring2, 7*(i // 4)), ring1)} pt += lookup[c]
print(pt) # stf22{c1ph4rsw1thatw15t}
stf22{c1ph4rsw1thatw15t}