ctf-crypto刷题第一期

        换新工作以后,攻防技术接触越来越少,但是ctf接触越来越多,这里通过平常做题的积累来快速提升ctf的能力。首先从crypto开始:

ctfshow密码学签到

有密文,有提示,倒过来就是flag

写个python脚本,倒过来字符:}wohs.ftc{galf

original_string = "}wohs.ftc{galf"
# 使用字符串切片将字符串倒过来
reversed_string = original_string[::-1]
print(reversed_string)

最终结果:flag{ctf.show}

ctf show crypto2(jsfuck)

下载文件并解压,大概就是[](!+这些字符组合的。联想到JSFuck是一种深奥JavaScript 编程风格。以这种风格写成的代码中仅使用 [、]、(、)、! 和 + 六种字符

在线解密:console.log("flag{3e858ccd79287cfe8509f15a71b4c45d}"

ctf show crypto3(颜文字解密)

解压文件后像是颜文字表情,颜文字解密


注意文件用python打开,并用latin-1显示,随后解密即可获取flag

ctf show easy_base(在线base解密)

复制密文,题目告诉你是base加密了,base解密网址:CTF在线工具-在线base编码|在线base解码|base16编码|base32编码|base64编码

4C455A5645334C44474A55484D5A42544F5132574956525A50464E464F4E4C474D4656454D334359474A554751564B4949493255535532464E42544643504A35

在线base解密,第一次base16解密成功

第二次base32解密成功

第三次base64解密成功:ctfshow{yu_ren_j1e_haPpy!!!}

ctf show 大牛的密码(脚本解密)

解压后是一个python脚本

from Crypto.Util.Padding import unpad

def swap(arr, a, b):
    arr[a], arr[b] = arr[b], arr[a]

def decrypt2(c, S_BOX):
    inv_S_BOX = [0] * len(S_BOX)
    for i, s in enumerate(S_BOX):
        inv_S_BOX[s] = i
    for _ in range(16):
        c = [c[i] for i in inv_S_BOX]
    return c

def decrypt1(m):
    enc = [m[i:i+BLOCK] for i in range(0, len(m), BLOCK)]
    for i in enc:
        for j in range(BLOCK-1, -1, -1):
            aa = j * 7 % BLOCK
            swap(i, j, aa)
    return [item for sublist in enc for item in sublist]

# 加密后的数据
S_BOX = [9, 31, 32, 38, 20, 1, 22, 4, 8, 2, 11, 21, 7, 18, 46, 23, 34, 3, 19, 12, 45, 30, 27, 37, 5, 47, 28, 36, 0, 43, 39, 10, 29, 14, 40, 24, 33, 16, 17, 6, 42, 15, 26, 41, 44, 25, 35, 13]
c = [99, 111, 102, 11, 107, 49, 11, 53, 121, 48, 114, 117, 11, 95, 112, 95, 109, 115, 11, 95, 101, 95, 119, 117, 79, 123, 111, 48, 110, 95, 121, 116, 121, 125, 116, 11, 119, 11, 97, 67, 11, 11, 11, 11, 11, 99, 110, 104]

# 解密过程
decrypted2 = decrypt2(c, S_BOX)
decrypted1 = decrypt1(decrypted2)

# 去除填充
flag = unpad(bytes(decrypted1), BLOCK)
print(flag)

重点分析decrypt2和decrypt1这两个函数,先分析decrypt2

def decrypt2(c, S_BOX):
    inv_S_BOX = [0] * len(S_BOX)
    for i, s in enumerate(S_BOX):
        inv_S_BOX[s] = i
    for _ in range(16):
        c = [c[i] for i in inv_S_BOX]
    return c
  1. 创建逆S_BOX:inv_S_BOX = [0] * len(S_BOX)。
  • 这行代码创建了一个与S_BOX长度相同的列表inv_S_BOX,并用0填充。这个列表将用来存储S_BOX的逆映射。
  • 例如,如果S_BOX的长度是48,那么inv_S_BOX的初始状态是:

inv_S_BOX = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

        2.填充逆S_BOX

for i, s in enumerate(S_BOX):
        inv_S_BOX[s] = i
  • 这里的enumerate(S_BOX)会生成S_BOX中每个元素的索引和值,i为索引,s为值(逆向的)。例如:
    S_BOX = [9, 31, 32, 38, 20, 1, 22, 4, 8, 2, 11, 21, 7, 18, 46, 23, 34, 3, 19, 12, 45, 30, 27, 37, 5, 47, 28, 36, 0, 43, 39, 10, 29, 14, 40, 24, 33, 16, 17, 6, 42, 15, 26, 41, 44, 25, 35, 13]
  • 第一次循环时,i = 0, s = 9。
  • 第二次循环时,i = 1, s = 31。
  • 第二次循环时,i = 2, s = 32。
  • 以此类推。。。
  • inv_S_BOX[s] = i 将 s 的值作为索引,i 的值作为内容填充到inv_S_BOX。最终inv_S_BOX是S_BOX的逆映射。

          3.填充逆S_BOX

for _ in range(16):
        c = [c[i] for i in inv_S_BOX]
  • c[i] for i in inv_S_BOX 表示用inv_S_BOX中的索引顺序重排c。
  • 例如,如果c = [a, b, c],且inv_S_BOX = [2, 0, 1],那么这行代码将c变成:

c = [c[2], c[0], c[1]] = [c, a, b]

  • 这个过程重复16次,使c恢复到原始状态。

再来分析decrypt1函数(函数其实运行完根本就没换)

def decrypt1(m):
    enc = [m[i:i+BLOCK] for i in range(0, len(m), BLOCK)]
    for i in enc:
        for j in range(BLOCK-1, -1, -1):
            aa = j * 7 % BLOCK
            swap(i, j, aa)
    return [item for sublist in enc for item in sublist]
  1. enc = [m[i:i+BLOCK] for i in range(0, len(m), BLOCK)]
  • 这行代码将数据m按照BLOCK大小分成多个小块。例如,如果m是[1, 2, 3, 4, 5, 6, 7, 8]且BLOCK是4,enc就会变成:enc = [[1, 2, 3, 4], [5, 6, 7, 8]]

     2.字节交换

for i in enc:
        for j in range(BLOCK-1, -1, -1):
            aa = j * 7 % BLOCK
            swap(i, j, aa)
  • 这部分代码对每个数据块进行字节交换操作。对于每个块,j从块的末尾(BLOCK-1)遍历到开头(0)。
  • aa = j * 7 % BLOCK计算了aa的位置。
  • swap(i, j, aa)交换块i中位置j和位置aa的元素。

例如,假设一个块是[1, 2, 3, 4],BLOCK是4:

    • j=3时,aa = 3 * 7 % 4 = 1,所以交换位置3和位置1,块变成[1, 4, 3, 2]。
    • j=2时,aa = 2 * 7 % 4 = 2,所以位置2和位置2交换(没有变化),块仍是[1, 4, 3, 2]。
    • j=1时,aa = 1 * 7 % 4 = 3,所以交换位置1和位置3,块变成[1, 2, 3, 4]。
    • j=0时,aa = 0 * 7 % 4 = 0,所以位置0和位置0交换(没有变化),块仍是[1, 2, 3, 4]。
  • 最终的块会变回原来的顺序。

   3.重组数据: return [item for sublist in enc for item in sublist]

  • 最后一步是将所有块重新组合成一个列表。这个列表就是解密后的数据。

逆向脚本

#对decrypt2进行逆向即可,decrypt2(S_BOX, c)
# 加密后的数据
c = [99, 111, 102, 11, 107, 49, 11, 53, 121, 48, 114, 117, 11, 95, 112, 95, 109, 115, 11, 95, 101, 95, 119, 117, 79, 123, 111, 48, 110, 95, 121, 116, 121, 125, 116, 11, 119, 11, 97, 67, 11, 11, 11, 11, 11, 99, 110, 104]
S_BOX = [9, 31, 32, 38, 20, 1, 22, 4, 8, 2, 11, 21, 7, 18, 46, 23, 34, 3, 19, 12, 45, 30, 27, 37, 5, 47, 28, 36, 0, 43, 39, 10, 29, 14, 40, 24, 33, 16, 17, 6, 42, 15, 26, 41, 44, 25, 35, 13]

# for i in c:
#     print("值"+str(S_BOX[i])+"位置:"+str(i))
# print("-"*50)

inv_c = [0] * len(c)
for j in range(16):
    for i in range(len(S_BOX)):
        inv_c[S_BOX[i]] = c[i]
    c = inv_c
    inv_c = [0] * len(c)
print(bytes(c))

ctf show crypto4(rsa)

打开题目是这个:p=447685307 q=2037 e=17

一看就像是描述RSA加密算法。

了解一下RSA加密的过程:

  1. 选择两个大质数:p 和 q。
  2. 计算它们的乘积:n = p * q。
  3. 计算 Euler 函数:φ(n) = (p - 1) * (q - 1)。
  4. 选择公钥指数:e,满足 1 < e < φ(n),且 e 与 φ(n) 互质。(互质概念:例如 8 与 10 的最大公约数是 2,不是 1,因此它们并不互质;又例如 7, 10, 13 的最大公约数是 1,因此它们互质。)
  5. 计算私钥指数:d,满足 d ≡ e^(-1) (mod φ(n)),即 d 是 e 在 φ(n) 模下的乘法逆元。

解密d过程:

import libnum
p=447685307 
q=2037 
e=17

n=p*q
# 计算 φ(n)
φ=(p-1)*(q-1)
# 计算 e 在模 φ(n) 下的逆元
d = libnum.invmod(e,φ)
print(d)

ctf show 萌新赛签到题

打开题目:Ao(mgHX^E)AN2PSBOu3qI0o,一看就是一个加密的

base64,base16,base32都不行,那就挨个base尝试

最终base85解密成功


ctf show BJDCTF2020 这是base??(自定义base解码表)

直接查看base.txt,是一串乱码,链接导入txt文件看

它给了一个码表,给了一个密文,转换一下格式:

联想题目提示了base,是不是想表达正常将密文的解密用的表替换为题目给的码表

import base64
dict = 'JKLMNOxyUVzABCDEFGH789PQIabcdefghijklmWXYZ0123456RSTnopqrstuvw+/='

nomal = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值