xtea

J6N05NDWM17IEHEPGUFN}4G

1
通过分析我们看出这是两个tea加密,只要两次tea即可解出

J}R_E}0DBU5PB%SHRYUUF_2

1
2
3
4
5
6
7
8
9
10
11
12
看tea里面,这个逆向很简单
v5 = *a3;
v6 = a3[1];
delta = (( - 855655493)) * 32;
for (unsigned int i = 0; i < round; i++)
{
v6 -= ((key[(delta >> 11) & 3]) + delta) ^ (v5 + ((v5 >> 5) ^ (16 * v5)));
delta += 855655493;
v5 -= (key[(delta & 3)] + delta) ^ (v6 + ((v6 >> 5) ^ (16 * v6)));
}
*a3 = v5;
a3[1] = v6;

image-20240902213431593

1
2
通过判断语句,找到加密后的flag,注意是小端序存储,也就是0x269669a3 3d0b78bd 6228a59d
小技巧:选中这里点击shift+e更快复制

image-20240902213509827

1
之后就是反过来解密,先是flag的后八位解密,然后flag更新,把更新后flag的前八位解密,最后十六进制转字符串

image-20240902213620411

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

解密代码如下:
#include <stdint.h>
int main()
{
int flag[3];
unsigned int key[4] = { 2,0,2,4 };

flag[0] = 0x269669a3;
flag[1] = 0x3D0b78bd;
flag[2] = 0x6228a59d;

int a2[2];
a2[0] = 0x3d0b78bd;
a2[1] = 0x6228a59d;

//第二次逆向
unsigned int v5 = *a2;
unsigned int v6 = a2[1];
unsigned int delta = - 855655493 * 32;
unsigned int round = 32;
for (unsigned int i = 0; i < round; i++)
{
v6 -= ((key[(delta >> 11) & 3]) + delta) ^ (v5 + ((v5 >> 5) ^ (16 * v5)));
delta += 855655493;
v5 -= ((key [(delta & 3)]) + delta) ^ (v6 + ((v6 >> 5) ^ (16 * v6)));
}
*a2 = v5;
a2[1] = v6;
flag[1] = a2[0];
flag[2] = a2[1];
for (int i = 0; i <2; i++)
{
printf("%x", a2[i]);
}
printf("\n");

int a3[2];
a3[0] = 0x269669a3;
a3[1] = 0x60c0d6e0;
//第一次逆向
v5 = *a3;
v6 = a3[1];
delta = (( - 855655493)) * 32;
for (unsigned int i = 0; i < round; i++)
{
v6 -= ((key[(delta >> 11) & 3]) + delta) ^ (v5 + ((v5 >> 5) ^ (16 * v5)));
delta += 855655493;
v5 -= (key[(delta & 3)] + delta) ^ (v6 + ((v6 >> 5) ^ (16 * v6)));
}
*a3 = v5;
a3[1] = v6;
flag[0] = a3[0];
flag[1] = a3[1];
for (int i = 0; i < 3; i++)
{
printf("%x",flag[i]);
}
printf("\n");

}

xxtea

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
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[((p&3)^e)&0xff] ^ z)))
void btea(uint32_t* v, int n, const uint32_t key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do {
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
}
else if (n < -1) /* Decoding Part */
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--)
{
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}
int main() {
unsigned char enc[] = { 0x64,0xf5,0xe1,0x78,0xe1,0xf0,
0x35,0xa8,0x34,0xff,0x12,0x05,
0xfb,0x13,0xe9,0xb0,0x50,0xa3,
0xb9,0x89,0xb1,0xda,0x43,0xc9,
0x4f,0xc8,0xdb,0x01,0x20,0xdb,
0x16,0xaf,0xed,0x67,0x17,0x96 };
int r = 9;
unsigned char input_key[13] = "moectf2024!!";

const uint32_t k[4] = { *((uint32_t*)input_key),*((uint32_t*)(input_key + 4)),*((uint32_t*)(input_key + 8)),0xccffbbbb };
btea(((uint32_t*)enc), -r, k);
for (int i = 0; i < 36; i++) {
printf("%c", enc[i]);
}
return 0;
}
改数值就好了

