0x00 抄错的字符

描述:

老师让小明抄写一段话,结果粗心的小明把部分数字抄成了字母,还因为强迫症把所有字母都换成大写。你能帮小明恢复并解开答案吗:QWIHBLGZZXJSXZNVBZW

根据提示,需要恢复原来的字符串才行。首先是数字转数字的:

1 : l(小写L)、I(大写i)
2 : Z/z
5 : S/s
8 : B
9 : g
0 : O/o

大概就是以上的情况,然后就是大小写的转换。分析完毕后发现这并不是什么明文,有点像Base64。简单尝试一下发现可行。写exp如下:

from base64 import b64decode
from string import printable
​
#字母数字对应表
Numlist = {'i': '1', 'l': '1', 'z': '2', 's': '5', 'g': '9', 'o': '0'}
​
#分割字符串
def cut(obj, sec):
    return [obj[i:i + sec] for i in range(0, len(obj), sec)]
​
#使用递归将字符串还原回所有可能的结果
def decode(str):
    res = []
    if len(str) > 1:
        relist = decode(str[1:])
        Rlist = decode(str[0])
        for i in Rlist:
            for j in relist:
                res.append(i + j)
    else:
        res.append(str[0].lower())
        res.append(str[0].upper())
        if str[0].lower() in Numlist:
            res.append(Numlist[str[0].lower()])
    return res
​
#判断base解码后是否是正常的字符
def isbase(str):
    res = b64decode(str)
    for i in res:
        if i not in printable.encode():
            return False
    return True
​
​
if __name__ == '__main__':
    enstr = 'QWIHBLGZZXJSXZNVBZW'
    #base64可以切片分别解码,减少运算数量
    enlist = cut(enstr, 4)
    flag = []
    for i in enlist:
        delist = decode(i)
        f = []
        for base in delist:
            base += '=' * (4 - len(base)) #填充=
            if isbase(base):
                print(base, end=',')
                f.append(b64decode(base).decode())
        flag.append(f)
        print()
    print()
​
    for i in flag:
        print(i)

运行结果如下:

根据题目作者名字(Aman)和正确单词拼写,构成正确的flag

Aman_very_cool

0x01 /.-

看题目名字就知道,莫斯密码

..-./.-../.-/--./----.--/-../...--/..-./-.-./-.../..-./.----/--.../..-./----./...--/----./----./...../-----/....-/-----.-
​
flag{d3fcbf17f9399504}

0x02 聪明的小羊

2位栅栏密码

fa{fe13f590lg6d46d0d0}
​
flag{6fde4163df05d900}

0x03 ok

Ook! 编码。exp见0x04

Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook! Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook!
Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook!
Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook!
Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook?
Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook!
Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook!
Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook!
Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook! Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook?
Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook?
Ook. Ook? Ook! Ook. Ook? Ook! Ook. Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook.
Ook! Ook! Ook! Ook! Ook! Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook!
Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook!
Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook!
Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook!
Ook! Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook.
Ook. Ook. Ook. Ook! Ook. Ook? Ook. 

0x04 [+-<>]

brainfuck 编码,这个和Ook是类似的。

+++++ +++++ [->++ +++++ +++<] >++.+ +++++ .<+++ [->-- -<]>- -.+++ +++.< ++++[ ->+++ +<]>+ +++.< +++++ +++[- >---- ----< ]>--- ----- ---.< +++++ ++[-> +++++ ++<]> +++.< +++++ +[->- ----- <]>-- ----- -.--. ----. --.++ +++++ +.<++ ++++[ ->+++ +++<] >++++ +.++. <++++ ++[-> ----- -<]>- ----- ----. -.<++ +++++ [->++ +++++ <]>+. ----. ++++. <++++ +++[- >---- ---<] >---- .+.<+ +++++ ++[-> +++++ +++<] >++++ +++++ ++.<

exp来自github的开源项目

#-*-coding:utf-8-*-
import sys
from collections import deque
​
class LoopError(Exception):
    pass
​
class OokParser(object):
    def __init__(self):
        self.BEGIN = ('!', '?')
        self.END = ('?', '!')
        self.primitives = {('.', '.'): 'inc',
                           ('!', '!'): 'dec',
                           ('.', '?'): 'right',
                           ('?', '.'): 'left',
                           ('!', '.'): 'write',
                           ('.', '!'): 'read'}
                           
    def parse(self, input_text):
        items = input_text.lower().replace('ook','').replace(' ', '').replace('\n','').replace('\r','')
        for i in range(0, len(items), 2):
            x = (items[i], items[i+1])
            if x in self.primitives or x in (self.BEGIN, self.END):
                yield x
​
class BrainfuckParser(object):
    def __init__(self):
        self.BEGIN = '['
        self.END = ']'
        self.primitives = {'+': 'inc',
                           '-': 'dec',
                           '>': 'right',
                           '<': 'left',
                           '.': 'write',
                           ',': 'read'}
                           
    def parse(self, input_text):
        for x in input_text:
            if x in self.primitives or x in (self.BEGIN, self.END):
                yield x
​
class Interpreter(object):
    MAX_NESTED_LOOPS = 1000
​
    def __init__(self, ook_mode=True):
        self.bf_parser = BrainfuckParser()
        self.ook_parser = OokParser()
        self.set_parser(ook_mode and self.ook_parser or self.bf_parser)
​
    def reset(self):
        self.cells = deque([0])
        self.index = 0
        self.input_buffer = []
        self.output_buffer = []
        self.open_loops = 0
        self.loop = []
​
    def inc(self):
        self.cells[self.index] += 1
​
    def dec(self):
        self.cells[self.index] -= 1
​
    def right(self):
        self.index += 1
        if self.index >= len(self.cells):
            self.cells.append(0)
​
    def left(self):
        if self.index == 0:
            self.cells.appendleft(0)
        else:
            self.index -= 1
​
    def write(self):
        self.output_buffer.append(self.cells[self.index])
            
    def read(self):
        try:
            self.cells[self.index] = int(input("Your input: "))
        except (TypeError, ValueError):
            print("Invalid input! Continuing ...")
​
    def as_ascii(self):
        return "".join([chr(c) for c in self.output_buffer])
​
    def set_parser(self, parser):
        self.parser = parser
        self.reset()
​
    def interpret_raw_text(self, text):
        self.input_buffer.extend(self.parser.parse(text))
        try:
            self.interpret_items(self.input_buffer)
        except IndexError:
            print(" ... (incomplete)")
        except LoopError:
            print("LoopError ... exiting")
            sys.exit(1)
​
    def interpret_items(self, items):
        for item in items:
            if self.open_loops:
                self.interpret_inside_loop(item)
            else:
                self.interpret_directly(item)
​
    def interpret_inside_loop(self, item):
        if item == self.parser.END:
            self.open_loops -= 1
            if self.open_loops == 0:
                while self.cells[self.index]:
                    self.interpret_items(self.loop)
                return
        elif item == self.parser.BEGIN:
            if self.open_loops < self.MAX_NESTED_LOOPS:
                self.open_loops += 1
            else:
                raise LoopError("Nesting maximum (%s) exceeded" 
                                % self.MAX_NESTED_LOOPS)
        self.loop.append(item)
