Reverse

Rustdroid

Java层智能看到调用了Native层的Check

看看SO,是个Rust,大体看一下是 RC4

这里先判断flag长度是否为43,和是否以WMCTF{}包裹

这里是rc4的S盒,可以动调或者直接模拟拿到S盒,fun@eZ是RC4的key

这里是单字节位移加密,同时还有给RC4加了一个异或

异或的值

单字节位移加密逻辑如下

1
2
3
4
5
6
7
8
9
10
def ROR(value, shift, bits=8):
return ((value >> shift) | (value << (bits - shift))) & ((1 << bits) - 1)

def rotate_enc(x):
x = ROR(x, 1) ^ 0xef
x = ROR(x, 2) ^ 0xbe
x = ROR(x, 3) ^ 0xad
x = ROR(x, 4) ^ 0xde
x = ROR(x, 5)
return x

这里再记录一下SO的调试方法

先 adb 连接一下模拟器

需要先把ida服务push到模拟器

1
adb push D:\CTF\RE\IDA_Pro_7.7\dbgsrv\android_server64(ida安装路径) /data/local/tmp/android_server64

然后连接

1
2
3
4
5
adb shell
su
cd /data/tmp/local
chmod 777 android_server64
./android_server64

再开个命令行转发一下端口

1
adb forward tcp:23946 tcp:23946

选择Remote Android debugger

然后Debugger里选择Attach to process,找到对应的包名进行附加

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from struct import pack
def ROR(value, shift, bits=8):
return ((value >> shift) | (value << (bits - shift))) & ((1 << bits) - 1)

def rotate_enc(x):
x = ROR(x, 1) ^ 0xef
x = ROR(x, 2) ^ 0xbe
x = ROR(x, 3) ^ 0xad
x = ROR(x, 4) ^ 0xde
x = ROR(x, 5)
return x
data = [0x4E4FCE594215BA1F, 0xC745BAE69BFD994, 0x87081E9C7F8AFCC0, 0x2BB08F87F5646BF5]
enc = []
for i in data:
enc += list(pack("<Q", i))
enc += list(pack("<I",0x29FF53E2))
#print(enc)
#enc = [0x1F, 0xBA, 0x15, 0x42, 0x59, 0xCE, 0x4F, 0x4E, 0x94, 0xD9, 0xBF, 0x69, 0xAE, 0x5B, 0x74, 0xC, 0xC0, 0xFC, 0x8A, 0x7F, 0x9C, 0x1E, 8, 0x87, 0xF5, 0x6B, 0x64, 0xF5, 0x87, 0x8F, 0xB0, 0x2B, 0xE2, 0x53, 0xFF, 0x29]
key = [0x66, 0x75, 0x6E, 0x40, 0x65, 0x5A]
xor_table = [0x77, 0x88, 0x99, 0x66]

def rc4(key, data):
key_length = len(key)
s = list(range(256))
j = 0
for i in range(256):
j = (j + s[i] + key[i % key_length]) % 256
s[i], s[j] = s[j], s[i]

res = []
i = j = 0
for index, val in enumerate(data):
i = (i + 1) % 256
j = (j + s[i]) % 256
s[i], s[j] = s[j], s[i]
k = s[(s[i] + s[j]) % 256]
res.append(val ^ k ^ xor_table[index % 4])
return res

decrypted_data = rc4(key, enc)
flag = "WMCTF{"
for i in range(36):
for j in range(30, 128):
if rotate_enc(j) == decrypted_data[i]:
flag += chr(j)
break
flag += "}"
print(flag)
#WMCTF{2a04aed7-e736-43c4-80a7-f6ed28de34eb}

re1

先Jadx看看,应该是有Hook

看看so

这里对几个函数memcmp、strlen、printf、strftime、scanf、fgetws进行了Hook

checkYourFlag是假逻辑

在JNI_Onload可以找到真正的加密逻辑

真正的在sub_F430

进入sub_F430就可以动调跟踪被Hook的函数

strlen对输入进行了异或

printf、scanf、strftime、fgetws实现了xtea

密文

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <stdint.h>

void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 0xfa11010d, sum = delta * num_rounds;
for (i = 0; i < num_rounds; i++) {
v1 -= (((v0 << 6) ^ (v0 >> 6)) + v0) ^ (sum + key[(unsigned char)sum >> 6]);
sum -= delta;
v0 -= (((v1 << 6) ^ (v1 >> 6)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0; v[1] = v1;
}

int main() {
uint32_t enc[] = { 0xEFC05FD2, 0x9378625E, 0x841F41A0 , 0x6D05F4A , 0xDC898F9A ,0x21AA7CFC ,0x4229FB0B ,0x31E52B8B };
uint32_t key[4] = { 0xffffffff, 0xaaaaaaaa, 0x11111111, 0x11111111 };
for(int i=0; i<8; i+=2){
decipher(66, &enc[i], key);
}

for (int i = 0; i < 32; i++) {
printf("%c", (*((char*)enc + i) ^ 0x5A ^ i));
}
}
#WMCTF{b86d69bbeedeccb9257782534}