ghctf

re

ASM?Signin!

ai 一把梭

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
#!/usr/bin/env python3

# Final DATA1 array after the DO1/DO2 swapping (32 bytes)
final_data1 = [
0x26, 0x27, 0x24, 0x25,
0x3F, 0x27, 0x34, 0x11,
0x32, 0x33, 0x30, 0x00,
0x36, 0x37, 0x34, 0x35,
0x3A, 0x3B, 0x38, 0x39,
0x3E, 0x3F, 0x3C, 0x3D,
0x2A, 0x2B, 0x28, 0x00,
0x2E, 0x2F, 0x2C, 0x2D
]

# DATA2 array that the encrypted flag is compared with (32 bytes)
data2 = [
0x69, 0x77, 0x77, 0x66,
0x73, 0x72, 0x4F, 0x46,
0x03, 0x47, 0x6F, 0x79,
0x07, 0x41, 0x13, 0x47,
0x5E, 0x67, 0x5F, 0x09,
0x0F, 0x58, 0x63, 0x7D,
0x5F, 0x77, 0x68, 0x35,
0x62, 0x0D, 0x0D, 0x50
]

flag_bytes = bytearray()

# Process each of the 8 blocks (4 bytes per block)
for i in range(8):
base = i * 4
# For each block, let:
# d1 = final_data1[base+1], d2 = final_data1[base+2], d3 = final_data1[base+3]
# Then:
# flag[0] = data2[base+0] XOR d1
# flag[1] = data2[base+1] XOR d2
# flag[2] = data2[base+2] XOR d2
# flag[3] = data2[base+3] XOR d3
f0 = data2[base + 0] ^ final_data1[base + 1]
f1 = data2[base + 1] ^ final_data1[base + 2]
f2 = data2[base + 2] ^ final_data1[base + 2]
f3 = data2[base + 3] ^ final_data1[base + 3]
flag_bytes.extend([f0, f1, f2, f3])

# Convert the flag bytes to a string
flag = flag_bytes.decode('ascii')
print("Flag:", flag)

FishingKit

main函数解出是假的flag

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
from z3 import *

s=z3.Solver()

l=[BitVec(f'{i}',8) for i in range(10)]

s.add(202 * l[8] + 216 * l[5] - 4 * l[4] - 330 * l[9] - 13 * l[4] - 268 * l[6] == -14982
, 325 * l[8] + 195 * l[0] + 229 * l[1] - 121 * l[6] - 409 * l[6] - (l[1] << 7) == 22606
, 489 * l[1] + 480 * l[6] + 105 * l[2] + 367 * l[3] - 135 * l[4] - 482 * l[9] == 63236
, 493 * l[1] - 80 * l[4] - 253 * l[8] - 121 * l[2] - 177 * l[0] - 243 * l[9] == -39664
, 275 * l[4] + 271 * l[6] + 473 * l[7] - 72 * l[5] - 260 * l[4] - 367 * l[4] == 14255
, 286 * l[0] + 196 * l[7] + 483 * l[2] + 442 * l[1] - 495 * l[8] - 351 * l[4] == 41171
, 212 * l[2] + 283 * l[7] - 329 * l[8] - 429 * l[9] - 362 * l[2] - 261 * l[6] == -90284
, 456 * l[5] + 244 * l[7] + 92 * l[4] + 348 * l[7] - 225 * l[1] - 31 * l[2] == 88447
, 238 * l[9] + 278 * l[7] + 216 * l[6] + 237 * l[0] + 8 * l[2] - 17 * l[9] == 83838
, 323 * l[9] + 121 * l[1] + 370 * l[7] - (l[4] << 6) - 196 * l[9] - 422 * l[0] == 26467
, 166 * l[9] + 90 * l[1] + 499 * l[2] + 301 * l[8] - 31 * l[2] - 206 * l[2] == 88247
, 355 * l[0] + 282 * l[4] + 44 * l[9] + 359 * l[8] - 167 * l[5] - 62 * l[3] == 76658
, 488 * l[6] + 379 * l[9] + 318 * l[2] - 85 * l[1] - 357 * l[2] - 277 * l[5] == 35398
, 40 * l[0] + 281 * l[4] + 217 * l[5] - 241 * l[1] - 407 * l[7] - 309 * l[7] == -35436
, 429 * l[3] + 441 * l[3] + 115 * l[1] + 96 * l[8] + 464 * l[1] - 133 * l[7] == 157448)
if s.check() == sat:
ans= s.model()
for i in range(10):
print(chr(ans[l[i]].as_long()),end='')



