Rating: 5.0

# Solution description:
Decompile Java and C. Write py-script to do the relevant code. Decrypt internal dynamic loaded payload. Analyze this code.

# Solution steps
1. `jadx-gui andry.apk` - Relevant parts of the code:
```java
native methods c1-c32

public Boolean check_password() {
Integer count = 0;
ListIterator<String> it = splitBySize(((EditText) findViewById(R.id.editPassword1)).getText().toString(), 2).listIterator();
while (it.hasNext()) {
Integer index = Integer.valueOf(it.nextIndex());
int d = Integer.parseInt(it.next(), 16);
switch (index.intValue() + 1) {
case 1: if (c1(d) != 6326) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 2: if (c2(d) != 2259) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 3: if (c3(d) != 455) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 4: if (c4(d) != 1848) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 5: if (c5(d) != 275400) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 6: if (c6(d) != 745) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 7: if (c7(d) != 1714) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 8: if (c8(d) != 1076) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 9: if (c9(d) != 12645) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 10: if (c10(d) != 2120) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 11: if (c11(d) != 153664) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 12: if (c12(d) != 10371) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 13: if (c13(d) != 37453) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 14: if (c14(d) != 203640) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 15: if (c15(d) != 691092) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 16: if (c16(d) != 36288) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 17: if (c17(d) != 753) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 18: if (c18(d) != 2011) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 19: if (c19(d) != 59949) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 20: if (c20(d) != 18082) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 21: if (c21(d) != 538) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 22: if (c22(d) != 12420) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 23: if (c23(d) != 2529) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 24: if (c24(d) != 1130) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 25: if (c25(d) != 6076) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 26: if (c26(d) != 11702) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 27: if (c27(d) != 47217) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 28: if (c28(d) != 1056) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 29: if (c29(d) != 207) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 30: if (c30(d) != 11315) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 31: if (c31(d) != 2676) { break; } else { count = Integer.valueOf(count.intValue() + 1); break; }
case 32: if (c32(d) != 261) { break(1) } else { count = Integer.valueOf(count.intValue() + 1); break; }
}
if (count.intValue() == 32) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}

private void handleActionFoo(String password_key) {
try {
byte[] byteArray = IOUtils.toByteArray(getApplicationContext().getAssets().open("enc_payload"));
XORDecrypt(byteArray, password_key);
String response = DynamicDecode(byteArray, "decrypt", "EASYPEASY");
Log.i("FLAG: ", "ptm{" + response + "}");
} catch (IOException e) {
e.printStackTrace();
}
}
```
2. Inside lib, get `resources/lib/x86/libandry-lib.so` -> use Cutter with ghidra-decompiler to copy out c-code for the c...-functions, and replace them until it's valid py code
I.e. example c function
```c
undefined8 Java_com_andry_MainActivity_c1(int32_t arg_8h, int32_t arg_ch, int32_t arg_10h) {
int32_t var_4h;
return CONCAT44(arg_8h, (arg_10h + 7) * 0x50 + 6);
}
```
becomes (removing `undefined8 Java_com_andry_MainActivity_` and all the parameters `int32_t arg_8h, int32_t arg_ch, int32_t` and `CONCAT44(`
```python
def c1(x): return (x+7)*0x50 + 6
```
3. Inside java code, regex-search `\d{3,8}` to get all the numbers in order. put them in py array
4. Implement a letter-bruteforcer and xor decrypter
```python
def c1(x): return (x + 7) * 0x50 + 6
def c2(x): return x * 0xc + 0xf
def c3(x): return x * 4 + 0xf
def c4(x): return ((x + 0x10) * 2 + 8) * 6
def c5(x): return (x + 5) * 0x1518
def c6(x): return (x + 6) * 8 + 0x19
def c7(x): return (x + 2) * 7 + 6
def c8(x): return (x + 10) * 6 + 0xe
def c9(x): return ((x + 6) * 9 + 10) * 9
def c10(x): return (x + 9) * 8 + 8
def c11(x): return x * 0x310
def c12(x): return ((x + 1) * 9 + 3) * 5 + 6
def c13(x): return x * 0x240 + 0xd
def c14(x): return (x * 0xfc + 6) * 4
def c15(x): return x * 0xb64
def c16(x): return (x + 7) * 0x1b0
def c17(x): return (x + 4) * 0x32 + 3
def c18(x): return x * 8 + 0x13
def c19(x): return (x * 0x32 + 10) * 9 + 9
def c20(x): return (x + 4) * 0x50 + 2
def c21(x): return (x + 10) * 6 + 0x10
def c22(x): return (x + 8) * 0xb4
def c23(x): return (x + 2) * 0x14 + 9
def c24(x): return (x + 0x14) * 10
def c25(x): return ((x + 5) * 6 + 7) * 4
def c26(x): return (x + 5) * 0xb4 + 2
def c27(x): return (x * 9 + 7) * 0x15 + 9
def c28(x): return (x + 0x24) * 8
def c29(x): return x * 2 + 9
def c30(x): return ((x + 2) * 0x10 + 7) * 5
def c31(x): return (x * 5 + 6) * 7 + 9
def c32(x): return x + 0x13

results = [6326,2259,455,1848,275400,745,1714,1076,12645,2120,153664,10371,37453,203640,691092,36288,753,2011,59949,18082,538,12420,2529,1130,6076,11702,47217,1056,207,11315,2676,261]

data = []
for i in range(32): f = eval("c"+str(i+1))
for j in range(256):
if f(j) == results[i]:
data.append(j)

with open("enc_payload", "rb") as ep:
edp = ep.read()

ba = bytearray()
for i in range(len(edp)):
ba.append(edp[i] ^ data[i%32])

with open("enc_payload.dec", "wb") as ep:
ep.write(ba)
```
5. Ghidra the enc_payload.dec
```c
String decrypt(String p0){
char cVar1;
char cVar2;
String ref;
int iVar3;
int local_0;
String pSVar4;
int iVar5;
undefined ref_00;
StringBuilder ref_01;

local_0 = 0;
ref_00 = "NUKRPFUFALOXYLJUDYRDJMXHMWQW";
pSVar4 = "";
ref = ref_00.toUpperCase();
iVar5 = 0;
while (iVar3 = ref.length(), iVar5 < iVar3) {
cVar1 = ref.charAt(iVar5);
ref_01 = new StringBuilder();
ref_01 = ref_01.append(pSVar4);
cVar2 = p0.charAt(local_0);
ref_01 = ref_01.append((short)((((int)cVar1 - (int)cVar2) + 0x1a) % 0x1a) + 'A');
pSVar4 = ref_01.toString();
iVar3 = p0.length();
local_0 = (local_0 + 1) % iVar3;
iVar5 = iVar5 + 1;
}
return pSVar4;
}
```
6. Run decrypt("EASYPEASY") in some java environment or rewrite it:
```
ep = "EASYPEASY"
for i, letter in enumerate("NUKRPFUFALOXYLJUDYRDJMXHMWQW"):
epc = ord(ep[i%len(ep)])
ol = ord(letter)
nc = (ol - epc + 0x1a) % 0x1a + ord('A')
print(chr(nc), end="")
```
7. Wrap flag in ptmFlag: ptm{JUSTABUNCHOFAWFULANDROIDMESS}