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解析