moejvav

先用jadx打开

image-20241023123526457

分析代码

1
2
3
4
5
6
先是把(flag^202)+32
for (byte b : encodedFlag)
{
Byte b2 = Byte.valueOf(b);
array.add(Byte.valueOf((byte) ((b2.byteValue() ^ 202) + 32)));
}
image-20241023123647012
1
一个vminsn数组,先不管他

image-20241023123738963

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
关键信息:
一个一个分析一下:
1. if (insn == 114514) {
break;
}
到114514停止

2. int insn = vmInsn[i];
i++
throw exceptions2[insn];//这里就是从exceptions2数组里找异常处理

3. 当insn==0时
catch (BuDaoLePaoException e) {
store = array.get(0).byteValue();
array.remove(0);
这个是将array[0]的值拿出来---->store=array[0]

4.1--5就是一系列运算

5.最后判定条件:当insn==6的时候,
i++
store==vminsn[i]需要成立

1
2
3
4
5
6
7
再联系数组分析:
通过观察数组能发现两种规律
第一种: 0 1 XX 2 XX 6 XX
第二种: 0 2 XX 2 XX 6 XX
结合上面的判定条件5.
就是说6后面的XX就是加密之后的数据
我们把他依次从后往前逆向两个计算,再逆向最开始的计算就能得到最开始的flag

最终代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
vmInsn = [0] * 310
vmInsn[0] = 0;vmInsn[1] = 1;vmInsn[2] = 60;vmInsn[3] = 2;vmInsn[4] = -20;vmInsn[5] = 6;vmInsn[6] = -25;vmInsn[7] = 0;vmInsn[8] = 1;vmInsn[9] = 60;vmInsn[10] = 2;vmInsn[11] = -20;vmInsn[12] = 6;vmInsn[13] = -27;vmInsn[14] = 0;vmInsn[15] = 1;vmInsn[16] = 60;vmInsn[17] = 2;vmInsn[18] = -20;vmInsn[19] = 6;vmInsn[20] = -33;vmInsn[21] = 0;vmInsn[22] = 1;vmInsn[23] = 60;vmInsn[24] = 2;vmInsn[25] = -20;vmInsn[26] = 6;vmInsn[27] = -31;vmInsn[28] = 0;vmInsn[29] = 1;vmInsn[30] = 60;vmInsn[31] = 2;vmInsn[32] = -20;vmInsn[33] = 6;vmInsn[34] = -50;vmInsn[35] = 0;vmInsn[36] = 1;vmInsn[37] = 60;vmInsn[38] = 2;vmInsn[39] = -20;vmInsn[40] = 6;vmInsn[41] = -36;vmInsn[42] = 0;vmInsn[43] = 1;vmInsn[44] = 60;vmInsn[45] = 2;vmInsn[46] = -20;vmInsn[47] = 6;vmInsn[48] = -39;vmInsn[49] = 0;vmInsn[50] = 1;vmInsn[51] = 60;vmInsn[52] = 2;vmInsn[53] = -20;vmInsn[54] = 6;vmInsn[55] = -24;vmInsn[56] = 0;vmInsn[57] = 1;vmInsn[58] = 60;vmInsn[59] = 2;vmInsn[60] = -20;vmInsn[61] = 6;vmInsn[62] = -52;vmInsn[63] = 0;vmInsn[64] = 1;vmInsn[65] = 60;vmInsn[66] = 2;vmInsn[67] = -20;vmInsn[68] = 6;vmInsn[69] = -29;vmInsn[70] = 0;vmInsn[71] = 1;vmInsn[72] = 60;vmInsn[73] = 2;vmInsn[74] = -20;vmInsn[75] = 6;vmInsn[76] = -52;vmInsn[77] = 0;vmInsn[78] = 1;vmInsn[79] = 14;vmInsn[80] = 2;vmInsn[81] = 5;vmInsn[82] = 6;vmInsn[83] = -64;vmInsn[84] = 0;vmInsn[85] = 1;vmInsn[86] = 14;vmInsn[87] = 2;vmInsn[88] = 5;vmInsn[89] = 6;vmInsn[90] = -58;vmInsn[91] = 0;vmInsn[92] = 1;vmInsn[93] = 14;vmInsn[94] = 2;vmInsn[95] = 5;vmInsn[96] = 6;vmInsn[97] = -63;vmInsn[98] = 0;vmInsn[99] = 1;vmInsn[100] = 14;vmInsn[101] = 2;vmInsn[102] = 5;vmInsn[103] = 6;vmInsn[104] = -52;vmInsn[105] = 0;vmInsn[106] = 1;vmInsn[107] = 14;vmInsn[108] = 2;vmInsn[109] = 5;vmInsn[110] = 6;vmInsn[111] = -90;vmInsn[112] = 0;vmInsn[113] = 1;vmInsn[114] = 14;vmInsn[115] = 2;vmInsn[116] = 5;vmInsn[117] = 6;vmInsn[118] = -39;vmInsn[119] = 0;vmInsn[120] = 1;vmInsn[121] = 14;vmInsn[122] = 2;vmInsn[123] = 5;vmInsn[124] = 6;vmInsn[125] = -43;vmInsn[126] = 0;vmInsn[127] = 1;vmInsn[128] = 14;vmInsn[129] = 2;vmInsn[130] = 5;vmInsn[131] = 6;vmInsn[132] = 26;vmInsn[133] = 0;vmInsn[134] = 1;vmInsn[135] = 14;vmInsn[136] = 2;vmInsn[137] = 5;vmInsn[138] = 6;vmInsn[139] = 25;vmInsn[140] = 0;vmInsn[141] = 1;vmInsn[142] = 14;vmInsn[143] = 2;vmInsn[144] = 5;vmInsn[145] = 6;vmInsn[146] = -49;vmInsn[147] = 0;vmInsn[148] = 1;vmInsn[149] = 14;vmInsn[150] = 2;vmInsn[151] = 5;vmInsn[152] = 6;vmInsn[153] = -64;vmInsn[154] = 0;vmInsn[155] = 1;vmInsn[156] = 10;vmInsn[157] = 2;vmInsn[158] = 5;vmInsn[159] = 6;vmInsn[160] = -51;vmInsn[161] = 0;vmInsn[162] = 1;vmInsn[163] = 10;vmInsn[164] = 2;vmInsn[165] = 5;vmInsn[166] = 6;vmInsn[167] = 25;vmInsn[168] = 0;vmInsn[169] = 1;vmInsn[170] = 10;vmInsn[171] = 2;vmInsn[172] = 5;vmInsn[173] = 6;vmInsn[174] = -45;vmInsn[175] = 0;vmInsn[176] = 1;vmInsn[177] = 10;vmInsn[178] = 2;vmInsn[179] = 5;vmInsn[180] = 6;vmInsn[181] = -55;vmInsn[182] = 0;vmInsn[183] = 1;vmInsn[184] = 10;vmInsn[185] = 2;vmInsn[186] = 5;vmInsn[187] = 6;vmInsn[188] = -47;vmInsn[189] = 0;vmInsn[190] = 1;vmInsn[191] = 10;vmInsn[192] = 2;vmInsn[193] = 5;vmInsn[194] = 6;vmInsn[195] = 24;vmInsn[196] = 0;vmInsn[197] = 1;vmInsn[198] = 10;vmInsn[199] = 2;vmInsn[200] = 5;vmInsn[201] = 6;vmInsn[202] = -41;vmInsn[203] = 0;vmInsn[204] = 1;vmInsn[205] = 10;vmInsn[206] = 2;vmInsn[207] = 5;vmInsn[208] = 6;vmInsn[209] = -60;vmInsn[210] = 0;vmInsn[211] = 1;vmInsn[212] = 10;vmInsn[213] = 2;vmInsn[214] = 5;vmInsn[215] = 6;vmInsn[216] = 22;vmInsn[217] = 0;vmInsn[218] = 1;vmInsn[219] = 10;vmInsn[220] = 2;vmInsn[221] = 5;vmInsn[222] = 6;vmInsn[223] = -40;vmInsn[224] = 0;vmInsn[225] = 1;vmInsn[226] = 10;vmInsn[227] = 2;vmInsn[228] = 5;vmInsn[229] = 6;vmInsn[230] = -60;vmInsn[231] = 0;vmInsn[232] = 2;vmInsn[233] = 14;vmInsn[234] = 2;vmInsn[235] = 10;vmInsn[236] = 6;vmInsn[237] = -15;vmInsn[238] = 0;vmInsn[239] = 2;vmInsn[240] = 14;vmInsn[241] = 2;vmInsn[242] = 10;vmInsn[243] = 6;vmInsn[244] = 50;vmInsn[245] = 0;vmInsn[246] = 2;vmInsn[247] = 14;vmInsn[248] = 2;vmInsn[249] = 10;vmInsn[250] = 6;vmInsn[251] = -51;vmInsn[252] = 0;vmInsn[253] = 2;vmInsn[254] = 14;vmInsn[255] = 2;vmInsn[256] = 10;vmInsn[257] = 6;vmInsn[258] = -31;vmInsn[259] = 0;vmInsn[260] = 2;vmInsn[261] = 14;vmInsn[262] = 2;vmInsn[263] = 10;vmInsn[264] = 6;vmInsn[265] = 50;vmInsn[266] = 0;vmInsn[267] = 2;vmInsn[268] = 14;vmInsn[269] = 2;vmInsn[270] = 10;vmInsn[271] = 6;vmInsn[272] = 50;vmInsn[273] = 0;vmInsn[274] = 2;vmInsn[275] = 14;vmInsn[276] = 2;vmInsn[277] = 10;vmInsn[278] = 6;vmInsn[279] = -35;vmInsn[280] = 0;vmInsn[281] = 2;vmInsn[282] = 14;vmInsn[283] = 2;vmInsn[284] = 10;vmInsn[285] = 6;vmInsn[286] = 50;vmInsn[287] = 0;vmInsn[288] = 2;vmInsn[289] = 14;vmInsn[290] = 2;vmInsn[291] = 10;vmInsn[292] = 6;vmInsn[293] = -35;vmInsn[294] = 0;vmInsn[295] = 2;vmInsn[296] = 14;vmInsn[297] = 2;vmInsn[298] = 10;vmInsn[299] = 6;vmInsn[300] = 51;vmInsn[301] = 0;vmInsn[302] = 2;vmInsn[303] = 14;vmInsn[304] = 2;vmInsn[305] = 10;vmInsn[306] = 6;vmInsn[307] = -17;vmInsn[308] = 114514;vmInsn[309] = 1919810

for i in range(0,308,7):
temp = vmInsn[i + 6] # 加密后的结果
# 等于1的情况
if vmInsn[i + 1] == 1:
temp -= vmInsn[i + 4]
temp ^= vmInsn[i + 2]
# 等于2的情况
else:
temp -= vmInsn[i + 4]
temp -= vmInsn[i + 2]
temp = temp - 32
temp = temp ^ 202
print(chr(temp%256), end="")

# moectf{jvav_eXcEpt10n_h4ndl3r_1s_s0_c00o0o1}

moedaily

参考博客:MoeCTF2024-wp_moectf2024官方wp-CSDN博客

image-20241024081518672

首先看到了一张表格图

image-20241024081546149

从这里我们可以知道最后解密出来的密文要是这些数字

image-20241024093820792

1
再点下面的框发现D到G都是由输入的flag所求出来的,之后后面绿的框是由s3cr3t!加密而来,而我们知道加密后的结果是上面flag的值,因此需要逆向回原文,并且每一字节转为1字符

接下来看加密表格,先看上面点击的E54和F54

image-20241024094342471

先来看看xlsx语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
BITAND 函数返回两个数的按位进行“与”(AND)运算后的结果。
-----> AND

BITXOR 函数返回两个数的按位进行“异或”(XOR)运算后的结果。
-----> XOR

BITLSHIFT 函数返回一个数向左移动指定位数后的数值。
-----> <<

BITRSHIFT 函数返回一个数向右移动指定位数后的数值。
-----> >>

CODE 函数用于返回文本字符串中第一个字符的 ASCII 代码

MID 函数返回文本字符串中从指定位置开始的特定数目的字符串。
=MID(文本, 开始位置, 字符个数)

IF 函数根据提供的条件参数,条件计算结果为 TRUE 时,返回一个值;条件计算结果为 FALSE 时,返回另一个值。
=IF(条件, [条件为 TRUE 时的返回值], [条件为 FALSE 时的返回值])

AND 函数返回逻辑值:如果所有参数值均为“真(TRUE)”,返回“真(TRUE)”,反之返回“假(FALSE)”。
=AND(测试条件1, [测试条件2], ...)
  • 由此来看这句话

    1
    2
    3
    =BITAND(F53+BITXOR(BITLSHIFT(E54,4)+E38,BITXOR(E54+D54,BITRSHIFT(E54,5)+F38)),4294967295)
    翻译完就是
    (F53+XOR((E54<<4))+E38,XOR(E54+D54,(E54<<5)+F38))) & 4294967295
  • 再多点几个就找到了规律:

    1
    2
    3
    4
    F54=(上+(左<<4+415144)^(左+3664448)^(左>>5+19883))&4294967295  
    B C 段用的是 114514,1919810
    E F 段用的是 415144,19883
    BC 和 EF 共进行32次