image-20250302155429602

继续看

GetModuleHandleA 函数 (libloaderapi.h) - Win32 apps | Microsoft Learn

GetProcAddress 函数 (libloaderapi.h) - Win32 apps | Microsoft Learn

VirtualProtect 函数 (memoryapi.h) - Win32 应用程序 |Microsoft 学习

image-20250303005218347

查看

image-20250303005234324

三个方法 挨个看

image-20250303005315443

继续进入查看

image-20250303005337984

密文没加载

image-20250303005436984

另一个方法就是初始化密文 key就是z3解的 我没仔细调试 猜的 端序 脚本一把嗦

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
#include <iostream>	
using namespace std;
#include <bits/stdc++.h>
void decrypt (uint32_t *v ,uint32_t *key){
uint32_t v1=v[1];
uint32_t v0=v[0];
int sum= 0x66778899* 24 ;
for(int i=0;i<24;i++){
v1 -= (key[(sum >> 11) & 3] + sum) ^ (v0 + ((v0 >> 5) ^ (16 * v0)));
sum -= 0x66778899;
v0 -= (key[sum & 3] + sum) ^ (v1 + ((v1 >> 5) ^ (16 * v1)));
}
v[0]=v0;
v[1]=v1;
}
int main (){
uint32_t enc[6]={0xA6975621, 0xDEC4D51A, 0x4D829CA4, 0x56C845D1,
0x5C96B4A7, 0x2087494D};
uint32_t key[]={0x756C6544, 0x61426578, 0x7469,0};
for (int i=0;i<6;i+=2){
decrypt(&enc[i],key);
}
uint8_t encc[24];
memcpy(encc, enc, sizeof(enc));

for(int i=0;i<24;i++){
printf("%c",encc[i]);
}

return 0;
}

LockedSecret

upx改了标志位

不难但是折磨

image-20250303172015861

我勒个超级大tea啊 直接逆

NSSCTF{!!!Y0u_g3t_th3_s3cr3t!!!}

TimeSpaceRescue

开始逆天了 开局闪退 找退出位置

image-20250304161610340

初始化就退

image-20250304161701723

一堆的反调试

image-20250304163136047

image-20250304163145489

检测应用名 最外层的函数直接删除就完了

image-20250305173509082

获取时间戳 获取md5 这里会有花指令 处理一下就行

image-20250305173550478

原来是去pe文件结构里面找时间戳 但是根据题目来看并不是 爆破 嘤嘤嘤

image-20250305174000186

md5赋值给a1 下面进行异或 看aes的部分 魔改挺多 心态大爆炸

image-20250305174047053

这题主要的问题就是把时间戳搞出来 爆破了

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


