Skip to content

Commit

Permalink
attack on challenge to whibox2
Browse files Browse the repository at this point in the history
  • Loading branch information
Medeah committed Oct 29, 2019
1 parent 6d44094 commit 29a332c
Show file tree
Hide file tree
Showing 12 changed files with 60,326 additions and 0 deletions.
25 changes: 25 additions & 0 deletions wbs_aes_whibox2_82/DCA/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
printrounds.c: ../target/82.c printrounds.patch
patch ../target/82.c -i printrounds.patch -o printrounds.c

printrounds: printrounds.c ../target/main.c
gcc -g -O3 printrounds.c ../target/main.c -o printrounds

rounds.trace: printrounds.py printrounds
python2 printrounds.py

ifs.c: analyse.py rounds.trace
python2 analyse.py > ifs.c

tracetransitions.c: ../target/82.c tracetransitions.patch ifs.c
patch ../target/82.c -i tracetransitions.patch -o tracetransitions.c
sed -i -e '/INSERTHERE/r ifs.c' tracetransitions.c

tracetransitions: tracetransitions.c ../target/main.c
gcc -g -O3 tracetransitions.c ../target/main.c -o tracetransitions

attack.config: trace_it.py tracetransitions
python2 trace_it.py

.PHONY: attack
attack: attack.config
daredevil -c attack.config
57 changes: 57 additions & 0 deletions wbs_aes_whibox2_82/DCA/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Attack
------
The DCA attack described here was found by Aleksei Udovenko ([email protected]) and programmed by Frederik Andersen ([email protected]).

The challenge calls 2542 functions multiple times in what it calls rounds. At the end of every function it decides which round should be called next, we can this a transition to a new round. This attack is based on the fact that some rounds always transition to exactly 2 different rounds, each with a ~50% chance. We can trace these transitions by writing a 0 or 1 depending on which is taken. These traces leak the key if we do DCA starting from the ciphertext. It even gives an exact match. Curiously this does not work if we attack the first round.

Usage
-----
One command runs all the steps in the attack:
```bash
make attack
```

