[actf-新生赛2020]crypto-classic0
题目信息
拿到手有两个压缩包 有一个压缩包是加密的 但是经过提示可以想到这是可以通过暴力破解得到压缩包内容的(虽然开始我没想到) 用ARPR直接破解 开始19000000截止现在的时间就可以
爆破出的压缩包内容是
#include<stdio.h>
char flag[25] = ***
int main()
{
int i;
for(i=0;i<25;i++)
{
flag[i] -= 3;
flag[i] ^= 0x7;
printf("%c",flag[i]);
}
return 0;
}
解释一下这段代码的意思:把明文的每个字符取出来过后 让其ascii码值减去3 然后再和0x7取异或(这一点很关键 对于一些不太熟悉python的人 比如我 最开始以为是把每个字符取七次方 然后呆呆地去写脚本 发现根本解不出来)最后得到密文
那么对应的解密思路也很清晰了 倒着来就可以了 把每个字符与0x7取异或再加上3就可以复原了
解密脚本(python)
cipher = "Ygvdmq[lYate[elghqvakl}"
flag=""
for i in cipher:
i = ord(i)
i ^=0x7
i+=3
flag+=chr(i)
print(flag)
这道题其实能够想得到用暴力破解的话 就已经成功60%了
[WUSTCTF2020]B@se1
题目信息
根据经验可以知道上面一行是base64加密的 但是直接去解密根本解不出来 这是经过base64扩展加密得到的 而且根据提示可以知道“少了点东西” 仔细看第二行发现是少了四个字符 而且上面一行应该是由下面一行经过base64加密得到的
那么可以遍历得到那四个未曾出现的字符
import string
c = 'JASGBWcQPRXEFLbCDIlmnHUVKTYZdMovwipatNOefghq56rs****kxyz012789+/'
for i in string.ascii_letters + string.digits: # string.ascii_letters所有字母 string.digits所有数字
if(i not in c):
print(i,end='')
# ju34
可以确定是 j u 3 4 四个字符
那么具体的思路就是考虑这4!种排列组合 那就有4!种字符串 我们同样可以采用暴力破解 遍历每一种可能
解密脚本
import binascii
import itertools
cipher = 'MyLkTaP3FaA7KOWjTmKkVjWjVzKjdeNvTnAjoH9iZOIvTeHbvD' # 全排列组合
s = ['j','u','3','4']
for i in itertools.permutations(s,4): # 4就是把s列表里的字母4个为一组排列
k = "JASGBWcQPRXEFLbCDIlmnHUVKTYZdMovwipatNOefghq56rs"+ "".join(i) + "kxyz012789+/" # "".join(i)排列的结果(join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串)
a = ""
for j in cipher:
a += bin(k.index(j))[2:].zfill(6)
print(binascii.a2b_hex(hex(eval("0b"+a))[2:-1])) # a2b_hex和binascii.unhexlify可以为16进制的 bytes 类型,也可以为十六进制 str 类型
# 举例:这里转为16进制后会出现0x471L,所以只有去掉0x和L就有了[2:-1]
对这个脚本进行解释:首先permutations()函数就是一个求排列组合的函数,当传入这四个字符的数组的时候会生成4!种排列组合,而"".join(i)是将每一种可能取出来,然后通过字符串拼接得到了一种可能得字符串。其次,通过遍历全排列组合中的每一个字符,k.index(j)找到字符j在字符串k中的索引。 bin(k.index(j))[2:] 将索引转为二进制字符串,切片去掉开头的0b。zfill(6) 将二进制字符串填充到6位。所以这一个循环的作用就是把每一个在cipher(全排列组合,也就是本来要解密的base64扩展编码)中的字符转换成为六位二进制,最后把这个二进制序列a转换成bytes输出
这道题做下来感觉好难 不看WP对我而言根本做不出来 能走的最远就是把每种可能得字符串输出 但是我并不知道为什么要用cipher的每个字符在k中的索引生成六位二进制,有知道的师傅可以说说嘛
[网鼎杯 2020 青龙组]you_raise_me_up
题目信息
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from Crypto.Util.number import *
import random
n = 2 ** 512
m = random.randint(2, n-1) | 1
c = pow(m, bytes_to_long(flag), n)
print 'm = ' + str(m)
print 'c = ' + str(c)
# m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075
# c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499
首先说说在做这道题之前走过的一些弯路 求解e即可 因为e和d天生互素 并且有了d可以通过变形m^e%n=c得到e 但是这样暴力破解时间复杂度太大了 无法求解
这道题是关于离散对数的一道题
关于离散对数
离散对数(Discrete logarithm)是一类重要的数论问题。对于一个素数p,整数g和y,满足关系:g^x ≡ y (mod p) 这里的x称为y关于g在模p意义下的离散对数,记为:x = log_g(y) (mod p)离散对数问题就是给定g、y和p,求x的的值。这是一个在多种公钥密码系统(如DH、ElGamal等)中非常关键的难题。
根据m^e%n=c可知 ,现在已知m,c,n而e未知满足求解离散对数的条件
解密脚本
import sympy
m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075
c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499
n = 2 ** 512
e = sympy.discrete_log(n,c,m)
print(hex(e))
求解出来是十六进制 找个在线网站16进制转换,16进制转换文本字符串,在线16进制转换 | 在线工具转字符串就可以了
这道题长知识了,其实如果知道这是离散对数的话就很好做了