picoCTF2022_wp

简单来写一下picoCTF2022的一些题解尽量持续更新中…


Crypto

basic-mod1

直接输入数字然后模37即可。。。

#python
c = input().split(' ')
c = [int(i) for i in c]

for i in c:
    tmp = i % 37
    if tmp < 26:
        print(chr(ord('A') + tmp), end='')
    elif tmp < 36:
        print(tmp - 26, end='')
    else:
        print('_', end='')

得到解密内容:R0UND_N_R0UND_CE58A3A0套上picoCTF{}即可

basic-mod2

计算出每个数字模41的逆,然后根据对应关系计算flag

#python
c = input().split(' ')
c = [int(i) for i in c]
m = ''

for i in c:
    tmp = pow(i, -1, 41)
    if tmp <= 26:
        m += chr(ord('A') + tmp - 1)
    elif tmp <= 36:
        m += chr(tmp - 27 + ord('0'))
    else:
        m += '_'

print('picoCTF{' + m + '}')

得到flag:picoCTF{1NV3R53LY_H4RD_B7FB947C}

credstuff

通过usernames.txt和passwords.txt找到所需的密码:cvpbPGS{P7e1S_54I35_71Z3}
credstuff
rot13得到flag:picoCTF{C7r1F_54V35_71M3}

morse-code

下载莫斯电报后用音频软件打开得到波形图:
morse-code
得到电报码:.–/…/…-/–…/…/…-/–…/…/----./-----/-…/.–/…—/-----/…-/----./…/–…/
进而得到flag:picoCTF{WH47_H47H_90D_W20U9H7}

rail-fence

根据提示使用栅栏解密,但是常规的栅栏解密不能得出flag,需要使用W型栅栏解密才能得出明文信息:
The flag is: WH3R3_D035_7H3_F3NC3_8361N_4ND_3ND_D81DB8E3套上picoCTF{}即可

substitution0

下载文件是一个替换题,直接丢到quipqiup - cryptoquip and cryptogram solver中进行解密(也可以用密文中vydzDKL{5GA5717G710B_3R0SG710B_A1N36772}这一信息进行回退)
得到flag:picoCTF{5UB5717U710N_3V0LU710N_B1D36772}

substitution1

和substitution0一样丢到quipqiup - cryptoquip and cryptogram solver中进行解密即可。。。
For this problem, the flag is: picoCTF{FR3QU3NCY_4774CK5_4R3_C001_E5B0CCDB}

substitution2

继续丢到quipqiup - cryptoquip and cryptogram solver中进行解密即可。。。
the flag is picoCTF{N6R4M_4N41Y515_15_73D10U5_6CF50B5C}

transposition-trial

下载文件后先分成三组,然后用第一组先看看信息有什么规律:

#python
m = 'heTfl g as iicpCTo{7F4NRP051N5_16_35P3X51N3_VE1A1D3D}B'
lenm = len(m)//3
m1 = m[:lenm]
m2 = m[lenm:lenm*2]
m3 = m[lenm*2:]
print(m1)

得到m1:heTfl g as iicpCTo 后将其转化为:The flag is picoCT 将对应位进行移动
(真就纯试啊好奇好评率怎么还有72)

// C/C++
#include <stdio.h>

int main()
{
    char m[3][20] = {"heTfl g as iicpCTo", "{7F4NRP051N5_16_35", "P3X51N3_VE1A1D3D}B"};
    char c[3][20] = {{'\0'}};
    for (int i = 0; i < 3; i++)
    {
        c[i][0] = m[i][2];
        c[i][1] = m[i][0];
        c[i][2] = m[i][1];
        c[i][4] = m[i][3];
        c[i][5] = m[i][4];
        c[i][6] = m[i][8];
        c[i][7] = m[i][6];
        c[i][10] = m[i][9];
        c[i][12] = m[i][14];
        c[i][14] = m[i][13];
        c[i][15] = m[i][17];
        c[i][16] = m[i][15];
        c[i][17] = m[i][16];
        //' '
        c[i][3] = m[i][5];
        c[i][8] = m[i][7];
        c[i][11] = m[i][10];
        //'i'
        c[i][9] = m[i][11];
        c[i][13] = m[i][12];
        printf("%s", c[i]);
    }

    return 0;
}

