密码学
1.家人们!谁懂啊,RSA签到都不会 (初级)
1 | from Crypto.Util.number import * |
1 | from Cryptodome.Util.number import long_to_bytes as l2b |
2.happy
1 | ('c=', '0x7a7e031f14f6b6c3292d11a41161d2491ce8bcdc67ef1baa9eL') |
1 | from sympy import symbols, Eq, solve |
1 | from Cryptodome.Util.number import long_to_bytes as l2b |
3.bigrsa
1 | from Crypto.Util.number import * |
先用factordb分解n1、n2
1 | from Cryptodome.Util.number import long_to_bytes as l2b |
b'SangFor{qSccmm1WrgvIg2Uq_cZhmqNfEGTz2GV8}'
4.crypto7
1 | 69f7906323b4f7d1e4e972acf4abfbfc,得到的结果用NSSCTF{}包裹。 |
md5解密:md5yyds
5.拟态签到题
ZmxhZ3tHYXFZN0t0RXRyVklYMVE1b1A1aUVCUkNZWEVBeThyVH0=
base64:flag{GaqY7KtEtrVIX1Q5oP5iEBRCYXEAy8rT}
6.base??
1 | dict:{0: 'J', 1: 'K', 2: 'L', 3: 'M', 4: 'N', 5: 'O', 6: 'x', 7: 'y', 8: 'U', 9: 'V', 10: 'z', 11: 'A', 12: 'B', 13: 'C', 14: 'D', 15: 'E', 16: 'F', 17: 'G', 18: 'H', 19: '7', 20: '8', 21: '9', 22: 'P', 23: 'Q', 24: 'I', 25: 'a', 26: 'b', 27: 'c', 28: 'd', 29: 'e', 30: 'f', 31: 'g', 32: 'h', 33: 'i', 34: 'j', 35: 'k', 36: 'l', 37: 'm', 38: 'W', 39: 'X', 40: 'Y', 41: 'Z', 42: '0', 43: '1', 44: '2', 45: '3', 46: '4', 47: '5', 48: '6', 49: 'R', 50: 'S', 51: 'T', 52: 'n', 53: 'o', 54: 'p', 55: 'q', 56: 'r', 57: 's', 58: 't', 59: 'u', 60: 'v', 61: 'w', 62: '+', 63: '/', 64: '='} |
查字典
1 | import base64 |
b'BJD{D0_Y0u_kNoW_Th1s_b4se_map}'
7.Vigenère
1 | Yzyj ia zqm Cbatky kf uavin rbgfno ig hnkozku fyyefyjzy sut gha pruyte gu famooybn bhr vqdcpipgu jaaju obecu njde pupfyytrj cpez cklb wnbzqmr ntf li wsfavm azupy nde cufmrf uh lba enxcp, tuk uwjwrnzn inq ksmuh sggcqoa zq obecu zqm Lncu gz Jagaam aaj qx Hwthxn'a Gbj gfnetyk cpez, g fwwang xnapriv li phr uyqnvupk ib mnttqnq xgioerry cpag zjws ohbaul drinsla tuk liufku obecu ovxey zjwg po gnn aecgtsneoa. |
https://www.guballa.de/vigenere-solver解密一下即可
1 | When in the Course of human events it becomes necessary for one people to dissolve the political bands which have connected them with another and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation. |
8.e的学问
1 | from Crypto.Util.number import * |
这道题的考点在于:平时的rsa中e和φ是互素的,而这里gcd(e,φ)=2而非1,所以需要多几个步骤:
- gcd(e,φ)!=1意味着无法求逆元(d)
- 流程:
1 | from math import gcd |
9.md5的破解
1 | from Crypto.Util.number import * |
逻辑就是补回之后爆破flag对比md5值:
1 | from hashlib import md5 |
Found flag: LitCTF{md5can123dexrypt213thoughcrpsh}
10.crypto1
1 | from gmpy2 import * |
这道题参考一下共模算法的单独的那个文档
11.crypto4
1 | from gmpy2 import * |
12.yafu (中级)
1 | from Cryptodome.Util.number import * |
这里附上一个代码直接调用factordb的api然后直接分解:
1 | import requests |
13.crypto2
1 | from gmpy2 import * |
简单的一b啊
1 | flag1= 100156221476910922393504870369139942732039899485715044553913743347065883159136513788649486841774544271396690778274591792200052614669235485675534653358596366535073802301361391007325520975043321423979924560272762579823233787671688669418622502663507796640233829689484044539829008058686075845762979657345727814280 |
14.childRSA
1 | from random import choice |
这里的随机大素数算法其实跟费马小定理很像:

1 | def getPrime(bits): |
这段 getPrime函数的目标是生成一个指定位数(如2048位)的大素数,其过程是:
- 从一个初始值
n = 2开始。 - 在一个循环中,不断用
n乘以一个从primes列表中随机选择的小素数,直到n的比特长度达到或超过目标位数。 - 然后检查
n + 1是否为素数。如果是,就返回n + 1;如果不是,就重复整个过程。
这意味着最终生成的素数 p具有 p = n + 1的形式,而 n是许多小素数(前10000个质数中的一部分)的乘积。因此,p - 1(即 n)的所有质因数都“很小”,并且都来自那个预设的小素数列表。
- 构造一个特殊的指数
m:令m为前10000个质数的乘积。由于p-1是许多小质数的乘积,并且这些小质数都包含在前10000个质数中,所以p-1一定能整除m(m % (p-1) == 0)。同理,q-1也能整除m。 - 应用费马小定理:根据费马小定理,因为
p是素数,且2不是p的倍数,所以有:
$ 2^{p-1} \equiv 1 \pmod{p} $ - 利用同余定理的幂规则:如果
a ≡ b (mod m),那么a^k ≡ b^k (mod m)。因为(p-1)能整除m,我们可以设m = k * (p-1)(k是某个整数)。那么:
$ 2^m = 2^{k*(p-1)} = (2^{p-1})^k \equiv 1^k \equiv 1 \pmod{p} $
这意味着2^m ≡ 1 (mod p)。换算成等式就是2^m = 1 + t * p,其中t是某个整数。 - 得到关键关系:从
2^m = 1 + t * p可以得到2^m - 1 = t * p。也就是说,2^m - 1是p的整数倍。 - 同理对
q:完全相同的推导也适用于q。因为q-1也能整除m,所以2^m - 1也是q的整数倍。 - 分解模数
n:现在我们知道:2^m - 1是p的倍数。2^m - 1是q的倍数。- 而
n = p * q。
所以,2^m - 1同时是p和q的倍数,即它是p和q的公倍数,因此也必然是它们最小公倍数lcm(p,q)的倍数。由于p和q都是素数,lcm(p, q) = n。
但是,更直接有效的方法是计算最大公约数 (gcd): - 计算
p = gcd(2^m - 1, n)。因为2^m - 1是p的倍数,但不是q的倍数(除非极其巧合),所以gcd(2^m - 1, n)很大概率会等于p。 - 一旦得到
p,就可以轻易计算出q = n / p。
这里用了一个优化算法, gcd(2^num−1,n)和gcd(gmpy2.powmod(2, num, n) - 1, n)等价 (其实我有点担心这个算法,所以这里gmpy2.powmod(2, num, n) - 1之后加一个n保险点)
1 | from Cryptodome.Util.number import isPrime, sieve_base as primes, long_to_bytes |
其实这个n我没想到的是这个居然是可以用分解网站直接分解。。
15.crypto6
1 | var="************************************" |
解密流程base16-32-64即可
NSSCTF{5e110989-dc43-1bd3-00b4-9009206158fe}
16.Is this only base?
SWZxWl=F=DQef0hlEiSUIVh9ESCcMFS9NF2NXFzM


IfqZQC{IbQ_Rp_E4S3_cR0!!!!!}

凯撒23:LitCTF{LeT_Us_H4V3_fU0!!!!!}
17.factordb中级
1 | e = 65537 |
1 | from Cryptodome.Util.number import long_to_bytes as l2b |
18.yafu
1 | from Crypto.Util.number import * |



让ai打个工即可
1 | from Cryptodome.Util.number import long_to_bytes as l2b |
19.Crazy_Rsa_Tech
1 | from Crypto.Util.number import * |
output:

涉及到低指数加密攻击,我单开一个文档讲。
弄懂之后就直接可以用crt代码解出来:
1 | from Cryptodome.Util.number import long_to_bytes as l2b |
nss密码学到此结束🎇
reverse
1.NSSCTF2025入门题目-Maze
还拿了三血无敌
用ida逆向发现了主函数:
点进move_player:

点进target_x:发现了初始位置和目标位置1,1和8,8

找了半天没找到地图,于是抱着试试的心态直接运行软件,之后竟然是可以移动的:

至此已经知道了目标和初始位置,就开始走迷宫:

走出了两条路(画箭头的地方都可以走):
ssdddwwddssddssaaassddds
ssddssaassddddddds
第一个不行,第二是答案(看来是要选短的那个)
2.NSSCTF2025入门题目-Xor
1 | int __fastcall main(int argc, const char argv, const char envp) |
输入值和0x7A异或之后和数组enc_0比较,点进去看:

