以下题目来源:ctfshow reverse + nssctf reverse

(ctfshow里面这个板块的题目有点少,不成体系)

(´・_・`)✍️📄

01 逆向签到题

🚩flag:flag{7ujm8ikhy6}

💡hint:基础分析

使用ida pro打开可以直接看到。

![截屏2025-08-09 21.33.46](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-09 21.33.46.png)


02 re2

🚩flag:flag{RC4&->ENc0d3F1le}

💡hint:基础分析 rc4解密

ida分析主函数,将flag.txt内容加密写入enflag.txt。

![截屏2025-08-10 09.15.00](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 09.15.00.png)

分析到标准rc4加密。

enflag.txt是flag.txt进行rc4加密后的结果。在这里进行解密。

这是密钥加密过程:

![截屏2025-08-10 09.23.26](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 09.23.26.png)

解密密钥:[Warnning]Access_Unauthoriz~d

![截屏2025-08-10 09.37.48](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 09.37.48.png)

对enflag.txt进行rc4解密。

![截屏2025-08-10 09.42.11](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 09.42.11.png)


03~05为萌新赛

03 flag白给

🚩flag:flag{HackAv}

💡hint:加壳

检查是否加壳,经过检查有壳。

![截屏2025-08-10 10.08.49](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 10.08.49.png)

使用upx脱壳。

upx -d flag.exe

![截屏2025-08-10 10.11.36](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 10.11.36.png)

然后使用ida找到flag。


04 签退

🚩flag:flag{c_t_f_s_h_0_w_!}

💡hint:python逆向

用pycdc反编译或python反编译 - 在线工具

![截屏2025-08-10 10.25.31](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 10.25.31.png)

得到python源代码:

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 2.7

import string
c_charset = string.ascii_uppercase + string.ascii_lowercase + string.digits + '()'
flag = 'BozjB3vlZ3ThBn9bZ2jhOH93ZaH9'

def encode(origin_bytes):
c_bytes = [ '{:0>8}'.format(str(bin(b)).replace('0b', '')) for b in origin_bytes ]
resp = ''
nums = len(c_bytes) // 3
remain = len(c_bytes) % 3
integral_part = c_bytes[0:3 * nums]
for x in [
0,
6,
12,
18]:
tmp_unit = [][int(tmp_unit[x:x + 6], 2)]
resp += ''.join([ c_charset[i] for i in tmp_unit ])
integral_part = integral_part[3:]
if remain:
remain_part = ''.join(c_bytes[3 * nums:]) + (3 - remain) * '0' * 8
tmp_unit = [ int(remain_part[x:x + 6], 2) for x in [
0,
6,
12,
18] ][:remain + 1]
resp += ''.join([ c_charset[i] for i in tmp_unit ]) + (3 - remain) * '.'
return rend(resp)


def rend(s):

def encodeCh(ch):

f = lambda x: chr(((ord(ch) - x) + 2) % 26 + x)
if ch.islower():
return f(97)
if (None,).isupper():
return f(65)

return (''.join,)((lambda .0: pass)(s))

解密脚本:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Python 2.7 解密脚本

import string
import binascii

# 定义字符集(与加密时一致)
c_charset = string.ascii_uppercase + string.ascii_lowercase + string.digits + '()'
flag = 'BozjB3vlZ3ThBn9bZ2jhOH93ZaH9'

def decode(encoded_str):
"""
解密函数:将编码后的字符串还原为原始字节
"""
# 移除可能的填充字符(原代码中的'.')
clean_str = encoded_str.rstrip('.')

# 将每个字符转换回6位二进制值
bit_groups = []
for c in clean_str:
try:
index = c_charset.index(c)
bit_groups.append('{:06b}'.format(index))
except ValueError:
continue

# 合并所有二进制位
bit_stream = ''.join(bit_groups)

# 分割为8位一组(原始字节)
bytes_list = []
for i in range(0, len(bit_stream), 8):
byte_bits = bit_stream[i:i+8]
if len(byte_bits) == 8:
bytes_list.append(int(byte_bits, 2))

return ''.join([chr(b) for b in bytes_list])

def reverse_rend(s):
"""
反转rend函数的变换
"""
result = []
for ch in s:
if ch.islower():
# 反转小写字母变换
original = chr(((ord(ch) - 97) - 2) % 26 + 97)
elif ch.isupper():
# 反转大写字母变换
original = chr(((ord(ch) - 65) - 2) % 26 + 65)
else:
# 非字母字符保持不变
original = ch
result.append(original)
return ''.join(result)

def decrypt(encoded_flag):
"""
完整解密流程:
1. 先反转rend函数的字母位移
2. 然后解码Base64-like编码
"""
# 第一步:反转字母位移
reversed_rend = reverse_rend(encoded_flag)

# 第二步:解码二进制数据
decoded_bytes = decode(reversed_rend)

return decoded_bytes

if __name__ == '__main__':
print("[*] 加密后的flag:", flag)
decrypted = decrypt(flag)
print("[+] 解密后的flag:", decrypted)

运行结果:

![截屏2025-08-10 10.29.44](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 10.29.44.png)


05 数学不及格

🚩flag:flag{newbee_here}

💡hint:反编译

ida pro反编译:

int __fastcall main(int argc, const char **argv, const char **envp)
{
unsigned int v4; // [rsp+14h] [rbp-4Ch]
char *endptr; // [rsp+18h] [rbp-48h] BYREF
char *v6; // [rsp+20h] [rbp-40h] BYREF
char *v7; // [rsp+28h] [rbp-38h] BYREF
char *v8; // [rsp+30h] [rbp-30h] BYREF
__int64 v9; // [rsp+38h] [rbp-28h]
__int64 v10; // [rsp+40h] [rbp-20h]
__int64 v11; // [rsp+48h] [rbp-18h]
__int64 v12; // [rsp+50h] [rbp-10h]
unsigned __int64 v13; // [rsp+58h] [rbp-8h]

v13 = __readfsqword(0x28u);
if ( argc != 5 )
{
puts("argc nonono");
exit(1);
}
v4 = strtol(argv[4], &endptr, 16) - 25923;
v9 = f(v4);
v10 = strtol(argv[1], &v6, 16);
v11 = strtol(argv[2], &v7, 16);
v12 = strtol(argv[3], &v8, 16);
if ( v9 - v10 != 0x233F0E151CLL )
{
puts("argv1 nonono!");
exit(1);
}
if ( v9 - v11 != 0x1B45F81A32LL )
{
puts("argv2 nonono!");
exit(1);
}
if ( v9 - v12 != 0x244C071725LL )
{
puts("argv3 nonono!");
exit(1);
}
if ( (int)v4 + v12 + v11 + v10 != 0x13A31412F8CLL )
{
puts("argv sum nonono!");
exit(1);
}
puts("well done!decode your argv!");
return 0;
}

判断了四个方程,并且v9=f(v4)

双击跟进f()函数,返回斐波那契数列第n项

于是(v9-v10)+(v9-v11)+(v9-v12)+(v4+v12+v11+v10)=3*v9+v4=0x19d024e75ff,十进制为1773860189695,又v9=f(v4)

__int64 __fastcall f(int a1)
{
int i; // [rsp+1Ch] [rbp-14h]
__int64 v3; // [rsp+20h] [rbp-10h]
_QWORD *ptr; // [rsp+28h] [rbp-8h]

if ( a1 <= 1 || a1 > 200 )
return 0LL;
ptr = malloc(8LL * a1);
*ptr = 1LL;
ptr[1] = 1LL;
v3 = 0LL;
for ( i = 2; i < a1; ++i )
{
ptr[i] = ptr[i - 1] + ptr[i - 2];
v3 = ptr[i];
}
free(ptr);
return v3;
}

写脚本爆破:

for v4 in range(3,100):
a = [1, 1]
for i in range(2,v4):
v9=a[i-1]+a[i-2]
if 3*v9+v4 == 1773860189695:
print(v4)
print(v9)
a.append(v9)

得到:

58
591286729879

得到v4,v9后解出argv数组

v9=591286729879
v4=58
print(hex(v9-0x233F0E151C))
print(hex(v9-0x1B45F81A32))
print(hex(v9-0x244C071725))
print(hex(v4+0x6543))

得到:

0x666c61677b
0x6e65776265
0x655f686572
0x657d

解密:

![截屏2025-08-10 10.43.40](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 10.43.40.png)


06~09为内部赛

06 批量生产的伪劣商品

🚩flag:ctfshow{群主最爱36D}

💡hint:安卓逆向 静态分析 反编译

apk文件,jadx打开,查看AndroidManifest.xml

![截屏2025-08-10 10.58.57](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 10.58.57.png)

找到app入口appinventor.ai_QA629A242D5E83EFA948B9020CD35CB60.checkme.a

![截屏2025-08-10 10.59.51](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 10.59.51.png)

即可看到flag。


07 来一个派森

🚩flag:ctfshow{zhe_bu_shi_flag}

💡hint:python逆向 静态分析 反编译

使用python反编译工具pyinstxtractor.py,将.exe文件转换成.pyc文件

python pyinstxtractor.py checkme.exe

![截屏2025-08-10 11.06.50](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 11.06.50.png)

python反编译 - 在线工具得到python源码

def b58encode(tmp = None):
tmp = list(map(ord, tmp))
temp = tmp[0]
base58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
for i in range(len(tmp) - 1):
temp = temp * 256 + tmp[i + 1]

tmp = []
while None:
temp = temp // 58
if temp == 0:
break
temp = ''
for i in tmp:
temp += base58[i]

tmp = []
for i in range(len(temp)):
tmp.append(chr(ord(temp[i]) ^ i))

check = ['A','5','q','O','g','q','d','\x7f','[','\x7f','s','{','G','A','x','`','D','@','K','c','-','c',' ','G','+','+','|','x','}','J','h','\\','l']
if tmp == check:
return 1

