Last active
October 4, 2019 08:37
-
-
Save hellman/42bdd7a359b8ebaf2bc19cb9ca49ff33 to your computer and use it in GitHub Desktop.
PwnThyBytes 2019 CTF - avec
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <stdint.h> | |
#include <unistd.h> | |
#include <assert.h> | |
#include <openssl/aes.h> | |
/* | |
gcc -O3 solve.c -L. -lghash_clmul -lcrypto -o solve | |
LD_LIBRARY_PATH=. time ./solve | |
... | |
j 0000000074000000: eca170b9065f6fac | |
pwned nonce: cc08407e4f4d770acc08407e00000001 | |
key: dce3354f78b6b53ddce3354f78b6b53d | |
5054424354467b376163663362363062 | |
PTBCTF{7acf3b60b | |
3038313937363765613637623464347d | |
0819767ea67b4d4} | |
~ 1 hour | |
*/ | |
typedef unsigned char u8; | |
typedef unsigned int u32; | |
static void xor_block(u8 *dst, const u8 *src) { | |
u32 *d = (u32 *) dst; | |
u32 *s = (u32 *) src; | |
*d++ ^= *s++; | |
*d++ ^= *s++; | |
*d++ ^= *s++; | |
*d++ ^= *s++; | |
} | |
int ghash_expand_clmul(u8* hk, void** ctxptr); | |
int ghash_clmul(u8* out, u8*in, size_t ln, u8* prevout, void* ctx); | |
int ghash_destroy_clmul(void *ghash_tables); | |
int good(u8 *nonce) { | |
if (nonce[0] != nonce[8]) return 0; | |
if (nonce[1] != nonce[9]) return 0; | |
if (nonce[2] != nonce[10]) return 0; | |
if (nonce[3] != nonce[11]) return 0; | |
if (nonce[12] != 0) return 0; | |
if (nonce[13] != 0) return 0; | |
if (nonce[14] != 0) return 0; | |
if (nonce[15] != 1) return 0; | |
return 1; | |
} | |
uint64_t MOD = 0x247f43cb7ull; | |
uint64_t G = 0x3bc02a1eb0a80bc8ull; | |
uint64_t gmul(uint64_t a, uint64_t b) { | |
uint64_t p = 0; | |
while (a && b) { | |
if (b & 1) p ^= a; | |
if (a >> 63) a = (a << 1) ^ MOD; | |
else a <<= 1; | |
b >>= 1; | |
} | |
return p; | |
} | |
int main(int argc, char *argv[]) { | |
u8 ZERO[16] = {}; | |
u8 CT[32] = "\x75\x31\x82\x22\x0e\x54\xf7\xf7\x61\xab\xc2\x7f\x58\x2d\x66\x11\xba\x9a\xe9\x77\x52\x9e\xa7\x8c\xee\x34\xf9\x56\x29\xb6\x6d\xc8"; | |
u8 TAG[16] = "\x97\x45\x52\xaa\xee\x43\x38\x8d\x76\x86\xfa\xe8\x52\xd1\xc0\xae"; | |
u8 AD[16] = "PTB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; | |
u8 LENS[16] = "\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x01\x00"; | |
AES_KEY enc_key, dec_key, dummykey; | |
AES_set_decrypt_key("assume_nothing!!", 128, &dummykey); | |
uint64_t K = G; | |
for (uint64_t j = 0; j < (1ull<<32)+1; j++) { | |
if ( (j & 0xffffff) == 0 )printf("j %016lx: %016lx\n", j, K); | |
u8 key[16] = {}; | |
u8 hkey[16] = {}; | |
u8 nonce[16] = {}; | |
memcpy(key, &K, 8); | |
memcpy(key+8, &K, 8); | |
AES_set_encrypt_key(key, 128, &enc_key); | |
AES_set_decrypt_key(key, 128, &dec_key); | |
AES_encrypt(ZERO, hkey, &enc_key); | |
void *ctx; | |
u8 buf[17] = {}; | |
ghash_expand_clmul(hkey, &ctx); | |
ghash_clmul(buf, AD, 16, buf, ctx); | |
ghash_clmul(buf, CT, 32, buf, ctx); | |
ghash_clmul(buf, LENS, 16, buf, ctx); | |
xor_block(buf, TAG); | |
ghash_destroy_clmul(ctx); | |
AES_decrypt(buf, nonce, &dec_key); | |
if (good(nonce)) { | |
printf("pwned nonce: "); | |
for(int i = 0; i < 16; i++) printf("%02x", nonce[i]); puts(""); | |
printf(" key: "); | |
for(int i = 0; i < 16; i++) printf("%02x", key[i]); puts(""); | |
u8 iv[16]; | |
nonce[15] = 2; | |
AES_encrypt(nonce, buf, &enc_key); | |
xor_block(buf, CT); | |
memcpy(iv, buf, 16); | |
AES_decrypt(buf, buf, &dummykey); | |
for(int i = 0; i < 16; i++) printf("%02x", buf[i]); puts(""); | |
printf("%s\n", buf); | |
nonce[15] = 3; | |
AES_encrypt(nonce, buf, &enc_key); | |
xor_block(buf, CT+16); | |
AES_decrypt(buf, buf, &dummykey); | |
xor_block(buf, iv); | |
for(int i = 0; i < 16; i++) printf("%02x", buf[i]); puts(""); | |
printf("%s\n", buf); | |
} | |
K = gmul(K, G); | |
} | |
return 0; | |
} | |
/* | |
pwned nonce: cc08407e4f4d770acc08407e00000001 | |
key: dce3354f78b6b53ddce3354f78b6b53d | |
5054424354467b376163663362363062 | |
PTBCTF{7acf3b60b | |
3038313937363765613637623464347d | |
0819767ea67b4d4} | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/sage | |
import os | |
from Crypto.Cipher import AES # Use `sage -sh` to install pycryptodome for AES.MODE.GCM | |
from Crypto.Util.number import bytes_to_long, long_to_bytes | |
def do_raise_entropy(input_msg): | |
cipher = AES.new("assume_nothing!!", AES.MODE_CBC, "\x00"*16) | |
return cipher.encrypt(input_msg) | |
def polish_key(key): | |
key = bytes_to_long(key[::-1]) | |
key = GF(2**64).fetch_int(key) | |
key = key ** 0xbcafffff435 | |
key = long_to_bytes( key.integer_representation() )[::-1] | |
assert len(key) == 8 | |
return key | |
def do_encrypt(data): | |
half = polish_key( os.urandom(8) ) | |
key = half + half | |
half2 = polish_key( os.urandom(8) ) | |
nonce = half2 + half2 | |
cipher = AES.new(key, AES.MODE_GCM, nonce = nonce[:12]) | |
cipher.update("PTB") | |
ciphertext, tag = cipher.encrypt_and_digest( do_raise_entropy(data) ) | |
open("flag.bin", "wb+").write(ciphertext + tag) | |
do_encrypt( open("flag.txt").read() ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment