Commit 9a8311de authored by Stefan Hackenberg's avatar Stefan Hackenberg
Browse files

Solution for lecture 3

parent 7320a9fe
%% Cell type:markdown id: tags:
# Lecture 3: Password Attack with Difference Analysis - Introduction
%% Cell type:markdown id: tags:
In this example we want to improve the basic passwdcheck to be resistant against the attack from the last tutorial.
## Improving the code
Let's first recap the password checking loop from the basic passwdcheck:
```c
for(uint8_t i = 0; i < sizeof(stored_password); i++)
{
if (stored_password[i] != passwd[i])
{
password_correct = 0;
break;
}
}
```
The timing attack discussed in the last example worked because the loop's runtime varies with the number of correct characters. Once the first wrong character occurs the loop breaks.
This is, what we want to change:
```c
for(uint8_t i = 0; i < sizeof(stored_password); i++)
{
if (stored_password[i] != passwd[i])
{
password_correct = 0;
}
}
```
This is an excerpt from `3_password_fixed.c`. It is clear that the loop does not break after the first wrong character and always all characters of the password are checked.
%% Cell type:markdown id: tags:
## Develop a new idea
%% Cell type:code id: tags:
``` python
import securec
from securec import util
scope, target = util.init()
```
%% Cell type:code id: tags:
``` python
securec.util.compile_and_flash('./3_password_fixed.c')
```
%% Cell type:code id: tags:
``` python
import struct
import time
import warnings
scope.default_setup()
scope.adc.samples = 500
def capture(attempt):
scope.arm()
target.simpleserial_write('p', attempt.encode('ascii') + b'\x00' * (10 - len(attempt)))
result = target.simpleserial_read('p', 1)
return util.capture(), not bool(result[0])
```
%% Cell type:code id: tags:
``` python
from bokeh.plotting import figure, show
from bokeh.io import output_notebook
from bokeh.models import CrosshairTool
from bokeh.palettes import Category10_10
output_notebook()
```
%% Cell type:code id: tags:
``` python
traces = [(attempt, capture(attempt)[0]) for attempt in ('\x00', 'a', 'i')]
```
%% Cell type:code id: tags:
``` python
p = figure(width=900, height=200)
p.add_tools(CrosshairTool())
for idx, ((attempt1, trace1), (attempt2, trace2)) in enumerate([
(traces[0], traces[1]),
(traces[0], traces[2]),
]):
p.line(
range(len(trace1)),
abs(trace1 - trace2),
line_color=Category10_10[idx],
legend_label=f'abs({attempt1} - {attempt2}) with MAD = {max(abs(trace1 - trace2)):.2f}'
)
show(p)
```
%% Cell type:markdown id: tags:
## MAD password attack
Given two traces $t_1, t_2$ their MAD value is defined as:
$$\text{MAD}(t_1, t_2) := \text{max}\big( \big| t_1[i] - t_2[i] \big| \big),$$
where $t[i]$ is the value of trace $t$ at point $i$.
%% Cell type:code id: tags:
``` python
def mad(trace1, trace2):
return max(abs(trace1 - trace2))
```
%% Cell type:code id: tags:
``` python
def attack_password_mad(
mad_threshold=0.045,
charlist='abcdefghijklmnopqrstuvwxyz0123456789',
basechar='\x00',
):
result = False
password = ''
while not result or len(password) > 9:
basetrace, _ = capture(password + basechar)
for c in charlist:
trace, result = capture(password + c)
if mad(trace, basetrace) > mad_threshold:
password += c
print(f'success: "{c}" => password = {password}')
break
else:
print('no found')
break
return password, result
```
%% Cell type:code id: tags:
``` python
attack_password_mad()
```
%% Cell type:code id: tags:
``` python
util.exit()
```
%% Cell type:code id: tags:
``` python
```
%% Cell type:markdown id: tags:
# Lecture 3: Password Attack with Difference Analysis - Analyse
%% Cell type:markdown id: tags:
In this example we want to improve the basic passwdcheck to be resistant against the attack from the last tutorial.
## Improving the code
Let's first recap the password checking loop from the basic passwdcheck:
```c
for(uint8_t i = 0; i < sizeof(stored_password); i++)
{
if (stored_password[i] != passwd[i])
{
password_correct = 0;
break;
}
}
```
The timing attack discussed in the last example worked because the loop's runtime varies with the number of correct characters. Once the first wrong character occurs the loop breaks.
This is, what we want to change:
```c
for(uint8_t i = 0; i < sizeof(stored_password); i++)
{
if (stored_password[i] != passwd[i])
{
password_correct = 0;
}
}
```
This is an excerpt from `3_password_fixed.c`. It is clear that the loop does not break after the first wrong character and always all characters of the password are checked.
%% Cell type:markdown id: tags:
## MAD password attack
Given two traces $t_1, t_2$ their MAD value is defined as:
$$\text{MAD}(t_1, t_2) := \text{max}\big( \big| t_1[i] - t_2[i] \big| \big),$$
where $t[i]$ is the value of trace $t$ at point $i$.
%% Cell type:code id: tags:
``` python
import securec
from securec import util
scope, target = util.init()
```
%% Cell type:code id: tags:
``` python
securec.util.compile_and_flash('./3_password_fixed.c')
```
%% Cell type:code id: tags:
``` python
import struct
import time
import warnings
import numpy as np
scope.default_setup()
scope.adc.samples = 500
def capture(attempt, count=1):
traces = []
for _ in range(count):
scope.arm()
target.simpleserial_write('p', attempt.encode('iso-8859-1') + b'\x00' * (10 - len(attempt)))
result = target.simpleserial_read('p', 1)
traces.append(util.capture())
return np.mean(np.array(traces), axis=0), not bool(result[0])
```
%% Cell type:code id: tags:
``` python
from bokeh.plotting import figure, show
from bokeh.io import output_notebook
from bokeh.models import CrosshairTool
from bokeh.palettes import Category10_10
from bokeh.models import Span, Label, BoxAnnotation
output_notebook()
```
%% Cell type:code id: tags:
``` python
def mad(trace1, trace2):
return max(abs(trace1 - trace2))
```
%% Cell type:code id: tags:
``` python
util.exit()
```
%% Cell type:markdown id: tags:
## Analysis of differences
%% Cell type:markdown id: tags:
<div style="background: #f0ffe0; padding: 15px; border: 1px solid slategray;">
<div class="h2" style="font-variant: small-caps;">Exercise 1</div>
Have a look at the assembly code of `3_password_fixed.c`. It's the `.lss` file. Understand instruction per instruction what the CPU is doing. The [XMEGA reference manual](http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-8210-8-and-16-bit-AVR-Microcontrollers-XMEGA-D_Manual.pdf) might be helpful.
</div>
%% Cell type:markdown id: tags:
<div style="background: #f0ffe0; padding: 15px; border: 1px solid slategray;">
<div class="h2" style="font-variant: small-caps;">Exercise 2</div>
Create a plot to explain your investigations and especially their relation to the MAD-Attack. The plot below is an example. The manual of [bokeh](https://docs.bokeh.org/en/latest/index.html) might be helpful. I used `line`, `Span`, `Label`.
<img src="Lecture 3: Password Attack with Difference Analysis - Analyse.png"></img>
</div>
%% Cell type:markdown id: tags:
<div style="background: #f0ffe0; padding: 15px; border: 1px solid slategray;">
<div class="h2" style="font-variant: small-caps;">Exercise 3</div>
Explain why
- At "ins 3" the green line is much higher than the others
- At "ins 3" the others are not equal in height
- The differences at "ins 1" are quite high
</div>
%% Cell type:markdown id: tags:
# Lecture 3: Password Attack with Difference Analysis - Analyse
%% Cell type:markdown id: tags:
In this example we want to improve the basic passwdcheck to be resistant against the attack from the last tutorial.
## Improving the code
Let's first recap the password checking loop from the basic passwdcheck:
```c
for(uint8_t i = 0; i < sizeof(stored_password); i++)
{
if (stored_password[i] != passwd[i])
{
password_correct = 0;
break;
}
}
```
The timing attack discussed in the last example worked because the loop's runtime varies with the number of correct characters. Once the first wrong character occurs the loop breaks.
This is, what we want to change:
```c
for(uint8_t i = 0; i < sizeof(stored_password); i++)
{
if (stored_password[i] != passwd[i])
{
password_correct = 0;
}
}
```
This is an excerpt from `3_password_fixed.c`. It is clear that the loop does not break after the first wrong character and always all characters of the password are checked.
%% Cell type:markdown id: tags:
## MAD password attack
Given two traces $t_1, t_2$ their MAD value is defined as:
$$\text{MAD}(t_1, t_2) := \text{max}\big( \big| t_1[i] - t_2[i] \big| \big),$$
where $t[i]$ is the value of trace $t$ at point $i$.
%% Cell type:code id: tags:
``` python
import securec
from securec import util
scope, target = util.init()
```
%% Cell type:code id: tags:
``` python
securec.util.compile_and_flash('./3_password_fixed.c')
```
%% Cell type:code id: tags:
``` python
import struct
import time
import warnings
import numpy as np
scope.default_setup()
scope.adc.samples = 500
def capture(attempt, count=1):
traces = []
for _ in range(count):
scope.arm()
target.simpleserial_write('p', attempt.encode('iso-8859-1') + b'\x00' * (10 - len(attempt)))
result = target.simpleserial_read('p', 1)
traces.append(util.capture())
return np.mean(np.array(traces), axis=0), not bool(result[0])
```
%% Cell type:code id: tags:
``` python
import math
from bokeh.plotting import figure, show
from bokeh.io import output_notebook
from bokeh.models import CrosshairTool
from bokeh.palettes import Category10_10
from bokeh.models import Span, Label, BoxAnnotation
output_notebook()
```
%% Cell type:code id: tags:
``` python
def mad(trace1, trace2):
return max(abs(trace1 - trace2))
```
%% Cell type:markdown id: tags:
## Analysis of differences
%% Cell type:markdown id: tags:
### Assembly code analysis
%% Cell type:markdown id: tags:
```c
uint8_t password_wrong = 0;
for (unsigned int i = 0; i < sizeof(stored_password) - 1; i++)
{
if (stored_password[i] != input[i])
// Load Indirect and Post-Increment. Z contains address to stored_password
22e: 21 91 ld r18, Z+
// Load Indirect and Post-Increment. X contains address to input
230: 8d 91 ld r24, X+
// Compare, Skip if Equal, i.e. (IF r18 == r24 => Jump over next assembly instruction <-> ldi r25, 0x01)
232: 28 13 cpse r18, r24
{
password_wrong = 1;
// Load immediate <-> r25 = 0x01 <-> password_wrong = 1 <-> if executed a peak in power consumption can be seen
234: 91 e0 ldi r25, 0x01 ; 1
// NOTE: Head of loop in assembly mostly at the end <-> i < sizeof(stored_password) - 1; i++
for (unsigned int i = 0; i < sizeof(stored_password) - 1; i++)
// Load immediate <-> r24 = 32
236: 80 e2 ldi r24, 0x20 ; 32
// Compare immediate <-> r30 == 0x08 <-> R30 = i and 0x08 = sizeof(stored_password)
// NOTE: Comparison in assembly done by subtraction --> r30 - 0x08, if 0, then Zero Flag is set
238: e8 30 cpi r30, 0x08 ; 8
// Compare with carry <-> r31 == r24 <-> if r31 - ( r24 + c ) != 0, then zero flag = 0 --> compare False
23a: f8 07 cpc r31, r24
// Branch not equal <-> If Zero Flag not set --> Jump -16 bytes up, i.e. back to 22e
23c: c1 f7 brne .-16 ; 0x22e <check_password+0x18>
23e: 99 83 std Y+1, r25 ; 0x01
{
password_wrong = 1;
}
}
```
%% Cell type:markdown id: tags:
### Plot
%% Cell type:code id: tags:
``` python
basetrace = capture('')[0]
traces = [(attempt, capture(attempt, count=10)[0]) for attempt in ('a', 'b', 'i', '\x00', '\xff')]
p = figure(height=500, sizing_mode='stretch_width', x_range=(20, 60))
p.add_tools(CrosshairTool())
for idx, (attempt, trace) in enumerate(traces):
difftrace = abs(trace - basetrace) * 10
p.line(
range(len(difftrace)),
difftrace,
line_color=Category10_10[idx],
legend_label=f'abs("" - {attempt.encode("iso-8859-1")})'
)
p.line(
range(len(difftrace)),
trace - 0.3,
line_color=Category10_10[idx],
)
for i, (x, label) in enumerate(zip(
range(29, 80, 4),
('ld r18, Z+', 'ld r24, X+', 'cpse r18, r24', 'ldi r25, 0x01', 'ldi r24, 0x20')
)):
p.add_layout(Span(location=x, dimension='height', line_color='darkslateblue', line_width=20, line_alpha=0.1))
p.add_layout(Label(x=x, y=p.plot_height, text=label, y_units='screen', x_offset=-15, y_offset=-35,
text_align='right', text_color='darkslateblue', angle=math.pi/2))
for idx, (_, trace) in enumerate(traces):
p.circle(x, (abs(trace - basetrace) * 10)[x], size=10, color=Category10_10[idx])
show(p)
```
%% Cell type:code id: tags:
``` python
util.exit()
```
%% Cell type:code id: tags:
``` python
```
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment