第一次遇到DCT,QAQ,终究还是被暴打了

DosSnake

考察16位汇编,大概打开看看,是一个贪吃蛇,按照游戏题的惯例,应当是胜利后自动输出flag

看一下有没有相关函数或者字符串

查字符串可以看到有DASCTF,然后交叉引用

大概是这样:

image-20240721174647593

可以看到用(di)dasctf和(si)后面的位数依次异或,一轮后重置di

直接写脚本

1
2
3
4
5
from prism import *
a = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x09, 0x63, 0x34, 0x32, 0x13, 0x2A, 0x2F, 0x2A, 0x37, 0x3C, 0x23, 0x00, 0x2E, 0x20, 0x10, 0x3A, 0x27, 0x2F, 0x24, 0x3A, 0x30, 0x75, 0x67, 0x65, 0x3C]
c = [0x44, 0x41, 0x53, 0x43, 0x54, 0x46]
pxor(a,c)
# DASCTF{H0wfUnnytheDosSnakeis!!!}

Strangeprograme

常规TEA,不多说

反调,附加调试进入主要判断逻辑

加密是一样的,区别是只加密第一组数据,然后异或后面的数据

直接写脚本解

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include<iostream>

void __cdecl enc(unsigned int* a1, unsigned int* a2)
{
unsigned int i; // [esp+DCh] [ebp-2Ch]
int v3; // [esp+E8h] [ebp-20h]
unsigned int v4; // [esp+F4h] [ebp-14h]
unsigned int v5; // [esp+100h] [ebp-8h]

//sub_4114D8(&unk_4250F3);
v5 = *a1;
v4 = a1[1];
v3 = 0;
for (i = 0; i < 0x10; ++i)
{
v5 += (a2[1] + (v4 >> 5)) ^ (v3 + v4) ^ (*a2 + 16 * v4);
v4 += (a2[3] + (v5 >> 5)) ^ (v3 + v5) ^ (a2[2] + 16 * v5);
v3 -= 0x61C88647;
}
*a1 = v5;
a1[1] = v4;
}

void __cdecl dec(unsigned int* a1, unsigned int* a2)
{
unsigned int i; // [esp+DCh] [ebp-2Ch]
int sum; // [esp+E8h] [ebp-20h]
unsigned int v4; // [esp+F4h] [ebp-14h]
unsigned int v5; // [esp+100h] [ebp-8h]

//sub_4114D8(&unk_4250F3);
v5 = *a1;
v4 = a1[1];

sum = 0;
for (i = 0; i < 0x10; ++i)
{
sum -= 0x61C88647;
}
for (i = 0; i < 0x10; ++i)
{
sum += 0x61C88647;
v4 -= (a2[3] + (v5 >> 5)) ^ (sum + v5) ^ (a2[2] + 16 * v5);
v5 -= (a2[1] + (v4 >> 5)) ^ (sum + v4) ^ (*a2 + 16 * v4);
}
*a1 = v5;
a1[1] = v4;
}




int main(void) {
unsigned int last[10] = {
0xBC2B4DF9, 0x6213DD13, 0x89FFFCC9, 0x0FC94F7D, 0x526D1D63, 0xE341FD50, 0x97287633, 0x6BF93638,
0x83143990, 0x1F2CE22C
};
unsigned int key[4] = {
0x12345678, 0x09101112, 0x13141516, 0x15161718
};
for (int i = 8; i > 0; i -= 2)
{
last[i] ^= last[0];
last[i + 1] ^= last[1];
dec(last, key);
}
dec(last, key);
std::cout << (char*)last;
}
# DASCTF{I4TH0ok_I5S0ooFunny_Isnotit?????}

BabyAndroid

这个题如果没有套娃,我愿夸它,但是出题人知不知道我以为我要解完了结果才是刚刚开始有多么崩溃

首先题目给了抓包信息

1
2
3
4
5
6
7
8
9
10
POST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
charset: utf-8
User-Agent: Dalvik/2.1.0 (Linux; U; Android 11; M2004J7AC Build/RP1A.200720.011)
Host: yuanshen.com
Connection: close
Accept-Encoding: gzip, deflate
Content-Length: 413

