“古剑山”第一届全国大学生网络攻防大赛-Crypto WP

发布时间 2023-12-08 19:19:02作者: 清纯少女小琪

Crypto

babyRSA

题目信息

p=105570604806073931560404187362816308950408774915960751676958845800335871518600455146040240314204606944641098914858159386588868785987100524581699043605351952348586132553458702298393907476955946990849442034441882748278181148503329309660427627438266645843535466462936882505833453738522673603026747578372964995367
q=143288358949089585215266953016278524463612148007190135453434243047032456958207376091733443584531919755660149037321119885867830905350806865862130270602628423547624190876473872180462192096873381471710899246073298439365336797201672838785511965949336068032011363484044690916570288372443303750426476423930352603827
e=33
c=2015688184356018702340063509729974600786840546364122789630929715337660295810961474144939260049892177486759513271253257458112942844435453563521353664294799145214833075575682837104619902593712323020851788866158742546117774717790910939444986189326649593286629046732910564929050955013637088916579175350308099506220813882274665233182543235264034038626524248300357250276274833999274982434790398489181021739913941634249265775997527901903799819193254397528348894700572493228638350806878366316533768758273322476421225382269304595973225131694907875536065669987510951854843686992445396860396865892650745594418900376500862332616

我的解答:

信息都给了,签到题。直接梭

exp:

import gmpy2
from Crypto.Util.number import long_to_bytes
p=105570604806073931560404187362816308950408774915960751676958845800335871518600455146040240314204606944641098914858159386588868785987100524581699043605351952348586132553458702298393907476955946990849442034441882748278181148503329309660427627438266645843535466462936882505833453738522673603026747578372964995367
q=143288358949089585215266953016278524463612148007190135453434243047032456958207376091733443584531919755660149037321119885867830905350806865862130270602628423547624190876473872180462192096873381471710899246073298439365336797201672838785511965949336068032011363484044690916570288372443303750426476423930352603827
e=33
c=2015688184356018702340063509729974600786840546364122789630929715337660295810961474144939260049892177486759513271253257458112942844435453563521353664294799145214833075575682837104619902593712323020851788866158742546117774717790910939444986189326649593286629046732910564929050955013637088916579175350308099506220813882274665233182543235264034038626524248300357250276274833999274982434790398489181021739913941634249265775997527901903799819193254397528348894700572493228638350806878366316533768758273322476421225382269304595973225131694907875536065669987510951854843686992445396860396865892650745594418900376500862332616
n = p*q
phi = (p-1) * (q-1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)

print(long_to_bytes(m))
#flag{39f7ba00d4050d5c51ba6fc1172ac0ed}

Vigenere+++

题目

import sys
from secret_file  import *
def _l(idx, s):
    return s[idx:] + s[:idx]
def main(p, k1, k2):
    s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}"
    t = [[_l((i+j) % len(s), s) for j in range(len(s))] for i in range(len(s))]
    i1 = 0
    i2 = 0
    c = ""
    for a in p:
        c += t[s.find(a)][s.find(k1[i1])][s.find(k2[i2])]
        i1 = (i1 + 1) % len(k1)
        i2 = (i2 + 1) % len(k2)
    return c

flag="flag{************************}"
key="**********"

# * 为马赛克,长度为1。 
# hint:  可以自己尝试下运行加密函数,看看秘钥对加密结果的影响。 
# hint:  首先根据线索求秘钥,秘钥不唯一,找到一个有效的,就能爆破flag了。 
print main(flag, key, key[::-1])

# 程序运行结果(即密文为):
kqTyKgfxgXT5a_RiTAua4_sbMkjDyE

我的解答:

1、我们考虑到在程序正常运行下,数组访问不会越界,我们在讨论时做以下约定:

2、关于 python 程序中定义的 _l 函数,发现以下等价关系:

3、关于 python 的 main 函数中三维矩阵 t 的定义,发现以下等价关系:

4、综合第 2 第 3 点的观察,有如下等价关系:

由于我们知道标志的 5 个字符,即flag{,还知道密钥长度为 10。那么脚本如下:

enc_str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}'
dec_dic = {k:v for v,k in enumerate(enc_str)}
encrypt = 'kqTyKgfxgXT5a_RiTAua4_sbMkjDyE'
flag_bg = 'flag{************************}'

sim_key = [dec_dic[encrypt[i]]-dec_dic[flag_bg[i]] for i in range(5)] # 破解模拟密钥
sim_key = sim_key + sim_key[::-1]

flag_ed = [dec_dic[v]-sim_key[k%10] for k,v in enumerate(encrypt)] # 模拟密钥解密
flag_ed = ''.join([enc_str[i%len(enc_str)] for i in flag_ed]) # 解码
print(flag_ed) 
#flag{4XLbSO0riF6BRp5ZvGTA81Ut}

guess_the_key

题目

主函数

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

int main(int argc, char **argv) {
	if (argc != 3) {
		printf("USAGE: %s INPUT OUTPUT\n", argv[0]);
		return 0;
	}
	FILE* input  = fopen(argv[1], "rb");
	FILE* output = fopen(argv[2], "wb");
	if (!input || !output) {
		printf("Error\n");
		return 0;
	}
	char key[] = "guessthekey";
	char d, q, t = 0;
	int ijk = 0;
	while ((q = fgetc(input)) != EOF) {
		d = (q + (key[ijk % strlen( key )] ^ t) + ijk*ijk) & 0xff;
		t = q;
        ijk++;
		fputc(d, output);
	}
	return 0;
}

msg01

Hi,there is nothing here,heiheihei.

msg01.enc

灄K覛嫮	蕲i#Nvp桪"亶"#p?hr谅K

msg02.enc

僂顕沶迷檎a6乸栐座渖層贽瑊农剹烁▕昑m豪{?h?ㄍ*RI戠Jqk?幓茼|\tk?罽辑蔓陔&盿磬]蛉?艝X峊糋?槔疕%色o[70?惹蜖O偌r~凷祰H鍗挬羌?鏬s橸)?铴欢?唫~Lo労鱎€?百@?暞苫桤?u赳?6I?i鳡磐?k剧{怄K証U?T覾y?詰P龃6AF??噔8?q鱾VM"?顗СF鷤?睂厭稲?簉C?锠[9诔惘)/倯nAXw拳▔? 扯'_浦k??犙壓???櫦?砐魡C?y?

我的解答:

显然主函数是一段加密的密码,而msg01中是一段明文文字 ,msg01.enc中是其加密后的文字,我们要找的flag应该是msg02.enc对应的解密后的明文。
这道题看上去就是一道写逆向代码的题目,但是里面有一个坑,我们尝试后发现msg01加密后并非是msg01.enc中的内容,这是因为它的加密代码中key是错误的,所以我们需要找出正确的key。
找出key的代码如下:

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

int main(int argc, char **argv) {
	
	FILE* input  = fopen("msg01.enc", "rb");
	if (!input ) {//如果有一个文件无法打开 
		printf("Error\n");
		return 0;
	}
	char c, p, t = 0;
	int i=0;
	char w[] = "Hi,there is nothing here,heiheihei.\n";  //原来input中的值
    unsigned int j = 0;
    while ((p = fgetc(input)) != EOF) {
        for (j=31;j<125;j++) {//在找k的真正值,只有当能够逆向回w时,真正找到k 
            c = (p - (j ^ t) - i*i) & 0xff;
            if (c == w[i]) {
                printf("%c",j);
                t = c;
                i++;
                break;
            }
        }
    }
	return 0;
}

得到key为 

VeryVeryLongKeyYouWillNeverKnowVery

然后使用密钥去得到解密,代码如下:

#include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 
 int main(int argc, char **argv) {
     FILE* input  = fopen("msg02.enc", "rb");
     FILE* output = fopen("msg02.txt", "wb");
     if (!input || !output) {
         printf("Error\n");
         return 0;
     }
    char c, p, t = 0;
    int i = 0;
    char k[] = "VeryVeryLongKeyYouWillNeverKnowVery";
    i = 0;
    c, p, t = 0;
    int g = 0;
    while ((p = fgetc(input)) != EOF) {
    	//printf("%c",p);
        c = (p - (k[i % strlen(k)] ^ t) - i*i) & 0xff;
        printf("Decrypting %x i=%d t=%d k=%d -> %d\n",p,i,t,(k[i % strlen(k)] ^ t),c);
        t = c;//c是改变之前的c 
        i++;
         printf("%c",c);
         fputc(c, output);
         g++;
         if (g>450) {break;}
    }
 
    return 0;
 }

得到

flag{101a6ec9f938885df0a44f20458d2eb4}