import hashlib
from Crypto.Cipher import AES
def sub_2110A0(data):
data = bytearray(data)
for i in range(0, 16, 2):
if i + 1 >= len(data):
break
a = data[i] ^ 0x05
b = data[i + 1] ^ 0x05
data[i], data[i + 1] = b, a
return bytes(data)
def sub_211030(data):
data = bytearray(data)
n = len(data)
for i in range(n // 2):
j = n - 1 - i
a = data[i] ^ 0x0F
b = data[j] ^ 0x0F
data[i], data[j] = b, a
return bytes(data)
def generate_key(input_data):
md5 = hashlib.md5(input_data).digest()
key = bytes([(b ^ 0x14) ^ 0x11 for b in md5])
return key
def aes_decrypt(key, ciphertext):
cipher = AES.new(key, AES.MODE_ECB)
try:
plaintext = cipher.decrypt(ciphertext)
except ValueError as e:
print(f"Decryption error: {e}")
return b''
return plaintext
enc1 = bytes([0xcd, 0x16, 0xdb, 0xb5, 0xd1, 0x02, 0xa4, 0x82, 0x8e, 0x59,
0x73, 0x9e, 0x96, 0x26, 0x56, 0xf2])
days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
for month in range(12):
for day in range(1, days_in_month[month] + 1):
input_data = bytearray(12)
input_data[0:4] = day.to_bytes(4, 'little')
input_data[4:8] = month.to_bytes(4, 'little')
input_data[8:12] = (124).to_bytes(4, 'little')
key = generate_key(bytes(input_data))
encrypted_key = sub_2110A0(key)
processed_cipher = sub_2110A0(enc1)
decrypted = aes_decrypt(encrypted_key, processed_cipher)
if not decrypted:
continue
flag1 = sub_211030(decrypted)
if b'NSSCTF' in flag1:
print(day, month + 1)
print(encrypted_key)
print(flag1.decode('latin-1')) # NSSCTF{W0w_Y0u'r
enc = bytes([
0x16, 0x8e, 0x46, 0xf2, 0x55, 0x7b, 0x92, 0x31,
0x30, 0xdc, 0xaa, 0x8a, 0xf3, 0x1c, 0xa0, 0xaa
])
key = b'\n\xe4\xfbFF+YTF+k\x87t&\x91\x07'
processed_cipher = sub_2110A0(enc)
decrypted = aes_decrypt(key, processed_cipher)
flag2 = sub_211030(decrypted)
print(flag2.decode('latin-1',('replace')))
#NSSCTF{W0w_Y0u're_@n_AE5_M@5t3r}

Room 0

难绷

image-20250304171606400

花指令

image-20250304171634088

image-20250304171644625

处理一下 这题有点像那个hgame的异常处理 忘了 也是一堆的花指令要修

image-20250304172148358

异常处理

image-20250304172232445

修复完花指令就是指令

image-20250304172304835

这里是那个key转换 4字节 ctrl s直接到对应的段

image-20250304172338365

image-20250304172358786

说一下 怎么找 首先初始化栈帧的前三位是固定的 第四位就是异常的触发点

image-20250306010229244

这里 让后面为0就行

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
#include<stdio.h>
#include <stdlib.h>
int main(){
int v2; // [esp+0h] [ebp-1Ch]
int i; // [esp+4h] [ebp-18h]
int v4; // [esp+8h] [ebp-14h]
int v5; // [esp+Ch] [ebp-10h]
int v6; // [esp+10h] [ebp-Ch]
int v7; // [esp+10h] [ebp-Ch]
unsigned int v8; // [esp+14h] [ebp-8h]
int v9;
int y;
v9=0x755ff000;
v6=0;
v8=0x75;
v5=0x5f;
v4=0xf0;
for(i=0;i<0xff,v9<0x755ff0ff;i++,v9++){
printf("%x\n",v9);
v6=0;
v8=0x75;
v5=0x5f;
v4=0xf0;
y=v9;
for ( i = 0; i < 32; ++i )
{
v7 = v6 * (v8 + 1415881080) * (y - 1467486175) * ((v8 - y) ^ (v8 >> 4));
v5 = (y + v5) ^ (8 * v4);
v4 = (y + v8) ^ (8 * v5);
v8 = (y + v4) ^ (8 * v5);
y -= v4 + v5 + v8;
if((y - 1415881080)==0){
printf("jjj%x",v9);
system("pause");
}
v6 = v7 + (v8 + 1467486175) * (((v8 - y) ^ (v8 >> 4)) / (y - 1415881080));
}

}
}

得到755ff0d3就是key

再去解smc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
print("A" * 32)
get = [0x2D, 0xD6, 0xB2, 0x58, 0xCB, 0xEA, 0x58, 0x56, 0x0A, 0xD7,
0x1F, 0x95, 0x77, 0x95, 0x15, 0xFD, 0x52, 0xBF, 0x4C, 0x4A,
0x80, 0xA5, 0x61, 0xEB, 0x3A, 0xA9, 0x44, 0xE8, 0x01, 0xAC,
0xBC, 0x95]
enc = [0x22, 0xC4, 0xA0, 0x5A, 0xDE, 0xED, 0x62, 0x5E, 0x25, 0xE2,
0x6D, 0xA6, 0x05, 0xA7, 0x20, 0x8D, 0x7D, 0x99, 0x52, 0x3E,
0x8C, 0xA7, 0x7F, 0xFA, 0x09, 0xD8, 0x62, 0xDB, 0x00, 0x80,
0xC2, 0xA9]
keystream = [(ord("A") ^ i) & 0xff for i in get]
for i in range(len(enc)):
enc[i] ^= keystream[i]
enc[i] &= 0xff
print("".join(map(chr, enc)))

Mio?Ryo?Soyo?

当时就不应该偷懒没安pyenv 这题要用python3.8 不然解包的时候库的pyc导不出来

image-20250304180923845

密文和l函数的加密流程

image-20250304182019553

从range那里大概就可以知道是一个base45的加密

image-20250304182830966

稍微修一下 就是简单的判断 修改字符

image-20250304183206685

base85 已经红了 流程就是base45 修改字符 base85 修改字符 倒序即可

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
sssssssssssss = bytes(
[
57,
118,
33,
114,
68,
56,
117,
115,
34,
52,
52,
95,
78,
40,
49,
59,
95,
85,
63,
122,
54,
33,
77,
110,
49,
54,
34,
109,
106,
122,
60,
92,
108,
91,
61,
51,
42,
62,
35,
38,
52,
67,
62,
122,
116,
48,
76,
50,
67,
51,
59,
41,
122,
45,
45,
51,
90,
]
)
MMiiiiiiooo = "".join(chr(i) for i in range(33, 118))
RRRRyooooooo = "".join(chr(i) for i in range(48, 93))


def inverse_caesar_shift(s, shift):
result = []
for c in s:
if "a" <= c <= "z":
result.append(chr((ord(c) - ord("a") - shift) % 26 + ord("a")))
elif "0" <= c <= "9":
result.append(chr((ord(c) - ord("0") + shift) % 10 + ord("0")))
else:
result.append(c)
return "".join(result)


def base45_decode(encoded_str):
n = len(encoded_str)
decoded_bytes = []
i = 0
while i < n:
if i + 3 <= n:
c0, c1, c2 = encoded_str[i : i + 3]
value = (
RRRRyooooooo.index(c0)
+ RRRRyooooooo.index(c1) * 45
+ RRRRyooooooo.index(c2) * 45 * 45
)
decoded_bytes.extend(value.to_bytes(2, "big"))
i += 3
elif i + 2 <= n:
c0, c1 = encoded_str[i : i + 2]
value = RRRRyooooooo.index(c0) + RRRRyooooooo.index(c1) * 45
decoded_bytes.extend(value.to_bytes(1, "big"))
i += 2
else:
raise ValueError("Invalid encoded string length")
return bytes(decoded_bytes)


import base64
encrypted_str = sssssssssssss.decode("latin-1")
base85_str = inverse_caesar_shift(encrypted_str, 9)
shifted_str1 = base64.a85decode(base85_str).decode()
base45_str = inverse_caesar_shift(shifted_str1, 7)
original_bytes = base45_decode(base45_str)
flag = original_bytes.decode()
print(flag)

canon

两层的vm 内层感觉还好 跟进一下流程 没上太大强度

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
#include<stdio.h>
#include <stdlib.h>
int main(){
__int64 v3; // rdx
__int64 v4; // r8
__int64 v6; // rdx
__int64 v7; // r8
int j; // [rsp+20h] [rbp-1F8h]
int i; // [rsp+24h] [rbp-1F4h]
int v10; // [rsp+28h] [rbp-1F0h]
int v11[4]; // [rsp+30h] [rbp-1E8h]
__int64 v12; // [rsp+40h] [rbp-1D8h]
__int64 v13; // [rsp+48h] [rbp-1D0h]
__int64 v14; // [rsp+50h] [rbp-1C8h]
int v15[8]; // [rsp+58h] [rbp-1C0h]
int v16[4]; // [rsp+78h] [rbp-1A0h]
char Str[12]; // [rsp+88h] [rbp-190h] BYREF
char Source[12]; // [rsp+94h] [rbp-184h] BYREF
char v19[16]; // [rsp+A0h] [rbp-178h] BYREF
char Destination[112]; // [rsp+B0h] [rbp-168h] BYREF
char Str1[112]; // [rsp+120h] [rbp-F8h] BYREF
char v22[112]; // [rsp+190h] [rbp-88h] BYREF

v15[0] = 1;
v15[1] = 5;
v15[2] = 6;
v15[3] = 3;
v15[4] = 4;
v15[5] = 1;
v15[6] = 4;
v15[7] = 5;
v16[0] = 0;
v16[1] = 1;
v16[2] = 2;
v11[0] = 0;
v11[1] = 0;
v11[2] = 0;
for ( i = 0; i < 8; ++i )
{
for ( j = 0; j < 3; ++j )
{
if ( i >= v16[j] )
{
v10 = v11[j];
if ( v10 < 8 )
{
if ( j )
{
if ( j == 1 )
{
printf("fun1 input2, input3, %d\n",v15[v10]);
}
else if ( j == 2 )
{
printf("fun2 input3, input1, %d\n",v15[v10]);
}
}
else
{
printf("fun3 input1, input2, %d\n",v15[v10]);
}
++v11[j];
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
fun3 input1, input2, 1	修改input1 input2没变
fun3 input1, input2, 5 完成base input1 input2没变
fun1 input2, input3, 1 修改input2 input3没变
fun3 input1, input2, 6 完成base input1 input2没变
fun1 input2, input3, 5 完成base input2 input3没变
fun2 input3, input1, 1 修改input3 input1没变
fun3 input1, input2, 3 修改input1 input2没变
fun1 input2, input3, 6 完成base input2 input3没变
fun2 input3, input1, 5 完成base input3 input1没变
fun3 input1, input2, 4 修改input1 input2没变
fun1 input2, input3, 3 修改input2 input3没变
fun2 input3, input1, 6 完成base input3 input1没变
fun3 input1, input2, 1 修改input1 input2没变
fun1 input2, input3, 4 修改input2 input3没变
fun2 input3, input1, 3 修改input3 input1没变
fun3 input1, input2, 4 修改input1 input2没变
fun1 input2, input3, 1 修改input2 input3没变
fun2 input3, input1, 4 修改input3 input1没变
fun3 input1, input2, 5 完成base input1 input2没变
fun1 input2, input3, 4 修改input2 input3没变
fun2 input3, input1, 1 修改input3 input1没变

跟进一下base 不是标准的说实话真不想写了 输入

1
aaaaaaaaaaaabbbbbbbbbbbbcccccccccccc

image-20250306124052290

标准的 能玩 再去细看 op对应的操作都是什么 把对应的解密函数写出来 纯纯代码量 都是可逆的 这里我是手解的 直接copy官方wp了

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
import base64
import math

new_table = "stuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr"
old_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

def rc4_decrypt(ciphertext, key):
key = key.encode()
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]

i = j = 0
plaintext = []
for byte in ciphertext:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
k = S[(S[i] + S[j]) % 256]
plaintext.append(((byte - 0x39) ^ k) % 256)
return bytes(plaintext)

def replay(violin, bass, mode):
if mode == 1:
res = ''
for i, char in enumerate(violin):
offset = ord(bass[i % len(bass)])
if 'a' <= char <= 'z':
res += chr((ord(violin[i]) - ord('a') - offset) % 26 + ord('a'))
elif 'A' <= char <= 'Z':
res += chr((ord(violin[i]) - ord('A') - offset) % 26 + ord('A'))
elif '0' <= char <= '9':
res += chr((ord(violin[i]) - ord('0') - offset) % 10 + ord('0'))
else:
res += violin[i]
return res

elif mode == 3:
Ek = ord(bass[0]) % 10 + 2
Dk = int(len(violin) / Ek)
res = ''
yushu = len(violin) % Ek
steps = []

if len(violin) % Ek == 0:
step = Dk
for i in range(Ek):
steps.append(step)

else:
big_step = math.ceil(len(violin) / Ek)
small_step = int(len(violin) / Ek)
for p in range(yushu):
steps.append(big_step)
for q in range(Ek - yushu):
steps.append(small_step)

n_column = 0
while n_column < math.ceil(len(violin) / Ek):
count_steps = 0
for one_step in steps:
if len(res) == len(violin):
break
else:
res += violin[n_column + count_steps]
count_steps += one_step
n_column += 1
return res

elif mode == 4:
step = ord(bass[0]) % 10 + 2
res = ''
res += violin[step:]
res += violin[:step]
return res

elif mode == 5:
violin_decode = base64.b64decode(violin.translate(str.maketrans(new_table, old_table)))
res = ''
for i, char in enumerate(violin_decode):
res += chr(char ^ ord(bass[i % len(bass)]) + 0x39)
return res

elif mode == 6:
violin_byte = base64.b64decode(violin.translate(str.maketrans(new_table, old_table)))
res = rc4_decrypt(violin_byte, bass)
return res.decode()


def main():
violin = ["WgvDmssEvcY326bHo3nNro3vXvvfmgrz", "gX+Ri9PG=bt5=00B6hscPQOL", "T6bHgUPL2gXUd=xT=FNHtPzV"]
v = [3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 2, 1, 1]
chord = [1, 4, 5, 4, 1, 4, 3, 4, 1, 6, 3, 4, 5, 6, 3, 1, 5, 6, 1, 5, 1]
for i in range(len(v)):
tmp = replay(violin[v[i] - 1], violin[v[i] % 3], chord[i])
violin[v[i] - 1] = tmp
print(''.join(violin))


if __name__ == '__main__':
main()

腐蚀

rust题 最难绷的一集

image-20250310155612914

读取文件

image-20250310161012901

将内容返回给enc文件

image-20250310164147547

进入这个函数 256 rc4

image-20250310172455913

image-20250310172430582

明显就是sbox

image-20250310172708674

image-20250310172718750

这是我们自定义png里面的东西

image-20250310193954504

这里就是我们初始化sbox的地方

image-20250310194027823

可以手动调试可以看见sbox的东西已经进行了修改

image-20250310194207953

这里就是key的东西 打乱了一下顺序但是问题不大 key为我们输入的前8位和后八位 并且打乱顺序 png文件的头尾还是好确定的

image-20250310194613055

我直接上网找了一个png (懒得找png头尾都是啥)

image-20250310194910146

1
0x60, 0x82, 0xAE, 0x42, 0x4E, 0x44, 0x49, 0x45, 0x1A, 0x0A, 0x0D, 0x0A, 0x4E, 0x47, 0x89, 0x50

image-20250310195307698

继续 在下面的a1可以找到我们的内容

image-20250310200148620

image-20250310202001504

这里看得见 我们加密以后的数据

image-20250310202046844

image-20250310202103612

仔细去对比数据会发现这东西他是会翻转的

image-20250310203205658

(最后的翻转确实是没想到 差点炸缸)

ezObfus

image-20250310203700517

花指令量大管饱 两眼一黑 好在没上什么逆天的花 不好认

image-20250310204426560

还有一些零散的就不一一展示了(写不动了)

image-20250310214917480

对key进行处理 查一下上面的特征可以知道是个hash 下面有个校验的函数 爆破

1
8C90F77B

直接四层大循环套着跑就完了 以十进制输入

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
import ctypes

# 加密后的标志数据
EncFlag = bytearray([
0x54, 0x55, 0x79, 0x9E, 0xA8,
0xE1, 0x1C, 0xDA, 0x04, 0x1D,
0xC1, 0x6E, 0x80, 0x82, 0x0D,
0x8A, 0x4C, 0x65, 0xE1, 0x46,
0x71, 0x31, 0xED, 0xD2, 0x14,
0xC5, 0x39, 0xB5, 0x49, 0xE2,
0x04, 0xA9
])

def decrypt(input_bytes, key):
for i in range(32):
v26 = (key >> (8 * (3 - (i % 4)))) & 0xFF
v26 ^= (i & 0xFF)

input_bytes[i] = (input_bytes[i] - i) & 0xFF
input_bytes[i] = ((input_bytes[i] >> 3) | (input_bytes[i] << 5)) & 0xFF
input_bytes[i] ^= v26


key = 0x8C90F77B

decrypt(EncFlag, key)

v66 = 0x811C9DC5
for i in range(4):
v71 = (key >> (i * 8)) & 0xFF
v67 = 0
if v71 % 2:
v67 = v66 ^ v71
else:
v67 = (16777619 * v66) & 0xFFFFFFFF
v67 = ((v67 >> 25) | (v67 << 7)) & 0xFFFFFFFF
v66 = (v67 - v71) & 0xFFFFFFFF

for j in range(32):
EncFlag[j] ^= (8 * ((v66 >> 16) & 0xFF)) & 0xFF

# 将结果转换为字符串并输出
result = EncFlag.decode('ascii', errors='replace')
print(result[:32]) # 确保只输出前32个字符


crypto

baby_factor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from Crypto.Util.number import long_to_bytes
import gmpy2

n = 2741832985459799195551463586200496171706401045582705736390510500694289553647578857170635209048629428396407631873312962021354740290808869502374444435394061448767702908255197762575345798570340246369827688321483639197634802985398882606068294663625992927239602442735647762662536456784313240499437659967114509197846086151042512153782486075793224874304872205720564733574010669935992016367832666397263951446340260962650378484847385424893514879629196181114844346169851383460163815147712907264437435463059397586675769959094397311450861780912636566993749356097243760640620004707428340786147078475120876426087835327094386842765660642186546472260607586011343238080538092580452700406255443887820337778505999803772196923996033929998741437250238302626841957729397241851219567703420968177784088484002831289722211924810899441563382481216744212304879717297444824808184727136770899310815544776369231934774967139834384853322157766059825736075553
phi = 2741832985459799195551463586200496171706401045582705736390510500694289553647578857170635209048629428396407631873312962021354740290808869502374444435394061448767702908255197762575345798570340246369827688321483639197634802985398882606068294663625992927239602442735647762662536456784313240499437659967114509197784246608456057052779643060628984335578973450260519106769911425793594847759982583376628098472390090331415895352869275325656949958242181688663465437185437198392460569653734315961071709533645370007008616755547195108861900432818710027794402838336405197750190466425895582236209479543326147804766393022786785337752319686125574507066082357748118175068545756301823381723776525427724798780890160482013759497102382173931716030992837059880049832065500252713739288235410544982532170147652055063681116147027591678349638753796122845041417275362394757384204924094885233281257928031484806977974575497621444483701792085077113227851520
c = 2675023626005191241628571734421094007494866451142251352071850033504791090546156004348738217761733467156596330653396106482342801412567035848069931148880296036606611571818493841795682186933874790388789734748415540102210757974884805905578650801916130709273985096229857987312816790471330181166965876955546627327549473645830218664078284830699777113214559053294592015697007540297033755845037866295098660371843447432672454589238297647906075964139778749351627739005675106752803394387612753005638224496040203274119150075266870378506841838513636541340104864561937527329845541975189814018246183215952285198950920021711141273569490277643382722047159198943471946774301837440950402563578645113393610924438585345876355654972759318203702572517614743063464534582417760958462550905093489838646250677941813170355212088529993225869303917882372480469839803533981671743959732373159808299457374754090436951368378994871937358645247263240789585351233
e = 65537

# 计算私钥d
d = gmpy2.invert(e, phi)
# 解密得到明文
m = pow(c, d, n)
# 转换为字节
flag = long_to_bytes(m)

print(f"Flag: {flag}")

baby_signin

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
from Crypto.Util.number import long_to_bytes
from sympy.ntheory.residue_ntheory import nthroot_mod
from sympy.ntheory.modular import crt


# 题目中给出的参数
p = 182756071972245688517047475576147877841
q = 305364532854935080710443995362714630091
n = 55807222544207698804941555841826949089076269327839468775219849408812970713531
c = 14745090428909283741632702934793176175157287000845660394920203837824364163635

# 求出 x^4 = c (mod p) 和 (mod q) 的所有解
roots_p = nthroot_mod(c, 4, p, all_roots=True)
roots_q = nthroot_mod(c, 4, q, all_roots=True)
print("模 p 的 4 次根:", roots_p)
print("模 q 的 4 次根:", roots_q)

# 利用 CRT 枚举所有组合候选
candidates = []
for rp in roots_p:
for rq in roots_q:
x, _ = crt([p, q], [rp, rq])
candidates.append(x)

# 去重后检查解是否满足 flag 格式
candidates = list(set(candidates))
for cand in candidates:
try:
m_bytes = long_to_bytes(cand)
if m_bytes.startswith(b"NSSCTF{"):
print("Flag found:", m_bytes.decode())
except Exception as e:
pass

EZ_Fermat

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
#!/usr/bin/env python3
from math import gcd
from Crypto.Util.number import long_to_bytes, inverse

# 已知参数(题目中给出的数值)
n = 101780569941880865465631942473186578520071435753163950944409148606282910806650879176280021512435190682009749926285674412651435782567149633130455645157688819845748439487113261739503325065997835517112163014056297017874761742768297646567397770742374004940360061700285170103292360590891188591132054903101398360047
e = 65537
c = 77538275949900942020886849496162539665323546686749270705418870515132296087721218282974435210763225488530925782158331269160555819622551413648073293857866671421886753377970220838141826468831099375757481041897142546760492813343115244448184595644585857978116766199800311200819967057790401213156560742779242511746
w = 32824596080441735190523997982799829197530203904568086251690542244969244071312854874746142497647579310192994177896837383837384405062036521829088599595750902976191010000575697075792720479387771945760107268598283406893094243282498381006464103080551366587157561686900620059394693185990788592220509670478190685244

# 多项式 f 的字符串表示
f_str = (
"2*x^332 - x^331 + x^329 + 3*x^328 - x^327 - 3*x^325 + x^323 - 3*x^322 - x^321 - 3*x^320 + x^319 + 2*x^318 - 4*x^317 - 3*x^315 - 2*x^314 + x^313 + x^312 + 2*x^311 + "
"2*x^309 + 2*x^308 + 5*x^307 + 2*x^306 + 3*x^305 + 5*x^304 + 4*x^303 + x^302 - x^301 - x^300 - 2*x^299 - 2*x^298 + x^297 + 3*x^296 - x^295 - 4*x^292 - "
"x^290 + 4*x^289 - x^287 - 3*x^286 + x^285 - 2*x^284 + x^283 - x^282 - 2*x^281 + x^280 - 2*x^279 + x^278 + 2*x^277 - 3*x^276 - x^275 - 4*x^274 - "
"3*x^273 - 5*x^272 - 2*x^271 - 3*x^270 + 2*x^269 + 2*x^268 - x^267 - 2*x^266 + x^265 + x^264 - 3*x^262 - 3*x^259 + 2*x^258 - x^257 + 2*x^256 + "
"2*x^255 - x^254 - 2*x^253 - x^252 + 2*x^251 - x^250 + x^249 + 2*x^247 + 2*x^246 + 2*x^245 - 2*x^244 - 3*x^243 + 2*x^242 - 3*x^241 - x^240 - "
"3*x^239 - x^236 - 3*x^235 - 2*x^234 - x^233 - 2*x^232 - x^231 - 3*x^230 - 2*x^229 - 4*x^228 - 2*x^227 - 3*x^226 + 2*x^225 + x^224 - x^223 - "
"2*x^221 + 3*x^219 - x^217 - 2*x^216 + x^215 + 2*x^213 - x^212 + 3*x^211 + x^210 + 4*x^209 + x^208 - x^206 - x^205 - x^204 + 2*x^203 - "
"3*x^202 + 2*x^199 - x^198 + 2*x^196 - 2*x^195 + 3*x^194 + 3*x^193 - x^192 + 4*x^191 + 2*x^189 + x^186 - x^185 - x^184 + 3*x^183 + x^182 + "
"2*x^181 - 2*x^180 + x^177 + x^175 - x^173 + 3*x^172 + x^170 + x^169 - x^167 - 2*x^166 - x^165 - 4*x^164 - 2*x^163 + 2*x^162 + 4*x^161 - "
"2*x^160 - 3*x^159 - 2*x^158 - 2*x^157 + x^156 - x^155 + 3*x^154 - 4*x^153 + x^151 + 2*x^150 + x^149 - x^148 + 2*x^147 + 3*x^146 + "
"2*x^145 - 4*x^144 - 4*x^143 + x^142 - 2*x^140 - 2*x^139 + 2*x^138 + 3*x^137 + 3*x^136 + 3*x^135 + x^134 - x^133 + 2*x^132 + "
"3*x^130 - 3*x^129 - 2*x^128 - x^127 - 2*x^126 + x^125 + x^124 - 2*x^123 + x^122 - x^121 + 3*x^120 - x^119 - 2*x^118 - x^117 - x^116 - "
"2*x^115 + 2*x^114 + 2*x^113 - 3*x^112 - x^111 - 4*x^110 + x^109 + x^108 + x^106 - 4*x^105 + x^104 - x^103 - x^101 + x^100 - 2*x^99 + "
"x^98 - x^97 + 3*x^96 + 3*x^94 - x^93 - x^92 + x^91 - 2*x^90 + x^89 - x^88 + x^87 - x^86 + x^85 + x^84 - x^83 + x^79 - 3*x^78 - 2*x^77 + "
"x^74 + 3*x^73 - x^72 - 3*x^71 - 2*x^70 + x^69 - 3*x^66 + x^65 + x^64 - 4*x^62 - x^61 + x^60 - x^59 + 3*x^58 - x^57 - x^54 + 3*x^53 + "
"x^51 - 3*x^50 - x^49 + 2*x^47 - x^46 - x^44 + x^43 - x^42 - 4*x^41 - 3*x^39 - x^37 - x^36 - 3*x^35 + x^34 + x^33 - 2*x^32 + 2*x^31 - "
"x^30 + 2*x^29 - 2*x^28 - 2*x^27 - x^24 + x^22 - 5*x^21 + 3*x^20 + 2*x^19 - x^18 + 2*x^17 + x^16 - 2*x^15 - 2*x^14 + x^13 + x^12 + "
"2*x^11 - 3*x^10 + 3*x^9 + 2*x^8 - 4*x^6 - 2*x^5 - 4*x^4 + x^3 - x^2 - 1"
)

# 将 '^' 替换为 Python 的幂运算符 '**'
f_str_eval = f_str.replace('^', '**')

# 使用 eval 时,在 locals 中传入 x=1 来计算 f(1)
f1 = eval(f_str_eval, {}, {"x": 1})
print("f(1) =", f1)

# 根据题意利用 2^(f(p)) ≡ 2^(f(1)) (mod p),因此 p | (2^(f(1)) - w)
A = pow(2, f1, n)
p_candidate = gcd(n, (A - w) % n)
print("p =", p_candidate)

# 分解 n
q = n // p_candidate
print("q =", q)

# 计算 RSA 私钥参数
phi = (p_candidate - 1) * (q - 1)
d = inverse(e, phi)

# 解密得到明文
m = pow(c, d, n)
flag = long_to_bytes(m)
print("flag =", flag.decode())

pwn

爆0

web

misc

爆0