闲着没事,刚好看见NSS上有比赛,就去做做,感觉有些吃力做的,可能AI太宠我了,或者最近取证做多了,现在做的有点呛。
NSSCTF2025入门题目-Xor
ida看
输入的字符和7A做异或,后与enc_0的内容进行对比

对enc_0的内容进行提取,丢厨子里就好

NSSCTF2025入门题目-Base64
直接ida看

找到密文,然后在字符串中找到码表

丢个厨子就好

NSSCTF2025入门题目-Rc4
也是直接看

v3就是RC4的密匙,密文放在enc_0中

数据提取之后直接喂给厨子就行
NSSCTF2025入门题目-UPX
查壳

直接用upx脱壳即可



查看反编译,主要是异或之后和v6进行比较,看栈的话发现v5和v6相邻,那么v6读取为负数的时候会读取到v5,将v5和v6的值按小端序拆成一共20个字节,因为v6后面添加的部分会把v6最后一个字节给覆盖掉,所以一开始的只取7个字节,这样就是完整的19字节
v5 = 0xE013C2E39292934
v6_qword = 0xF25091325091312
v6_dword = 117574159
v5_bytes = v5.to_bytes(8, byteorder='little')
v6_q_truncated = v6_qword & 0xFFFFFFFFFFFFFF
v6_q_bytes = v6_q_truncated.to_bytes(7, byteorder='little')
v6_d_bytes = v6_dword.to_bytes(4, byteorder='little')
flag1 = [chr(b ^ 0x7A) for b in v5_bytes]
flag2 = [chr(b ^ 0x7A) for b in v6_q_bytes]
flag3 = [chr(b ^ 0x7A) for b in v6_d_bytes]
flag = ''.join(flag1 + flag2 + flag3)
print(flag)
![]()
NSSCTF2025入门题目-ida的使用

直接看找到第一段NSSCTF{

查看字符串找到第二段IDA_1s_4_VeRy_Impo


根据提示找到第三段rTan_t0ol_iN_

第四段提示,找到输出的代码,那就进行动调

在print_nothing处下断点,将rip的地址改为print_flag4


运行可得到第四段rever5e_en8ine3ring}
然后拼接起来就可以了
NSSCTF2025入门题目-认识asm

就是给你看汇编,核心就是flag [i] = flag [i] ^ (flag [i+1] + 1),根据这个写逆向的脚本
def decrypt(enc_flag):
flag = list(enc_flag)
length = len(flag)
for i in range(length - 3, -1, -1):
flag[i] ^= (flag[i + 1] + 1)
return bytes(flag)
if __name__ == "__main__":
enc_flag = bytes([0x1a, 0x7, 0x17, 0x16, 0x13, 0x3a, 0x39, 0x15, 0x1d, 0x2d, 0x35, 0x1d, 0x13, 0x3b, 0x10, 0x4,0x11, 0x9, 0xb, 0xc, 0xc, 0x2a, 0x4, 0xf, 0x1c, 0x28, 0x6, 0xc, 0x12, 0x8, 0x6, 0x7e, 0x7d])
decrypted_flag = decrypt(enc_flag)
print(decrypted_flag.decode('utf-8', errors='replace'))
![]()
NSSCTF2025入门题目-Z3
查看伪代码

在cul中找到z3的函数

这个比较小,不用z3也行,但是都这么说了,还是写个z3的脚本
from z3 import *
a=[Int('a[%d]'%i) for i in range(10)]
s=Solver()
s.add(2*a[7] + 8*a[6] + 8*a[5] + 2*a[4] + 4*a[3] + 5*a[1] + 2*a[0] + 6*a[2] + a[8] + 5*a[9] == 3976)
s.add(a[5] + 9*a[3] + 7*a[2] + 5*a[1] + 3*a[0] + 7*a[4] + 4*a[6] + 6*a[7] + 8*a[8] + 5*a[9] == 5265)
s.add(7*a[8] + 2*a[6] + 6*a[4] + 7*a[3] + 7*a[2] + 3*a[1] + 8*a[0] + 5*a[5] + 4*a[7] + 9*a[9] == 5284)
s.add(7*a[6] + 5*a[5] + 6*a[4] + 3*a[3] + 9*a[0] + 6*a[1] + 4*a[2] + 9*a[7] + 8*a[8] + 7*a[9] == 5925)
s.add(7*a[8] + 8*a[6] + 6*a[4] + a[2] + 4*a[1] + 3*a[0] + 2*a[3] + 5*a[5] + 2*a[7] + 3*a[9] == 4048)
s.add(3*a[8] + 9*a[7] + 7*a[6] + 4*a[4] + 4*a[3] + 5*a[0] + 8*a[1] + 6*a[2] + 4*a[5] + 7*a[9] == 5072)
s.add(5*a[7] + 2*a[3] + 2*(a[0] + a[1]) + 3*a[2] + a[4] + 7*a[5] + 2*a[6] + 3*a[8] + 2*a[9] == 2813)
s.add(3*a[8] + 5*a[7] + 7*a[6] + 3*a[5] + 7*a[4] + 7*a[1] + a[0] + 7*a[2] + 8*a[3] + 6*a[9] == 5004)
s.add(2*a[8] + 5*a[6] + 5*a[5] + 5*a[4] + 9*a[3] + 5*a[0] + 9*a[1] + a[2] + 5*a[7] + a[9] == 4490)
s.add(6*a[8] + 7*a[7] + 5*a[6] + 6*a[3] + 4*a[1] + 6*a[0] + 8*a[2] + 6*a[4] + 8*a[5] + 7*a[9] == 5936)
if s.check() == sat:
ans = s.model()
for i in range(0,10):
print(chr(ans[a[i]].as_long()), end="")
else:
print("no")
![]()
运行出来其中一块,根据题目条件的意思,那就是缺少的就是NSSCTF{}包起来就好了
NSSCTF2025入门题目-Debug
ida打开

