https://www.ichunqiu.com/battalion?t=1&r=70899
+ + + + + + + + + + +
三种思路解题
作者:大鲲智联
import
numpy
as
np
dataset = np.load(
'./ctf_ciscn_2024.npz'
, allow_pickle=
True
)
print(dataset.files)
图1 打印相关属性
图2 获取数据长度
print(
"{}"
.format(dataset[
'index'
]))
print(
"{}"
.format(dataset[
'input'
]))
print(
"{}"
.format(dataset[
'trace'
]))
图3 打印数据内容
a…z0…9_!@#
共40个字符,trace是功耗轨迹数据,至此数据已经加载和分析完毕,接下来看看解题思路。思路1
import
matplotlib.pyplot
as
plt
trace = dataset[
'trace'
]
# 获取trace
num = len(dataset[
'trace'
])
# 数量
i =
0
# 第几位密码
for
x
in
range(num):
index = dataset[
'index'
][x]
# 读取下标
# 根据下标值来绘制图
if
index == i:
print(
"当前第{}位密码,输入的字符为'{}'"
.format(index+
1
, dataset[
'input'
][x]))
# 绘制功率轨迹图
plt.figure(figsize=(
20
,
2
))
plt.grid(
True
)
plt.plot(trace[x][:
1000
])
# 绘制
plt.show()
图4 根据功耗轨迹图可以判别第1位密码是下划线_
图5 根据功耗轨迹图可以判别第2位密码是字母c
_ciscn_2024_
,flag值为flag{_ciscn_2024_}
。思路2
import
numpy
as
np
index_array = dataset[
'index'
]
input_array = dataset[
'input'
]
trace_array = dataset[
'trace'
]
t = []
for
i
in
range(
40
):
x_loc = np.argmin(trace_array[i])
# 求最低峰的X坐标位置
print(
"{} 最低峰位置 {}"
.format(input_array[i], x_loc))
t.append(x_loc)
max_index = np.argmax(t)
# 返回最大值的索引
print(
"n第1位正确密码字符 '{}'"
.format(input_array[max_index]))
图6 根据功耗轨迹低峰位置判断第1位正确密码字符
import
numpy
as
np
index_array = dataset[
'index'
]
input_array = dataset[
'input'
]
trace_array = dataset[
'trace'
]
pwdrange_len = len(
"abcdefghijklmnopqrstuvwxyz0123456789_!@#"
)
# 密码字符范围长度
pass_len = len(trace_array) / pwdrange_len
# 猜测的密码长度
password =
""
for
x
in
range(int(pass_len)):
t = []
for
i
in
range(
40
):
x_loc = np.argmin(trace_array[x*
40
+ i])
t.append(x_loc)
max_index = np.argmax(t)
# # 返回最大值的索引
password = password + input_array[max_index]
# 拼接密码
print(
"n正确密码 - '{}'"
.format(password))
# 打印结果
图7 自动化分析低峰值还原密码,但是无法正确判断最后一位
思路3
# 导入必要的库
import
numpy
as
np
from
numpy
import
corrcoef
index_array = []
input_array = []
trace_array = []
index_array = dataset[
'index'
]
input_array = dataset[
'input'
]
trace_array = dataset[
'trace'
]
pwdrange_len = len(
"abcdefghijklmnopqrstuvwxyz0123456789_!@#"
)
# 密码字符范围长度
# 计算第1位密码所有字符功耗轨迹平均值
block_trace = trace_array[
0
:
39
]
# 0-39是第1位密码所有字符功耗轨迹范围
avg_trace = np.mean(block_trace, axis=
0
)
# 求第1组的平均值
# 开始计算每次输入和当前组的平均值的相关系数值
for
i
in
range(pwdrange_len):
corr = corrcoef(avg_trace, trace_array[i])[
0
][
1
]
print(
"当前输入字符{}, 与平均值的相关系数 - {}"
.format(input_array[i], corr))
图8 第1位正确密码计算的相关系数远低于其他值的相关系数
# 导入必要的库
import
numpy
as
np
from
numpy
import
corrcoef
index_array = []
input_array = []
trace_array = []
index_array = dataset[
'index'
]
input_array = dataset[
'input'
]
trace_array = dataset[
'trace'
]
pwdrange_len = len(
"abcdefghijklmnopqrstuvwxyz0123456789_!@#"
)
# 密码字符范围长度
# 计算最后1位密码所有字符功耗轨迹平均值
block_trace = trace_array[
480
:
519
]
# 480-519是最后1位密码所有字符功耗轨迹范围
avg_trace = np.mean(block_trace, axis=
0
)
# 求最后1组的平均值
# 开始计算每次输入和当前组的平均值的相关系数值
for
i
in
range(
480
,
520
):
corr = corrcoef(avg_trace, trace_array[i])[
0
][
1
]
print(
"当前输入字符{}, 与平均值的相关系数 - {}"
.format(input_array[i], corr))
图9 最后1位密码的相关系数值
# 导入必要的库
import
numpy
as
np
from
numpy
import
corrcoef
index_array = []
input_array = []
trace_array = []
index_array = dataset[
'index'
]
input_array = dataset[
'input'
]
trace_array = dataset[
'trace'
]
pwdrange_len = len(
"abcdefghijklmnopqrstuvwxyz0123456789_!@#"
)
# 密码字符范围长度
pass_len = len(trace_array) / pwdrange_len
# 猜测的密码长度
threshold =
0.90
# 设定阈值,用于判断密码字符是否正确
flag =
""
#
for
block
in
range(int(pass_len)):
block_trace = trace_array[(block * pwdrange_len) : ((block+
1
) * pwdrange_len)]
# 分批取每组能耗轨迹
avg = np.mean(block_trace, axis=
0
)
# 求每组的平均值
for
i
in
range(pwdrange_len):
# 开始计算每次输入和当前组的平均值的相关系数值
corr = corrcoef(avg, trace_array[i+pwdrange_len*block])[
0
][
1
]
# 设置判断阈值,然后打印满足条件的输入字符
if
corr < threshold:
flag += input_array[i+pwdrange_len*block]
# 最后打印结果
print(
"flag{}{}{}"
.format(
"{"
, flag,
"}"
))
图10 根据计算相关系数方式正确还原所有密码
总结
关于大鲲智联
+ + + + + + + + + + +
选手解法
作者:Chive_Maiam
i=
1
# 提取 trace 数据
trace = npz_file[
'trace'
]
for
x
in
range(
40
*i,
40
*(i+
1
)):
print(
f"x:
{x}
,
{input_data[x]}
"
)
# 绘制第一个 trace 的功率轨迹图
plt.figure(figsize=(
100
,
6
))
plt.plot(trace[x], label=
'Trace 0'
)
# 绘制第一个 trace 数据
plt.title(
'Power Trace'
)
plt.xlabel(
'Sample Number'
)
plt.ylabel(
'Amplitude'
)
plt.legend()
plt.grid(
True
)
plt.show()
_ciscn_2024_
flag{_ciscn_2024_}
+ + + + + + + + + + +
原文始发于微信公众号(春秋伽玛):官方WP | 侧信道攻击赛题Power Trajectory Diagram解析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论