CTF中Crypto题目分析(2)

572 阅读4分钟

我正在参与掘金创作者训练营第6期,点击了解活动详情

[AFCTF2018]Vigenère

下载附件,发现一些随机排列的字符串以及一段代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int main()
{
	freopen("flag.txt","r",stdin);
	freopen("flag_encode.txt","w",stdout);
	char key[] = /*SADLY SAYING! Key is eaten by Monster!*/;
	int len = strlen(key);
	char ch;
	int index = 0;
	while((ch = getchar()) != EOF){
		if(ch>='a'&&ch<='z'){
			putchar((ch-'a'+key[index%len]-'a')%26+'a');
			++index;
		}else if(ch>='A'&&ch<='Z'){
			putchar((ch-'A'+key[index%len]-'a')%26+'A');
			++index;
		}else{
			putchar(ch);
		}
	}
	return 0;
}

根据题目判断是维吉尼亚密码:

维吉尼亚密码(又译维热纳尔密码)是使用一系列凯撒密码组成密码字母表的加密算法,属于多表密码的一种简单形式。

我们找到一个在线解码网站

www.guballa.de/vigenere-so…

就能解出来flag:

flag{Whooooooo_U_Gotcha!}

所以没有GET到给了代码有啥用。

[ACTF新生赛2020]crypto-classic0

下载附件:

cipher文件 :

Ygvdmq[lYate[elghqvakl}

hint.txt :

哼,压缩包的密码?这是小Z童鞋的生日吧==

怀疑需要我们爆破压缩包。就根据生日进行八位数字爆破。

19990306

得到代码:

#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; 
}

根据这个我们可以推断出python代码:

cipher='Ygvdmq[lYate[elghqvakl}'
for i in range(0,24):
    flag=ord(cipher[i]) ^ 0x7
    flag += 3
    print ( chr(flag),end='' )

得到flag:

flag{my_naive_encrytion}

[WUSTCTF2020]B@se

密文:MyLkTaP3FaA7KOWjTmKkVjWjVzKjdeNvTnAjoH9iZOIvTeHbvD==

JASGBWcQPRXEFLbCDIlmnHUVKTYZdMovwipatNOefghq56rs****kxyz012789+/

oh holy shit, something is missing...

下载了附件,内容如上图,根据题目判断是base编码。但是解不出来,根据第二行的内容少了4个字符,怀疑需要我们爆破这四个数。然后再根据四位数的顺序进行爆破,通过base64换表操作来解出密文。

现看看缺了那个四位数:

import string
s = "JASGBWcQPRXEFLbCDIlmnHUVKTYZdMovwipatNOefghq56rs****kxyz012789+/"
for i in string.ascii_letters + string.digits:
    if(i not in s):
        print i
#ju34

然后爆破所有可能就可以了:

from Crypto.Util.number import *
from gmpy2 import *
from functools import reduce
import sympy
import itertools
#JASGBWcQPRXEFLbCDIlmnHUVKTYZdMovwipatNOefghq56rs****kxyz012789+/
# coding:utf-8
def My_base64_encode(inputs,s):
	bin_str = []
	for i in inputs:
		x = str(bin(ord(i))).replace('0b', '')
		bin_str.append('{:0>8}'.format(x))
	#print(bin_str)
	outputs = ""
	nums = 0
	while bin_str:
		temp_list = bin_str[:3]
		if(len(temp_list) != 3):
			nums = 3 - len(temp_list)
			while len(temp_list) < 3:
				temp_list += ['0' * 8]
		temp_str = "".join(temp_list)
		#print(temp_str)
		temp_str_list = []
		for i in range(0,4):
			temp_str_list.append(int(temp_str[i*6:(i+1)*6],2))
		#print(temp_str_list)
		if nums:
			temp_str_list = temp_str_list[0:4 - nums]
			
		for i in temp_str_list:
			outputs += s[i]
		bin_str = bin_str[3:]
	outputs += nums * '='
	print("Encrypted String:\n%s "%outputs)
	
def My_base64_decode(inputs,s):
	bin_str = []
	for i in inputs:
		if i != '=':
			x = str(bin(s.index(i))).replace('0b', '')
			bin_str.append('{:0>6}'.format(x))
	#print(bin_str)
	outputs = ""
	nums = inputs.count('=')
	while bin_str:
		temp_list = bin_str[:4]
		temp_str = "".join(temp_list)
		#print(temp_str)
		if(len(temp_str) % 8 != 0):
			temp_str = temp_str[0:-1 * nums * 2]
		for i in range(0,int(len(temp_str) / 8)):
			outputs += chr(int(temp_str[i*8:(i+1)*8],2))
		bin_str = bin_str[4:]	
	print("Decrypted String:\n%s "%outputs)
#s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
h=['j','u','3','4']
h1=list(itertools.permutations(h,4))
for i in h1:
	m="".join(i)
	s = "JASGBWcQPRXEFLbCDIlmnHUVKTYZdMovwipatNOefghq56rs"+m+"kxyz012789+/"
	input_str="MyLkTaP3FaA7KOWjTmKkVjWjVzKjdeNvTnAjoH9iZOIvTeHbvD=="
#My_base64_encode(input_str)
	My_base64_decode(input_str,s)
#flag{base64_1s_v3ry_e@sy_and_fuN} 

[网鼎杯 2020 青龙组]you_raise_me_up

先看附件给的代码:

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

告诉了我们c是由m,n,flag组成的式子求出来了,现在反过来让我们求flag。

本题涉及了离散对数的知识点:

离散对数(英语:Discrete logarithm)是一种基于同余运算和原根的一种对数运算。而在实数中对数的定义 logba是指对于给定的a和b,有一个数x,使得bx=a。相同地在任何群G中可为所有整数k定义一个幂数为bK,而离散对数logba是指使得bK=a的整数k

根据推导得到离散对数:bytes_to_long(flag) = log(m mod n) (c mod n)

得到我们需要的公式:bytes_to_long(flag) = discrete_log(c, (m mod n))

找了个脚本去解码:

m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075
c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499
n = 2 ** 512
import sympy
flag=sympy.discrete_log(2**512,c,m)
import binascii
print(binascii.unhexlify(hex(flag)[2:]))
flag{5f95ca93-1594-762d-ed0b-a9139692cb4a}