追到process_blocks函数中

根据传参,追到encrypt中

就是一个skip32的加密过程

在这里打下断点,因为v4此时是经过加密的结果,因此只要找到此时寄存器的值即可

追到var_30找到flag

NSSCTF2025入门题目-Vm~

就是按照opcode_1里的数组进行一些的操作后,与_data_start_进行比较,根据这个顺序进行复原即可


targets = [0x67,0x29,0x29,0x2A,0x6D,0x46,0x01,0x03,0x17,0x8E,0x78,0x5A,0x15,0x53,0x0C,0x66,0x7D,0x46,0x0C,0xDA,0x3A,0x07]
opcodes = [1,3,3,2,1,5,3,3,2,1,1,2,3,2,3,4,1,2,3,4,1,3]
flag = []
for target, opcode in zip(targets, opcodes):
if opcode == 1:
original = target - 25
elif opcode == 2:
original = target + 25
elif opcode == 3:
original = target ^ 0x7A
elif opcode == 4:
original = target // 2
elif opcode == 5:
original = target
else:
original = 0
flag.append(chr(original))
print(''.join(flag))
![]()
NSSCTF2025入门题目-Tea

就是一个tea加密,找到key,enc,delta即可



直接写个tea的解密脚本即可
import struct
def tea_decrypt(cipher: int, key: list) -> int:
delta = 4277588
v0 = cipher & 0xFFFFFFFF
v1 = (cipher >> 32) & 0xFFFFFFFF
sum_val = delta * 32
k0, k1, k2, k3 = key
for _ in range(32):
temp = ( (v0 + sum_val) ^ ((v0 << 4) + k2) ^ ((v0 >> 5) + k3) ) & 0xFFFFFFFF
v1 = (v1 - temp) & 0xFFFFFFFF
temp = ( (v1 + sum_val) ^ ((v1 << 4) + k0) ^ ((v1 >> 5) + k1) ) & 0xFFFFFFFF
v0 = (v0 - temp) & 0xFFFFFFFF
sum_val = (sum_val - delta) & 0xFFFFFFFF
return (v1 << 32) | v0
def decrypt_flag(key: list, enc: list) -> str:
ciphers = []
for i in range(0, len(enc), 2):
low = enc[i]
high = enc[i + 1]
ciphers.append( (high << 32) | low )
plain_bytes = b""
for cipher in ciphers:
plain = tea_decrypt(cipher, key)
plain_bytes += struct.pack("<Q", plain)
plain_bytes = plain_bytes.rstrip(b"\x00")
return plain_bytes.decode("ascii", errors="replace")
key_1 = [
0xDEADBEEF,
0xBAADF00D,
0xDEADC0DE,
0xDEAD10CC
]
enc_0 = [
0xF0006EE4, 0xBE9A7391,
0x602AF1CA, 0x83748F0E,
0x346C8EE0, 0x36DE99D7,
0x90C4868B, 0x59C40BC2
]
flag = decrypt_flag(key_1, enc_0)
print(f"flag: {flag}")
![]()
NSSCTF2025入门题目-pyc
die看一眼

先去用Pyinstaller解包

3.12版本的,把魔法头补一下

用pycdc直接复原

找到加密的函数在extra.cul中,在库中找到补全魔法头,用pycdc进行还原



写个脚本进行复原
enc = [
52, 41, 41, 57, 46, 60, 1, 10, 3, 25,
37, 19, 9, 37, 10, 3, 14, 18, 21, 20,
37, 24, 3, 14, 31, 25, 21, 30, 31, 7
]
flag = ''.join([chr(num ^ 122) for num in enc])
print( flag)

NSSCTF2025入门题目-Maze