Since we attack the last round, we need to reverse the key schedule. This can be done using [Stark](https://github.com/SideChannelMarvels/Stark):
```bash
aes_keyschedule 3e4b16d37537f883bcfb8bbed372adcb 10
```


Individual Steps
----------------

First, we generate the executable that prints the round numbers
```bash
make printrounds
```

Print the rounds called with a random plaintext:
```bash
python2 printrounds.py
```

Analyze which rounds transitions to trace and generate c code to trace them
```bash
python2 analyse.py > ifs.c
```

Generate the executable to trace transitions:
```bash
make tracetransitions
```

Trace the transitions and generate a config file for daredevil. [Here](https://github.com/SideChannelMarvels/Daredevil/wiki) is a description of how to attack the last round of AES.
```bash
python2 trace_it.py
```

Run [Daredevil](https://github.com/SideChannelMarvels/Daredevil):
```bash
daredevil -c attack.config
```

Reverse the key schedule:
```bash
aes_keyschedule 3e4b16d37537f883bcfb8bbed372adcb 10
```

59 changes: 59 additions & 0 deletions wbs_aes_whibox2_82/DCA/analyse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from __future__ import division, print_function
from collections import defaultdict
import sys


def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)




def load_round():
with open("rounds.trace", "r") as f:
rounds = map(int, f.readlines()[:-1])
eprint("done reading rounds")
return rounds


def filter_good(next):
twonext = []
for key, val in next.iteritems():
if len(val) == 2:
# eprint("next for key:", key)
# eprint(list(val.iteritems())[0])
# eprint(list(val.iteritems())[1])
total = list(val.iteritems())[1][1] + list(val.iteritems())[0][1]
rating = list(val.iteritems())[0][1] / total

twonext.append((abs(0.5 - rating), total, val, key))

return filter(lambda x: x[0] < 0.2 and x[1] > 9, twonext)


def goodforall(rounds):
next = defaultdict(lambda: defaultdict(int))
prev = rounds[0]
for number in rounds[1:]:
next[prev][number] += 1
prev = number
return next

def print_code(good, trace_ouput=True):
for rat, total, val, key in good:
hmm = list(val.iteritems())
print("""if (prev == %d) {
if (round == %d) {
printf("0 ");
} else if (round == %d){
printf("1 ");
}
}""" % (key, hmm[0][0], hmm[1][0]))


if __name__ == "__main__":
rounds = load_round()
next_round = goodforall(rounds)
good = filter_good(next_round)

print_code(good)
10 changes: 10 additions & 0 deletions wbs_aes_whibox2_82/DCA/printrounds.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
0a1,2
> #include <stdio.h>
>
59989c59991
< while (round >= 0)
---
> while (round >= 0) {
59990a59993,59994
> printf("%d\n", round);
> }
16 changes: 16 additions & 0 deletions wbs_aes_whibox2_82/DCA/printrounds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from random import randrange, seed
import subprocess


def ranpt():
plaintext = []
for _ in xrange(16):
plaintext.append("{:02X}".format(randrange(0, 256)))
return plaintext

seed(42)
plainst = ranpt()
out = subprocess.check_output(["./printrounds", "".join(plainst)])
with open("rounds.trace", "w") as f:
f.write(out)

79 changes: 79 additions & 0 deletions wbs_aes_whibox2_82/DCA/trace_it.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from __future__ import print_function
from random import randrange
import subprocess
import sys
from multiprocessing import Pool


def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)




def ranpt():
plaintext = []
for _ in xrange(16):
plaintext.append("{:02X}".format(randrange(0, 256)))
return plaintext


def f(i):
plainst = ranpt()
out, cipher, empty = subprocess.check_output(["./tracetransitions", "".join(plainst)]).split("\n")

out = bytearray(map(int, out.split()))
eprint("trace {}".format(i))
eprint("".join(plainst) + " -> " + cipher)
eprint("trace length:" + str(len(out)) + "\n")

plainst = bytearray(map(lambda x: int(x, 16), plainst))
cipherout = bytearray()
for i in range(0, 32, 2):
cipherout.append(int(cipher[i: i+2], 16))

return out, plainst, cipherout

if __name__ == "__main__":
subprocess.check_call(["make", "tracetransitions"])
number_of_traces = 50
p = Pool(4)
print("tracing...")
traces = p.map(f, range(number_of_traces))

with open("plaintext.trace", "wb") as pt:
with open("ciphertext.trace", "wb") as ci:
with open("tracefile.trace", "wb") as tr:
for trace in traces:
tr.write(trace[0])
pt.write(trace[1])
ci.write(trace[2])
trace_len = len(trace[0])

with open("attack.config", "w") as f:
f.write("""[Traces]
files=1
trace_type=i
transpose=true
index=0
nsamples={0}
trace=tracefile.trace {1} {0}
[Guesses]
files=1
guess_type=u
transpose=true
guess=ciphertext.trace {1} 16
[General]
threads=4
order=1
return_type=double
window=0
algorithm=AES
position=LUT/AES_AFTER_SBOXINV
round=0
bytenum=all
bitnum=all
memory=8G
top=20""".format(trace_len, number_of_traces))
14 changes: 14 additions & 0 deletions wbs_aes_whibox2_82/DCA/tracetransitions.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
0a1,2
> #include <stdio.h>
>
59989c59991,59992
< while (round >= 0)
---
> int prev;
> while (round >= 0) {
59990a59994,59998
> // INSERTHERE
>
> prev = round;
> }
> printf("\n");
14 changes: 14 additions & 0 deletions wbs_aes_whibox2_82/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# WhibOx Contest Edition 2 Challenge 82

Gordon F uploaded this challenge to WhibOx Contest Edition 2. The challenge was given the name stoic_thompson. It was broken after 8 days and placed 12.

See the dashboard here: https://whibox.cyber-crypt.com/dashboard

Download the challenge here: https://whibox.cyber-crypt.com/show/candidate/82.c


Components
----------

* `target` contains the original challenge and instructions on how to compile it and how to use it.
* `DCA` contains the DCA attack against this challenge.
Loading

0 comments on commit 29a332c

Please sign in to comment.