然后写代码逆回去:
1 | # enc_0 数组的值(十六进制) |
Recovered FLAG: NSCTF{Xor_is_basic_ree}~但是结果不对我等回来看
3.NSSCTF2025入门题目-Base64

base64加密,但是常规加密不对,接着看伪代码中的b64_encode函数:
1 | __int64 __fastcall b64_encode(__int64 a1, unsigned __int64 a2, __int64 a3) |
ai解析发现了一个:B64_TABLE,也就是自定义的base64

NSSCTF{Kind_of_different_Base64}
4.NSSCTF2025入门题目-Rc4
RC4 是一种加密方法,属于 流密码,它的工作原理相对简单。基本流程是这样的:
- 密钥生成:RC4 使用一个密钥(比如一串字符或数字)来生成一个密钥流(一个伪随机的字节序列)。
- 加密过程:加密时,RC4 会把明文和这个密钥流的每个字节进行 异或 操作。简单来说,异或就是两者比较,结果是相同为 0,不同为 1。这个过程每次使用一个新的字节。
- 解密过程:因为加密和解密都用相同的密钥流,只要再次用同样的密钥流和密文进行异或,就能还原出原来的明文。
- 这是一道rc4的题目:
1.主函数:
1 | int __fastcall main(int argc, const char argv, const char envp) |
1 | 2.rc4_init函数:unsigned __int64 __fastcall rc4_init(__int64 a1, __int64 a2, int a3) |
1 | 3.rc4_crypt函数:__int64 __fastcall rc4_crypt(__int64 a1, __int64 a2, int a3) |
4.enc_0的内容
1 | .rdata:0000000140013050 enc_0 db 0E8h, 2Bh, 33h, 25h, 0B2h, 55h, 0E9h, 0Dh, 5Dh, 0AAh |
1. 分析 RC4 加密过程
你提供的代码使用了 RC4 加密算法。RC4 的工作原理是:首先使用一个密钥初始化一个状态数组 S(在 rc4_init 函数中),然后使用该数组生成伪随机的密钥流,与数据进行异或操作以加密或解密数据。
在这段代码中,密钥是 "SakuraiCora",并且数据是通过 rc4_crypt 函数加密或解密的。
2. 主函数解析
在主函数中,程序首先通过 scanf 获取用户输入的 flag,然后进行如下操作:
- 使用
"SakuraiCora"作为密钥初始化 RC4 算法(通过rc4_init)。 - 使用
rc4_crypt对用户输入的 flag 进行 RC4 解密。 - 将解密后的结果与预定义的加密数据
enc_0进行比较。
如果解密后的前 24 个字符与 enc_0 完全匹配,则输出 "You get flag!",否则输出 "Wrong flag!"。
3. **rc4_init** 函数解析
rc4_init 函数用于初始化 RC4 算法的 S-盒(状态数组)。该函数的核心是通过密钥来打乱 256 字节的数组 S,这个数组在加密和解密过程中会被不断修改。具体步骤如下:
- 先将数组
S初始化为0, 1, 2, ..., 255。 - 然后使用密钥
"SakuraiCora"对S数组进行打乱。
4. **rc4_crypt** 函数解析
rc4_crypt 函数用于加密或解密数据。其核心原理是利用 RC4 的伪随机生成算法(PRGA)生成伪随机的密钥流,并将密钥流与数据进行异或操作,得到加密或解密后的结果。
5. 破解步骤
- 密钥
**SakuraiCora**:密钥用于初始化 RC4 算法。将"SakuraiCora"作为输入,调用rc4_init函数来初始化状态数组S。 - 密文
**enc_0**:enc_0是预定义的密文数组,它存储了正确 flag 的加密结果。我们需要将用户输入的 flag 与这个加密结果进行比较。 - 解密过程:通过
rc4_crypt函数,我们可以对加密后的密文(即用户输入的 flag)进行解密。将"SakuraiCora"作为密钥,解密后得到原始的 flag。 - 对比结果:解密后的前 24 个字符需要与
enc_0数组完全匹配。如果匹配,说明解密成功,输出正确的 flag。
1 | # RC4 算法 |
NSSCTF{y0u_solved_Rc4!}
misc
1.这是哪里

百度识图:
其实这个酒店非常有特征这个床和床旁边居然是透明玻璃隔了一个厕所。。。

这个酒店都搜不到了。。。其实我是搜到了解析、这也未尝不是一道misc呢
{厦门市思明区鼓浪屿康泰路25号17746048875}
2.GIF有点大

导入剪映,逐帧看看,有二维码NSS{The_G1F_ls_T00_b1g}