​
    def interpret_directly(self, item):
        if item == self.parser.END:
            raise ValueError("End without begin")
        elif item == self.parser.BEGIN:
            self.open_loops = 1
            self.loop = []
        elif item in self.parser.primitives:
            method = self.parser.primitives[item]
            getattr(self, method)()
        else:
            print("Unknown token '%s' - ignored" % (item, ))
​
    def interpret_file(self, fname):
        file = open(fname, 'r')
        self.interpret_raw_text(file.read())
        
    def interactive_mode(self):
        print("Ook! and Brainfuck interpreter V1.0")
        print("Type '?' to display the status of the interpreter. ")
        print("Type 'b' to enter brainfuck mode. Empty input quits.")
        while True:
            inp = input("oo> ").strip()
            if inp == "?":
                print(self)
            elif inp == "b":
                print("Entering brainfuck mode. Type 'o' to return to Ook!")
                self.set_parser(self.bf_parser)
            elif inp == "o":
                print("Entering Ook! mode. Type 'b' to return to brainfuck.")
                self.set_parser(self.ook_parser)
            elif inp == "":
                print(self)
                break
            else:
                self.interpret_raw_text(inp)
​
    def __repr__(self):
        rep = "\n".join(["Cells\t\t: %s", 
                         "Raw output\t: %s",
                         "ASCII output\t: %s"])
​
        return rep % (list(self.cells),
                      " ".join([str(i) for i in self.output_buffer]), 
                      self.as_ascii())
​
def print_usage():
    print("\nUsage:")
    print("\tInterpret Ook! : python ook.py -o <FILENAME>")
    print("\tInterpret BrainFuck : python ook.py -b <FILENAME>")
    print("\tInteractive mode: python ook.py -i\n")
​
​
if __name__ == '__main__':
    if len(sys.argv) < 2:
        print_usage()
    elif len(sys.argv) == 2 and sys.argv[1] == "-i":
        ook = Interpreter()
        ook.interactive_mode()
    elif len(sys.argv) == 3:
        if sys.argv[1] == "-b":
            ook = Interpreter(ook_mode=False)
            ook.interpret_file(sys.argv[2])
            print(ook)
        elif sys.argv[1] == "-o":
            ook = Interpreter(ook_mode=True)
            ook.interpret_file(sys.argv[2])
            print(ook)
        else:
            print_usage()
    else:
        print_usage()

使用方法如下:

$ python ook.py -o ook.txt
Cells           : [0, 125]
Raw output      : 102 108 97 103 123 48 97 51 57 52 100 102 53 53 51 49 50 99 53 49 97 125
ASCII output    : flag{0a394df55312c51a}
​
$ python ook.py -b brainfuck.txt
Cells           : [0, 125]
Raw output      : 102 108 97 103 123 48 100 56 54 50 48 56 97 99 53 52 102 98 102 49 50 125
ASCII output    : flag{0d86208ac54fbf12}

0x05 把猪困在猪圈里

打开文件发现是乱码,最后以=结尾,尝试base64解码失败,观察其内容结构和图片类似,因此猜测是图片Base64。创建html文件:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>test</title>
	</head>
	<body>
		<img src="data:image/png;base64,/9j/......oA/9k="/>
	</body>
</html>

数据太多就不全贴了,从data:image/png;base64,之后开始粘贴替换即可。保存后使用浏览器打开

对照猪圈密码表

flag{thisispigpassword}

0x06 你喜欢下棋吗

解压文件后为一个压缩包和 解压密码.txt,内容如下:

你喜欢下棋吗?
解压密码为小写
4423244324433534315412244543

数字为棋盘密码(波利比奥斯方正密码),exp如下:

from re import findall, compile

def de_Polybius(cryptostr):
    Polybius_dic = {
        '11': 'A', '12': 'B', '13': 'C', '14': 'D', '15': 'E', '21': 'F', '22': 'G',
        '23': 'H', '24': 'I', '25': 'K', '31': 'L', '32': 'M', '33': 'N', '34': 'O',
        '35': 'P', '41': 'Q', '42': 'R', '43': 'S', '44': 'T', '45': 'U', '51': 'V',
        '52': 'W', '53': 'X', '54': 'Y', '55': 'Z'
    }
    list = findall(r'.{2}', cryptostr)
    cc = [Polybius_dic[i] for i in list]
    dd = ''.join(cc)
    if 'I' in dd:
        ee = dd.replace('I', 'J')
    result = ("{}\n{}".format(dd, ee)).encode()
    return result

print(de_Polybius('4423244324433534315412244543'))

#THISISPOLYBIUS
#THJSJSPOLYBJUS

根据单词应该选择THISISPOLYBIUS,转换为小写后解压压缩包

又一个TXT

一种5bit的编码
bugku里面的内容为小写
bugku{11111 11001 00011 00111 01001 11011 10110 11111 10000 01110 11011 10110 11111 01001 00001}

5bit的编码,百度查询得知为博多编码(这里为ITA2模式)

from io import BytesIO
from baudot import decode_to_str, codecs, handlers
from base64 import b16encode


def cut(obj, sec):
    return [obj[i:i + sec] for i in range(0, len(obj), sec)]


def de_baudotITA2(cryptostr):
    cryptostr = cryptostr.replace(' ', '')
    cryptostr = cut(cryptostr, 5)
    x = b''
    if cryptostr[0] != '11111':
        x += b'1F'
    for i in cryptostr:
        x += b16encode(int(i,2).to_bytes(1, 'little'))
    with BytesIO(x) as code_stream:
        reader = handlers.HexBytesReader(code_stream)
        return (decode_to_str(reader, codecs.ITA2_US)).encode()

cryptostr = '11111 11001 00011 00111 01001 11011 10110 11111 10000 01110 11011 10110 11111 01001 00001'
print(de_baudotITA2(cryptostr))
#BAUD0TC0DE

转换为小写即可

0x07 小山丘的秘密

解压后发现一张图以及flag.txt,内容分别为:

bugku{PLGTGBQHM}

其中A=1,flag全为小写

棋盘表示矩阵,此为key

1 2 3
0 1 4
5 6 0

在根据题目的提示得知为希尔密码。A=1则说明不是标准的表,而是替换表。因此得到exp

import numpy as np
import math

table = ['z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
         'v', 'w', 'x', 'y']
enstr = 'PLGTGBQHM'.lower()
key_matrix = [[1, 2, 3], [0, 1, 4], [5, 6, 0]]

#密文:Str类型 , 字母表。根据字母表求矩阵
def Matenc(enstr, table):
    size = int(math.sqrt(len(enstr)))
    enc_matrix = []
    for i in range(size):
        a = []
        for j in range(i, len(enstr), size):
            a.append(table.index(enstr[j]))
        enc_matrix.append(a)
    print("enc_matrix\t:", enc_matrix)
    return enc_matrix

#密文矩阵序列,key矩阵,字母表
def decode(enc_matrix, key_matrix, table):
    key_inv = np.matrix(np.array(key_matrix)).I % len(table)
    result = key_inv * np.array(enc_matrix) % len(table)
    destr = ''
    resulttable = []
    for i in range(result.shape[0]):
        for j in range(result.shape[1]):
            resulttable.append(round(result.T[i, j]))
    for i in range(9):
        destr += table[resulttable[i]]
    return destr