得到明文:The flag is picoCTF{7R4N5P051N6_15_3XP3N51V3_AE131DBD}

Vigenere

学习了一下Vigenere算法的加密原理,相当于是将字母表按123排列后分组计算明文字符加密钥字符再模26。直接找一个在线解密网站解密出flag:
picoCTF{D0NT_US3_V1G3N3R3_C1PH3R_b0fq78b8}

diffie-hellman

先用Diffie-Hellman算法算出密钥 K = g a ∗ b ( m o d    q ) K = g^{a*b} (mod\;q) K=gab(modq) ,然后根据信息将字母表和0~9拼在一起使用凯撒解密即可

#python
p = 13
g = 5
a = 7
b = 3
K = pow(g, a*b, p)

table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
c = "H98A9W_H6UM8W_6A_9_D6C_5ZCI9C8I_DI9D987F"
m = ''
_A = ord('A')
_Z = ord('Z')

for i in c:
    if _A <= ord(i) <= _Z:
        tmp = (ord(i) - _A - K) % 36
        m += table[tmp]
    elif i == '_':
        m += '_'
    else:
        tmp = (ord(i) - ord('0') + 26 - K) % 36
        m += table[tmp]

print('picoCTF{' + m + '}')

得到flag:picoCTF{C4354R_C1PH3R_15_4_817_0U7D473D_8D48432A}

Very Smooth

根据信息搜索到是一个光滑数的RSA加密,可以使用模数相关攻击 - CTF Wiki (ctf-wiki.org)中的 p − 1 p-1 p1 q − 1 q-1 q1 是光滑数使用Pollard’s p-1算法算出p。然后再常规rsa即可

#python
import gmpy2
from Crypto.Util.number import *

def Pollards_p_1(N):
    a = 2
    n = 2
    while True:
        a = pow(a, n, N)
        p = gmpy2.gcd(a-1, N)
        if p != 1 and p != N:
            #print('np = ', n)
            #print('p = ', p)
            return p
        n += 1

e = 0x10001
n = 0x809fbd8b667d664f01fe1b0387e0b424efe2035e2dec4d249ace30563d0e1a50050020880c2f01bad63b22e21125d780d887cffdb1165268e6be788cd49ad8a9a1d27482f1a8ccbb37adc0deee65d09f312ebaab854782e2411d917181fef63d478b7e25391ac10d0330cafcb5c8d859ee1e403be029ce5dd75f864deabe5a65645b099afb7af4ed84dd75d1e4b966e2a0662ece5409feeacb2a277ddf05b72153ff6f36524f7693cc432269b56bd8ab3d601844aef6a6130eaaec08f92f9816ed0e7781a23a043570364807bef579c1e9175e3fe2b1d8f52356230feea244ce1b88b2342c9e40b25583a1fe558bdfb3a7115a4c71a6f06b706419ce8e21a3e1
c = 0x74ce97c4712bc3827a9f6021089c093a7540a6280330a9ec7c6f446a88093c33a6b9a0a1fdf2cad96e32344970adbf26601d9baf2c4e9892dde435dc994bde4754fddbac47a475b3907a455c6f671484b473b5481080224406b1d48d48da5ba0d9fccdc5732cb64c0f02c32ddc1413f66bd95b8e5a929e5b1f14843bd8f5d4747a4aabcc64217a187db6913facce48f2019b5524633153ee40a4376960b7f669f331da29227fa9a8c09a58a6f3db7453dd89a6093c062ff95502cc7cca5ee497c8ec6265413f5d05d1b720b4eb620875b6f6d2a7958e2391835497a106f4c280cd1ca8b9605bbef5952b54dffc028c160c1495e5cd2957f6f2bbb2e868823b6a

p = Pollards_p_1(n)
q = n // p
assert p*q == n
d = gmpy2.invert(e, (p-1)*(q-1))
m = pow(c, d, n)
print(long_to_bytes(m))