又由这张图发现是两次大加密,也就是总共64次,下面用上面加密的接着

image-20241024095149247

至此就可以从最后的答案开始编写代码了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def xor(m,n):
return m^n
def decode(x,y,n):
k=[114514,1919810,415144,19883]
if n%2==1:
p,q=k[0],k[1]
else:
p, q = k[2], k[3]
x,y,n=y-(xor((x<<4)+p,xor(x+114514*((n+1)//2),(x>>5)+q)))&4294967295,x,n-1
if n==0:
return x,y
return decode(x,y,n)
flag=""
while 1:
x,y=int(input('x=')),int(input('y='))
x,y=decode(x,y,64)
x,y=decode(x,y,64)
flag += chr(x & 0xFF)+chr((x >> 8) & 0xFF)+chr((x >> 16) & 0xFF)+chr((x >> 24) & 0xFF)
flag += chr(y & 0xFF)+chr((y >> 8) & 0xFF)+chr((y >> 16) & 0xFF)+chr((y >> 24) & 0xFF)
print(flag)

SecretModule

这题是真没思路,跟着wp走一遍

image-20241024162156181

由这个我们把重点关注在customize.sh上

image-20241024162302860

记事本打开,很明显的base64提示

image-20241024162339828

下载至本地,这里是为什么不太清楚

image-20241024162408847

得到压缩包解压出来download,接着用记事本打开

image-20241024162450095

chatgpt解析一下

image-20241024162736409

叫gpt秒了额

image-20241024163028149

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import hashlib
import itertools

# 预设的 MD5 哈希值
target_md5 = "77a58d62b2c0870132bfe8e8ea3ad7f1"

# 两种可能的值
options = ["114514", "1919810"]

# 暴力破解生成7个值的所有组合
for combination in itertools.product(options, repeat=7):
concatenated = ''.join(combination)
# 计算 MD5 哈希值
md5_hash = hashlib.md5(concatenated.encode()).hexdigest()
# 检查是否匹配目标哈希值
if md5_hash == target_md5:
break

print(combination, concatenated)
1
moectf{114514114514191981011451411451419198101919810}