就是一个迷宫图,找到迷宫和起点终点即可


追到move_player的check_move中,找到迷宫

在player和taget中找到起点终点

写个脚本计算路程
import hashlib
from collections import deque
def solve_binary_maze():
binary_str = "0000000000011011101001001010100111101110000100001001110111100100010000011111111000000000100000000000"
def parse_binary_maze(binary_str):
if len(binary_str) < 100:
binary_str += "0" * (100 - len(binary_str))
maze = []
for i in range(10):
start = i * 10
end = start + 10
row = [int(c) for c in binary_str[start:end]]
maze.append(row)
return maze
maze = parse_binary_maze(binary_str)
print("解析后的10x10迷宫:")
for i, row in enumerate(maze):
print(f"行{i}: {row}")
print("\n可视化迷宫:")
print("(■=障碍, □=可通行)")
for row in maze:
print("".join(["■" if c == 0 else "□" for c in row]))
start = None
for y in range(10):
for x in range(10):
if maze[y][x] == 1:
start = (y, x)
break
if start:
break
end = None
for y in range(9, -1, -1):
for x in range(9, -1, -1):
if maze[y][x] == 1:
end = (y, x)
break
if end:
break
print(f"\n自动识别的起点: (y={start[0]}, x={start[1]})")
print(f"自动识别的终点: (y={end[0]}, x={end[1]})")
directions = [
('d', (0, 1)),
('s', (1, 0)),
('a', (0, -1)),
('w', (-1, 0))
]
queue = deque()
visited = set([start])
queue.append((start[0], start[1], "", visited.copy()))
def is_valid(y, x):
return 0 <= x < 10 and 0 <= y < 10 and maze[y][x] == 1
while queue:
y, x, path, visited = queue.popleft()
if (y, x) == end:
return {
'path': path,
'length': len(path),
'flag': f"NSSCTF{{{hashlib.md5(path.encode()).hexdigest()}}}"
}
for move, (dy, dx) in directions:
ny, nx = y + dy, x + dx
next_pos = (ny, nx)
if is_valid(ny, nx) and next_pos not in visited:
new_visited = visited.copy()
new_visited.add(next_pos)
queue.append((ny, nx, path + move, new_visited))
return None
if __name__ == "__main__":
result = solve_binary_maze()
if result:
print("\n迷宫求解结果:")
print(f"最短路径: {result['path']}")
print(f"路径长度: {result['length']} 步")
print(f"Flag: {result['flag']}")

NSSCTF2025入门题目-JS太鼓达人
打开html是个游戏

找到程序的源代码在taiko.js中


发现采用了混淆

经过观察,在gameEnd中找到一个scoreNumber的判定,猜测是达成分数,直接修改大于0

随便点一下,然后听歌就可以了
NSSCTF2025入门题目-XTea

追到check_flag中,找到一个xtea的加密,找到对应的ciphertext,key,delta即可




直接写个脚本进行解密
def xtea_decrypt(v, key):
v0, v1 = v
k0, k1, k2, k3 = key
delta = 0x9E3779B9
sum_val = delta * 32
for _ in range(32):
v1 -= (v0 + ((v0 >> 5) ^ (16 * v0))) ^ (key[(sum_val >> 11) & 3] + sum_val)
v1 &= 0xFFFFFFFF
sum_val -= delta
v0 -= (v1 + ((v1 >> 5) ^ (16 * v1))) ^ (key[sum_val & 3] + sum_val)
v0 &= 0xFFFFFFFF
return [v0, v1]
def xtea_encrypt_verify(v, key):
v0, v1 = v
k0, k1, k2, k3 = key
delta = 0x9E3779B9
sum_val = 0
for _ in range(32):
v0 += (v1 + ((v1 >> 5) ^ (16 * v1))) ^ (key[sum_val & 3] + sum_val)
v0 &= 0xFFFFFFFF
sum_val += delta
v1 += (v0 + ((v0 >> 5) ^ (16 * v0))) ^ (key[(sum_val >> 11) & 3] + sum_val)
v1 &= 0xFFFFFFFF
return [v0, v1]
key_hex = "0D 00 00 00 00 00 00 00 07 00 00 00 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
key_bytes = bytes.fromhex(key_hex)
if len(key_bytes) != 32:
print(f"密钥长度错误: 预期32字节,实际{len(key_bytes)}字节")
else:
key = [
int.from_bytes(key_bytes[0:4], byteorder='little'),
int.from_bytes(key_bytes[4:8], byteorder='little'),
int.from_bytes(key_bytes[8:12], byteorder='little'),
int.from_bytes(key_bytes[12:16], byteorder='little')
]
print("修正后解析的密钥(十六进制):")
print([hex(k) for k in key])
ciphertext = [
0x590D36D1, 0x6FA9B5E2,
0xDA7190AD, 0xC54B0AA0,
0xADA5ED54, 0x4AD07F84,
0x8A4CF3C0, 0x7FEFB22F
]
plaintext_blocks = []
for i in range(0, 8, 2):
block = [ciphertext[i], ciphertext[i+1]]
decrypted = xtea_decrypt(block, key)
plaintext_blocks.extend(decrypted)
valid = True
for i in range(0, 8, 2):
original_block = [ciphertext[i], ciphertext[i+1]]
encrypted_block = xtea_encrypt_verify([plaintext_blocks[i], plaintext_blocks[i+1]], key)
if encrypted_block != original_block:
valid = False
print(f"块{i//2}验证失败: 预期{original_block},实际{encrypted_block}")
if not valid:
print("解密验证失败,无法生成正确的flag")
else:
flag_bytes = b""
for block in plaintext_blocks:
flag_bytes += block.to_bytes(4, byteorder='little', signed=False)
printable_flag = []
for b in flag_bytes:
if 32 <= b <= 126:
printable_flag.append(chr(b))
else:
printable_flag.append(f"\\x{b:02x}")
print(''.join(printable_flag))