得到flag:picoCTF{91e08d13}

Sequences

查看代码,是个线性递归函数计算。贴两种计算方法的链接:

常规解方程如何求解线性递归关系|Study.com
矩阵算法求解线性递归关系|黑客地球 (hackerearth.com)

回到题目,给出的线性方程是 :
f ( x ) = { 1 ,    x = 0 2 ,    x = 1 3 ,    x = 2 4 ,    x = 3 21 ∗ f ( x − 1 ) + 301 ∗ f ( x − 2 ) − 9549 ∗ f ( x − 3 ) + 55692 ∗ f ( x − 4 ) ,    x ⩾ 4 f(x) = \begin{cases} 1,\,\,x = 0\\ 2,\,\,x=1\\ 3,\,\,x=2\\ 4,\,\,x=3\\ 21*f(x-1) + 301*f(x-2) - 9549*f(x-3) +55692*f(x-4),\,\,x\geqslant4\\ \end{cases} f(x)= 1,x=02,x=13,x=24,x=321f(x1)+301f(x2)9549f(x3)+55692f(x4),x4
要我们计算出 s o l = f ( 2 e 7 ) sol = f(2e7) sol=f(2e7) 然后进入到 decrypt_flag(sol) 函数中,将 s o l   % 1   0 5 sol\,\%1\,0^5 sol%105 进行md5加密后与VERIF_KEY验证成功后,将其sha256与给出的密文的每个字符异或一下就行
不难看出问题主要是求解线性递归函数的值,根据提示应该就是使用上述的矩阵算法求解一下就行(正好学习一下用sage解矩阵问题)

#sage
import hashlib
import sys

ITERS = int(2e7)
VERIF_KEY = "96cc5f3b460732b442814fd33cf8537c"
ENCRYPTED_FLAG = bytes.fromhex(
    "42cbbce1487b443de1acf4834baed794f4bbd0dfe08b5f3b248ef7c32b")

a0 = matrix([1, 2, 3, 4]).transpose()
T = matrix(ZZ, 4, 4)
T[0] = [0, 1, 0, 0]
T[1] = [0, 0, 1, 0]
T[2] = [0, 0, 0, 1]
T[3] = [55692, -9549, 301, 21]

def cnt_Ti(i):
    if i == 1:
        return T
    elif i % 2:
        return T*cnt_Ti(i-1)
    else:
        return cnt_Ti(i//2) ^ 2

def m_func(i):
    tmp = cnt_Ti(i)*a0
    return tmp[0][0]

# Decrypt the flag
def decrypt_flag(sol):
    sol = sol % (10**10000)
    sol = str(sol)
    sol_md5 = hashlib.md5(sol.encode()).hexdigest()

    if sol_md5 != VERIF_KEY:
        print("Incorrect solution")
        sys.exit(1)

    key = hashlib.sha256(sol.encode()).digest()
    flag = bytearray([char ^^ key[i]
                     for i, char in enumerate(ENCRYPTED_FLAG)]).decode()

    print(flag)

if __name__ == "__main__":
    sol = m_func(ITERS)
    decrypt_flag(sol)

有两点要稍微注意一下,首先是我跑sage的时候不知道为什么装饰器调用不了所以也没用(不过此题好像也用不到就是了),其次是sage中的异或是^^,需要在decrypt_flag函数中稍微修改一下就行
得到flag:picoCTF{b1g_numb3rs_4ebc92cc}

Sum-O-Primes

查看gen.py,发现对于两个1024bit的素数p和q,给出了 x = p + q x=p+q x=p+q n = p ∗ q n=p*q n=pq
直接算出 k m = ( p − 1 ) ∗ ( q − 1 ) = n − x + 1 km=(p-1)*(q-1) = n - x + 1 km=(p1)(q1)=nx+1 其中k是一未知常数。用km也可以计算出适用与私钥的d值,因为对于 e ∗ d ′ = n 1 ∗ k ∗ m + 1 e*d' = n_1 *k *m+1 ed=n1km+1 来说必可以找到一个 n 2 n_2 n2 使得 e ∗ d ′ = n 2 ∗ m + 1 e*d '=n_2 * m +1 ed=n2m+1 成立。
因此可以计算出私钥,进一步计算出明文

# python
from Crypto.Util.number import long_to_bytes
import gmpy2

x = 0x1603fc8d929cb31edf62bcce2d06794f3efd095accb163e6f2b78941bd8c646d746369636a582aaac77c16a9486881a9e3db26d742e48c4adcc417ef98f310a0c5433ab077dd872530c3c3c77fe0c080d84154bfdb4c920df9617e986999104d9284516c7babc80dc53718d59032aefdf41b9be53957dea3f00a386b2666d446e
n = 0x75302ba292dc4bf47ffd690b8edc70ef1fcca5e148b2b9c1b60227788afcfe77a0097929ed3789fe51ac66f678c558244890a09ae4af3e7d098fd366a1c859edabbff1c9e164d5354968798107ae8518fcaab3743de58a141ffd26c1e16cb09fed1f6b0d68536ec7fba744ed120fea8c3a7ac1ebfa55d664d2f321fb44e814650147a9031f3bfa8f69d87393c7d88976d28d147398a355020bcb8e5613f0b29028b77db710e163ca1019fd3c3a065465ea457adec45243c385d12d3a1de3178f6ca05964be92e8b5bc24d420956de96ccc9ce39e70705660eb6b2f4e675aac7d6d7ba45c84223fc5819b37aa85beff1382f1c2c3b97603150f30c17f7e674441
c = 0x562888c70ce9a5c5ed9a0be1b6196f854ba2efcdb6dd0f79319ee9e1142659f90a6bae67481eb0f635f445d3c9889da84639beb84ff7159dcf4d3a389873dc90163270d80dbb9503cbc32992cb592069ba5b3eb2bbe410a3121d658f18e100f7bd878a25c27ab8c6c15b690fce1ca43288163c544bfce344bcd089a5f4733acc7dc4b6160718e3c627e81a58f650281413bb5bf7bad5c15b00c5a2ef7dbe7a44cce85ed5b1becd5273a26453cb84d327aa04ad8783f46d22d61b96c501515913ca88937475603437067ce9dc10d68efc3da282cd64acaf8f1368c1c09800cb51f70f784bd0f94e067af541ae8d20ab7bfc5569e1213ccdf69d8a81c4746e90c1
e = 65537

km = n - x + 1
d = gmpy2.invert(e, km)
FLAG = pow(c, d, n)
print(long_to_bytes(FLAG))

得到flag:picoCTF{674b189f}

NSA Backdoor

打开gen.py,先是使用了和题目Very Smooth相同的生成光滑数算法生成了p和q,然后以 c = 3 F L A G   ( m o d   ( p ∗ q ) ) c=3^{FLAG}\,(mod\,(p*q)) c=3FLAG(mod(pq)) 的形式得到密文c
转化为求解离散对数问题,根据提示使用Pohlig-Hellman algorithm这个算法求解即可(详细一点的可以看这一篇离散对数问题——pohlig-hellman算法讲解_DrGilbert的博客)
需要注意的是,先将n分解为p和q之后,首先断言flag转换成的bit较小,即 c = 3 F L A G c = 3^{FLAG} c=3FLAG 成立,那么如果能够算出 c = 3 x   ( m o d   p ) c = 3^x \,(mod\,p) c=3x(modp) 或者 c = 3 x   ( m o d   q ) c = 3^x \,(mod\,q) c=3x(modq) 有一个成立的x值的话,这个x值就是flag

# python
# 先求解p,q
import gmpy2

def Pollards_p_1(N):
    a = 2
    n = 2
    while True:
        a = pow(a, n, N)
        ok = gmpy2.gcd(a-1, N)
        if ok != 1 and ok != N:
            # print('np = ', n)
            # print('p = ', ok)
            return ok
        n += 1

n = 0x71c27455f38b75f08868b5965d7afba3d81bff38f3b63271ad9250b9d7dc8c909d3555593c2eff9c27a3c259f8e95da41d55544a362494476141c8ccb93fc7d9019d965a20e16d55daf57b5663ede8d5ad97b7be239ecacb2636621ef997854f18f6da1394101dfb8229a2253dbc3ffc995cc6197bd85455f6178c14dbb9a611b3b42530fcdc5c36c5f63fd3796efdfc440a76cf966ff8c56e7e55872a57aa3a335c2b10a82421bcd1cd0d238496f2830d6524f6ba8e9890e30c4e6ad11df8948f4b428d8089a5d9455baca34cee61cb238042bcf8293aab13595aeb90fedabf23b1d0e82c6882824aa0f78c2208de641d9592a170ed839728f6c7e6b6bdf831
c = 0x2560971fdf742d398ae3e677082ab950e99edde5577abcc4d704d65577ec287169d209f2033c82e7574f7e6c27540bb07416cd12b5fca1bb5c7ae23e80bb00b81a5c49116fa3cca6ab72f4a56b2bf0d51c58eedb918faa1e88d6fddb7dd358c1cdaa6e61964284014919662f75adaad5065a3633067b2297cd4657d39c8e2cdb02fd80ba33447abb8bfcd4dd68166f487094108afe5b4378f5f6eb9209f503b718dec9c841089551db648f5b5a84357b2319eb1b27935c3bc47c645f732d36cfffcb0e7f1c8ec5859413e6d62f7ed9af27f4712ca91bbdb9526ea19414c82090a52a78e6bbc2a756b5756017ee08326cd7b1d5dd9fff6afb12bcb93fb541a542
# c = pow(3, FLAG, n)

p = Pollards_p_1(n)
q = n // p
assert p*q == n
print(p)
print(q)

先记录一下由密码学笔记:离散对数求解相关算法实现 - 代码天地 (codetd.com)用python实现的Pohlig-Hellman算法,但是跑了一个小时没解出来。。。用sage秒了

#sage
from Crypto.Util.number import long_to_bytes

R = GF(107878320716069936845347261730222923402619282584236808136469656719645067255143372538361375857163594280233925663413568686520703251291382637679919197208920902793419007945364505474185442005931731898039583502138819092649272834779913753377381462765827012568092442233669634217190652686190269458879367972776287369087)
c = R(4718447750724026960198694353334844739217505692188089979205287902511725532311569199632417744122258940413006438515024778380545236447199956486141746728921282928492469653129506822466650013787028619239094093189336116702354002575036042441159707662906078282774445269111406924195008479670069966761807780816630970097935613962494172989787492148192467844779659251027338850586442721256070023515234734429552425201570424044244493798745985930424493915946539530113932455027066048161948792422458683395300567227203873395399720109905411980171312819916204231817116409767525860309628443293880324309777205417461936368372497941988812891458)
e = R(3)

flag = discrete_log(c,e)
print(long_to_bytes(flag))

得到flag:picoCTF{fd0d45f6}
PS:这题还是学到了蛮多的,CRT、exgcd、一些离散对数算法以及sage的应用等等,值得研究


Misc

主要在做crypto,做三个简单的隐写的misc。。。

Enhance!

下载一个.svg图片,之前没接触过,大概搜了一下是一个用XML格式定义图像的东西。不大了解语法,不过直接用010editor打开看信息就行:
在这里插入图片描述得到flag:picoCTF{3nh4nc3d_56e87c96}

Lookey here

打开下载的txt文本,显然查找picoCTF即可:
在这里插入图片描述
得到flag:picoCTF{gr3p_15_@w3s0m3_0abe82b2}

St3g0

根据提示使用stegsolve看看lsb隐写,发现flag位于文件开始处。
flag:picoCTF{7h3r3_15_n0_5p00n_f2f7a0e5}


Web

(等待后期慢慢填坑ing…)

Includes

直接打开源代码,在style.css和script.js中找到注释掉的flag:
picoCTF{1nclu51v17y_1of2_f7w_2of2_5a94a145}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值