flag = input('输入flag:')
if b58encode(flag):
print('you win')
else:
print('try again')

解密脚本:

def b58decode():
# 已知的check数组
check = ['A', '5', 'q', 'O', 'g', 'q', 'd', '\x7f', '[', '\x7f', 's', '{', 'G', 'A', 'x', '`', 'D', '@', 'K', 'c',
'-', 'c', ' ', 'G', '+', '+', '|', 'x', '}', 'J', 'h', '\\', 'l']

# 第一步:逆向异或操作
base58_chars = []
for i in range(len(check)):
# 逆向异或:encrypted_char ^ i = original_char
original_char = chr(ord(check[i]) ^ i)
base58_chars.append(original_char)

# 第二步:Base58解码(逆向原编码过程)
base58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

# 将Base58字符转换为对应的索引
indices = [base58.index(c) for c in base58_chars]

# 第三步:将Base58索引转换为大整数
num = 0
for i in indices:
num = num * 58 + i

# 第四步:将大整数转换为原始字节
original_bytes = []
while num > 0:
original_bytes.append(num % 256)
num = num // 256

# 字节顺序是反的,需要反转
original_bytes = original_bytes[::-1]

# 转换为字符串
flag = ''.join([chr(b) for b in original_bytes])

return flag


# 测试解密
decrypted_flag = b58decode()
print("解密后的flag:", decrypted_flag)

结果:

![截屏2025-08-10 11.15.44](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 11.15.44.png)


08 好好学习 天天向上

🚩flag:flag{good_good_study_day_day_up}

💡hint:静态分析 反编译 爆破

爆破脚本

from pwn import *
tab = 'abdefglostuyp{}_'
aa = open('cStuday.exe', 'rb').read()[0x2400: 0x13400]
def deeptry(i, v4, s):
if v4<0:
return False
if i==0:
#print(i,hex(v4),s)
if v4 == 0:
print('-->'+s)
return False
for j in range(16):
v2 = 17*(j + 16*i)
p = 8 * (tab.index(s[0]) + v2)
#print(hex(p))
tmp = v4 - u64(aa[p:p+8])
deeptry(i-1, tmp, tab[j]+s)

s = '}'
deeptry(31,0x1C836D8E5C11047F,s)


09 屏幕裂开了

🚩flag:flag{i_hope_you_didnt_click_the_button_99999__justRE_in_Static}

💡hint:静态分析 反编译 安卓逆向

jadx打开。

![截屏2025-08-10 11.23.23](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 11.23.23.png)

定位关键函数checkflag

![截屏2025-08-10 11.26.18](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 11.26.18.png)

rc4加密但是不好解密。S盒打乱那部分要重复 99999 次。

s = [i for i in range(256)]
k = (b"InfinityLoop"*22) [0:256]

for hit_count in range(99999):
j = 0
for i in range(256):
j = (s[i]+j+k[i])%256
s[i],s[j] = s[j],s[i]

answer =[0xA6,0x3D,0x54,0x0B0,0x74,0xCC,0xBD,0x2A,0x4A,0x0DE,0x0BD,0x35,0x0D1,0x1D,0x80,0x32,0x5F,0x64,0x2F,0x0C5,0x0DD,0x11,0x3E,0x95,0x0CC,0x17,0x13,0x0E5,0x5E,0x65,0x0CE,0x42,0x9E,0x47,0x0C8,0x0F3,0x4D,0x8A,0x0A6,0x1F,0x0F0,0x50,0x27,0x0A2,0x28,0x81,0x24,0x0A7,0x0B4,0x90,0x0FC,0x93,0x8A,0x0C1,0x77,0x0D5,0x16,0x1E,0x0FD,0x87,0x0C7,0x0BB,0x0B3,0x0]

v10,v11 = 0,0
v14 = s
tab = [0]*63
for j in range(63):
v11 = v11+1
v10 = (v14[v11] + v10)& 0xff
v14[v11],v14[v10] = v14[v10],v14[v11]
tab[j] = v14[(v14[v10]+ v14[v11]) %256]

flag = [answer[i]^tab[i] for i in range(63)]
print(bytes(flag))

运行结果:

flag{i_hope_you_didnt_click_the_button_99999__justRE_in_Static}


10~11为七夕杯

10 逆向签到

🚩flag:ctfshow{re_sign_is_easy_}

💡hint:静态分析 反编译

分析这个:

![截屏2025-08-10 11.31.46](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 11.31.46.png)

用cyberchef分析:

7B776F6873667463h

5F6E6769735F6572h

5F797361655F7369h

7Dh

得到:

ctfshow{re_sign_is_easy_}


11 easy_magic

🚩flag:ctfshow{7x_flag_is_here}

💡hint:静态分析 反编译 md5

16进制字符串,md5解密。

cb4bc1bdc7a7a220b6df7fc49611ab8a

https://www.somd5.com

![截屏2025-08-10 11.46.59](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 11.46.59.png)


以下题目来源nssctf

12 [SWPUCTF 2021 新生赛]re1

🚩flag:NSSCTF{easy_reverse}

💡hint:c 语言逆向 逆向技术

反编译

int __fastcall main(int argc, const char **argv, const char **envp)
{
char Str2[1008]; // [rsp+20h] [rbp-60h] BYREF
char Str1[1000]; // [rsp+410h] [rbp+390h] BYREF
int i; // [rsp+7FCh] [rbp+77Ch]

_main();
strcpy(Str2, "{34sy_r3v3rs3}");
printf("please put your flag:");
scanf("%s", Str1);
for ( i = 0; i <= 665; ++i )
{
if ( Str1[i] == 101 )
Str1[i] = 51;
}
for ( i = 0; i <= 665; ++i )
{
if ( Str1[i] == 97 )
Str1[i] = 52;
}
if ( strcmp(Str1, Str2) )
printf("you are wrong,see again!");
else
printf("you are right!");
system("pause");
return 0;
}

解题脚本:

def decrypt_flag():
# 已知加密后的flag
encrypted_flag = "{34sy_r3v3rs3}"

# 逆向替换:'3'->'e','4'->'a'
decrypted = []
for char in encrypted_flag:
if char == '3':
decrypted.append('e')
elif char == '4':
decrypted.append('a')
else:
decrypted.append(char)

return ''.join(decrypted)


# 测试解密
original_flag = decrypt_flag()
print("原始flag应该是:", original_flag)

13 [SWPUCTF 2021 新生赛]简简单单的逻辑

🚩flag:NSSCTF{EZEZ_RERE}

💡hint:Python XOR 算法分析

flag = 'xxxxxxxxxxxxxxxxxx'
list = [47, 138, 127, 57, 117, 188, 51, 143, 17, 84, 42, 135, 76, 105, 28, 169, 25]
result = ''
for i in range(len(list)):
key = (list[i]>>4)+((list[i] & 0xf)<<4)
result += str(hex(ord(flag[i])^key))[2:].zfill(2)
print(result)
# result=bcfba4d0038d48bd4b00f82796d393dfec

解题脚本:

def decrypt_flag():
# 已知数据
encrypted_hex = "bcfba4d0038d48bd4b00f82796d393dfec"
key_list = [47, 138, 127, 57, 117, 188, 51, 143, 17, 84, 42, 135, 76, 105, 28, 169, 25]

# 将十六进制字符串分割为每两个字符一组
encrypted_bytes = [int(encrypted_hex[i:i+2], 16) for i in range(0, len(encrypted_hex), 2)]

# 计算每个key
keys = []
for num in key_list:
key = (num >> 4) + ((num & 0xf) << 4)
keys.append(key)

# 逆向计算原始flag
flag = ""
for i in range(len(encrypted_bytes)):
# 异或操作是可逆的:A ^ B = C ⇒ A = B ^ C
original_char = chr(encrypted_bytes[i] ^ keys[i])
flag += original_char

