2021-10-20 MSSCTF_2021_Finals_WP

Crypto

Block_of_Hash_new

题目代码

MSSCTF_2021_FINALS

from Crypto.Util.number import*
from hashlib import sha256
import socketserver
import signal
import string
import random
flag=b"FLAG"*4
theplain=b"a"*16
from Crypto.Cipher import AES
from binascii import hexlify
table = string.ascii_letters+string.digits

HashKey = b'welcometomssctf!'
def pad(m):
    padlen = 16 - len(m) % 16
    return m + padlen * bytes([padlen])

MENU = br'''
<OPTION>
'''

BLANK = br'''
 ______   __                 __                         ___           ____  ____                __       
|_   _ \ [  |               [  |  _                   .' ..]         |_   ||   _|              [  |      
  | |_) | | |  .--.   .---.  | | / ]          .--.   _| |_             | |__| |   ,--.   .--.   | |--.   
  |  __'. | |/ .'`\ \/ /'`\] | '' <         / .'`\ \'-| |-'            |  __  |  `'_\ : ( (`\]  | .-. |  
 _| |__) || || \__. || \__.  | |`\ \        | \__. |  | |             _| |  | |_ // | |, `'.'.  | | | |  
|_______/[___]'.__.' '.___.'[__|  \_]        '.__.'  [___]           |____||____|\'-;__/[\__) )[___]|__] 
                                                                                           
###  #################   wow #####  The #####  Block_of_Hash #####  has #####  just #####  began  #################  ##
'''
class Task(socketserver.BaseRequestHandler):
    def _recvall(self):
        BUFF_SIZE = 2048
        data = b''
        while True:
            part = self.request.recv(BUFF_SIZE)
            data += part
            if len(part) < BUFF_SIZE:
                break
        return data.strip()

    def send(self, msg, newline=True):
        try:
            if newline:
                msg += b'\n'
            self.request.sendall(msg)
        except:
            pass

    def recv(self, prompt=b'SERVER <INPUT>: '):
        self.send(prompt, newline=False)
        return self._recvall()

    def MyHash(self, m):
        aes = AES.new(HashKey , AES.MODE_CBC , iv = HashKey)
        return aes.encrypt(m)[-16:]


    def proof_of_work(self):
        proof = (''.join([random.choice(table)for _ in range(16)])).encode()
        sha = self.MyHash(proof)
        self.send(b"[+] sha256(XXX+" + proof[3:] + b") == " + hexlify(sha))
        XXX = self.recv(prompt = b'[+] Plz Tell Me XXX :')
        if len(XXX) != 3 or self.MyHash(XXX + proof[3:]) != sha:
            return False
        return sha
    
        
    def transaction_hash_generator(self,hashes,transaction):
        block = pad(transaction) + hashes
        return self.MyHash(block)

    def Pr0of_oF_w00k(self,hashes,limited,transaction):
        nonce = random.randrange(0,limited)
        proof = pad(transaction + hex(nonce)[2:].encode()) + hashes
        sha = self.MyHash(proof)
        return sha

    def handle(self):
        
        FirstBlockHash = self.proof_of_work()
        if not FirstBlockHash:
            return
        signal.alarm(180)
        self.send(BLANK)
        for _ in range(5):
            transaction = b"0x114514 transfer 1 bitcoin to 0x1919810"
            BlockHash = self.transaction_hash_generator(FirstBlockHash,transaction)

            limited = 2**11
            self.send(b"SERVER <OUTPUT>:" + str(limited).encode())
            for i in range(3):
                BlockHash = self.Pr0of_oF_w00k(BlockHash,limited,transaction)
            BlockHash = hexlify(BlockHash)
            self.send(b"SERVER <OUTPUT>:Do you already compute the hash? I will give you some hint:" + BlockHash[:29])
            guess = self.recv()
            if guess == BlockHash:
                self.send(b"SERVER <OUTPUT>:Oh you are true")
            else:
                self.send(b"SERVER <OUTPUT>:you Lose!    :(")
                break
        else:
            self.send(b"SERVER <OUTPUT>:flag is " + flag + b'  :)' )
                
        self.send(b"\nConnection has been closed  =.=  ")
        self.request.close()


class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass

class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
    pass

if __name__ == "__main__":
    HOST, PORT = '0.0.0.0', 10001
    print("HOST:POST " + HOST+":" + str(PORT))
    server = ForkedServer((HOST, PORT), Task)
    server.allow_reuse_address = True
    server.serve_forever()

题目分析

是一个AES_CBC高复杂度的破解,限时180s

如果按照正常方法,起码10几分钟

官方WP解法:

  1. 提前将后几轮的IV计算好放入字典
  2. 提前加密后面几轮密文放入字典
  3. 爆破预测,查字典

额外笔记:

  1. strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
  2. if m2 in noncedic可表达m2是否在noncedic的列表内(python基础语法)
  3. 记录到字典减少时间复杂度

EXP

from pwn import *
from Crypto.Util.number import *
from hashlib import sha256
import string
from pwnlib.util.iters import mbruteforce
import time
from binascii import hexlify , unhexlify
from Crypto.Cipher import AES
table = string.ascii_letters+string.digits
transaction = b"0x114514 transfer 1 bitcoin to 0x1919810"
HashKey = b'welcometomssctf!'
aes = AES.new(key = HashKey , mode = AES.MODE_CBC, iv = HashKey)
iv = aes.encrypt(transaction[:32])[-16:]
aes = AES.new(key = HashKey , mode = AES.MODE_ECB)
dic = {
   }

context.log_level="debug"

#context.log_level = 'debug'
XOR = lambda s1,s2: bytes([x1^x2 for x1,x2 in zip(s1,s2)])

def MyHash(m):
    aes = AES.new(HashKey , AES.MODE_CBC , iv = HashKey)
    return aes.encrypt(m)[-16:]

def pad(m):
    padlen = 16 - len(m) % 16
    return m + padlen * bytes([padlen])

def pow(io):
    io.recvuntil(b"XXX+")
    suffix = io.recv(13)
    io.recvuntil(b"== ")
    cipher = unhexlify(io.recvline().strip().decode("utf8"))
    proof = mbruteforce(lambda x: MyHash((x.encode() + suffix)) == cipher, table, length=3, method='fixed')
    io.sendlineafter(b"XXX :", proof) 
    return cipher
def transaction_hash_generator(hashes):
    block = pad(transaction) + hashes
    return MyHash(block)

def getdic(limited):#预测IV表,减少复杂度
    for nonce in range(limited):
        m = pad(transaction[32:] + hex(nonce)[2:].encode())
        m = XOR(m , iv)#aes(明文 xor iv)=cbc
      
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值