if __name__ == '__main__':
    enc_matrix = Matenc(enstr, table)
    flag = decode(enc_matrix, key_matrix, table)
    print("flag\t\t: " + flag)

#enc_matrix	: [[16, 20, 17], [12, 7, 8], [7, 2, 13]]
#flag		: whatahill

0x08 EN-气泡

题目说明为气泡加密,解密后发现仍为气泡密码,反复三次后得flag

from bubblepy import BubbleBabble

# 导入包bubblepy
str = 'xivak-notuk-cupad-tarek-zesuk-zupid-taryk-zesak-cined-tetuk-nasuk-zoryd-tirak-zysek-zaryd-tyrik-nisyk-nenad-tituk-nysil-hepyd-tovak-zutik-cepyd-toral-husol-henud-titak-hesak-nyrud-tarik-netak-zapad-tupek-hysek-zuned-tytyk-zisuk-hyped-tymik-hysel-hepad-tomak-zysil-nunad-tytak-nirik-copud-tevok-zasyk-nypud-tyruk-niryk-henyd-tityk-zyral-nyred-taryk-zesek-corid-tipek-zysek-nunad-tytal-hitul-hepod-tovik-zurek-hupyd-tavil-hesuk-zined-tetuk-zatel-hopod-tevul-haruk-cupod-tavuk-zesol-ninid-tetok-nasyl-hopid-teryl-nusol-heped-tovuk-hasil-nenod-titek-zyryl-hiped-tivyk-cosok-zorud-tirel-hyrel-hinid-tetok-hirek-zyped-tyrel-hitul-nyrad-tarak-hotok-cuvux'
str1 = 'xivak-norok-norad-tipol-norol-nipid-tisuk-zotak-nurud-tesil-nitok-hepod-torek-cesuk-coryd-tinak-zorik-nined-tomyl-nosal-hopid-tuvuk-zomek-zupod-tovuk-zumak-zoryd-tipuk-nyruk-zepyd-tonuk-zasol-nunud-tenok-nuvyl-nevax'
str2 = 'ximil-hynyk-rotil-rytek-masal-folif-cysuh-zoboh-zobol-himok-dosyf-fizyx'
# str是待解密字符
Str = BubbleBabble()
print(Str.decode(str))
print(Str.decode(str1))
print(Str.decode(str2))

#b'xivak-norok-norad-tipol-norol-nipid-tisuk-zotak-nurud-tesil-nitok-hepod-torek-cesuk-coryd-tinak-zorik-nined-tomyl-nosal-hopid-tuvuk-zomek-zupod-tovuk-zumak-zoryd-tipuk-nyruk-zepyd-tonuk-zasol-nunud-tenok-nuvyl-nevax'
#b'ximil-hynyk-rotil-rytek-masal-folif-cysuh-zoboh-zobol-himok-dosyf-fizyx'
#b'bugku{th1s_1s_A_Bubb13}'

0x09 你以为是md5吗

题目提示MD5的构成,MD5就是一串16进制数,所以构成只有0~f

from string import hexdigits

str = 'bci177a7a9c7udf69c248647b4dfc6fd84o'

for i in str:
    if i in hexdigits:
        print(i,end='')
        
#bc177a7a9c7df69c248647b4dfc6fd84

然后使用CMD5在线平台解密为:666666666666

0x0A Math&English

Math是指做数学题

你会数学和英语吗?
3×7=
11×3=
sin(Π/6)+sin(Π/6)=                  
2×11=
3×cos(2Π)=
22×2=
6×9=
2.5×2=
tan(Π) + 1 = 
5×7=
7×9-9=
ln(e) + 2 =
(6×6)-1=
4×10 + cos(0) =
26×2 =
ln(e) × 10 +3 =

21 33 1 22 3 44 54 5 1 35 54 3 35 41 52 13

English是指元音密码:

#字母表
table_dict={'A':1,'B':11,'C':12,'D':13,'E':2,'F':21,'G':22,
            'H':23,'I':3,'J':31,'K':32,'L':33,'M':34,'N':35,
            'O':4,'P':41,'Q':42,'R':43,'S':44,'T':45,'U':5,
            'V':51,'W':52,'X':53,'Y':54,'Z':55
           }
reverse_table_dict={k:v for v,k in table_dict.items()}

#密文列表
c=[21,33,1,22,3,44,54,5,1,35,54,3,35,41,52,13]

flag=''
for i in range(len(c)):
    #解密出明文
    flag+=reverse_table_dict[c[i]]
print('bugku{'+flag[6:].lower()+'}')

#bugku{yuanyinpwd}

0x0B easy_crypto

虽然是01,但是长短不一,可能为莫斯密码,尝试转换和解密

0010 0100 01 110 1111011 11 11111 010 000 0 001101 1010 111 100 0 001101 01111 000 001101 00 10 1 0 010 0 000 1 01111 10 11110 101011 1111101

..-. .-.. .- --. ----.-- -- ----- .-. ... . ..--.- -.-. --- -.. . ..--.- .---- ... ..--.- .. -. - . .-. . ... - .---- -. ----. -.-.-- -----.-

flag{m0rse_code_1s_interest1n9!}

0x0C 7+1+0

解压得到字符串 4nXna/V7t2LpdLI44mn0fQ==

使用python尝试base64解码结果为

b'\xe2u\xe7k\xf5{\xb7b\xe9t\xb28\xe2i\xf4}'

这样可能不够直观,将奇数位的16进制字符删去后为:

?u?k?{?b?t?8?i?}

可以看到偶数位的数都是正确的。所以再输出ASCII码看一下

226,117,231,107,245,123,183,98,233,116,178,56,226,105,244,125

可以看到奇数位的数ASCII值很大,这显然不正确。结合题目 7+1 = 8,一个字符也是8bit。

可打印的字符的ASCII范围在125以内,转换为二进制也只需要7位,对于大于128的数,将最高位置零后,则刚好是可打印的字符。具体演示如下:

例如第一位为226,转换为二进制数后为 1110 0010
将最高位(第一位)置0后为 0110 0010
再转换回来十进制为 98
对应的字符为 'b'

那么现在可以理解作者的意图了。将7bit的字符转换为8bit,则是在其最高位进行 +1和+0。因为+0后值不变,所以偶数位的值是正常的。exp如下:

from base64 import b64decode

enc = '4nXna/V7t2LpdLI44mn0fQ=='
dec = b64decode(enc)

flag = ''
for i in range(len(dec)):
    if i % 2 == 0:  #奇数位的数下标为偶数
        flag += chr(dec[i] & 0x7f) # 0x7f : 0111 1111
    else:
        flag += chr(dec[i])

print(flag)

#bugku{7bit28bit}

0x0D 黄道十二宫

首先是获得了图片

首先需要将字符提取出来,没有什么好的办法,使用手工吧(或者先QQ截图识别,然后在校正)。注意,这里的 1 和 ) 比较相似,需要仔细区分。

