nepctf-2023

主要做了re,难度不小,可惜后面的题目没时间看了

misc

codes

main函数第三个变量就是环境变量,逐个输出就可以

与AI共舞的哈夫曼

直接用gpt照着写一个

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
def decompress(input_file, output_file):
with open(input_file, 'rb') as f:
# Read frequency information
num_symbols = f.read(1)[0]
frequencies = {}
for _ in range(num_symbols):
byte = f.read(1)[0]
freq_bytes = f.read(4)
freq = (freq_bytes[0] << 24) | (freq_bytes[1] << 16) | (freq_bytes[2] << 8) | freq_bytes[3]
frequencies[byte] = freq

# Rebuild Huffman tree
root = build_huffman_tree(frequencies)

# Read compressed data
compressed_data = f.read()

current_node = root
decompressed_data = bytearray()
for bit in compressed_data:
for i in range(7, -1, -1):
bit_value = (bit >> i) & 1
if bit_value == 0:
current_node = current_node.left
else:
current_node = current_node.right

if current_node.char is not None:
decompressed_data.append(current_node.char)
current_node = root

with open(output_file, 'wb') as f:
f.write(decompressed_data)

ConnectedFive

送分,下赢就行

Pwn

HRP-CHAT-1

SQL注入,注册的用户里带'-- ,查询的时候会把后面的语句注释掉,绕过statement查询,输出flag

HRP-CHAT-3

Roll出来H3,然后用技能1,相加溢出为负,得到flag

RE

九龙拉棺

flag分成了两段,程序里的tea解出来只有前半段。

程序中有一段数据经过RC4+base32+base58+base64之后,得到了一个dll,其中包含了另一段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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <iostream>
#include <stdint.h>
#include <stdio.h>

// 加密函数
void encrypt(uint32_t *v, uint32_t *k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i; /* set up */
uint32_t delta = 0x9e3779b9; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
} /* end cycle */
v[0] = v0;
v[1] = v1;
}
// 解密函数
void decrypt(uint32_t *v, uint32_t *k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i; /* set up */
uint32_t delta = 0x9e3779b9; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i < 32; i++) { /* basic cycle start */
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
} /* end cycle */
v[0] = v0;
v[1] = v1;
}

int main() {
unsigned int v12[16];
v12[0] = 0x88AFD2D6;
v12[1] = 0x3FBE45A7;
v12[2] = 0x27AAD1B9;
v12[3] = 0x8CB3E51E;
v12[4] = 0x9348FFA;
v12[5] = 0xE19F3C42;
v12[6] = 0xFFDD0D86;
v12[7] = 0xEDB97383;
v12[8] = 0x12C4C0BF;
v12[9] = 0x1B67BD19;
v12[10] = 0xF7A514D6;
v12[11] = 0x18F95254;
v12[12] = 0xAB100CB0;
v12[13] = 0xCBA137;
v12[14] = 0x2A91712;
v12[15] = 0xC58D0D9E;
uint32_t k[4] = {1, 2, 3, 4};
for (int c = 0; c < 8; c++) {
decrypt(&v12[2 * c], k);
for (int j = 0; j < 4; j++) {
printf("%c", (v12[2 * c] >> 8 * j) & 0xff);
}
for (int j = 0; j < 4; j++) {
printf("%c", (v12[2 * c + 1] >> 8 * j) & 0xff);
}
}

unsigned int v16[16];
v16[0] = 0x1DC74989;
v16[1] = 0xD979AF77;
v16[2] = 0x888D136D;
v16[3] = 0x8E26DB7F;
v16[4] = 0xC10C3CC9;
v16[5] = 0xC3845D40;
v16[6] = 0xC6E04459;
v16[7] = 0xA2EBDF07;
v16[8] = 0xD484388D;
v16[9] = 0x12F956A2;
v16[10] = 0x5ED7EE59;
v16[11] = 0x43137F85;
v16[12] = 0xEF43F9F0;
v16[13] = 0xB29683AA;
v16[14] = 0x8E3640B4;
v16[15] = 0xC2D36177;

uint32_t k2[4] = {0x12, 0x34, 0x56, 0x78};
for (int c = 0; c < 8; c++) {
decrypt(&v16[2 * c], k2);
for (int j = 0; j < 4; j++) {
printf("%c", (v16[2 * c] >> 8 * j) & 0xff);
}
for (int j = 0; j < 4; j++) {
printf("%c", (v16[2 * c + 1] >> 8 * j) & 0xff);
}
}
return 0;
}
// iu41m0pv3x7kllzu8pdq6mt9n2nwjdp6kat8ent4dhn5r158iz2f0cmr0u7yxyq}
// NepCTF{c9cdnwdi3iu41m0pv3x7kllzu8pdq6mt9n2nwjdp6kat8ent4dhn5r158iz2f0cmr0u7yxyq}