data=TwMkYUkg4bYsY0hL99ggYWnVjWyXQrWAdNmToB0eBXbS6wBzL6ktorjNWI9VOroTU4HgIUYyzGLpcHzd1zNGT+bFZZI7IoxJwpcgXfdwW1LSmiNSP+PuSUsqAzNclF1nJ07b4tYyLWg0zTypbzWsLhOIM+6uci3RFZLREUCALafi01M8mS+KMNxX1Pyn8mSP+KKKjQ5S5fasHRSn+L9qBFws0mWavpfI0QEiMgarxv0iGhYU8cfgonWyL70RvoXET5VUDP1vfYWIBLzzzaAqLC0OiMtUK3TTATSU7yijdgXm18OKMcGIke/NZIM6Sr5fL3t6psDOOkw2C/5uYrJVPn+D6U9KTL64bgREppDqMOvhvbhtuf/S3ASW/+rhtPMtoaD8FxDg0wWSLZA53fQfNA==

很明显data就是flag,然后要逆程序

jadx(原谅我安卓只会jadxQAQ)搜索yuanshen.com找到发送位置

image-20240721175844067

然后它用反射调用了encrypt方法,没有搜索到,同时也没看到site.qifen.note.ui.Encrypto,然后详细看这段代码,发现它加载了sex.jpg然后解密作为dex,那么查看解密方法,解密dex,发现是rc4,直接复制为文本解密

然后看加密方式

image-20240721180421330

得到密钥:0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D

解密数据得到

1
458.853181,-18.325492,-18.251911,-2.097520,-21.198660,-22.304648,21.103162,-5.786284,-15.248906,15.329286,16.919499,-19.669045,30.928253,-37.588034,-16.593954,-5.505211,3.014744,6.553616,31.131491,16.472500,6.802400,-78.278577,15.280099,3.893073,56.493581,-34.576344,30.146729,4.445671,6.732204

???什么玩意

然后再一看数据传入

1
2
String cipher = (String) checkMethod.invoke(checkerClass.getDeclaredConstructor(new Class[0]).newInstance(new Object[0]), NoteActivity.this.sendInit(contentText));

这里还有一个sendInit

一看是个native,apktool解包,ida开

image-20240721181218663

可以找到encrypt函数

这里复制下来网上搜索可以查到,这个算法是DCT2,一维的,搜索可以看到:

离散余弦变换

但是DCT3并不可以直接逆向DCT2,查了很多资料也没查到

然后就看着佬的wp复现了

逆向时,把DCT3的$x_0/2$去掉,然后后面处理相同,

同时对每个值乘以$\sqrt{\frac{2}{N}}$和$\sqrt{\frac{1}{N}}$也是在DCT2同样的位置处理,代码:

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
void dct3(const std::vector<double>& Y, std::vector<double>& X) {
int N = Y.size();
X.resize(N);

for (int n = 0; n < N; ++n) {
double sum = 0;
for (int k = 0; k < N; ++k) {
if (k == 0)
{
sum += Y[k] * std::cos(3.14159265 * k * (n + 0.5) / N) * std::sqrt(1.0 / N);
}
else
{
sum += Y[k] * std::cos(3.14159265 * k * (n + 0.5) / N) * std::sqrt(2.0 / N);
}

}
X[n] = sum;
}

}
int main(void) {
std::vector<double> res = { 458.853181,-18.325492,-18.251911,-2.097520,-21.198660,-22.304648,21.103162,-5.786284,
-15.248906,15.329286,16.919499,-19.669045,30.928253,-37.588034,-16.593954,-5.505211,
3.014744,6.553616,31.131491,16.472500,6.802400,-78.278577,15.280099,3.893073,
56.493581,-34.576344,30.146729,4.445671,6.732204 };
std::vector<double> X;
dct3(res, X);
for (double x : X) {
std::cout << x << ",";
}
std::cout << std::endl;

for (int i = 0; i < 29; i++) {
unsigned char chr = (char)std::round(X[i]);
std::cout << chr;
}
}
// DASCTF{Y0u_Ar3Re4lly_H@ck3r!}

补充DCT变换公式(一维):

image-20240722132702606

逆变换

image-20240722132724585

就按上面写的那样写就好了