return flag

# 获取并打印flag
flag = decrypt_flag()
print("解密后的flag:", flag)

14 [SWPUCTF 2021 新生赛]简简单单的解

🚩flag:NSSCTF{REAL_EZ_RC4}

💡hint:Python RC4 语言逆向

import base64,urllib.parse
key = "HereIsFlagggg"
flag = "xxxxxxxxxxxxxxxxxxx"

s_box = list(range(256))
j = 0
for i in range(256):
j = (j + s_box[i] + ord(key[i % len(key)])) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
res = []
i = j = 0
for s in flag:
i = (i + 1) % 256
j = (j + s_box[i]) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
t = (s_box[i] + s_box[j]) % 256
k = s_box[t]
res.append(chr(ord(s) ^ k))
cipher = "".join(res)
crypt = (str(base64.b64encode(cipher.encode('utf-8')), 'utf-8'))
enc = str(base64.b64decode(crypt),'utf-8')
enc = urllib.parse.quote(enc)
print(enc)
# enc = %C2%A6n%C2%87Y%1Ag%3F%C2%A01.%C2%9C%C3%B7%C3%8A%02%C3%80%C2%92W%C3%8C%C3%BA

解题脚本:

import base64, urllib.parse

enc = "%C2%A6n%C2%87Y%1Ag%3F%C2%A01.%C2%9C%C3%B7%C3%8A%02%C3%80%C2%92W%C3%8C%C3%BA"
key = "HereIsFlagggg"


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

res = []
i = j = 0
for s in ciphertext:
i = (i + 1) % 256
j = (j + s_box[i]) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
t = (s_box[i] + s_box[j]) % 256
k = s_box[t]
res.append(chr(ord(s) ^ k))

return "".join(res)


def main():
# 1. url 解码
url_decoded = urllib.parse.unquote(enc)
# 2. base64先编码,再解码,相当于啥也没干,不管他
# 3. rc4解码和编码的算法一样,复制粘贴就行了
key = "HereIsFlagggg"
flag = rc4_decrypt(url_decoded, key)
print(flag)


if __name__ == "__main__":
main()

15 [SWPUCTF 2021 新生赛]非常简单的逻辑题

🚩flag:NSSCTF{Fake_RERE_QAQ}

💡hint:Python 逆向技术 语言逆向

flag = 'xxxxxxxxxxxxxxxxxxxxx'
s = 'wesyvbniazxchjko1973652048@$+-&*<>'
result = ''
for i in range(len(flag)):
s1 = ord(flag[i])//17
s2 = ord(flag[i])%17
result += s[(s1+i)%34]+s[-(s2+i+1)%34]
print(result)
# result = 'v0b9n1nkajz@j0c4jjo3oi1h1i937b395i5y5e0e$i'

解题脚本:

def decrypt_flag(encrypted_result):
s = 'wesyvbniazxchjko1973652048@$+-&*<>'
flag = []

# 将加密结果分成两个字符一组
pairs = [encrypted_result[i:i + 2] for i in range(0, len(encrypted_result), 2)]

for i, pair in enumerate(pairs):
# 获取两个加密字符
c1, c2 = pair[0], pair[1]

# 找到第一个字符在s中的位置
pos1 = s.index(c1)

# 计算s1
# 因为 pos1 = (s1 + i) % 34
# 所以 s1 = (pos1 - i) % 34
s1 = (pos1 - i) % 34

# 找到第二个字符在s中的位置(从末尾计算)
# s[-(s2 + i + 1) % 34] = c2
# 所以 -(s2 + i + 1) % 34 = s.index(c2) - len(s)
# 但更简单的方法是遍历所有可能的s2
found = False
for s2_candidate in range(17):
if s[-(s2_candidate + i + 1) % 34] == c2:
s2 = s2_candidate
found = True
break

if not found:
print(f"无法解密第{i}个字符对: {pair}")
continue

# 计算原始ASCII码
original_char = chr(s1 * 17 + s2)
flag.append(original_char)

return ''.join(flag)


# 已知数据
encrypted_result = 'v0b9n1nkajz@j0c4jjo3oi1h1i937b395i5y5e0e$i'

# 解密
flag = decrypt_flag(encrypted_result)
print("解密后的flag:", flag)

16 [SWPUCTF 2021 新生赛]老鼠走迷宫

🚩flag:NSSCTF{69193150b15c87d39252d974bc323217}

💡hint:Python 逆向 DFS

下载是一个没有后缀的附件,通过010打开,看到4d 5a判断是.exe文件。

使用ida pro打开,看到字符串很多py前缀推测是.pyc文件。

使用pyinstxtractor解析

然后反编译获得源码:

# uncompyle6 version 3.8.0
# Python bytecode 3.7.0 (3394)
# Decompiled from: Python 3.9.12 (tags/v3.9.12:b28265d, Mar 23 2022, 23:52:46) [MSC v.1929 64 bit (AMD64)]
# Embedded file name: 5.py
# Compiled at: 1995-09-28 00:18:56
# Size of source mod 2**32: 272 bytes
import random, msvcrt
row, col = (12, 12)
i, j = (0, 0)
maze = [
[
1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[
1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[
1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1],
[
1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[
1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1],
[
1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[
1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1],
[
1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1],
[
1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1],
[
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1],
[
1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
[
1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[
1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1],
[
1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1],
[
1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[
1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1],
[
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1],
[
1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[
1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
[
1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1],
[
1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1],
[
1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[
1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[
1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],
[
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1]]
print('Mice walk in a maze: wasd to move,q to quit')
print("flag is the shortest path's md5,example:if the shortest path is wasdsdw,the flag is md5('wasdsdw')")
i, j = (0, 1)
n = 0
while 1:
if i == row * 2:
if j == col * 2 - 1:
print('ohhhh!!!!you did it')
break
print('your position:({},{})'.format(i, j))
inp = msvcrt.getch()
n += 1
ti, tj = i, j
if b'a' == inp and i > 0:
tj -= 1
else:
if b'w' == inp and j > 0:
ti -= 1
else:
if b's' == inp and j < row * 2:
ti += 1
else:
if b'd' == inp and i < col * 2:
tj += 1
else:
if b'q' == inp:
exit('bye!!')
else:
print('What???')
continue
if maze[ti][tj] == 1:
print(random.choice(['no wayy!!', "it's wall", 'nop']))
continue
elif maze[ti][tj] == 0:
print(random.choice(['nice!!', 'yeah!!', 'Go on']))
i, j = ti, tj

解题脚本:

import hashlib
from collections import deque

# 定义迷宫
maze = [
[1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1],
[1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1]
]

# 定义移动方向及其对应的字符
directions = [(-1, 0, 'w'), (1, 0, 's'), (0, -1, 'a'), (0, 1, 'd')]

def find_shortest_path():
# 起点 (0,1) 和终点 (24,23)
start = (0, 1)
end = (24, 23)

# 使用BFS搜索最短路径
queue = deque()
queue.append((start[0], start[1], ""))
visited = set()
visited.add((start[0], start[1]))

while queue:
x, y, path = queue.popleft()

# 检查是否到达终点
if x == end[0] and y == end[1]:
return path

# 尝试四个方向
for dx, dy, d in directions:
nx, ny = x + dx, y + dy

# 检查边界和墙壁
if 0 <= nx < 25 and 0 <= ny < 25 and maze[nx][ny] == 0 and (nx, ny) not in visited:
visited.add((nx, ny))
queue.append((nx, ny, path + d))

# 查找最短路径
shortest_path = find_shortest_path()
print("最短路径:", shortest_path)

# 计算flag (路径的MD5)
flag = hashlib.md5(shortest_path.encode()).hexdigest()
print("flag:", flag)

17 [SWPUCTF 2021 新生赛]fakerandom

🚩flag:NSSCTF{FakeE_random}

💡hint:Python XOR 语言逆向

import random
flag = 'xxxxxxxxxxxxxxxxxxxx'
random.seed(1)
l = []
for i in range(4):
l.append(random.getrandbits(8))
result=[]
for i in range(len(l)):
random.seed(l[i])
for n in range(5):
result.append(ord(flag[i*5+n])^random.getrandbits(8))
print(result)
# result = [201, 8, 198, 68, 131, 152, 186, 136, 13, 130, 190, 112, 251, 93, 212, 1, 31, 214, 116, 244]

这是一个基于伪随机数生成器的异或加密算法。

解题脚本:

import random

def decrypt_flag(encrypted_result):
# 第一步:恢复初始的4个随机种子
random.seed(1)
l = [random.getrandbits(8) for _ in range(4)]

# 第二步:解密每个字符
flag = []
for i in range(4): # 4个种子
random.seed(l[i])
for n in range(5): # 每个种子对应5个字符
# 获取加密时的随机数
rand_num = random.getrandbits(8)
# 解密:密文异或随机数
decrypted_char = encrypted_result[i*5 + n] ^ rand_num
flag.append(chr(decrypted_char))

return ''.join(flag)

# 给定的加密结果
encrypted_result = [201, 8, 198, 68, 131, 152, 186, 136, 13, 130, 190, 112, 251, 93, 212, 1, 31, 214, 116, 244]

# 解密
flag = decrypt_flag(encrypted_result)
print("解密后的flag:", flag)

18 [SWPUCTF 2021 新生赛]fakebase

🚩flag:NSSCTF{WHAt_BASe31}

💡hint:Python 算法分析 语言逆向

flag = 'xxxxxxxxxxxxxxxxxxx'

s_box = 'qwertyuiopasdfghjkzxcvb123456#$'
tmp = ''
for i in flag:
tmp += str(bin(ord(i)))[2:].zfill(8)
b1 = int(tmp,2)
s = ''
while b1//31 != 0:
s += s_box[b1%31]
b1 = b1//31

print(s)

# s = u#k4ggia61egegzjuqz12jhfspfkay

解题脚本:

import libnum

def decrypt_flag(encoded_str, s_box):
# 尝试所有可能的k值(0-4)
for k in range(5):
b1 = k
# 逆序处理编码字符串
for char in reversed(encoded_str):
b1 = b1 * 31 + s_box.index(char)

# 方法1:使用libnum直接转换为字符串
try:
flag = libnum.n2s(b1).decode('latin-1')
print(f"尝试k={k},方法1结果: {flag}")
except:
pass

# 方法2:手动转换为二进制再转字符串
try:
binary_str = bin(b1)[2:]
# 补全为8的倍数
if len(binary_str) % 8 != 0:
binary_str = binary_str.zfill((len(binary_str) // 8 + 1) * 8)

flag = ''
for i in range(0, len(binary_str), 8):
byte = binary_str[i:i+8]
flag += chr(int(byte, 2))
print(f"尝试k={k},方法2结果: {flag}")
except:
pass

# 给定的编码表和加密结果
s_box = 'qwertyuiopasdfghjkzxcvb123456#$'
encoded_str = 'u#k4ggia61egegzjuqz12jhfspfkay'

# 解密
decrypt_flag(encoded_str, s_box)

19 [SWPUCTF 2021 新生赛]astJS

🚩flag:NSSCTF{astIsReallyFunny}

💡hint:逆向技术 XOR 逆向

题目描述:这也是程序?得到的flag请使用NSSCTF{}格式提交。

得到的是一个.json文件。

上网查了一下,考点是AST抽象语法树还原为js代码。

{
"type": "Program",
"start": 0,
"end": 233,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 233,
"expression": {
"type": "CallExpression",
"start": 0,
"end": 232,
"callee": {
"type": "FunctionExpression",
"start": 1,
"end": 229,
"id": null,
"expression": false,
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 13,
"end": 229,
"body": [
{
"type": "FunctionDeclaration",
"start": 18,
"end": 177,
"id": {
"type": "Identifier",
"start": 27,
"end": 29,
"name": "bE"
},
"expression": false,
"generator": false,
"async": false,
"params": [
{
"type": "Identifier",
"start": 30,
"end": 33,
"name": "str"
},
{
"type": "Identifier",
"start": 34,
"end": 37,
"name": "key"
}
],
"body": {
"type": "BlockStatement",
"start": 38,
"end": 177,
"body": [
{
"type": "VariableDeclaration",
"start": 46,
"end": 70,
"declarations": [
{
"type": "VariableDeclarator",
"start": 50,
"end": 69,
"id": {
"type": "Identifier",
"start": 50,
"end": 53,
"name": "arr"
},
"init": {
"type": "CallExpression",
"start": 56,
"end": 69,
"callee": {
"type": "MemberExpression",
"start": 56,
"end": 65,
"object": {
"type": "Identifier",
"start": 56,
"end": 59,
"name": "str"
},
"property": {
"type": "Identifier",
"start": 60,
"end": 65,
"name": "split"
},
"computed": false,
"optional": false
},
"arguments": [
{
"type": "Literal",
"start": 66,
"end": 68,
"value": "",
"raw": "''"
}
],
"optional": false
}
}
],
"kind": "var"
},
{
"type": "ReturnStatement",
"start": 77,
"end": 171,
"argument": {
"type": "CallExpression",
"start": 84,
"end": 171,
"callee": {
"type": "MemberExpression",
"start": 84,
"end": 167,
"object": {
"type": "CallExpression",
"start": 84,
"end": 162,
"callee": {
"type": "MemberExpression",
"start": 84,
"end": 91,
"object": {
"type": "Identifier",
"start": 84,
"end": 87,
"name": "arr"
},
"property": {
"type": "Identifier",
"start": 88,
"end": 91,
"name": "map"
},
"computed": false,
"optional": false
},
"arguments": [
{
"type": "ArrowFunctionExpression",
"start": 92,
"end": 161,
"id": null,
"expression": false,
"generator": false,
"async": false,
"params": [
{
"type": "Identifier",
"start": 93,
"end": 94,
"name": "i"
}
],
"body": {
"type": "BlockStatement",
"start": 97,
"end": 161,
"body": [
{
"type": "ReturnStatement",
"start": 107,
"end": 153,
"argument": {
"type": "CallExpression",
"start": 114,
"end": 153,
"callee": {
"type": "MemberExpression",
"start": 114,
"end": 133,
"object": {
"type": "Identifier",
"start": 114,
"end": 120,
"name": "String"
},
"property": {
"type": "Identifier",
"start": 121,
"end": 133,
"name": "fromCharCode"
},
"computed": false,
"optional": false
},
"arguments": [
{
"type": "BinaryExpression",
"start": 134,
"end": 152,
"left": {
"type": "CallExpression",
"start": 134,
"end": 148,
"callee": {
"type": "MemberExpression",
"start": 134,
"end": 146,
"object": {
"type": "Identifier",
"start": 134,
"end": 135,
"name": "i"
},
"property": {
"type": "Identifier",
"start": 136,
"end": 146,
"name": "charCodeAt"
},
"computed": false,
"optional": false
},
"arguments": [],
"optional": false
},
"operator": "^",
"right": {
"type": "Identifier",
"start": 149,
"end": 152,
"name": "key"
}
}
],
"optional": false
}
}
]
}
}
],
"optional": false
},
"property": {
"type": "Identifier",
"start": 163,
"end": 167,
"name": "join"
},
"computed": false,
"optional": false
},
"arguments": [
{
"type": "Literal",
"start": 168,
"end": 170,
"value": "",
"raw": "''"
}
],
"optional": false
}
}
]
}
},
{
"type": "ExpressionStatement",
"start": 181,
"end": 227,
"expression": {
"type": "CallExpression",
"start": 181,
"end": 227,
"callee": {
"type": "MemberExpression",
"start": 181,
"end": 192,
"object": {
"type": "Identifier",
"start": 181,
"end": 188,
"name": "console"
},
"property": {
"type": "Identifier",
"start": 189,
"end": 192,
"name": "log"
},
"computed": false,
"optional": false
},
"arguments": [
{
"type": "CallExpression",
"start": 193,
"end": 226,
"callee": {
"type": "Identifier",
"start": 193,
"end": 195,
"name": "bE"
},
"arguments": [
{
"type": "Literal",
"start": 196,
"end": 222,
"value": "EXXH_MpjxBxYnjggrM~eerv",
"raw": "'EXXH_MpjxBxYnjggrM~eerv'"
},
{
"type": "Literal",
"start": 223,
"end": 225,
"value": 11,
"raw": "11"
}
],
"optional": false
}
],
"optional": false
}
}
]
}
},
"arguments": [],
"optional": false
}
}
],
"sourceType": "module"
}

转换好 的js代码

(function () {
function bE(str,key){
var arr = str.split(‘’);
return arr.map(i=>{
return String.fromCharCode(i.charCodeAt()^key);
}).join(‘’)
}
console.log(bE(‘EXXH_mpjx\x7FBxYnjggrM~eerv’,11));
}());

进行运行

NSSCTF{astIsReallyFunny}


20 [SWPUCTF 2021 新生赛]easyapp

🚩flag:NSSCTF{apkYYDS}

💡hint:安卓逆向 JAVA XOR

先010查看开头为50 4B 03 04 ,判断为.zip文件,修改后缀。得到.apk文件,使用jadx打开。

jadx-gui

找到三个关键函数:

![截屏2025-08-10 14.02.42](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 14.02.42.png)

![截屏2025-08-10 14.02.53](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 14.02.53.png)

![截屏2025-08-10 14.03.03](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 14.03.03.png)

从第一个关键函数中得到类似于乱码的字符串

第三个关键函数中我们知道是异或运算,并且key是123456789

第二个关键函数把key改成了987654321

得到解题脚本:

text ='棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌'
key = 987654321
flag =''

for i in range(len(text)):
flag += chr((ord(text[i]) ^ key) % 128)
print(flag)

运行得到:

NSSCTF{apkYYDS}


21 [SWPUCTF 2021 新生赛]PYRE

🚩flag:NSSCTF{more_qwq_lol}

💡hint:RC4 Base64 Python

下载的附件没有后缀,在010中看到文件头是4D 5A 90 00,推测是.exe文件。

exe转python。

# 题目
import hashlib
import base64


# 密钥调度
def init(a, b):
n = 0
b = hashlib.md5(b.encode()).hexdigest()
m = []
for i in range(256):
a.append(i)
m.append(b[i % len(b)])
for i in range(256):
n = (n + a[i] + ord(m[i])) % 256
a[i], a[n] = a[n], a[i]


# 伪随机数生成
def Encrypt(a, b):
n = c = 0
s = ''
for i in b:
n = (n + 1) % 256
c = (c + a[n]) % 256
a[n], a[c] = a[c], a[n]
t = chr(ord(i) ^ a[(a[n] + a[c]) % 256])
s += t
s = base64.b64encode(s.encode())
return s


input_str = input('input flag pls:')
s = []
init(s, 'bJLVFYw3WI5ncGez')
if Encrypt(s, input_str).decode() == 'w4s1PUYsJ8OYwpRXVjvDkVPCgzIEJ27Dt2I=':
print('good!')
# 解密
import hashlib
import base64


# 密钥调度
def init(a, b):
n = 0
b = hashlib.md5(b.encode()).hexdigest()
m = []
for i in range(256):
a.append(i)
m.append(b[i % len(b)])
for i in range(256):
n = (n + a[i] + ord(m[i])) % 256
a[i], a[n] = a[n], a[i]


# 伪随机数生成
def Encrypt(a, b):
n = c = 0
s = ''
for i in b:
n = (n + 1) % 256
c = (c + a[n]) % 256
a[n], a[c] = a[c], a[n]
t = chr(ord(i) ^ a[(a[n] + a[c]) % 256])
s += t
# s = base64.b64encode(s.encode())
return s


# 重现初始化步骤
s = []
init(s, 'bJLVFYw3WI5ncGez')

# 解码加密结果
encoded_str = 'w4s1PUYsJ8OYwpRXVjvDkVPCgzIEJ27Dt2I='
decoded_bytes = base64.b64decode(encoded_str)

# 使用 RC4 解密
decrypted_str = Encrypt(s, decoded_bytes.decode())

print(decrypted_str)

运行得到:

NSSCTF{more_qwq_lol}


22 [LitCTF 2023]世界上最棒的程序员

🚩flag:NSSCTF{I_am_the_best_programmer_ever}

💡hint:逆向技术 语言逆向

使用ida pro打开,搜索flag。

![截屏2025-08-10 14.19.58](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 14.19.58.png)


23 [NSSCTF 2022 Spring Recruit]easy C

🚩flag:NSSCTF{easy_Re}

💡hint:逆向技术 语言逆向

#include <stdio.h>
#include <string.h>

int main(){
char a[]="wwwwwww";
char b[]="d`vxbQd";

//try to find out the flag
printf("please input flag:");
scanf(" %s",&a);

if(strlen(a)!=7){
printf("NoNoNo\n");
system("pause");
return 0;
}

for(int i=0;i<7;i++){
a[i]++;
a[i]=a[i]^2;
}

if(!strcmp(a,b)){
printf("good!\n");
system("pause");
return 0;
}

printf("NoNoNo\n");
system("pause");
return 0;
//flag 记得包上 NSSCTF{} 再提交!!!
}

解题思路分析

这段C代码的逻辑是:

  1. 用户输入一个7字符的flag
  2. 对每个字符进行两个操作:
    • 先执行 a[i]++ (ASCII值加1)
    • 然后执行 a[i] = a[i]^2 (ASCII值与2异或)
  3. 将处理后的字符串与 "dvxbQd”` 比较

逆向解密步骤

要还原原始flag,我们需要逆向这两个操作:

  1. 先逆向异或操作:original ^ 2 = encryptedoriginal = encrypted ^ 2
  2. 再逆向自增操作:original = encrypted - 1
# 给定的加密字符串
encrypted = "d`vxbQd"

flag = ""
for c in encrypted:
# 逆向操作1:异或2
step1 = ord(c) ^ 2
# 逆向操作2:减1
original_char = chr(step1 - 1)
flag += original_char

# 按照题目要求添加NSSCTF{}格式
print("解密后的flag:", f"NSSCTF{{{flag}}}")

24 [SWPUCTF 2021 新生赛]re2

🚩flag:NSSCTF{nss_caesar}

💡hint:C 语言逆向 算法分析

ida pro反编译:

int __fastcall main(int argc, const char **argv, const char **envp)
{
char Str2[64]; // [rsp+20h] [rbp-90h] BYREF
char Str[68]; // [rsp+60h] [rbp-50h] BYREF
int v7; // [rsp+A8h] [rbp-8h]
int i; // [rsp+ACh] [rbp-4h]

_main();
strcpy(Str2, "ylqq]aycqyp{");
printf(&Format);
gets(Str);
v7 = strlen(Str);
for ( i = 0; i < v7; ++i )
{
if ( (Str[i] <= 96 || Str[i] > 98) && (Str[i] <= 64 || Str[i] > 66) )
Str[i] -= 2;
else
Str[i] += 24;
}
if ( strcmp(Str, Str2) )
printf(&byte_404024);
else
printf(aBingo);
system("pause");
return 0;
}

解题脚本:

def decrypt_flag():
encrypted = "ylqq]aycqyp{"
flag = []

for c in encrypted:
# 判断字符是否在加密时的特殊范围内
if (ord(c) <= ord('b') + 24 and ord(c) >= ord('a') + 24) or \
(ord(c) <= ord('B') + 24 and ord(c) >= ord('A') + 24):
# 逆向操作:加密时加24,解密时减24
decrypted_char = chr(ord(c) - 24)
else:
# 逆向操作:加密时减2,解密时加2
decrypted_char = chr(ord(c) + 2)
flag.append(decrypted_char)

return ''.join(flag)


# 解密并打印flag
flag = decrypt_flag()
print("解密后的flag:", flag)


# 验证解密是否正确
def encrypt_flag(flag):
encrypted = []
for c in flag:
if (ord(c) <= ord('b') and ord(c) >= ord('a')) or \
(ord(c) <= ord('B') and ord(c) >= ord('A')):
encrypted_char = chr(ord(c) + 24)
else:
encrypted_char = chr(ord(c) - 2)
encrypted.append(encrypted_char)
return ''.join(encrypted)


# 验证
print("验证加密结果:", encrypt_flag(flag)) # 应该输出 "ylqq]aycqyp{"

anss_caesar}

最终flag为:NSSCTF{nss_caesar}


25 [SWPUCTF 2022 新生赛]base64

🚩flag:NSSCTF{base_64_NTWQ4ZGDNC7N}

💡hint:Base64 C 逆向技术

ida pro分析。

使用shift+f12.

![截屏2025-08-10 15.14.19](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 15.14.19.png)

得到base64字符串:TlNTQ1RGe2Jhc2VfNjRfTlRXUTRaR0ROQzdOfQ==

进行解码,得到flag。


26 [WUSTCTF 2020]level2

🚩flag:NSSCTF{Just_upx_-d}

💡hint:脱壳 UPX壳 逆向技术

分析头部,是elf文件。

使用upx进行脱壳。

upx -d attachment-15.elf

然后使用ida pro打开。

看到flag。

![截屏2025-08-10 16.20.55](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 16.20.55.png)


27 [HUBUCTF 2022 新生赛]simple_RE

🚩flag:NSSCTF{a8d4347722800e72e34e1aba3fe914ae}

💡hint:Base64 C 逆向技术

使用ida pro打开,得到一串字符串。

5Mc58bPHLiAx7J8ocJIlaVUxaJvMcoYMaoPMaOf

看着像BASE64,解码一下,没解出来,应该是自定义编码。

![截屏2025-08-10 16.24.48](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 16.24.48.png)

看加密函数

__int64 sub_401770()
{
__int64 result; // rax

result = (unsigned int)dword_407030;
if ( !dword_407030 )
{
dword_407030 = 1;
return sub_401700();
}
return result;
}

还有:

.rdata:0000000000404000 00000041 C qvEJAfHmUYjBac+u8Ph5n9Od17FrICL/X0gVtM4Qk6T2z3wNSsyoebilxWKGZpRD

.data:0000000000403020 00000039 C 5Mc58bPHLiAx7J8ocJIlaVUxaJvMcoYMaoPMaOfg15c475tscHfM/8==

解题脚本:

import base64

str1 = "5Mc58bPHLiAx7J8ocJIlaVUxaJvMcoYMaoPMaOfg15c475tscHfM/8==" #str1是要解密的代码
string1 = "qvEJAfHmUYjBac+u8Ph5n9Od17FrICL/X0gVtM4Qk6T2z3wNSsyoebilxWKGZpRD" #string1是改过之后的base64表
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))

28 [HDCTF 2023]easy_re

🚩flag:NSSCTF{a8d4347722800e72e34e1aba3fe914ae}

💡hint:Base64 UPX 脱壳

upx脱壳之后,使用ida pro打开。

int __fastcall main(int argc, const char **argv, const char **envp)
{
int i; // [rsp+2Ch] [rbp-4h]

_main(argc, argv, envp);
func(a, encode_a);
puts("Please input your flag:");
scanf("%s", s);
for ( i = 1; i <= 32; ++i )
f3(s);
func(s, encode_s);
if ( !strcmp(encode_s, a) )
puts("Congratulations! You get the flag");
else
puts("Sorry,try again");
return 0;
}
void __cdecl func(char *x, char *y)
{
unsigned __int8 *v3; // rax
unsigned __int8 v4; // cl
int v5; // ecx
int v6; // eax
int v7; // ecx
int v8; // eax
int v9; // eax
int v10; // eax
unsigned __int8 a4[4]; // [rsp+29h] [rbp-67h]
unsigned __int8 a3[3]; // [rsp+2Dh] [rbp-63h]
char b[76]; // [rsp+30h] [rbp-60h] BYREF
int k; // [rsp+7Ch] [rbp-14h]
int j; // [rsp+80h] [rbp-10h]
int i; // [rsp+84h] [rbp-Ch]
int len; // [rsp+88h] [rbp-8h]
int index; // [rsp+8Ch] [rbp-4h]
char *xa; // [rsp+A0h] [rbp+10h]

xa = x;
index = 0;
len = strlen(x);
i = 0;
j = 0;
k = 0;
strcpy(b, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
while ( len-- )
{
v3 = (unsigned __int8 *)xa++;
v4 = *v3;
LODWORD(v3) = i++;
a3[(int)v3] = v4;
if ( i == 3 )
{
a4[0] = a3[0] >> 2;
a4[1] = ((16 * a3[0]) & 0x30) + (a3[1] >> 4);
a4[2] = ((4 * a3[1]) & 0x3C) + (a3[2] >> 6);
a4[3] = a3[2] & 0x3F;
for ( i = 0; i <= 3; ++i )
{
v5 = a4[i];
v6 = index++;
y[v6] = b[v5];
}
i = 0;
}
}
if ( i )
{
for ( j = i; j <= 2; ++j )
a3[j] = 0;
a4[0] = a3[0] >> 2;
a4[1] = ((16 * a3[0]) & 0x30) + (a3[1] >> 4);
a4[2] = ((4 * a3[1]) & 0x3C) + (a3[2] >> 6);
a4[3] = a3[2] & 0x3F;
for ( j = 0; i >= j; ++j )
{
v7 = a4[j];
v8 = index++;
y[v8] = b[v7];
}
while ( 1 )
{
v9 = i++;
if ( v9 > 2 )
break;
v10 = index++;
y[v10] = 61;
}
}
y[index] = 0;
}

其他信息:

加密字符串:SERDVEZ7WTB1X2hAdjJfL1wvXEA1N2VyM2RfN2hlX3IzdjNyczN9

#!/usr/bin/env python3
# coding: utf-8
"""
尝试从给定的 Base64 "加密字符串" 恢复原始输入 s,
前提假设 f3 每轮对每个字节做 (b = b + key[i%k]) 或 (b = b - key[i%k])(mod 256)。
执行 32 轮后比较 base64( result ) == a。

方法:
1. 尝试把给定的字符串当作 base64/urlsafe base64 解码,得到 s_after。
2. 对各可能的 key 长 k=1..12,使用已知前缀(NSSCTF{, flag{, FLAG{, etc)推导 key_byte mod 8。
3. 若 key 的 mod8 部分在周期上自洽,则用该 key_mod8 还原整个明文并判断是否是可打印/包含 flag 模式。
4. 同时尝试“加法”与“减法”两种方向。
"""

import base64
import binascii
import itertools
import string

# 题目提供的“加密字符串”(被认为是 a,即 base64 编码的某个字符串)
a_candidates = [
"SERDVEZ7WTB1X2hAdjJfL1wvXEA1N2VyM2RfN2hlX3IzdjNyczN9"
]

# 可能的 flag 前缀列表(按常见 CTF/题目风格)
prefixes = ["NSSCTF{", "flag{", "FLAG{", "CTF{", "SECCON{", "ctf{", "HTB{"]

# 工具函数:尝试多种 base64 解码(标准 / urlsafe / 补齐)
def try_b64_variants(s):
out = []
# Try as standard base64
cand = s
# add paddings up to 3 '='
for pad in range(0, 4):
t = cand + ("=" * pad)
try:
b = base64.b64decode(t, validate=False)
out.append(b)
except Exception:
pass
# try urlsafe
for pad in range(0, 4):
t = s + ("=" * pad)
try:
b = base64.urlsafe_b64decode(t)
out.append(b)
except Exception:
pass
# try replacing '_'->'/' and '-'->'+'
alt = s.replace("_", "/").replace("-", "+")
for pad in range(0, 4):
t = alt + ("=" * pad)
try:
b = base64.b64decode(t, validate=False)
out.append(b)
except Exception:
pass
# unique
uniq = []
for x in out:
if x not in uniq:
uniq.append(x)
return uniq

# 判断是否是“像 flag”的字符串(高比例可打印并包含大括号等)
def looks_like_flag(bs):
try:
txt = bs.decode('utf-8')
except Exception:
# if cannot decode as utf-8, consider false
return False
printable = sum(1 for ch in txt if ch in string.printable)
ratio = printable / max(1, len(txt))
# require reasonable printability and a brace or prefix
if ratio > 0.9 and ("{" in txt or "NSSCTF" in txt or "flag" in txt.lower()):
return True
return False

# 尝试基于 prefix 推导 key_mod8 并还原(方向 = +1 表示 f3 是加法,-1 表示减法)
def try_key_from_prefix(s_after, prefix, max_k=12, direction=1):
"""
s_after: bytes after 32 rounds
prefix: known initial bytes of original plaintext (str)
direction: +1 if b_after = b_orig + 32*key (mod256)
-1 if b_after = b_orig - 32*key (mod256)
"""
plen = len(prefix)
prefix_bytes = prefix.encode('utf-8')
L = len(s_after)
results = []
for k in range(1, max_k + 1):
# key_mod8 array init with None
key_mod8 = [None] * k
ok = True
# Try to deduce key_mod8 from known prefix positions
for i in range(min(plen, L)):
b_after = s_after[i]
b_orig = prefix_bytes[i]
# we need 32 * key_mod ≡ dir*(b_after - b_orig) (mod 256)
diff = (b_after - b_orig) & 0xFF
if direction == -1:
diff = (-diff) & 0xFF # convert equation to same LHS form
# diff must be a multiple of 32 for a solution to exist
if diff % 32 != 0:
ok = False
break
kmod8 = (diff // 32) % 8 # key byte modulo 8
idx = i % k
if key_mod8[idx] is None:
key_mod8[idx] = kmod8
else:
if key_mod8[idx] != kmod8:
ok = False
break
if not ok:
continue
# For any key positions still None, we can't deduce from prefix; try all 8 possibilities but prune later.
# Build list of possible assignments for key slots: if known -> single value else -> all 0..7
choices = []
for km in key_mod8:
if km is None:
choices.append(list(range(8)))
else:
choices.append([km])
# Now iterate all combinations (8^(num_none)) but typically small because k small
for combo in itertools.product(*choices):
key_mod8_full = list(combo)
# reconstruct original candidate:
orig = bytearray(L)
for i in range(L):
km = key_mod8_full[i % k]
delta = (32 * km) & 0xFF
if direction == 1:
# b_after = b_orig + delta -> b_orig = b_after - delta
orig[i] = (s_after[i] - delta) & 0xFF
else:
# b_after = b_orig - delta -> b_orig = b_after + delta
orig[i] = (s_after[i] + delta) & 0xFF
# check printable / contains prefix
try:
txt = orig.decode('utf-8')
except Exception:
continue
if txt.startswith(prefix) and looks_like_flag(orig):
results.append((k, key_mod8_full, txt))
# also accept candidates that contain braces and are printable
if looks_like_flag(orig):
results.append((k, key_mod8_full, txt))
# if found some results for this k, record them (no need to try larger combos for same k)
if results:
# we still continue to collect possibly more results for other k
pass
return results

def main():
for a in a_candidates:
print("=== trying candidate a:", a)
decs = try_b64_variants(a)
if not decs:
print(" [!] no base64 decode succeeded for this candidate.")
continue
for s_after in decs:
print(" -> got decoded bytes (len={}): {}".format(len(s_after), repr(s_after[:60])))
# try both directions (add / subtract)
all_results = []
for direction in (1, -1):
dirname = "add" if direction == 1 else "sub"
for pref in prefixes:
res = try_key_from_prefix(s_after, pref, max_k=10, direction=direction)
if res:
for item in res:
k, key_mod8, txt = item
print(" [FOUND] direction={}, prefix={}, k={}, key_mod8={}, candidate:".format(dirname, pref, k, key_mod8))
print(" ", txt)
all_results.append((dirname, pref, k, key_mod8, txt))
if not all_results:
print(" No candidate found with prefix heuristics. You may try larger key length or different prefix.")
else:
print(" Total candidates found:", len(all_results))
print("Done.")

if __name__ == '__main__':
main()

其实直接base64解了就好,这里想多了还去写脚本。

HDCTF{Y0u_h@v2_//@57er3d_7he_r3v3rs3}

改成

NSSCTF{Y0u_h@v2_//@57er3d_7he_r3v3rs3}


29 [HNCTF 2022 Week1]超级签到

🚩flag:NSSCTF{hell0_w0rld}

💡hint:C 逆向技术 语言逆向

直接打开IDA的strings表,查看其中的字符串"wrong flag",然后右键List cross reference to 找到引用该字符串的地方,肯定就是判断Flag的地方了. 后面就按照正常流程分析就可以了

![截屏2025-08-10 16.48.25](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 16.48.25.png)

hello_world不对,看到admin的帖子说,把o都换成0,就能过了。


30 [SWPUCTF 2022 新生赛]easyre

🚩flag:NSSCTF{oh_you_find_it}

💡hint:C 逆向技术 语言逆向

一图到底。

![截屏2025-08-10 16.54.08](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 16.54.08.png)


31 [GFCTF 2021]wordy

🚩flag:NSSCTF{u_are2wordy}

💡hint:花指令 C 逆向技术

  1. 定位main函数
  • 方法1:通过_libc_start_main函数调用链定位
  • 方法2:IDA文本搜索”main”(Ctrl+T跳转下一个匹配项)
  • 方法3:观察IDA导航栏棕红色异常代码段
  1. 识别花指令特征
  • 异常跳转指令(红色标记的jmp)
  • 跳转目标地址为loc_xxxx+1形式
  • 后续字节码无法正常反汇编
  • 典型模式:0xEB 0xFF 0xC0(jmp short 0xFFC0)
  1. 手动修复方法
# 单字节修补示例
Edit -> Patch program -> Assemble
将 EB FF 改为 90 90(NOP指令)
  1. IDAPython批量修复脚本
start = 0x1144
end = 0x3100

for i in range(start, end):
if get_wide_byte(i) == 0xEB and get_wide_byte(i+1) == 0xFF:
patch_byte(i, 0x90) # 仅修改EB为90
# patch_byte(i+1, 0x90) # 可选修复FF
  1. 两种解题路径

方法A:完整反编译

  1. 修复后按P创建函数
  2. F5生成伪代码
  3. 提取所有putchar()参数拼接flag

方法B:非预期解

# 修改初始判断条件
mov dword ptr [rbp-4], 0 → 改为1
# 或NOP掉关键跳转
jz short loc_xxxx → 改为90 90
  1. 注意事项
  • 显示操作码字节(Options -> General -> Disassembly)
  • 花指令可能多层嵌套,需反复验证

原始输出:GF�CTF{u_are2wordy}
修正格式:NSSCTF{u_are2wordy}

核心是通过特征码识别+批量修补恢复原始逻辑。


32 [NISACTF 2022]string

🚩flag:NSSCTF{5353316611126}

💡hint:C 逆向技术 动态调试

反编译找到核心代码。

puts(“The length of flag is 13”);
srand(seed);
printf(“NSSCTF{”);
for ( m = 0; m < 13; ++m )
{
v4 = rand();
printf(“%d”, (unsigned int)(v4 % 8 + 1));
}
putchar(125);

双击seed:
seed dd 2766h ; DATA XREF: flag+133↑r

#include <stdio.h>
#include <stdlib.h>

int main() {
int seed = 0x2766;
int m;
int v4;

srand(seed);
for ( m = 0; m < 13; ++m ) {
v4 = rand();
printf("%d", (unsigned int)(v4 % 8 + 1));
}
}

  gcc exp.c
./a.out
5353316611126%

33 [HNCTF 2022 Week1]贝斯是什么乐器啊?

🚩flag:NSSCTF{B@se64_HAHAHA}

💡hint:C 逆向技术 动态调试

解题脚本

key = “NRQ@PAu;8j[+(R:2806.i”
s = []
for i in key:
s.append(ord(i))
print(s)

for i in range(len(s)):
s[i] = s[i]+i
print(chr(s[i]),end=‘’)

print(s)

b‘NRQ@PAu;8j[+(R:2806.i’
[78, 82, 81, 64, 80, 65, 117, 59, 56, 106, 91, 43, 40, 82, 58, 50, 56, 48, 54, 46, 105]
NSSCTF{B@se64_HAHAHA}


34 [UTCTF 2020]Basics(RE)

🚩flag:NSSCTF{str1ngs_1s_y0ur_fr13nd}

💡hint:C 逆向技术

看文件头,改后缀.elf

使用die确定没有加壳。

使用ida pro打开,strings到flag。

.rodata:00000000000020C0 0000001F C utflag{str1ngs_1s_y0ur_fr13nd}


35 [NISACTF 2022]sign-ezc++

🚩flag:NSSCTF{this_is_NISA_re_sign}

💡hint:C 逆向技术

int __fastcall main(int argc, const char **argv, const char **envp)
{
Man *v3; // rbx
Human *v4; // rbx
std::string name; // [rsp+20h] [rbp-20h] BYREF
char v7; // [rsp+37h] [rbp-9h] BYREF
Human *m; // [rsp+38h] [rbp-8h]

_main();
std::allocator<char>::allocator(&v7);
std::string::string(&name, "NISACTF", &v7);
v3 = (Man *)operator new(0x18uLL);
Man::Man(v3, (std::string)&name, 4);
m = v3;
std::string::~string(&name);
std::allocator<char>::~allocator(&v7);
(*((void (__fastcall **)(Human *))m->_vptr_Human + 1))(m);
v4 = m;
if ( m )
{
Human::~Human(m);
operator delete(v4);
}
return 0;
}

human可疑。

void __cdecl Human::give_flag(Human *const this)
{
int i; // [rsp+2Ch] [rbp-54h]

for ( i = 0; i < strlen(flag); ++i )
flag[i] ^= 0xAu;
}

并在内存中发现:

.data:000000000046A020 flag            db 44h, 2 dup(59h), 49h, 5Eh, 4Ch, 71h, 7Eh, 62h, 63h
.data:000000000046A020 ; DATA XREF: Human::give_flag(void)+21↑o
.data:000000000046A020 ; Human::give_flag(void)+37↑o ...
.data:000000000046A020 db 79h, 55h, 63h, 79h, 55h, 44h, 43h, 59h, 4Bh, 55h, 78h
.data:000000000046A020 db 6Fh, 55h, 79h, 63h, 6Dh, 64h, 77h, 14h dup(0)

写脚本解密:

s=[0x44,0x59,0x59,0x49,0x5E,0x4C,0x71,0x7E,0x62,0x63,0x79,0x55,0x63,0x79,0x55,0x44,0x43,0x59,0x4B,0x55,0x78,0x6F,0x55,0x79,0x63,0x6D,0x64,0x77,0x14]
for letter in s:
print(chr(letter^0xA),end="")

NSSCTF{this_is_NISA_re_sign}

36 [NSSCTF 2022 Spring Recruit]easy Python

🚩flag:NSSCTF{this_is_NISA_re_sign}

💡hint:Base64 Python 算法分析

import string

def encode(string,string2):
tmp_str = str()
ret = str()
bit_string_str = string.encode()
remain = len( string ) % 3
remain_str = str()
for char in bit_string_str:
b_char = (bin(char)[2:])
b_char = '0'*(8-len(b_char)) + b_char
tmp_str += b_char
for i in range(len(tmp_str)//6):
temp_nub = int(tmp_str[i*6:6*(i+1)],2)
ret += string2[temp_nub]
if remain==2:
remain_str = tmp_str[-4:] + '0'*2
temp_nub = int(remain_str,2)
ret += string2[temp_nub] + "="
elif remain==1:
remain_str = tmp_str[-2:] + '0'*4
temp_nub = int(remain_str,2)
ret += string2[temp_nub] + "="*2
return ret.replace("=","")

res = encode(input(),string.ascii_uppercase+string.ascii_lowercase+string.digits+'+/')

if res == "TlNTQ1RGe2Jhc2U2NCEhfQ":
print("good!")
else:
print("bad!")

解题脚本:

import string

def decode(encoded_str, alphabet):
# 计算需要添加的填充字符
padding = 4 - (len(encoded_str) % 4)
if padding != 4:
encoded_str += '=' * padding

# 创建字符到索引的映射
char_to_index = {c: i for i, c in enumerate(alphabet)}
char_to_index['='] = 0 # 填充字符处理

# 将每个字符转换为6位二进制
binary_str = ''
for char in encoded_str:
if char in char_to_index:
binary_str += f"{char_to_index[char]:06b}"

# 按8位分割二进制字符串
bytes_list = []
for i in range(0, len(binary_str), 8):
byte = binary_str[i:i+8]
if len(byte) == 8:
bytes_list.append(int(byte, 2))

# 转换为字节并解码
decoded_bytes = bytes(bytes_list)
return decoded_bytes.decode('utf-8')

# 测试解码
alphabet = string.ascii_uppercase + string.ascii_lowercase + string.digits + '+/'
encoded_flag = "TlNTQ1RGe2Jhc2U2NCEhfQ"
decoded_flag = decode(encoded_flag, alphabet)
print("解码结果:", decoded_flag)

# 验证编码
def encode(string, string2):
tmp_str = str()
ret = str()
bit_string_str = string.encode()
remain = len(string) % 3
remain_str = str()
for char in bit_string_str:
b_char = (bin(char)[2:])
b_char = '0'*(8-len(b_char)) + b_char
tmp_str += b_char
for i in range(len(tmp_str)//6):
temp_nub = int(tmp_str[i*6:6*(i+1)],2)
ret += string2[temp_nub]
if remain == 2:
remain_str = tmp_str[-4:] + '0'*2
temp_nub = int(remain_str,2)
ret += string2[temp_nub] + "="
elif remain == 1:
remain_str = tmp_str[-2:] + '0'*4
temp_nub = int(remain_str,2)
ret += string2[temp_nub] + "="*2
return ret.replace("=", "")

# 验证解码是否正确
test_input = "NSSCTF{base64!!}"
encoded = encode(test_input, alphabet)
print("编码验证:", encoded == encoded_flag) # 应该输出True

37 [HNCTF 2022 Week1]你知道什么是Py嘛?

🚩flag:NSSCTF{Pyth0n_1s_th3_best_l@nguage}

💡hint:Python XOR 逆向技术

s = str(input("please input your flag:"))


arr=[29, 0, 16, 23, 18, 61, 43, 41, 13, 28, 88, 94, 49, 110, 66, 44, 43, 28, 91, 108, 61, 7, 22, 7, 43, 51, 44, 46, 9, 18, 20, 6, 2, 24]

if(len(s)!=35 or s[0]!='N'):
print("error")
exit(0)

for i in range(1,len(s)):
if(ord(s[i-1])^ord(s[i])!=arr[i-1]):
print("error!")
exit(0)
print("right!")

解题脚本:

arr = [29, 0, 16, 23, 18, 61, 43, 41, 13, 28, 88, 94, 49, 110, 66, 44, 43, 28, 91, 108, 61, 7, 22, 7, 43, 51, 44, 46, 9, 18, 20, 6, 2, 24]

# 已知第一个字符是'N'
flag = ['N'] * 35

# 逐个计算后续字符
for i in range(1, 35):
flag[i] = chr(ord(flag[i-1]) ^ arr[i-1])

# 组合成完整字符串
flag_str = ''.join(flag)
print("正确的flag是:", flag_str)

# 验证脚本
def verify(flag):
if len(flag) != 35 or flag[0] != 'N':
return False
for i in range(1, len(flag)):
if ord(flag[i-1]) ^ ord(flag[i]) != arr[i-1]:
return False
return True

# 验证我们找到的flag是否正确
print("验证结果:", verify(flag_str))

38 [广东省大学生攻防大赛 2022]pyre

🚩flag:NSSCTF{2889e7a3-0d6b-4cbb-b6e9-04c0f26c9dca}

💡hint:Python PYC 逆向技术

反编译,爆破b。

c = [
144, 163, 158, 177, 121, 39, 58, 58, 91, 111, 25, 158, 72, 53, 152, 78, 171, 12, 53, 105, 45, 12, 12, 53, 12, 171, 111, 91, 53, 152, 105, 45, 152, 144, 39, 171, 45, 91, 78, 45, 158, 8
]
max_b = 200
res = []
for b in range(1, max_b):
tmp = []
for i in range(len(c)):
for j in range(128):
if j*33 % b == c[i]:
tmp.append(j)
break
if len(tmp) == len(c):
res.append(tmp)

for r in res:
print(''.join([chr(x) for x in r]))

flag{2889e7a3-0d6b-4cbb-b6e9-04c0f26c9dca}


39 [GDOUCTF 2023]Tea

🚩flag:NSSCTF{hzCtf_94_re666fingcry5641qq}

💡hint:TEA XTEA 动态调试

解压是个exe文件,没有加壳。

在 ida 使用快捷键 shift+f12打开字符串窗口搜索关键字 flag

双击进入,然后一直点击快捷键 x 找到调用处,分析关键代码

for ( j = 0; j < 10; ++j )
// 输入函数,scanf
sub_1400111FE("%x", &v8[j]);
// v7重新赋值
sub_140011339(v7);
// v8备份到v9
sub_140011145(v8, v9);
// v7为key,v8为输入的值,进行tea加密
sub_1400112B7(v8, v7);
// 验证加密的结果是否符合预期
v6 = sub_140011352(v8);
if ( v6 )
{
// sub_140011195 为打印函数
printf("you are right\n");
for ( k = 0; k < 10; ++k )
{
for ( m = 3; m >= 0; --m )
printf("%c", (v9[k] >> (8 * m)));
}
}
else
{
printf("fault!\nYou can go online and learn the tea algorithm!");
}

进入 sub_1400117D0函数,可以看到, key的值修改为 [2233, 4455, 6677, 8899]

进入 sub_140011900 函数,可以看到是Tea加密

TEA(Tiny Encryption Algorithm)是一种轻量级的对称加密算法,由David Wheeler和Roger Needham于1994年提出,其核心特点是结构简单(仅需20行代码)、效率高(基于Feistel网络结构),适用于资源受限的环境。它通过多轮(通常32轮)的位运算(加法、异或、移位)和密钥混合(128位密钥分为4个32位子密钥)对64位数据块进行加密,每轮操作包含对明文的非线性变换和密钥的轮换使用,虽然安全性曾受限于密钥相关攻击,但改进版XTEA和XXTEA修复了这些弱点,至今仍广泛应用于嵌入式系统和网络协议中。

进入 sub_140011B60 函数,得到加密后的数据,写解题脚本

def main():
key = [2233, 4455, 6677, 8899]

value = [
0x1A800BDA,
0xF7A6219B,
0x491811D8,
0xF2013328,
0x156C365B,
0x3C6EAAD8,
0x84D4BF28,
0xF11A7EE7,
0x3313B252,
0xDD9FE279
]

dalte = 0x0F462900 # 注意这里 C 代码是 0xF462900
# Python 无符号溢出需要手动限制 32 位
MASK32 = 0xFFFFFFFF

for i in range(8, -1, -1): # i 从 8 到 0
wheel = 33
sum_val = (dalte * (i + wheel)) & MASK32

while wheel > 0:
wheel -= 1
sum_val = (sum_val - dalte) & MASK32

value[i + 1] = (value[i + 1] - ((sum_val + key[(sum_val >> 11) & 3]) ^
(value[i] + ((value[i] >> 5) ^ ((value[i] << 4) & MASK32))))) & MASK32

value[i] = (value[i] - (sum_val ^ (value[i + 1] + ((value[i + 1] >> 5) ^
((value[i + 1] << 4) & MASK32))) ^
(sum_val + key[sum_val & 3]))) & MASK32

# 输出结果
for v in value:
print(f"{v:08x}", end="")

if __name__ == "__main__":
main()

485a4354467b687a4374665f39345f726536363666696e6763727935363431710000717d00000000

![截屏2025-08-10 17.51.22](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 17.51.22.png)


40 [GXYCTF 2019]luck_guy

🚩flag:NSSCTF{do_not_hate_me}

💡hint:

elf文件,ida pro 反编译。

核心代码为

![截屏2025-08-10 17.57.48](/Users/serenius/Library/Application Support/typora-user-images/截屏2025-08-10 17.57.48.png)

解题脚本:

flag = ''
f2 = [0x7F, 0x66, 0x6F, 0x60, 0x67, 0x75, 0x63, 0x69][::-1] # 反转数组

for i in range(8):
if i % 2 == 1:
flag += chr(f2[i] - 2) # 奇数索引减2
else:
flag += chr(f2[i] - 1) # 偶数索引减1

print(flag)

hate_me}

加上前缀信息:GXY{do_not_hate_me}