NSSCTF2025入门题目-Unity
一个用Unity做的游戏

玩一下发现根本过不了

发现是mono框架的,那就直接找源代码进行修改

直接找到程序,用dnSpy打开

找到GameManager,编辑加分的方法,变成一次100

修改之后编译保存

但是不知道为什么就是显示不完全,找了半天找不到,没办法直接用取证的工具爆搜了

也算是补全了
NSSCTF2025入门题目-AES

直接查看伪代码,标准的aes,找到密文v6和密匙,注意这里的密文是小端序,需要调整顺序

NSSCTF2025入门题目-DES
也是直接查看伪代码

这里分析代码逻辑,标准的des,就是将明文拆成两部分去进行对比,进行分开解密,v10为密文,v8为密匙

NSSCTF2025入门题目-花指令

打开程序发现多处需要修改的地方

第一处花指令,直接将跳转nop

第二处花指令

将跳转擦除

第三处花指令,jz和jnz的永真跳转

直接nop掉

找到key

写一个脚本进行解密
def decrypt(ciphertext, key):
key_len = len(key)
plaintext = []
for i, c in enumerate(ciphertext):
key_char = ord(key[i % key_len])
plain_char = c ^ key_char
plaintext.append(chr(plain_char) if 32 <= plain_char <= 126 else f"\\x{plain_char:02x}")
return ''.join(plaintext)
key = "Ciallo"
print(f"使用密钥: {key}")
print("=" * 50)
answer1_part1 = [
0, 0, # 索引0和1缺失
50, 47, 56, 41, 56, 93, 86, 88, 94, 9, 33, 13
]
valid_answer1_part1 = [v for v in answer1_part1 if v is not None]
result1 = decrypt(valid_answer1_part1, key)
print(f"第一个answer1解密结果: {result1}")
print(f"对应密文值: {valid_answer1_part1}")
answer2 = [
ord('&'), ord('D'), 0x0a, ord('^'), ord('\\'), ord('_'), ord('n'), ord(']'),
2,
ord(']'), ord('U'), ord('B'), ord('"'), ord('P')
]
result2 = decrypt(answer2, key)
print(f"flower_2解密结果: {result2}")
print(f"对应密文值: {answer2}")
print("-" * 50)
answer3 = [
0, # 索引0缺失
92, 76, 84, 8, 86, 114, 95, 80, 95, 92, 11, 118, 8, 83, 17
]
valid_answer3 = [v for v in answer3 if v is not None]
result3 = decrypt(valid_answer3, key)
print(f"flower_3解密结果: {result3}")
print(f"对应密文值: {valid_answer3}")
第一部分少了两个,最后一部分的验证少了第一个字节,动调一个个试一下就好
NSSCTF2025入门题目-SMC

看到smc的特征函数,可以直接进行解密,或者使用动调调试,这题有反调试,所以写脚本
import idautils
import idc
import idaapi
def decrypt_and_patch_flag(start_addr, size=395, key=0x99):
decrypted = []
for i in range(size):
addr = start_addr + i
byte = idc.get_wide_byte(addr)
decrypted_byte = byte ^ key
decrypted.append( (addr, decrypted_byte) )
for addr, b in decrypted:
if 0x20 <= b <= 0x7E:
print(chr(b), end="")
else:
print(f"[{b:02X}]", end="")
print("\n")
modified = 0
for addr, b in decrypted:
idc.patch_byte(addr, b)
modified += 1
flag_start = 0x00007FF7FB9914A1
decrypt_and_patch_flag(flag_start)
还原之后看见数据,为汇编中有异或

将之前的数据进行异或处理

毕竟是新生赛,确实不难,但是就是有点做着呛
427

被折叠的 条评论
为什么被折叠?



