[BSidesSF2020]decrypto-1

encrypt

import sys
import json
import hashlib


class Crypto:

    def __init__(self, key):
        if not isinstance(key, bytes):
            raise TypeError('key must be of type bytes!')
        self.key = key
        self._buf = bytes()
        self._out = open("/dev/stdout", "wb")

    def _extend_buf(self):
        self._buf += self.key

    def get_bytes(self, nbytes):
        while len(self._buf) < nbytes:
            self._extend_buf()
        ret, self._buf = self._buf[:nbytes], self._buf[nbytes:]
        return ret

    def encrypt(self, buf):
        if not isinstance(buf, bytes):
            raise TypeError('buf must be of type bytes!')
        stream = self.get_bytes(len(buf))
        return bytes(a ^ b for a, b in zip(buf, stream))

    def set_outfile(self, fname):
        self._out = open(fname, "wb")

    def encrypt_file(self, fname):
        buf = open(fname, "rb").read()
        self._out.write(self.encrypt(buf))


class JSONCrypto(Crypto):#Crypto的子类.

    def encrypt_file(self, fname):
        buf = open(fname, "r").read().strip()
        h = hashlib.sha256(buf.encode('utf-8')).hexdigest()
        data = {
                "filename": fname,
                "hash": h,
                "plaintext": buf,
        }
        outbuf = json.dumps(data, sort_keys=True, indent=4)
        self._out.write(self.encrypt(outbuf.encode("utf-8")))


def main(argv):
    if len(argv) not in (3, 4):
        print("%s <key> <infile> [outfile]" % sys.argv[0])
        return
    argv.pop(0)
    key = argv.pop(0)
    inf = argv.pop(0)
    crypter = JSONCrypto(key.encode("utf-8"))
    if sys.argv:
        crypter.set_outfile(argv.pop(0))
    crypter.encrypt_file(inf)


if __name__ == '__main__':
    main(sys.argv)

decrypt

通过代码审计,可以大致了解加密过程为将数据格式化为:
在这里插入图片描述
这个形式后,再与多次重复的key(为了长度和data一样)进行异或来得到密文.我们猜测fname的名字应该为flag.txt(因为密文为flag.txt.enc),这样,如果key不够长的话,我们很容易就可以求出key了.

import json
data = {
                "filename": 'flag.txt',
                "hash": 'h',

        }
outbuf = json.dumps(data, sort_keys=True, indent=4)
cipher_pre=open('flag.txt.enc','rb').read()
for i in range(43):
    print(chr(cipher_pre[i]^ord(outbuf[i])))
key='n0t4=l4g'
for i in range(8):
    key+=key
    #使key足够长.
print(key)
flag=''
for i in range(len(cipher_pre)):
    flag+=chr(ord(key[i])^cipher_pre[i])
print(flag)

# {
#     "filename": "flag.txt",
#     "hash": "2f98b8afa014bf955533a3e72cee0417413ff744e25f2b5b5838f5741cd69547",
#     "plaintext": "CTF{plz_dont_r0ll_ur_own_crypto}"
# }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值