Вводные
На исследование представлен файл APKey.zip
объемом 1144778
байт с хеш-суммой SHA256 0e901ee8858a83d64bf65daead62785c89ac157440b8c1affbc62b32036cccf1
. Пароль на архив hackthebox
.
Проверим архив
Вычислим контрольную сумму, чтобы удостовериться в валидности файлов.
$ ls -la APKey.zip
-rw-r--r-- 1 kiberdruzhinnik kiberdruzhinnik 1144778 Sep 10 16:44 APKey.zip
$ echo "0e901ee8858a83d64bf65daead62785c89ac157440b8c1affbc62b32036cccf1 APKey.zip" | sha256sum -c
APKey.zip: OK
Контрольная сумма совпала, поэтому можно приступать к распаковке архива.
$ unzip APKey.zip
Archive: APKey.zip
[APKey.zip] APKey.apk password:
inflating: APKey.apk
Исследование приложения
Перед нами стандартный контейнер с Android-приложением.
$ file APKey.apk
APKey.apk: Android package (APK), with MANIFEST.MF and classes.dex
Загрузим файл в jadx
.
Сразу же видим MainActivity
с обфусцированными методами.
Далее явно идет проверка на имя пользователя admin
и пароль, результатом которого будет хеш-сумма MD5 a2a3d412e92d896134d9c9126d756f
.
Нам стоит посмотреть внимательнее на функции b.a(g.a())
.
Функция g.a
похожа на набор байт. Она содержит в себе вызовы функций h.a
, i.a
, f.a
, e.a
, c.a
, d.a
, a.a
. Если посмотреть на эти функции, то они будут аналогичны текущей функции. Все эти функции возвращают строку.
С помощью онлайн компилятора Java восстановим недостающие строки (изначальные вызовы будут написаны в комментарии рядом).
public static String a() {
StringBuilder sb = new StringBuilder();
ArrayList arrayList = new ArrayList();
arrayList.add("722gFc");
arrayList.add("n778Hk");
arrayList.add("jvC5bH");
arrayList.add("lSu6G6");
arrayList.add("HG36Hj");
arrayList.add("97y43E");
arrayList.add("kjHf5d");
arrayList.add("85tR5d");
arrayList.add("1UlBm2");
arrayList.add("kI94fD");
sb.append((String) arrayList.get(8));
sb.append("kHtZuV"); // h.a()
sb.append("rSE6qY"); // i.a()
sb.append("6HxWkw"); // f.a()
sb.append("HyeaX9"); // e.a()
ArrayList arrayList2 = new ArrayList();
arrayList2.add("ue7888");
arrayList2.add("6HxWkw");
arrayList2.add("gGhy77");
arrayList2.add("837gtG");
arrayList2.add("HyTg67");
arrayList2.add("GHR673");
arrayList2.add("ftr56r");
arrayList2.add("kikoi9");
arrayList2.add("kdoO0o");
arrayList2.add("2DabnR");
sb.append((String) arrayList2.get(9));
sb.append("FlEGyL"); // c.a()
ArrayList arrayList3 = new ArrayList();
arrayList3.add("jH67k8");
arrayList3.add("8Huk89");
arrayList3.add("fr5GtE");
arrayList3.add("Hg5f6Y");
arrayList3.add("o0J8G5");
arrayList3.add("Wod2bk");
arrayList3.add("Yuu7Y5");
arrayList3.add("kI9ko0");
arrayList3.add("dS4Er5");
arrayList3.add("h93Fr5");
sb.append((String) arrayList3.get(5));
sb.append("wAxcoc"); // d.a()
sb.append("85S94kFpV1"); // a.a()
return sb.toString();
}
Результатом этой функции будет строка 1UlBm2kHtZuVrSE6qY6HxWkwHyeaX92DabnRFlEGyLWod2bkwAxcoc85S94kFpV1
, которая передается в функцию b.a
для дешифровки.
Проведем аналогичную работу с этой функцией.
public static String b() {
char charAt = "wAxcoc".charAt(1);
char charAt2 = "rSE6qY".charAt(2);
char charAt3 = "rSE6qY".charAt(1);
return String.valueOf(charAt) + String.valueOf(charAt2) + String.valueOf(charAt3);
}
public static String a(String str) {
char charAt = "kHtZuV".charAt(0); // h.a()
char charAt2 = "85S94kFpV1".charAt(8); // a.a()
char charAt3 = "HyeaX9".charAt(5); // e.a()
char charAt4 = "rSE6qY".charAt(4); // i.a()
char charAt5 = "kHtZuV".charAt(1); // h.a()
char charAt6 = "kHtZuV".charAt(4); // h.a()
char charAt7 = "kHtZuV".charAt(3); // h.a()
char charAt8 = "kHtZuV".charAt(3); // h.a()
char charAt9 = "kHtZuV".charAt(0); // h.a()
char charAt10 = "85S94kFpV1".charAt(8); // a.a()
char charAt11 = "85S94kFpV1".charAt(8); // a.a()
char charAt12 = "rSE6qY".charAt(0); // i.a()
char charAt13 = "FlEGyL".charAt(3); // c.a()
char charAt14 = "6HxWkw".charAt(3); // f.a()
char charAt15 = "6HxWkw".charAt(0); // f.a()
char charAt16 = "FlEGyL".charAt(0); // c.a()
SecretKeySpec secretKeySpec = new SecretKeySpec((String.valueOf(charAt) + String.valueOf(charAt2) + String.valueOf(charAt3) + String.valueOf(charAt4) + String.valueOf(charAt5).toLowerCase() + String.valueOf(charAt6) + String.valueOf(charAt7).toLowerCase() + String.valueOf(charAt8) + String.valueOf(charAt9) + String.valueOf(charAt10).toLowerCase() + String.valueOf(charAt11).toLowerCase() + String.valueOf(charAt12) + String.valueOf(charAt13).toLowerCase() + String.valueOf(charAt14) + String.valueOf(charAt15) + String.valueOf(charAt16)).getBytes(), b());
Cipher cipher = Cipher.getInstance(b());
cipher.init(2, secretKeySpec);
return new String(cipher.doFinal(Base64.decode(str, 0)), "utf-8");
}
В результате получаем следующий код, который можно запустить и получить флаг:
import java.util.ArrayList;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class MyClass {
public static String b() {
char charAt = "wAxcoc".charAt(1);
char charAt2 = "rSE6qY".charAt(2);
char charAt3 = "rSE6qY".charAt(1);
return String.valueOf(charAt) + String.valueOf(charAt2) + String.valueOf(charAt3);
}
public static String a(String str) throws Exception {
char charAt = "kHtZuV".charAt(0); // h.a()
char charAt2 = "85S94kFpV1".charAt(8); // a.a()
char charAt3 = "HyeaX9".charAt(5); // e.a()
char charAt4 = "rSE6qY".charAt(4); // i.a()
char charAt5 = "kHtZuV".charAt(1); // h.a()
char charAt6 = "kHtZuV".charAt(4); // h.a()
char charAt7 = "kHtZuV".charAt(3); // h.a()
char charAt8 = "kHtZuV".charAt(3); // h.a()
char charAt9 = "kHtZuV".charAt(0); // h.a()
char charAt10 = "85S94kFpV1".charAt(8); // a.a()
char charAt11 = "85S94kFpV1".charAt(8); // a.a()
char charAt12 = "rSE6qY".charAt(0); // i.a()
char charAt13 = "FlEGyL".charAt(3); // c.a()
char charAt14 = "6HxWkw".charAt(3); // f.a()
char charAt15 = "6HxWkw".charAt(0); // f.a()
char charAt16 = "FlEGyL".charAt(0); // c.a()
SecretKeySpec secretKeySpec = new SecretKeySpec((String.valueOf(charAt) + String.valueOf(charAt2) + String.valueOf(charAt3) + String.valueOf(charAt4) + String.valueOf(charAt5).toLowerCase() + String.valueOf(charAt6) + String.valueOf(charAt7).toLowerCase() + String.valueOf(charAt8) + String.valueOf(charAt9) + String.valueOf(charAt10).toLowerCase() + String.valueOf(charAt11).toLowerCase() + String.valueOf(charAt12) + String.valueOf(charAt13).toLowerCase() + String.valueOf(charAt14) + String.valueOf(charAt15) + String.valueOf(charAt16)).getBytes(), b());
Cipher cipher = Cipher.getInstance(b());
cipher.init(2, secretKeySpec);
Base64.Decoder decoder = Base64.getDecoder();
return new String(cipher.doFinal(decoder.decode(str)), "utf-8");
}
public static void main(String args[]) throws Exception {
System.out.println(a("1UlBm2kHtZuVrSE6qY6HxWkwHyeaX92DabnRFlEGyLWod2bkwAxcoc85S94kFpV1"));
}
}
Флаг
HTB{m***_0**********_w****_n**_h***}