저장을 안해두니 다시 짜기 귀찮음;;

예제는 noxCTF2018 JavaCorporation


https://ctftime.org/task/6542



서버

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import socket
import threading
import random
from Crypto.Cipher import AES
 
key = 'NotGonnaHappenAA'
 
class ThreadedServer(object):
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind((self.host, self.port))
 
    def listen(self):
        self.sock.listen(20)
        while True:
            client, address = self.sock.accept()
            client.settimeout(60)
            threading.Thread(target = self.listenToClient,args = (client,address)).start()
 
    def getIV(self):
        return ''.join([chr(random.randrange(0256)) for i in range(16)])
 
    def encrypt(self, plaintext):
        iv = self.getIV()
        aes = AES.new(key, AES.MODE_CBC, iv)
        return iv + aes.encrypt(plaintext)
 
    def decrypt(self, ciphertext):
        aes = AES.new(key, AES.MODE_CBC, ciphertext[:16])
        return aes.decrypt(ciphertext[16:])
 
    def pkcs5(self, s):
        pad_len = ((-len(s)) % 16)
        if pad_len == 0:
            pad_len = 16
 
        return s + chr(pad_len) * pad_len
 
    def check_pad(self, s):
        pad_len = ord(s[-1])
        if pad_len > 16 or pad_len == 0:
            return False
 
        pad = s[-pad_len:]
        for byte in pad:
            if ord(byte) != pad_len:
                return False
 
        return True
 
    def listenToClient(self, client, address):
        while True:
            try:
                length = int(client.recv(2))
                if (length % 16 != 0 or length <= 16):
                    client.close()
                    break
                else:
                    ciphertext = client.recv(length)
                    plaintext = self.decrypt(ciphertext)
                    if self.check_pad(plaintext):
                        client.send('1')
                    else:
                        client.send('0')
 
            except Exception as e:
                print e
                client.close()
                return False
 
if __name__ == "__main__":
    ThreadedServer('0.0.0.0'3141).listen()
cs



어택

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import socket
 
BLOCK_SIZE = 16
 
def check_pad(cipher):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(('127.0.0.1'3141))
    sock.send(cipher)
    result = b""
    for i in range(0x20,0x40):
        result += sock.recv(1)
    sock.close()
    return result
    
def unpadding_pkcs7(block):
    len_b = len(block)
    n_padd = ord(block[-1])
    if(n_padd==0):
        raise ValueError('bad padding')
    for c in range(0, n_padd):
        if(n_padd != ord(block[len_b-1-c])):
            raise ValueError('bad padding')
            
    unpad_block = block[:-n_padd]
    return unpad_block
 
def get_nextBlock_decrypt(cipher, iv):
    knownP = b""
    for padding_len in range(1,BLOCK_SIZE+1):
        candiP = b""
        result = b""
        for startIdx in range(0x00x810x20):
            sendFeed = b""
            for i in range(startIdx,startIdx+0x20):
                makeIV = b"\x00"*(BLOCK_SIZE-padding_len) + bytes([i ^ (iv[-padding_len]) ^ padding_len])
                for j in range(0,len(knownP)):
                    makeIV += bytes([(iv[len(makeIV)]) ^ (knownP[j]) ^ padding_len])
                sendFeed += str(len(makeIV+cipher)).encode('utf-8')+makeIV+cipher # length send
            result += check_pad(sendFeed)
        print(result)
        candiP = result.decode().find("1")
        candiP= bytes([candiP])
        knownP = candiP + knownP
    return knownP
    
def OraclePaddingAttack(cipher):
    KnownP = b""
    ciphers = []
    for i in range(0len(cipher), BLOCK_SIZE):
        ciphers.append(cipher[i:i+BLOCK_SIZE])
    for i, c in enumerate(ciphers[1:]):
        preIV = ciphers[i]
        KnownP += get_nextBlock_decrypt(c, preIV)
        print(KnownP)
    return KnownP
 
cipher = open("Encrypted.txt","rb").read()
print("len : %d " % len(cipher))
plain = OraclePaddingAttack(cipher)
print(plain)
cs



https://github.com/mwielgoszewski/python-paddingoracle


from paddingoracle import BadPaddingException, PaddingOracle  
from pwn import *

r = remote('chal.noxale.com', 3141)

with open('Encrypted.txt', 'rb') as f:
    data = f.read()

iv = data[:16]
cipher = data[16:]

class PadBuster(PaddingOracle):  
    def __init__(self, **kwargs):
        super(PadBuster, self).__init__(**kwargs)

    def oracle(self, data, **kwargs):
        r.send(bytes(48))
        r.send(iv+data)
        if r.recv(1) == '0':
            raise BadPaddingException

padbuster = PadBuster()
value = padbuster.decrypt(cipher, block_size=16, iv=iv)
print('Decrypted: %r' % (value))     






+ Recent posts