Review

很多反调试,主要操作其实就是一个xxtea+取反+AES,没有魔改

xxtea之后还有一个生成AES密钥的操作,有几位跟结果中与后一位相同的个数有关,就48种可能,遍历一下就行,虽然最终结果就是0

1
2
3
4
5
6
7
8
9
10
11
12
13
from Crypto.Cipher import AES

password = b"\x19\x28\x6E\x04\x19\x28\x6E\x04\x46\x55\xC8\x04\x46\x55\xC8\x04"

text = b"\xF4\x9C\xDD\x41\x03\xDD\x5A\x13\x2E\x55\x97\x9E\xFF\xD5\x08\xD9\xF6\xD1\x09\x8C\x68\x9E\x92\xFF\x75\x0F\x80\x95\x4B\x16\xB9\xC6\x7F\x54\x2E\x20\x35\xFC\x1B\x46\x14\xAA\xDA\x5E\x4F\xBD\x59\x71"
aes = AES.new(password, AES.MODE_ECB)

den_text = aes.decrypt(text)

for z in range(0, len(den_text), 4):
tmp = 0xffffffff-int.from_bytes(den_text[z : z + 4], byteorder="little")
print(tmp, end=", ")

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
#include <stdint.h>
#include <stdio.h>
#define DELTA 0x9e3779b9
#define MX \
(((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ \
((sum ^ y) + (key[(p & 3) ^ e] ^ z)))

void btea(uint32_t *v, int n, uint32_t const key[4]) {
uint32_t y, z;
uint32_t 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() {
uint32_t v[12] = {2309579534, 3094518205, 2274467788, 4072683167,
418971191, 2065596768, 236488259, 3759075494,
2770389782, 2907179657, 384852496, 1019579761};
uint32_t const k[4] = {0x00000019, 0x00000000, 0x0000006E, 0x00000003};
int n = 12;

btea(v, -n, k);
uint8_t *tmp = (uint8_t *)v;
for (int i = 0; i < 48; i++) {
printf("%c", tmp[i]);
}
return 0;
}

eeeeerte

易语言,逆起来很恶心,用IDA插件恢复了部分函数名,图片点击根据总次数共有三种响应,一种是正常的加密逻辑,输入是key,不过加密的是假flag。第二种是弹窗输出真flag加密后的结果。第三个是画图。

因为key和flag都没有,猜测第三个画出来的是key,但是我在linux下用wine跑弹不出画板,不知道会不会真的弹出来图,所以用python按照给出的左上角和右下角的坐标画了一个,得到key是NITORI2413,然后按照加密的过程一点点逆就可以了。

不过结果是47位,不能被8整除,最后一位填充什么未知,懒得逆所以直接爆破。

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <cstdio>
#include <cstdlib>
#include <ctype.h>
#include <iostream>
unsigned char R[256] = {
0xA3, 0xD7, 0x09, 0x83, 0xF8, 0x48, 0xF6, 0xF4, 0xB3, 0x21, 0x15, 0x78,
0x99, 0xB1, 0xAF, 0xF9, 0xE7, 0x2D, 0x4D, 0x8A, 0xCE, 0x4C, 0xCA, 0x2E,
0x52, 0x95, 0xD9, 0x1E, 0x4E, 0x38, 0x44, 0x28, 0x0A, 0xDF, 0x02, 0xA0,
0x17, 0xF1, 0x60, 0x68, 0x12, 0xB7, 0x7A, 0xC3, 0xE9, 0xFA, 0x3D, 0x53,
0x96, 0x84, 0x6B, 0xBA, 0xF2, 0x63, 0x9A, 0x19, 0x7C, 0xAE, 0xE5, 0xF5,
0xF7, 0x16, 0x6A, 0xA2, 0x39, 0xB6, 0x7B, 0x0F, 0xC1, 0x93, 0x81, 0x1B,
0xEE, 0xB4, 0x1A, 0xEA, 0xD0, 0x91, 0x2F, 0xB8, 0x55, 0xB9, 0xDA, 0x85,
0x3F, 0x41, 0xBF, 0xE0, 0x5A, 0x58, 0x80, 0x5F, 0x66, 0x0B, 0xD8, 0x90,
0x35, 0xD5, 0xC0, 0xA7, 0x33, 0x06, 0x65, 0x69, 0x45, 0x00, 0x94, 0x56,
0x6D, 0x98, 0x9B, 0x76, 0x97, 0xFC, 0xB2, 0xC2, 0xB0, 0xFE, 0xDB, 0x20,
0xE1, 0xEB, 0xD6, 0xE4, 0xDD, 0x47, 0x4A, 0x1D, 0x42, 0xED, 0x9E, 0x6E,
0x49, 0x3C, 0xCD, 0x43, 0x27, 0xD2, 0x07, 0xD4, 0xDE, 0xC7, 0x67, 0x18,
0x89, 0xCB, 0x30, 0x1F, 0x8D, 0xC6, 0x8F, 0xAA, 0xC8, 0x74, 0xDC, 0xC9,
0x5D, 0x5C, 0x31, 0xA4, 0x70, 0x88, 0x61, 0x2C, 0x9F, 0x0D, 0x2B, 0x87,
0x50, 0x82, 0x54, 0x64, 0x26, 0x7D, 0x03, 0x40, 0x34, 0x4B, 0x1C, 0x73,
0xD1, 0xC4, 0xFD, 0x3B, 0xCC, 0xFB, 0x7F, 0xAB, 0xE6, 0x3E, 0x5B, 0xA5,
0xAD, 0x04, 0x23, 0x9C, 0x14, 0x51, 0x22, 0xF0, 0x29, 0x79, 0x71, 0x7E,
0xFF, 0x8C, 0x0E, 0xE2, 0x0C, 0xEF, 0xBC, 0x72, 0x75, 0x6F, 0x37, 0xA1,
0xEC, 0xD3, 0x8E, 0x62, 0x8B, 0x86, 0x10, 0xE8, 0x08, 0x77, 0x11, 0xBE,
0x92, 0x4F, 0x24, 0xC5, 0x32, 0x36, 0x9D, 0xCF, 0xF3, 0xA6, 0xBB, 0xAC,
0x5E, 0x6C, 0xA9, 0x13, 0x57, 0x25, 0xB5, 0xE3, 0xBD, 0xA8, 0x3A, 0x01,
0x05, 0x59, 0x2A, 0x46,
};

char key[] = "NITORI2413";

void enc(unsigned char *buffer) {
for (int i = 0; i < 32; i++) {
for (int j = 0; j < 8; j++) {
printf("%02x ", buffer[j]);
}
printf("\n");
if ((i / 8) % 2 == 0) {
unsigned char a0 = buffer[0];
unsigned char a1 = buffer[1];
a0 ^= R[a1 ^ key[(4 * i) % 10]];
a1 ^= R[a0 ^ key[(4 * i + 1) % 10]];
a0 ^= R[a1 ^ key[(4 * i + 2) % 10]];
a1 ^= R[a0 ^ key[(4 * i + 3) % 10]];
// auto tmp = (unsigned short *)buffer;
unsigned short tmp[4];
for (int j = 0; j < 4; j++)
tmp[j] = (buffer[2 * j] << 8) | buffer[2 * j + 1];
tmp[0] = tmp[3] ^ (i + 1);
tmp[3] = tmp[2];
tmp[2] = tmp[1];
tmp[1] = (a0 << 8) | a1;
tmp[0] ^= tmp[1];
for (int j = 0; j < 4; j++) {
buffer[2 * j] = (tmp[j] >> 8) & 0xff;
buffer[2 * j + 1] = (tmp[j]) & 0xff;
}
} else {
unsigned short tmp[4];
for (int j = 0; j < 4; j++)
tmp[j] = (buffer[2 * j] << 8) | buffer[2 * j + 1];
auto s_tmp = tmp[0];
tmp[0] = tmp[3];
tmp[3] = tmp[2];
tmp[2] = (tmp[1] ^ s_tmp) ^ (i + 1);
unsigned char a0 = buffer[0];
unsigned char a1 = buffer[1];
a0 ^= R[a1 ^ key[(4 * i) % 10]];
a1 ^= R[a0 ^ key[(4 * i + 1) % 10]];
a0 ^= R[a1 ^ key[(4 * i + 2) % 10]];
a1 ^= R[a0 ^ key[(4 * i + 3) % 10]];
tmp[1] = (a0 << 8) | a1;

for (int j = 0; j < 4; j++) {
buffer[2 * j] = (tmp[j] >> 8) & 0xff;
buffer[2 * j + 1] = (tmp[j]) & 0xff;
}
}
}
}

void dec(unsigned char *buffer) {
for (int i = 31; i >= 0; i--) {
if ((i / 8) % 2 == 0) {
unsigned short tmp[4];
for (int j = 0; j < 4; j++)
tmp[j] = (buffer[2 * j] << 8) | buffer[2 * j + 1];
tmp[0] ^= tmp[1];
unsigned char a0 = (tmp[1] >> 8) & 0xff;
unsigned char a1 = (tmp[1]) & 0xff;
tmp[1] = tmp[2];
tmp[2] = tmp[3];
tmp[3] = tmp[0] ^ (i + 1);
for (int j = 0; j < 4; j++) {
buffer[2 * j] = (tmp[j] >> 8) & 0xff;
buffer[2 * j + 1] = (tmp[j]) & 0xff;
}
a1 ^= R[a0 ^ key[(4 * i + 3) % 10]];
a0 ^= R[a1 ^ key[(4 * i + 2) % 10]];
a1 ^= R[a0 ^ key[(4 * i + 1) % 10]];
a0 ^= R[a1 ^ key[(4 * i) % 10]];
buffer[0] = a0;
buffer[1] = a1;
} else {
unsigned short tmp[4];
for (int j = 0; j < 4; j++)
tmp[j] = (buffer[2 * j] << 8) | buffer[2 * j + 1];
unsigned char a0 = (tmp[1] >> 8) & 0xff;
unsigned char a1 = (tmp[1]) & 0xff;
a1 ^= R[a0 ^ key[(4 * i + 3) % 10]];
a0 ^= R[a1 ^ key[(4 * i + 2) % 10]];
a1 ^= R[a0 ^ key[(4 * i + 1) % 10]];
a0 ^= R[a1 ^ key[(4 * i) % 10]];
buffer[0] = a0;
buffer[1] = a1;
unsigned short s_tmp = (a0 << 8) | a1;
tmp[1] = (tmp[2] ^ (i + 1)) ^ s_tmp;
tmp[2] = tmp[3];
tmp[3] = tmp[0];
for (int j = 1; j < 4; j++) {
buffer[2 * j] = (tmp[j] >> 8) & 0xff;
buffer[2 * j + 1] = (tmp[j]) & 0xff;
}
}
}
}

int main() {
// unsigned char plain[] = "flag{Misdirection?MysteriousJack?FAAAKE}";
// for (int i = 0; i < 40; i += 8)
// enc(&plain[i]);
// for (int i = 0; i < 40; i++) {
// printf("%02x ", plain[i]);
// }
// printf("\n");

for (int c = 0; c <= 0xff; c++) {
unsigned char cipher[49] = {
0xc6, 0x6c, 0x4e, 0xf7, 0x74, 0xa7, 0xf1, 0x88, 0xdf, 0xa1,
0x6a, 0x9a, 0x15, 0x2e, 0xa9, 0xa0, 0xb7, 0xfa, 0x9f, 0x5a,
0xbb, 0x6d, 0x6a, 0xc8, 0xc9, 0x76, 0xcb, 0x1, 0xd7, 0x12,
0x8f, 0x28, 0x16, 0x7e, 0xcf, 0xe3, 0x1, 0x57, 0x38, 0x95,
0xe1, 0x6b, 0x4c, 0x36, 0x58, 0x74, 0x5a, 0x00, 0x00};
for (int i = 0; i < 40; i += 8)
dec(&cipher[i]);
cipher[47] = c;
for (int i = 40; i < 48; i += 8)
dec(&cipher[i]);
printf("%d %s\n", c, cipher);
}
}
wmctf-2023 starctf-2023

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×