%..@*>@?==%88%5
.@%#@@90-7$^=*@
17.(>()1@##-$40
~.*6?#%#8#=75+1
(*@*1%#>.0@5)%?
%*^=)&>=1%.+7&#
8681(+8*@@(.@@@
#*=#$3*#%.#%%.3
.*+7.7+@===+)61

然后嘛,查询黄道十二宫相关信息。经过了解得知改密文需要重排。重排规则看视频(黄道十二宫杀手的密码信「340」是怎么被破解的)了解。

大体规则如下:

  • 首先,记住当前的矩阵规格(15*9)

  • 然后,斜线取值,如果到尾部了,就循环回去

    • 斜线不是45度,从(1,1)开始,第二个就是(2,3),既 x 增加一个单位,y 增加两个单位

    • 第一轮到第八行就是(8,15),那么第九行就是(9,17),但是没有第17个,循环回去那么15过了就是1。所以此时取(9,1)

  • 到达最后一行后,又从首行开始,其 x 值是上一次的下一个。既此时应该取 (1,2),然后是(2,4)。

了解规则后,写exp:

def cut(obj, sec):
    return [obj[i:i + sec] for i in range(0, len(obj), sec)]


enstr = '%..@*>@?==%88%5.@%#@@90-7$^=*@17.(>()1@##-$40~.*6?#%#8#=75+1(*@*1%#>.0@5)%?%*^=)&>=1%.+7&#8681(+8*@@(.@@@#*=#$3*#%.#%%.3.*+7.7+@===+)61'

x = 0  # 横坐标
y = 0  # 纵坐标
s = ''  # 临时str
line = 9  # 行数
l = 15  # 列数
enlist = cut(enstr, l) #切成二维字符数组
delist = []

for i in range(len(enstr)):
    s += enlist[y][x]
    y += 1
    if y >= line:
        y %= line
        x = int((i + 1) / line)
    else:
        x = (x + 2) % l
    if (i + 1) % l == 0:
        delist.append(s)
        s = ''

for i in delist:
    print(i)

得到转换后的密文:

%%>%..@3*.#(#0+
@#+.@)8@7@*7@@1
#5&8=.*9@=)#6#7
>0#7%%8$+@-#5?*
13@?7-+(^(*==$$
1*=+#==^4~@)8%=
%=0.*&*.+8*1*1>
@#)8@76%=@%6%..
?#1(%15@(#>%...

再根据AZdecrypt工具进行解密,AZdecrypt工具下载链接

0x0E 给你私钥吧

解压获得四个文件,打开python文件查看

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import base64
from flag import flag


f=open(r"pubkey.pem","r")
key=RSA.importKey(f.read())
cipher=PKCS1_OAEP.new(key)
cipher_txt=base64.b64encode(cipher.encrypt(flag))

with open(r"flag.enc","wb") as f:
    f.write(cipher_txt)
    f.close()

可以直观的看到,采用公钥对flag进行RSA加密。同时也给了私钥,所以可以直接写exp尝试解密。

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import base64

ciphertext = open(r"flag.enc", "r").read()
f = open(r"privatekey.pem","r")
key = RSA.importKey(f.read())
cipher = PKCS1_OAEP.new(key)
flag = cipher.decrypt(base64.b64decode(ciphertext))
print(flag)

'''
Traceback (most recent call last):
  File "给你私钥吧/exp.py", line 7, in <module>
    key = RSA.importKey(f.read())
  File "RSA.py", line 770, in import_key
    return _import_keyDER(der, passphrase)
  File "RSA.py", line 685, in _import_keyDER
    raise ValueError("RSA key format is not supported")
ValueError: RSA key format is not supported
'''

发现直接报错了,所以这里的私钥可能是有问题的。对私钥进行简单分析(使用openssl工具)

ubuntu:~/RsaCtfTool$ openssl rsa -in privatekey.pem -text -noout
RSA Private-Key: (2048 bit, 2 primes)
modulus:	#N
    00:d1:2b:63:9d:f7:59:a9:9c:9a:db:57:50:0b:bd:
    63:50:41:aa:70:f8:e7:3f:6e:a1:58:b2:3b:9a:f5:
    75:91:5c:f6:8c:f8:e5:7b:04:5b:be:bc:f7:8a:9b:
    ca:72:bf:0e:63:cb:6e:c3:53:d6:61:42:04:8c:b6:
    9e:b5:f2:0c:dc:6b:af:6c:85:e7:7e:6f:2a:a9:06:
    dc:58:68:fc:b0:f0:33:0d:eb:55:07:6e:df:1b:22:
    6e:f5:49:26:dd:2a:d3:c9:43:c8:eb:35:cb:8c:85:
    84:8e:05:ea:86:80:98:8a:18:27:01:b6:a0:dc:54:
    96:77:60:ca:c2:81:36:ad:5b:3d:9f:1c:f7:95:2b:
    89:8c:fa:af:86:3a:90:bf:d5:8d:f0:fa:3f:35:8a:
    7e:b8:bc:be:1b:fc:f1:38:72:bb:b9:fc:c2:b3:30:
    a3:8f:3f:d6:89:46:7f:ef:22:f0:27:54:9f:53:d4:
    60:e9:fe:bb:48:f1:ae:15:f7:bf:ba:93:06:96:41:
    fd:53:c4:6f:c9:71:56:0f:59:55:d8:f6:e4:19:f5:
    98:1a:9b:a3:93:71:8d:78:5f:58:65:96:07:f5:11:
    f6:cc:40:77:83:4e:05:9f:36:8e:b0:5b:ca:79:64:
    ea:2d:c8:cd:1b:13:f6:2a:29:ea:24:4a:38:76:ff:
    59:67
publicExponent: 65537 (0x10001)		#e
privateExponent: 0
prime1: 0	#p
prime2:		#q
    00:ee:4e:18:98:45:cc:78:ef:ef:4a:c3:e8:1d:8a:
    ef:99:7f:73:5d:58:33:b5:c7:e8:49:4b:91:74:ae:
    21:1b:a8:82:31:e2:56:7e:e6:df:99:01:32:8e:0c:
    6d:bc:5e:24:b3:43:77:47:85:ae:7e:88:ec:40:9c:
    a1:d7:29:01:e3:2a:58:2f:29:12:60:eb:98:51:fc:
    bb:0f:ff:20:80:5d:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00
exponent1: 0
exponent2: 0
coefficient: 0

可以看到私钥中有N、e。但是没有完整的p和q。所以这是一个缺损的私钥。

现在有两种解决方案:

  • 利用N和部分的q进行高位攻击获取到完整的p和q,然后完成解密

  • 利用公钥进行攻击和解密

前者较为麻烦,直接使用后者快速高效,使用RsaCtfTool快速解密(github上自提)

ubuntu:~/RsaCtfTool$ python3 RsaCtfTool.py --publickey pubkey.pem  --uncipherfile flag.enc
HEX : 0x6275676b757b7477305f5469673372735f6c3056335f64346e63316e677e6569217d
INT (big endian) : 2918586387313427374648113440268372321293127400371659767444946173589057060433633661
INT (little endian) : 3709215666712012992462466403546646476981044684602414906342022350687712344355075426
utf-8 : bugku{tw0_Tig3rs_l0V3_d4nc1ng~ei!}
utf-16 : 畢歧筵睴弰楔㍧獲江嘰弳㑤据渱繧楥紡
STR : b'bugku{tw0_Tig3rs_l0V3_d4nc1ng~ei!}'

0x0F 这是个盲兔子,竟然在唱歌!

下载解压得到txt文件,打开显示乱码,直接拖入浏览器,查看到内容如下

⡥⠂⡶⡃⡔⡷⡦⡛⡨⠁⠟⡚⠉⠇⡳⡜⡉⡤⡴⡑⡓⡆⡑⡔⡆⡠⡩⡹⠂⡢⡪⡵⡢⡟⡶⡹⠃⡒⠁⡥⡞⠟⡚⡞⡣⡣⡤⡀⡡⡆⠉⡼⡻⠀⠉⡧⡙⠇⡦⡇⡧⡅⡺⡑⠺⡑⡉⡑⠂⡞⡱⡳⠁⡊⡢⡩⡊⡚⡊⡕⡛⠀⡕⠂⡩⡱⡾⡴⠂⡶⡛⠈⡹⡇⡗⡑⠃⠁⡆⡝⡽⡺⡨⡙⠛⠅⠁⡠⡇⡩⡅⡸⡑⡧⡑⡸⠅⡆⡨⠛⡣⡨⡑⡢⡝⠁⡟⡚⡿⠺⠛⡿⡕⡴⡛⡡⠀⡔⠉⠂⡴⡃⠃⠀⡿⡹⠄⡺⡀⡵⡊⡝⡪⡨⡛⡦⡖⡛⡧⡡⡪⠈⡲⠟⡝⡔⡕⠅⡄⡞⠟⠂⡵⡉⠅⡩⡦⡼⡈⡴⡩⡈⠟⡞⡦⡩⡆⡛⡴⡾⡈⡁⡁⡗⠺⡹⡾⡆⡢⡹⡠⡈⡃⡛⠆⡁⡖⡻⡉⡡⡻⡓⠆⡁⡼⡷⠃⡛⠅⡵⠈⡝⡂⠉⡃⡄⡠⡠⡡⡒⡁⡃⡁⠅⡾⡨⠆⡘⠇⡄⡁⡲⠅⡖⠛⡓⡤⡃⡕⡺⡃⡝⡛⡳⠀⡢⡒⡙⠂⠺⡱⡉⡻⡒⡨⡄⡒⡒⡈⡱⡧⡽⠆⡉⡷⡹⠛⡊⠟⡥⡜⡳⡶⠆⡺⠉⠂⡂⡛⡥⡓⡝⡴⠆⡽⡟⠅⡿⡻⡸⡺⠆⡇⠂⠈⡼⡤⡕⠂⠈⡤⠅⠛⠁⡇⡟⡧⡈⡗⡲⡊⡸⠉⡻⠺⡱⡻⡥⠍=

使用盲文解密得到如下

U2FsdGVkX1/j97ClyTDacvadvPYI2RZERoFI3b1Un/jnSSTpQv9LK09Wi7VwWuJa
aya2nAC1zRYzjzek0e2YAND2Fk8Iwga31vmMJXi+51PwYuHaWaH5vX+SXaRm1ojO
+OeDkQ0d92Ds30OI4JpEzmZXkVfkWQZ8B/mde5tn/2Ey5YVLxDYx/nVYvkDNxqqg
INvRIPxsk6qfKyQKc6qLG3k5E8mr9stPPQbqsq5NX6h7tqB5f+cTseJsmkC0Rbi2
AyKbXtbbxAWM6yGI+z/UlCF6J92rkUcmD6Mo5OKHJ6w28LTe28T5+1woWxgBzH9K
AKU=

根据题目提示,这是兔子(Rabbit)加密,解密得

♬♯♩¶♬♫¶♭♩¶♫♪‖♯♬♭♩♬‖♫‖∮‖♩♬§‖♪¶‖♬♩♬§‖♩¶∮♬♬‖♪¶♭¶♯♫♯♩♫‖‖♬§‖♫♬♯♬§♫‖♩♩♫∮♬♩♫‖‖♪¶∮♫‖♫♫♯=

音乐加密,解密得

bugku{2at746c5jfc6nh5klxs0c7bcvrzfv5nv}

0x10 道友不来算一算凶吉?

打开txt查看

半仙我夜观天象,掐指一算,卜出卦象如下,不知道的有无道友可解此卦。

密文:升益艮归妹井萃旅离旅困未济屯未济中孚未济升困噬嗑鼎震巽噬嗑解节井萃离未济蒙归妹大畜无妄解兑临睽升睽未济无妄遁涣归妹

嗯?为什么还有a和b呢?
a=5
b=7

然后打开py文件查看

# -- coding:UTF-8 --
from secret import flag

def encrpyt5():
    enc=''
    for i in flag:
        enc+=chr((a*(ord(i)-97)+b)%26+97)
    return(enc)

def encrypt4():
    temp=''
    offset=5
    for i in range(len(enc)):
        temp+=chr(ord(enc[i])-offset-i)
    return(temp)

大概捋一下思路就是flag经过encrpyt5()函数得到enc,enc经过encrypt4()函数得到temp。

在txt里面有一个密文需要破解,根据提示,这应该和卦有关的加解密,一找就找到了相关的文章。写exp解卦。

import base64

s = '升益艮归妹井萃旅离旅困未济屯未济中孚未济升困噬嗑鼎震巽噬嗑解节井萃离未济蒙归妹大畜无妄解兑临睽升睽未济无妄遁涣归妹'

def defuxi64(str):
    dic = {'乾': 'A', '坤': 'B', '屯': 'C', '蒙': 'D', '需': 'E', '讼': 'F', '师': 'G', '比': 'H', '小畜': 'I', '履': 'J',
           '泰': 'K', '否': 'L', '同人': 'M', '大有': 'N', '谦': 'O', '豫': 'P', '随': 'Q', '蛊': 'R', '临': 'S', '观': 'T',
           '噬嗑': 'U', '贲': 'V', '剥': 'W', '复': 'X', '无妄': 'Y', '大畜': 'Z', '颐': 'a', '大过': 'b', '坎': 'c', '离': 'd',
           '咸': 'e', '恒': 'f', '遁': 'g', '大壮': 'h', '晋': 'i', '明夷': 'j', '家人': 'k', '睽': 'l', '蹇': 'm', '解': 'n',
           '损': 'o', '益': 'p', '夬': 'q', '姤': 'r', '萃': 's', '升': 't', '困': 'u', '井': 'v', '革': 'w', '鼎': 'x', '震': 'y',
           '艮': 'z', '渐': '1', '归妹': '2', '丰': '3', '旅': '4', '巽': '5', '兑': '6', '涣': '7', '节': '8', '中孚': '9',
           '小过': '0', '既济': '+', '未济': '/'}
    b64text = ''
    i = 0
    while i < len(str):
        x = str[i]
        if x not in dic:
            i += 1
            x += str[i]
        if x not in dic:
            print("解密失败,密文错误")
            exit(1)
        b64text += dic[x]
        i += 1
    print(b64text)
    return base64.b64decode(b64text+'='*(len(b64text)%4))


if __name__ == '__main__':
    print(defuxi64(s))
    
#b'\xb6\x9c\xf6\xbe\xce\x1d\xe2\xef\xc2\xff\xdf\xed\xb9Lr\xe5I\xfc\xbe\xc7\x7f\x0ffX\x9f\xa4\xa5\xb6_\xd8\x83\xbd'

但是发现解出来的有问题,根据加密算法,这里的解应该是可正常的字符才对,所以需要找到问题出在哪里。接着上网找资源,发现一篇卦顺序图,里面有一张图:

闭合为1,断开为0,那么它们就可以转换为6bit的二进制数。再根据上面的exp思路(其实就是base64的换表),重新制作替换表

首先替换为二进制
'坤': '000000', '剥': '000001', '比': '000010', '观': '000011', '豫': '000100', '晋': '000101', '萃': '000110',
'否': '000111', '谦': '001000', '艮': '001001', '蹇': '001010', '渐': '001011', '小过': '001100', '旅': '001101',
'咸': '001110', '遁': '001111', '师': '010000', '蒙': '010001', '坎': '010010', '涣': '010011', '解': '010100',
'未济': '010101', '困': '010110', '讼': '010111', '升': '011000', '蛊': '011001', '井': '011010', '巽': '011011',
'恒': '011100', '鼎': '011101', '大过': '011110', '姤': '011111',
'复': '100000', '颐': '100001', '屯': '100010', '益': '100011', '震': '100100', '噬嗑': '100101', '随': '100110',
'无妄': '100111', '明夷': '101000', '贲': '101001', '既济': '101010', '家人': '101011', '丰': '101100', '离': '101101',
'革': '101110', '同人': '101111', '临': '110000', '损': '110001', '节': '110010', '中孚': '110011', '归妹': '110100',
'睽': '110101', '兑': '110110', '履': '110111', '泰': '111000', '大畜': '111001', '需': '111010', '小畜': '111011',
'大壮': '111100', '大有': '111101', '夬': '111110', '乾': '111111'

再根据顺序替换为base表:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
'坤': 'A', '剥': 'B', '比': 'C', '观': 'D', '豫': 'E', '晋': 'F', '萃': 'G', '否': 'H', '谦': 'I', '艮': 'J', '蹇': 'K',
'渐': 'L', '小过': 'M', '旅': 'N', '咸': 'O', '遁': 'P', '师': 'Q', '蒙': 'R', '坎': 'S', '涣': 'T', '解': 'U',
'未济': 'V', '困': 'W', '讼': 'X', '升': 'Y', '蛊': 'Z', '井': 'a', '巽': 'b', '恒': 'c', '鼎': 'd', '大过': 'e',
'姤': 'f', '复': 'g', '颐': 'h', '屯': 'i', '益': 'j', '震': 'k', '噬嗑': 'l', '随': 'm', '无妄': 'n', '明夷': 'o',
'贲': 'p', '既济': 'q', '家人': 'r', '丰': 's', '离': 't', '革': 'u', '同人': 'v', '临': 'w', '损': 'x', '节': 'y',
'中孚': 'z', '归妹': '0', '睽': '1', '兑': '2', '履': '3', '泰': '4', '大畜': '5', '需': '6', '小畜': '7', '大壮': '8',
'大有': '9', '夬': '+', '乾': '/'

这个时候再来解密(这里就不贴代码了,直接替换上述代码的dic即可。运行结果如下),解出来一个base编码,然后尝试对该密文进行base64。此时得到的,应该就是经过两次加密算法之后的temp。

YjJ0aGNtNWViVzVYWldkblUyaGtVR05nU2w1Y1VnPT0
b2thcm5ebW5XZWdnU2hkUGNgSl5cUg==

根据加密算法写出解密算法,然后得到完整exp

encrpyt4的算法简单,直接加回去即可,无需分析。主要再分析下encrpyt5

思路1:逆推

def encrpyt5():
    enc=''
    for i in flag:
        enc+=chr((a*(ord(i)-97)+b)%26+97)
    return(enc)

这里有很多信息

  • 首先是减97和最后的加97,那么也就是说原文应该都是大于等于97(a)的

  • 其次是余26,说明原文最大的只有 97+25 = 122 (z)

综上所述,说明原文只有小写字母,否则不会没有判断字符的范围就直接进行该运算。

首先滤清enc和flag的关系
ord(enc[i]) = (a*(ord(flag[i])-97)+b)%26+97
<=> ord(enc[i]) - 97 = (a*(ord(flag[i])-97)+b)%26

令 ord(flag[i])-97  为 x,ord(enc[i]) - 97 为 y,简化公式
y = (a * x + b) % 26
x , y 的范围均为 0~25, 现在写出x关于y的公式即可 
x = (y + n * 26 -b) / a  (n = 0,1,2,3,4)

已知 x 一定为整数,既
(y + n * 26 -b) % a = 0
否则除不尽,该公式转化得
((y - b) % a + n * (26 % a)) % a = 0
<=> (y - b) % a + n * (26 % a) = a * k (k = 0,1,2,3...)
<=> n * (26 % a) = a * k - (y - b) % a
将a和b代入得
n * (26 % 6) = 5 * k - (y - 7) % 5
<=> n = 5 * k - (y - 7) % 5
因为(y - 7) % 5 一定小于5,所以k取1即可,
n = 5 - (y - 7) % 5

但是这里可能会出现一个问题,如果(y-7)%5=0,那么n=5,
代入式子 (y + n * 26 -b) % a = 0 中发现,n=0页满足条件。
那么代入 x = (y + n * 26 -b) / a 中的式子中时就会得出多出多个x
因为这里应该取最小化的n使得 x 在范围内0~25内。
但是如果那样就式子就会过于复杂,所以只需要在最后进行余26的处理来修正即可
x = ((y + n * 26 -b) / a) % 26

思路2:爆破/碰撞/打表

  • 打表:只需要使用加密函数将a-z依次加密输出即可获得加密前后的字符集关系表,根据表进行还原替换即可

  • 爆破/碰撞:在解密函数中使用加密函数,依次取出密文,每次都从a开始加密,将结果和密文比较,一致则输出该加密前的字符,以此获得全部明文

打表是这几种方法中综合效率中最高的。锻炼思维的话可以尝试逆推。

import base64

s = '升益艮归妹井萃旅离旅困未济屯未济中孚未济升困噬嗑鼎震巽噬嗑解节井萃离未济蒙归妹大畜无妄解兑临睽升睽未济无妄遁涣归妹'


def defuxi64(str):
    dic = {'坤': 'A', '剥': 'B', '比': 'C', '观': 'D', '豫': 'E', '晋': 'F', '萃': 'G', '否': 'H', '谦': 'I', '艮': 'J', '蹇': 'K',
           '渐': 'L', '小过': 'M', '旅': 'N', '咸': 'O', '遁': 'P', '师': 'Q', '蒙': 'R', '坎': 'S', '涣': 'T', '解': 'U',
           '未济': 'V', '困': 'W', '讼': 'X', '升': 'Y', '蛊': 'Z', '井': 'a', '巽': 'b', '恒': 'c', '鼎': 'd', '大过': 'e',
           '姤': 'f', '复': 'g', '颐': 'h', '屯': 'i', '益': 'j', '震': 'k', '噬嗑': 'l', '随': 'm', '无妄': 'n', '明夷': 'o',
           '贲': 'p', '既济': 'q', '家人': 'r', '丰': 's', '离': 't', '革': 'u', '同人': 'v', '临': 'w', '损': 'x', '节': 'y',
           '中孚': 'z', '归妹': '0', '睽': '1', '兑': '2', '履': '3', '泰': '4', '大畜': '5', '需': '6', '小畜': '7', '大壮': '8',
           '大有': '9', '夬': '+', '乾': '/'}
    b64text = ''
    i = 0
    while i < len(str):
        x = str[i]
        if x not in dic:
            i += 1
            x += str[i]
        if x not in dic:
            print("解密失败,密文错误")
            exit(1)
        b64text += dic[x]
        i += 1
    return base64.b64decode(b64text + '=' * (4 - len(b64text) % 4))


def decrpyt5(enc):
    dec = ''
    a, b = 5, 7
    for i in enc:
        y = ord(i) - 97     # 化简为 y
        n = a - (y - 7) % a     # 求满足情况的任意n
        x = int(((y + n * 26 - b) / a) % 26)    # int强制类型转换
        dec += chr(x + 97)  # 存储
    return dec


def decrpyt4(enc):
    dec = ''
    offset = 5
    for i in range(len(enc)):
        dec += chr(ord(enc[i]) + offset + i)
    return dec


if __name__ == '__main__':
    fucidetext = defuxi64(s).decode()  # 解卦
    fucidetext = base64.b64decode(fucidetext).decode()  # base64解码
    print(fucidetext)

    dec4text = decrpyt4(fucidetext) #encrpyt4的解密算法
    print(dec4text)

    dec5text = decrpyt5(dec4text)   #encrpyt5的解密算法
    print(dec5text)
    
#okarn^mnWeggShdPc`J^\R
#tqhzwhxzdsvwdzwdxvavul
#shaodayouxiduoduyijing

0x11 一段新闻

解压得到一个txt,显示有20kb但是打开发现只有一小段话。

近日,教育部、财政部印发《关于实施中小学幼儿园教师国家级培训计划(2021—2025年)的通知》(以下简称《通知》),明确“十四五”期间“国培计划”实施思路、支持方向、工作重点,推进教师培训提质增效,助力教师队伍高质量发展。《通知》要求,“十四五”期间,要重点支持中西部欠发达地区农村义务教育学校、幼儿园骨干教师、校园长和培训者深度培训;实现巩固拓展教育脱贫攻坚成果同乡村振兴有效衔接,支持国家乡村振兴重点帮扶县教师校长能力整体提升;辐射带动省、市、县、校级教师培训,实现教师培训全覆盖。 《通知》从培训内容体系、机制改革、能力建设、监管评价4个方面明确10项重点工作。在内容方面,强调要突出教师核心素养培养,将思想政治和师德师风作为必修内容。在机制改革方面,强调要实行分层分类精准培训,建立教师自主发展机制;创新教师发展协同机制,深入实施教师发展“一对一”精准帮扶;推动人工智能与教师培训融合,探索“智能+教师培训”,形成人工智能支持教师终身学习、持续发展的机制。在能力建设方面,强调要完善教师专业发展支持服务体系,加强市县教师发展机构专业化建设,建强专业化教师培训队伍,加强培训资源和平台建设,实现优质资源全面覆盖、全体共享。在监管评价方面,强调强化培训实施的监管评价,对教师学习过程和效果进行综合评价,适时提供反馈和跟踪指导。

为0宽字符隐藏信息,使用在线工具直接解压,得到24字社会主义核心加密密文

公正公正公正友善公正公正民主公正法治法治诚信民主法治法治公正爱国法治敬业平等友善敬业公正自由和谐富强公正诚信自由法治自由平等诚信平等法治敬业公正诚信平等法治平等平等诚信平等法治自由法治文明法治敬业平等诚信平等法治自由和谐富强平等诚信平等法治平等公正友善爱国公正自由公正平等法治文明法治和谐法治自由公正民主公正诚信自由公正自由平等诚信平等法治和谐公正友善敬业公正和谐公正敬业公正民主和谐民主公正敬业法治和谐公正友善法治和谐诚信平等法治诚信和谐

exp

# -*- coding:utf-8 -*-
from urllib.request import unquote

def de_Socialism(cryptostr):
    values = '富强民主文明和谐自由平等公正法治爱国敬业诚信友善'
    duo = []
    for i in cryptostr:
        num = values.index(i)
        if num == -1:
            continue
        elif num & 1:
            continue
        else:
            duo.append(num >> 1)
    hexs = []
    i = 0
    while (i < len(duo)):
        if duo[i] < 10:
            hexs.append(duo[i])
        elif duo[i] == 10:
            i += 1
            hexs.append(duo[i] + 10)
        else:
            i += 1
            hexs.append(duo[i] + 6)
        i += 1
    res = ''.join([hex(i)[2:].upper() for i in hexs])
    if len(res) == 0:
        return 0
    splited = []
    for i in range(len(res)):
        if i & 1 == 0:
            splited.append('%')
        splited.append(res[i])
    result = unquote(''.join(splited))
    return result.encode()

if __name__ == '__main__':
    print(de_Socialism("公正公正公正友善公正公正民主公正法治法治诚信民主法治法治公正爱国法治敬业平等友善敬业公正自由和谐富强公正诚信自由法治自由平等诚信平等法治敬业公正诚信平等法治平等平等诚信平等法治自由法治文明法治敬业平等诚信平等法治自由和谐富强平等诚信平等法治平等公正友善爱国公正自由公正平等法治文明法治和谐法治自由公正民主公正诚信自由公正自由平等诚信平等法治和谐公正友善敬业公正和谐公正敬业公正民主和谐民主公正敬业法治和谐公正友善法治和谐诚信平等法治诚信和谐"))

#b'flag{why_d0nt_you_try_t0_understand_socia1ism?}'

0x12 RSSSSSA

得到一个txt,打开发现一个e和多组n和c

$$
m^e = c_1\ mod\ n_1
$$


$$
m^e = c_2\ mod\ n_2
$$


$$
m^e = c_3\ mod\ n_3
$$


使用不同的模数n,相同的公钥指数e加密相同的信息。就会得到多个(m^e) ==ci (mod ni),将(m^e)视为一个整体M,这就是典型的中国剩余定理适用情况。按照中国剩余定理小节容易求得m^e的值,当e较小时直接开e方即可。

# 来源:https://www.bilibili.com/read/cv13406617/

import libnum
from gmpy2 import invert, gcd, iroot


def op(x):
    res = 1
    for i in x:
        res *= i
    return res


def CRT(m, a):
    assert (len(m) == len(a))
    M = op(m)
    sum = 0
    for m, a in zip(m, a):
        Mi = M // m
        ti = invert(Mi, m)
        sum += a * ti * Mi
    return sum % M


def GCRT(m, a):
    assert (len(m) == len(a))
    curm, cura = m[0], a[0]
    for m, a in zip(m[1:], a[1:]):
        d = gcd(curm, m)
        c = a - cura
        assert (c % d == 0)
        K = c // d * invert(curm // d, m // d)
        cura += curm * K
        curm = curm * m // d
    return cura % curm


e = 29
n = [
    30327806559308143170251580709344293187241377730282921872781575442079759214585250363018838833645033147048274099882927502135822532658361986843089038971809699440265951177983452623836631182131316783838858410002798162604085127069663694047960859197275399255233610031615817404372364349637055800705223698180870067436988096453852212302215116141417320041306889953482862584091194471138823690888819261753453934793173621702326066309884946089600954181869152898879815596750534117681142535676578782280108274188679221706983417414010745084946761574988283779791817969892384961589321416872995532377690950727835973399647956491090102555409,
    21201945432185822273274384690776217497058902883149769388717005633136179247488270702594230376181288768858812012728332675867062647184506694171059959523739358150427193785288862325490483145892589156285417654675409522395461778047750713685913892924628709666682898716590870448590373784915689173142592010032611604863227130433544024508077340982534157235155525782725897976772958969688875400789351919632303930452916408599309209320071861151825269791353531470198408880292345886431587538581009065968803858039954194364023302947597373427552936469472639511930960050054058074397349282354505376836608524919420271358644040625272611834141,
    22066722902445052583751020956045490471001229482392491124491605354676847417172264621341464938604744547196288089839857467414993454346487337649230414610787992018112868327537703873968574017809192037003789320466268844177192403612544118218277599434212247848173311593650429895564484864389688450385022488374534161927558878171030816097844863947341831453646609936063871558801826304657779664413322335636640541461530342335752307248094073705764721946570652851209785138013258495645549732438232440380725327458972312411697319199017195198686877941387699409525165884596929130086232751883272627080260637468553554114550895128931332556731,
    22201854184449819277142185267444382273897841368693102934683821764656962395743826157719287435432760269046740745554089225345079284556882054478011586504345324432037743900501514661174050074095054738909658615769021337525829263909874107830437595890817773992121956416657353703784722839247395770361048793369307710079965231303120658766595423843609770605074056488132086912631857454296414163240447182566834479775710868231123976843543989150070863055009604342636257860806777650229259057896505901924417615469387152636729167180379751548900559610148369495057752373605259839922528981148145028120068953655171238962097381144518051147647,
    23083840233620992224264526611828536460163558999895002497626591923027006640369297896797243966752151170505775381864181314027021495993588967339108820520528972816379841269197877268187639445751437743759925034716110259215833511647315164717603384871571434294945499053929574035111488209616165563966647430661297795173473421242368063748311843339991310650516321423828411278303633083702771322000349673510635860126984256969661571754688788776209025080804889751723316765593984981235995307564443348633486717797511234178142487310778666548407208267425343907584339092352000989025888560813696453621147789642611872568202165905056714548393,
    23218822553600624275851570918327600443202628196986792799225558073420180848161120578874626283971398879263850567245985782927539083923897342980706479709569579629418591343916765139087666874177802508777776627037319228004136490718510415593236575453393195566284309655647871922536044561206875353630359295663312099218766232095780724182736486077598036512073334536846225792741359530446751954255489310204542643379502811042809497521182466190499994814904710462792494798490083908932248164953870969612782940162469775904944210724177461134898671189252356405455733124848794067548040801451291259009951270923040763880342053172756399581161,
    15537621716770448782502134748692657546482394987891814167799488723003580500457315182184780510271452262025473252065075152671351786862081823121704341999623090322622893909472600153140827895279392030437881151726836273881483138361166633444702898613389403354997826623821941237846412179222285546753657710048063757827302566538233983504273873252358216792306525072453406699162260561047287090285490165275142295462447156551127598082848917540871566229207376989948730655600666112133543582179171414297735210520886697976984424647098383547804465263579778326244367614695099540268893495474464880528394459062149362976029449912614166126761]
c = [
    6046094125227689870033870506917812276305436053796436442363822401342062726188042561670757795460948077415972706427946093618320717744079441259077874700893204459036501380012163686628771354515016380758564221578468509762354597066344146672996248499856111282865676568650895987550682149774776905594210993204175895358464315828610392955454920047755436033052407392579110231386427222684373442110938309074563238848319417352567379700597401198483471415807726938645013860932841996827926718400267742249916874079269259123794751964917045940979213140450626289795549071713337129466329394763935853156424248229732551544822323764365359825485,
    5845552286578226566598806127534836409831300694599972428266617271147189508983086233231766595846029052663890341733882461545982026551439575193608090205669127833427025577685774642780332691084053603909859869193052420285065348378657385164191605378649460509586471212644006322411828860570889277856429353408252263239239828396565949357208821626888694650997167695580553398057963048443171407094467284923234982142222808183498767632834628360161922076588397865384233638848062174627983119799111822718694488311274624762022407317556646065445367315918249540635444036633880194363965914260210883151429898423440605220973034396774973125632,
    15903392352203298605877945674465143966769721737532685945162112598239954843499500918942681985964024463454447115748161245918002002655617193080894539813344429249706695035313266913563071057661003650948948239324748886703222675088558181086755212852968181312257303494407773363350004731534848190264255069536036133029778028229221293469762527695954265711168400217935692988501544247020837424584759831204521029707454822146517072769268420888169838807185669690437151962231817248323732857623620673773191557407520247312964435867860663874242179929967218588152288202476576081222176785925045418916462303292404117304143574686336544149629,
    9669717038949021329020108540640237663067756966280810642417630134992373130879787768749181913381401511774773393506456589516952861294673561533008751071662723277608866325874519278507984666760149692092823573606053373801025601646795839172562607132726532904679698936251789947925155456255628127932509101557747423647220724762995217296493861282238350001729340519429193525028741636093329396359178973155083792632330011484299821599210312002159965537430090985352568581714148228760952230630659713444400585630168629530652207170759737992501963831886075598264013355139219445863531555822055994574891400262563108434859568651780227557975,
    7914090642636266923294026791261427849044695562739254282481166732020837928041454353817133871854948761397284836379753705671724947241779482598081203575216043223216563037754382992648875469848870865515423794755447621640988585802308628444956443228403796584499863761840901610073862093944795357445536465073500157568848798543720484354000858578319564737563857043549861785205215491288782410945294230845471220683129677585701046542907136512616807429274294758158965956146717352157078092334387660733724142855367118044193694310952976603009653011262032422467651663006916850935081716939520365535884320814471253649009945816472423048447,
    11988310991395265980081594718856590638441631362665678269045945813797124375621091172731397011814305000162712601455584541005431841875115788140698346738764417691906578333694503756521160780120138569779573589730959145320537390172280626510886154211649716255438845119004751973530199741765756641003306339421117668796100661313571568100843237996562080095649017634551873879219917272328238629844657368364890324594141674498942544827428056492747949043332622214494766621587698339619576784948756333563714427524714670635509179215190783959390410232309595570890592221268445440689742423642145049491551659385729937300897657450196112613804,
    13758385300968829470189169449584800778823082473607121434049610051116374924292341244419430157132107552964735632092568046439074559673147580828760077490267517852677562615547566840913903686439783964549498803731879665085652815249977620067028187162008373600851339874309707587214786555705953533197711132611955125553398328736012543728815790951625456481002420603689802771155816294782083229750332438335093308789359642911367376579780093093577929312234635979675059828551040384269343053231849182709709271027703443106568079145606579815607660891685636327906452992083196131013003312334278998794497774078191519059014857427818993752773]

if __name__ == '__main__':
    m = CRT(n, c)
    m1 = iroot(m, e)  # 开e次方
    print(m1)
    print(libnum.n2s(int(m1[0])))

#(mpz(56006392793427932363904888802080919147021465251212119978037492467678175693655632715991384875030569597), True)
#b'flag{b3f4fe99-7b70-4fde-bac6-3243eff89f0b}'