本文最后更新于6 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com
import bcrypt
PEPPER = b"number1" # 固定 pepper
COST = 5 # 固定 cost=5
def bcrypt_with_pepper(password: str) -> str:
# 把输入密码(可能含 \x00)解析成真实字节
pwd_bytes = password.encode('utf-8').decode('unicode_escape').encode('latin1')
# 添加 pepper
combined = pwd_bytes + PEPPER
# 自动生成盐(cost=5)
salt = bcrypt.gensalt(rounds=COST)
# 计算 bcrypt
hashed = bcrypt.hashpw(combined, salt)
return hashed.decode()
if __name__ == "__main__":
password = input("输入密码: ")
hashed = bcrypt_with_pepper(password)
print("bcrypt 哈希结果:")
print(hashed)
salt 和pepper 是什么?
salt是随机生成嵌入到哈希中的字符,用了salt 后:即使两个用户用了相同密码(比如都用 “123456”),各自的 salt 不同,最终哈希结果也完全不同(比如你的代码中,同一密码生成的哈希每次都不一样),彩虹表会彻底失效 —— 攻击者不可能提前计算出 “所有密码 + 所有可能 salt” 的组合。
pepper 是在密码前后添加的固定字符,不会体现在hash中,加密者自己保存。
破解添加了pepper的hash(知道pass的情况下)
1、获取pepper
python.exe .\d.py
输入密码: a
bcrypt 哈希结果:
$2b$05$ZTvj5aQDc9dZc1tmGCUDUuSbj3kxrPIQPBrLYhXlHGJes4Q47AqOG
echo $2b$05$ZTvj5aQDc9dZc1tmGCUDUuSbj3kxrPIQPBrLYhXlHGJes4Q47AqOG > hash指定的pass
echo a > pass.txtpepper 可以添加在pass 前面,也可以添加在pass 后面。
D:\hashcat-7.1.2\hashcat-7.1.2>hashcat.exe -a 1 -m 3200 hash pass.txt rockyou.txt -O -D 2
D:\hashcat-7.1.2\hashcat-7.1.2>hashcat.exe -a 1 -m 3200 hash rockyou.txt pass.txt -O -D 2这里是添加在 pass 后面
Session..........: hashcat
Status...........: Running
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))
Hash.Target......: $2b$05$ZTvj5aQDc9dZc1tmGCUDUuSbj3kxrPIQPBrLYhXlHGJe...47AqOG
Time.Started.....: Mon Nov 10 09:47:07 2025 (6 secs)
Time.Estimated...: Thu Nov 13 16:50:20 2025 (3 days, 7 hours)
Kernel.Feature...: Pure Kernel (password length 0-72 bytes)
Guess.Base.......: File (pass.txt), Left Side
Guess.Mod........: File (rockyou.txt), Right Side
Speed.#01........: 50 H/s (18.37ms) @ Accel:1 Loops:32 Thr:16 Vec:1
Speed.#02........: 0 H/s (0.00ms) @ Accel:1 Loops:32 Thr:16 Vec:1
Speed.#03........: 0 H/s (0.00ms) @ Accel:1 Loops:32 Thr:16 Vec:1
Speed.#04........: 0 H/s (0.00ms) @ Accel:1 Loops:32 Thr:16 Vec:1
Speed.#*.........: 50 H/s
Recovered........: 0/1 (0.00%) Digests (total), 0/1 (0.00%) Digests (new)
Progress.........: 291/14344385 (0.00%)
Rejected.........: 0/291 (0.00%)
Restore.Point....: 0/1 (0.00%)
Restore.Sub.#01..: Salt:0 Amplifier:291-292 Iteration:0-32
Restore.Sub.#02..: Salt:0 Amplifier:0-0 Iteration:0-32
Restore.Sub.#03..: Salt:0 Amplifier:0-0 Iteration:0-32
Restore.Sub.#04..: Salt:0 Amplifier:0-0 Iteration:0-32
Candidate.Engine.: Device Generator
Candidates.#01...: amustang -> amustang
Candidates.#02...: [Copying]
Candidates.#03...: [Copying]
Candidates.#04...: [Copying]
Hardware.Mon.#01.: Temp: 0c Fan: 0% Util: 0% Core: 400MHz Mem: 800MHz Bus:16
Hardware.Mon.#02.: Temp: 0c Fan: 0% Util: 0% Core: 400MHz Mem: 400MHz Bus:16
Hardware.Mon.#03.: Temp: 0c Fan: 0% Util: 0% Core: 400MHz Mem: 800MHz Bus:16
Hardware.Mon.#04.: Temp: 0c Fan: 0% Util: 0% Core: 400MHz Mem: 400MHz Bus:16
$2b$05$ZTvj5aQDc9dZc1tmGCUDUuSbj3kxrPIQPBrLYhXlHGJes4Q47AqOG:anumber1获取到pepper=number1
qiaojojo
welcome@Hacked:~$ echo -n -e '\x00' | sudo /opt/hash_system/hash_passwd.py
Enter Password> [+] Hash: $2b$05$4I8RL9HIjLK38CT/wkzyMuiKl3P9LQX1uEx9jVae6r35An5gEMdS6掩码加字典,字典加掩码,?b
?b 是一个 字符集占位符,用于表示「所有可能的字节(0x00-0xFF)」,包括可打印字符(如字母、数字、符号)和不可打印的二进制字符(如控制字符、空字节等)。
-a 6:字典 + 掩码模式(Dictionary + Mask)
-a 7:掩码 + 字典模式(Mask + Dictionary)
PS D:\Tools\hashcat-6.2.6> .\hashcat.exe -m 3200 -a 6 -d 1 D:\test\x00.hash D:\Tools\rockyou.txt ?b -O
PS D:\Tools\hashcat-6.2.6> .\hashcat.exe -m 3200 -a 7 -d 1 D:\test\x00.hash ?b D:\Tools\rockyou.txt -OSession..........: hashcat
Status...........: Running
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))
Hash.Target......: $2b$05$4I8RL9HIjLK38CT/wkzyMuiKl3P9LQX1uEx9jVae6r35...gEMdS6
Time.Started.....: Mon Nov 10 10:26:02 2025 (10 secs)
Time.Estimated...: Tue Nov 18 07:35:03 2025 (7 days, 21 hours)
Kernel.Feature...: Pure Kernel (password length 0-72 bytes)
Guess.Base.......: File (rockyou.txt), Right Side
Guess.Mod........: Mask (?b) [1], Left Side
Guess.Queue.Base.: 1/1 (100.00%)
Guess.Queue.Mod..: 1/1 (100.00%)
Speed.#01........: 2015 H/s (22.90ms) @ Accel:1 Loops:32 Thr:16 Vec:1
Speed.#02........: 1365 H/s (22.96ms) @ Accel:1 Loops:32 Thr:16 Vec:1
Speed.#03........: 0 H/s (0.00ms) @ Accel:1 Loops:32 Thr:16 Vec:1
Speed.#04........: 2018 H/s (22.47ms) @ Accel:1 Loops:32 Thr:16 Vec:1
Speed.#*.........: 5401 H/s
Recovered........: 0/1 (0.00%) Digests (total), 0/1 (0.00%) Digests (new)
Progress.........: 53696/3672162560 (0.00%)
Rejected.........: 0/53696 (0.00%)
Restore.Point....: 0/256 (0.00%)
Restore.Sub.#01..: Salt:0 Amplifier:209-210 Iteration:0-32
Restore.Sub.#02..: Salt:0 Amplifier:212-213 Iteration:0-32
Restore.Sub.#03..: Salt:0 Amplifier:0-0 Iteration:0-32
Restore.Sub.#04..: Salt:0 Amplifier:209-210 Iteration:0-32
Candidate.Engine.: Device Generator
Candidates.#01...: skimberly -> $HEX[d86b696d6265726c79]
Candidates.#02...: $HEX[827069637475726573] -> $HEX[ff7069637475726573]
Candidates.#03...: [Copying]
Candidates.#04...: |kimberly -> $HEX[bf6b696d6265726c79]
Hardware.Mon.#01.: Temp: 0c Fan: 0% Util: 0% Core: 400MHz Mem: 800MHz Bus:16
Hardware.Mon.#02.: Temp: 0c Fan: 0% Util: 0% Core: 400MHz Mem: 800MHz Bus:16
Hardware.Mon.#03.: Temp: 0c Fan: 0% Util: 0% Core: 400MHz Mem: 800MHz Bus:16
Hardware.Mon.#04.: Temp: 0c Fan: 0% Util: 0% Core: 400MHz Mem: 800MHz Bus:16
$2b$05$4I8RL9HIjLK38CT/wkzyMuiKl3P9LQX1uEx9jVae6r35An5gEMdS6:$HEX[006e756d62657231]

