-
Notifications
You must be signed in to change notification settings - Fork 262
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
3 changed files
with
65 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# InsomniHack Teaser 2022 | ||
|
||
### Table of contents | ||
|
||
* [nobus-101 (re)](nobus-101) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# nobus-101 | ||
|
||
After reverse-engineering the binary, we learned that it uses the Dual_EC_DRBG backdoored | ||
keys. The curve generatoin itself is deterministic, but we needed to reverse it. It looks like | ||
this: | ||
|
||
```python | ||
MAGIC = 0x132867e88e82431dc40ba24e11bf3ec7ffb18764a3b4df1f5957fd5f37d8be40 | ||
|
||
def gen_backdoor(): | ||
P = P256.G | ||
e = MAGIC | ||
d = mod_inv(e, P256.q) | ||
Q = e * P | ||
return P, Q, d | ||
``` | ||
|
||
This makes it possible to recover the seed using only two random numbers, using the well-studied | ||
attack technique on Dual_EC_DRBG keys. | ||
|
||
We modified the https://github.com/AntonKueltz/dual-ec-poc attack to get a deterministic | ||
seed recovery. | ||
|
||
The interesting piece of our code is: | ||
|
||
```python | ||
def recover_s(bits0, bits1, Q, d): | ||
for high_bits in range(2**16): | ||
guess = (high_bits << (8 * 30)) | bits0 | ||
on_curve, y = find_point_on_p256(guess) | ||
|
||
if on_curve: | ||
# use the backdoor to guess the next 30 bytes | ||
point = Point(guess, y, curve=P256) | ||
s = (d * point).x | ||
r = (s * Q).x & (2**(8 * 30) - 1) | ||
|
||
if r == bits1: | ||
return s | ||
|
||
|
||
def main(): | ||
P, Q, d = gen_backdoor() | ||
data = requests.get("http://nobus101.insomnihack.ch:13337/prng").text | ||
bits0, bits1, *rest = data.split() | ||
bits0 = int(bits0, 16) | ||
bits1 = int(bits1, 16) | ||
|
||
s = recover_s(bits0, bits1, Q, d) | ||
curve = DualEC(s, P, Q) | ||
prediction = hex(curve.genbits())[2:].rjust(60, '0') | ||
text = requests.post("http://nobus101.insomnihack.ch:13337/flag", data=prediction.encode()) | ||
|
||
print(text.text) | ||
``` | ||
|
||
This allowed us to recover the flag. |
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