Skip to content

Commit 2d2e64a

Browse files
committed
Open source 2020 quals challenges
1 parent c72f5c2 commit 2d2e64a

File tree

964 files changed

+156511
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

964 files changed

+156511
-1
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/python3 -u
2+
#Copyright 2020 Google LLC
3+
#
4+
#Licensed under the Apache License, Version 2.0 (the "License");
5+
#you may not use this file except in compliance with the License.
6+
#You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
import random
17+
from Crypto.Util.number import *
18+
import gmpy2
19+
20+
a = 0xe64a5f84e2762be5
21+
chunk_size = 64
22+
23+
def gen_prime(bits):
24+
s = random.getrandbits(chunk_size)
25+
26+
while True:
27+
s |= 0xc000000000000001
28+
p = 0
29+
for _ in range(bits // chunk_size):
30+
p = (p << chunk_size) + s
31+
s = a * s % 2**chunk_size
32+
if gmpy2.is_prime(p):
33+
return p
34+
35+
n = gen_prime(1024) * gen_prime(1024)
36+
e = 65537
37+
flag = open("flag.txt", "rb").read()
38+
print('n =', hex(n))
39+
print('e =', hex(e))
40+
print('c =', hex(pow(bytes_to_long(flag), e, n)))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CTF{__donald_knuths_lcg_would_be_better_well_i_dont_think_s0__}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
n = 0xab802dca026b18251449baece42ba2162bf1f8f5dda60da5f8baef3e5dd49d155c1701a21c2bd5dfee142fd3a240f429878c8d4402f5c4c7f4bc630c74a4d263db3674669a18c9a7f5018c2f32cb4732acf448c95de86fcd6f312287cebff378125f12458932722ca2f1a891f319ec672da65ea03d0e74e7b601a04435598e2994423362ec605ef5968456970cb367f6b6e55f9d713d82f89aca0b633e7643ddb0ec263dc29f0946cfc28ccbf8e65c2da1b67b18a3fbc8cee3305a25841dfa31990f9aab219c85a2149e51dff2ab7e0989a50d988ca9ccdce34892eb27686fa985f96061620e6902e42bdd00d2768b14a9eb39b3feee51e80273d3d4255f6b19
2+
e = 0x10001
3+
c = 0x6a12d56e26e460f456102c83c68b5cf355b2e57d5b176b32658d07619ce8e542d927bbea12fb8f90d7a1922fe68077af0f3794bfd26e7d560031c7c9238198685ad9ef1ac1966da39936b33c7bb00bdb13bec27b23f87028e99fdea0fbee4df721fd487d491e9d3087e986a79106f9d6f5431522270200c5d545d19df446dee6baa3051be6332ad7e4e6f44260b1594ec8a588c0450bcc8f23abb0121bcabf7551fd0ec11cd61c55ea89ae5d9bcc91f46b39d84f808562a42bb87a8854373b234e71fe6688021672c271c22aad0887304f7dd2b5f77136271a571591c48f438e6f1c08ed65d0088da562e0d8ae2dadd1234e72a40141429f5746d2d41452d916
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#Copyright 2020 Google LLC
2+
#
3+
#Licensed under the Apache License, Version 2.0 (the "License");
4+
#you may not use this file except in compliance with the License.
5+
#You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import gmpy2
16+
import sympy
17+
from Crypto.Util.number import *
18+
19+
n = 0xab802dca026b18251449baece42ba2162bf1f8f5dda60da5f8baef3e5dd49d155c1701a21c2bd5dfee142fd3a240f429878c8d4402f5c4c7f4bc630c74a4d263db3674669a18c9a7f5018c2f32cb4732acf448c95de86fcd6f312287cebff378125f12458932722ca2f1a891f319ec672da65ea03d0e74e7b601a04435598e2994423362ec605ef5968456970cb367f6b6e55f9d713d82f89aca0b633e7643ddb0ec263dc29f0946cfc28ccbf8e65c2da1b67b18a3fbc8cee3305a25841dfa31990f9aab219c85a2149e51dff2ab7e0989a50d988ca9ccdce34892eb27686fa985f96061620e6902e42bdd00d2768b14a9eb39b3feee51e80273d3d4255f6b19
20+
e = 0x10001
21+
c = 0x6a12d56e26e460f456102c83c68b5cf355b2e57d5b176b32658d07619ce8e542d927bbea12fb8f90d7a1922fe68077af0f3794bfd26e7d560031c7c9238198685ad9ef1ac1966da39936b33c7bb00bdb13bec27b23f87028e99fdea0fbee4df721fd487d491e9d3087e986a79106f9d6f5431522270200c5d545d19df446dee6baa3051be6332ad7e4e6f44260b1594ec8a588c0450bcc8f23abb0121bcabf7551fd0ec11cd61c55ea89ae5d9bcc91f46b39d84f808562a42bb87a8854373b234e71fe6688021672c271c22aad0887304f7dd2b5f77136271a571591c48f438e6f1c08ed65d0088da562e0d8ae2dadd1234e72a40141429f5746d2d41452d916
22+
23+
a = 0xe64a5f84e2762be5
24+
chunk_size = 64
25+
26+
a_inv = gmpy2.invert(a, 2**chunk_size)
27+
ab = n % 2**chunk_size
28+
abg = a_inv * ab * 2 % 2 ** chunk_size
29+
xab = (n - (abg << chunk_size)) % 2**(chunk_size*2)
30+
31+
for x in sympy.divisors(xab):
32+
if x.bit_length() <= chunk_size and xab // x <= x:
33+
print('testing', hex(x))
34+
chunks = n.bit_length() // (chunk_size*2)
35+
p = 0
36+
a = x
37+
for i in range(chunks):
38+
p += a << (i * chunk_size)
39+
a = a * a_inv % 2**chunk_size
40+
if n % p == 0:
41+
print('factor found:', hex(p))
42+
q = n//p
43+
phi = (p-1)*(q-1)
44+
assert gmpy2.gcd(e, phi) == 1
45+
d = gmpy2.invert(e, phi)
46+
print(long_to_bytes(pow(c, d, n)))
47+
break

2020/quals/crypto-sharky/challenge.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#! /usr/bin/python3
2+
#
3+
#Copyright 2020 Google LLC
4+
#
5+
#Licensed under the Apache License, Version 2.0 (the "License");
6+
#you may not use this file except in compliance with the License.
7+
#You may obtain a copy of the License at
8+
#
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
import binascii
18+
import os
19+
import sha256
20+
21+
# Setup msg_secret and flag
22+
FLAG_PATH = 'data/flag.txt'
23+
NUM_KEYS = 8
24+
MSG = b'Encoded with random keys'
25+
26+
with open(FLAG_PATH, 'rb') as f:
27+
FLAG = f.read().strip()
28+
29+
30+
def sha256_with_secret_round_keys(m: bytes, secret_round_keys: dict) -> bytes:
31+
"""Computes SHA256 with some secret round keys.
32+
33+
Args:
34+
m: the message to hash
35+
secret_round_keys: a dictionary where secret_round_keys[i] is the value of
36+
the round key k[i] used in SHA-256
37+
38+
Returns:
39+
the digest
40+
"""
41+
sha = sha256.SHA256()
42+
round_keys = sha.k[:]
43+
for i, v in secret_round_keys.items():
44+
round_keys[i] = v
45+
return sha.sha256(m, round_keys)
46+
47+
48+
def generate_random_round_keys(cnt: int):
49+
res = {}
50+
for i in range(cnt):
51+
rk = 0
52+
for b in os.urandom(4):
53+
rk = rk * 256 + b
54+
res[i] = rk
55+
return res
56+
57+
if __name__ == '__main__':
58+
secret_round_keys = generate_random_round_keys(NUM_KEYS)
59+
digest = sha256_with_secret_round_keys(MSG, secret_round_keys)
60+
print('MSG Digest: {}'.format(binascii.hexlify(digest).decode()))
61+
GIVEN_KEYS = list(map(lambda s: int(s, 16), input('Enter keys: ').split(',')))
62+
assert len(GIVEN_KEYS) == NUM_KEYS, 'Wrong number of keys provided.'
63+
64+
if all([GIVEN_KEYS[i] == secret_round_keys[i] for i in range(NUM_KEYS)]):
65+
print('\nGood job, here\'s a flag: {0}'.format(FLAG))
66+
else:
67+
print('\nSorry, that\'s not right.')
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CTF{sHa_roUnD_k3Ys_caN_b3_r3vERseD}

2020/quals/crypto-sharky/sha256.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#! /usr/bin/python3
2+
#Copyright 2020 Google LLC
3+
#
4+
#Licensed under the Apache License, Version 2.0 (the "License");
5+
#you may not use this file except in compliance with the License.
6+
#You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
import struct
17+
18+
class SHA256:
19+
20+
def __init__(self):
21+
self.h = [
22+
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c,
23+
0x1f83d9ab, 0x5be0cd19
24+
]
25+
26+
self.k = [
27+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
28+
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
29+
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
30+
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
31+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
32+
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
33+
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
34+
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
35+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
36+
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
37+
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
38+
]
39+
40+
def rotate_right(self, v, n):
41+
w = (v >> n) | (v << (32 - n))
42+
return w & 0xffffffff
43+
44+
def compression_step(self, state, k_i, w_i):
45+
a, b, c, d, e, f, g, h = state
46+
s1 = self.rotate_right(e, 6) ^ self.rotate_right(e, 11) ^ self.rotate_right(e, 25)
47+
ch = (e & f) ^ (~e & g)
48+
tmp1 = (h + s1 + ch + k_i + w_i) & 0xffffffff
49+
s0 = self.rotate_right(a, 2) ^ self.rotate_right(a, 13) ^ self.rotate_right(a, 22)
50+
maj = (a & b) ^ (a & c) ^ (b & c)
51+
tmp2 = (tmp1 + s0 + maj) & 0xffffffff
52+
tmp3 = (d + tmp1) & 0xffffffff
53+
return (tmp2, a, b, c, tmp3, e, f, g)
54+
55+
def compression(self, state, w, round_keys = None):
56+
if round_keys is None:
57+
round_keys = self.k
58+
for i in range(64):
59+
state = self.compression_step(state, round_keys[i], w[i])
60+
return state
61+
62+
def compute_w(self, m):
63+
w = list(struct.unpack('>16L', m))
64+
for _ in range(16, 64):
65+
a, b = w[-15], w[-2]
66+
s0 = self.rotate_right(a, 7) ^ self.rotate_right(a, 18) ^ (a >> 3)
67+
s1 = self.rotate_right(b, 17) ^ self.rotate_right(b, 19) ^ (b >> 10)
68+
s = (w[-16] + w[-7] + s0 + s1) & 0xffffffff
69+
w.append(s)
70+
return w
71+
72+
def padding(self, m):
73+
lm = len(m)
74+
lpad = struct.pack('>Q', 8 * lm)
75+
lenz = -(lm + 9) % 64
76+
return m + bytes([0x80]) + bytes(lenz) + lpad
77+
78+
def sha256_raw(self, m, round_keys = None):
79+
if len(m) % 64 != 0:
80+
raise ValueError('m must be a multiple of 64 bytes')
81+
state = self.h
82+
for i in range(0, len(m), 64):
83+
block = m[i:i + 64]
84+
w = self.compute_w(block)
85+
s = self.compression(state, w, round_keys)
86+
state = [(x + y) & 0xffffffff for x, y in zip(state, s)]
87+
return state
88+
89+
def sha256(self, m, round_keys = None):
90+
m_padded = self.padding(m)
91+
state = self.sha256_raw(m_padded, round_keys)
92+
return struct.pack('>8L', *state)

0 commit comments

Comments
 (0)