[WP]NPUCTF 2020 彩虹题详解
这比赛对miscer极不友好,一天半做一个大题可还行
薛定谔的服务器在没交上flag之前永远不知道它是被D了还是换端口了还是关掉了
拿到flag的题目
汇编题不用看汇编
有困难找xor
result有点像ascii
转一转一半字符是对的,猜测另一半要xor 0x42
跑一跑
#include<stdio.h> #include<string.h> int main() { int a[]={0x66,0x2e,0x61,0x25,0x7b,0x26,0x30,0x1d,0x79,0x72,0x75,0x1d,0x6b,0x2c,0x6f,0x35,0x5f,0x3a,0x38,0x74,0x2d,0x74,0x34,0x1d,0x61,0x77,0x6d,0x7d,0x7d}; for(int i=0;i<29;i++){ if(i%2==1){ a[i]=a[i]^0x42; } printf("%c",a[i]); } //} }
把对着的数字找出来,用a-z代替1-26;
F是星期五 F1是星期五下面第一个数字
S2是星期天 S22是星期天下第二个数字
quipqiup爆破压缩包密码
一个一个试
解压后图片
对两张表
看一看得到 欢迎来到西北工业大学CTF比赛世界上最简单的比赛
包一下就是flag
题目给了三个文件,分别分析
发现后面有东西,应该是摩斯电码,空格替换成. \t替换成-解密得到 'autokey'
留着备用
HxD中发现三种奇怪的东西 'E2 80 8B' 'E2 80 8C' 'E2 80 8D'
提出来把前缀替换掉
稍微分一下发现前缀相同
试了三分密码等各种密码
发现是三进制
B替换成0 C替换成1 D替换成2一行算完转十进制转ascii
解密完大致是 XXXX NTFS XXXX
使用
分离这个文件,得到
看起来像是base64的东西,又尝试了很久
最后发现是应该统计字频排序
排完再base64解密得到信息enstego
这是一个加密文件用的软件
到这放一放
查一查发现字符串
HxD打开把这个东西去掉
改文件后缀为.encrypt,就可以用enstego打开了
要密码前面的autokey还没用过
用autokey当密钥解了一下不行,最后尝试爆破
密码是iamthepasswd
解密文件得到彩虹图
分离彩虹图得到有密码的压缩包
爆了十分钟未果 尝试在图片中寻找密码
发现这些黄色有点奇怪 ,每行黄色的颜色值都不相同
每行提取一下拿到压缩包的passwd
解密压缩包得到docx文件
有隐藏文字
中间穿插着大写的ALPHUCK
去掉大写字母用alphuck解密
回收站
提示回收站 ,找到回收站的目录
一层一层找,flag有十二个文件夹
拿出来看,每个文件夹都是flag的部分图片
拼一下
未拿到flag的题目
老千层饼(网站又崩了截不了图)
7z强行解压题目给的文件
一个hint 33*33想到二维码
查看图片通道
透明度通道不明黑点,估计一下可能差不多33*33个
提取出来按33*33重绘成二维码
反相一下补一下角就可以扫
图片末端发现7z文件
base64解密得到
CyberChef的脚本 ,解密的对象应该是之前二维码扫出来的base64串,但很显然其中几个密钥是错的.到此思路终结
解题用到的其他脚本
AUTOKEY无密钥爆破
from ngram_score import ngram_score from pycipher import Autokey import re from itertools import permutations qgram = ngram_score('quadgrams.txt') trigram = ngram_score('trigrams.txt') ctext = 'achnrvxzzuglarucalznwcygfggrufryvbzqjoxjymxvchhhdmliddcwmhghclpebtzwlojvew' ctext = re.sub(r'[^A-Z]','',ctext.upper()) # keep a list of the N best things we have seen, discard anything else class nbest(object): def __init__(self,N=1000): self.store = [] self.N = N def add(self,item): self.store.append(item) self.store.sort(reverse=True) self.store = self.store[:self.N] def __getitem__(self,k): return self.store[k] def __len__(self): return len(self.store) #init N=100 for KLEN in range(3,20): rec = nbest(N) for i in permutations('ABCDEFGHIJKLMNOPQRSTUVWXYZ',3): key = ''.join(i) + 'A'*(KLEN-len(i)) pt = Autokey(key).decipher(ctext) score = 0 for j in range(0,len(ctext),KLEN): score += trigram.score(pt[j:j+3]) rec.add((score,''.join(i),pt[:30])) next_rec = nbest(N) for i in range(0,KLEN-3): for k in xrange(N): for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ': key = rec[k][1] + c fullkey = key + 'A'*(KLEN-len(key)) pt = Autokey(fullkey).decipher(ctext) score = 0 for j in range(0,len(ctext),KLEN): score += qgram.score(pt[j:j+len(key)]) next_rec.add((score,key,pt[:30])) rec = next_rec next_rec = nbest(N) bestkey = rec[0][1] pt = Autokey(bestkey).decipher(ctext) bestscore = qgram.score(pt) for i in range(N): pt = Autokey(rec[i][1]).decipher(ctext) score = qgram.score(pt) if score > bestscore: bestkey = rec[i][1] bestscore = score print bestscore,'autokey, klen',KLEN,':"'+bestkey+'",',Autokey(bestkey).decipher(ctext)
字频统计
#!/usr/bin/python3 # -*- coding=utf8 -*- """ # @Author : pig # @CreatedTime:2020-02-27 16:51:52 # @Description : """ my_str = """ wwZlZ8WcndwljcdcG8wdj8W8Z8dZllGjZc8lWjnlWd8WwZ5jl8ccWZcZGjd5ZwZ5WZ8dZcwjwl5GnnWdwcwlnWd5lGnZWlnnwdnjnw8ndnc58d5cndlnjZlWddjwWWwZllj5c5jGwZnZ5WcZljdwd8c85ndGGljcl5ccwdWl8w5lwWn8WnwnWlGZwdcnGGl5G8WcnnWZnWjZwWcGwZcWc8ncWW5jnWwcZl8W8cdwWldlnwW5ddwlnlwncWlcwGZddj5djZWc5jcWdn5jdjwnj85GWGjnjwGdjZGj5jjwjlw8dlwWj5Wjn5n8dwwdjZlc5lZwdWldZlnGwl85cWnjdWcWlwj8WGdlGncnZWGGd5ZncW5d55nW5wlWj8jGWnWj8jwZZwWZ88nWG5nn5WlWnGdWw5Zn8jdlnGcnll8WncZjnGndlwn5W8wlWjlnl5ccnGWGnnnc58WnjlGnG55Zwdn5cZdjdZZ5WljG5G5wclddWlc8Z8nGjjWd8w8Wdw8nccc8wZdjcnGdljZnnj5ww8885lcWW8W8j5dG8jZZwG55GjnwZW5Z8G5ZlGc5ZZncZ5cd8j85GW5njWWncn55Gj5nj5nwnW58jG8GcnjZdWcl8wj8ncj8l8cn5jjcjn8lldnGjw8cjcdWWjGddZljdjdZnG8djnZccZldlWllw5ZZ8wj5Gn5w8Zj55nZZ5wdww8lndwd8Wlj8WGjnlnncZW8ZZWZnjjlwWGZZlZc5cd8Zl855wZnWw8wWjZ85cGc5Z8ccjdw5GnZWnGjcdGGnZ5wwwWGG5dW5ldjwGZZdZwdG5cGGnZGlGcW5ccWZ8cGljdGcdld8cj8jwnlj88ZZ5jn5lcZGdwZl58WZZl5ccwccwG5d5w8Z5wllj5ddnn5w8588WwGjl5G55dWG8clGcjWwlwGlWWnZdZG85Gcjc5wnwjGndnddjwn5cc5W5wwdWlG5nWZwnGw8lcWldcwnG5WcjjcWlGZc8Gn58ZWjZ85ljlncZj5ccdZWGjdd8ncZ8www55cwGWZn5ZZlnWldcWcnclWlZG5djGWcl8ZG8cZwwc8wl88W5ZwZjwZGGlcWcWnZZ5Zj5w5ZdZclZZWnccGwcG8W8ZWlc8wcZ555Z85ljWG5jZ8wllWjWjlZc5lG8cwWlnjlGlWl5nlGwnjGGjGdwj85ddW5ZwZddjWldjcjljjGwndZjWWZGcdWcZW5cdldj8WZjGljlWncZ58jnZWjl8wjZG5Zwlcl5dd """ def str_count(strs): '''利用字典中的get方法, 如果存在加1, 如果字母不存在返回0''' str_dict = {} for i in strs: str_dict[i] = str_dict.get(i,0) + 1 return str_dict count = str_count(my_str) print (count)