?l | 小写字母 | a b c ... z | 26 个小写英文字母 |
?u | 大写字母 | A B C ... Z | 26 个大写英文字母 |
?d | 数字 | 0 1 2 ... 9 | 10 个数字 |
?s | 特殊符号 | ! @ # $ % ^ & * ( ) ...(共 33 个) | 可打印的特殊符号(如标点、运算符) |
?b | 所有字节 | 0x00-0xFF(包含不可打印字符,如换行、空字节) | 覆盖所有可能的二进制字节,范围最广 |
?h | 十六进制 | 0-9 a-f A-F(共 16 个字符) | 适合破解十六进制格式的密码 |
ftasy
不太懂
这个 bcrypt 实际上有72字节的限制,⽆论你输⼊多少,它和 salt 组合之后只会处理前⾯ 72 字
节。那如果需要知道 salt 值,最好的⽅法就是逐个爆破。
这⾥可以知道条件有:
1、hash经过 (password + salt ),五轮加密输出。
2、输⼊总⻓ ≤ 30。
3、输⼊总⻓的字节 ≤ 72。
那我构造 71字节就可以得到 salt 的第⼀位,
构造70字节就可以得到 salt 的第⼆位,
依此类推。
⾸先分别找到 1字节、2字节、3字节的字符。为什么要到3⽽不是2,30x ≤ 72 ≤ 30y,明显y要到3



