复刻《Hacknet》游戏 "INCOMING CONNECTION" 全屏警告覆盖层动画的 Windows 桌面工具。
支持单次播放与驻留检测两种模式:直接运行播一次动画;--watch 常驻托盘,检测到端口扫描时自动触发。
- 6 秒完整动画:0.2s 淡入(黑条展开)→ 保持 → 0.2s 淡出,开场/收尾 0.5s 内 10Hz 闪烁(复刻原版时间轴)
- 全屏透明覆盖层:置顶、鼠标点击穿透、不进任务栏,显示期间不干扰任何操作
- 复刻原版视觉:黑色警告条、滚动红黑斜纹、警示图标、Kremlin 标题、终端风详情文字
- 三音效纯内存播放:beep 提示音 + DoomShock/BrightFlash 双音叠加(运行时混音,不写临时文件)
- 分辨率自适应:元素尺寸按屏幕高度相对
ScaleBase缩放,任何分辨率下占屏比例一致 - watch 驻留检测:托盘常驻 + 双信号扫描检测,触发时把真实攻击源 IP 注入详情文字
- 自绘配置/日志窗口:托盘菜单可视化编辑全部配置项,日志窗口 2 秒自动刷新并保持查看位置
- 零网络、零外部依赖、零安装(运行时仅依赖 Windows 内置 .NET Framework 4.8)
- Windows 10 / Windows 11
- .NET Framework 4.8(系统内置组件,无需安装任何 runtime)
IncomingConnectionOverlay.exe
运行即播放覆盖层动画,按 Duration 秒数自动退出;按 ESC 可强制退出。
| 参数 | 说明 |
|---|---|
--preview |
普通可拖动窗口模式,便于调试动画 |
--snapshot <path> [t] |
渲染第 t 秒(默认 3.0)的单帧到 png,无头自验证用 |
--dumpsound <path> |
导出运行时合成的激活音效 wav,检查混音/拼接 |
--watch |
驻留后台(托盘),检测到端口扫描自动触发覆盖层(见下节) |
IncomingConnectionOverlay.exe --watch
常驻系统托盘(隐藏窗口 + 100ms 轮询,无需管理员权限),检测到疑似端口扫描(nmap 等)时自动触发一次覆盖层动画。
双信号检测(任一命中即触发):
- 连接表信号(可按源 IP 归因):轮询
GetExtendedTcpTable,只统计新出现的入站连接(连接级去重,RDP/SSH 等长连接只在建立瞬间计一次,不误报);同一源 IP 在 3 秒窗口内满足任一条件即触发:- 触及的不同本地端口数 ≥ 8(回环源也只走这一门槛,防本机服务自连误报)
- 非回环源且入站事件总数 ≥ 24
- RST 洪峰信号(抓纯 SYN 扫描,无源 IP 归因):轮询
GetTcpStatistics的dwOutRsts增量,3 秒内 ≥40 判定为对关闭端口的扫描
触发行为:
- 连接表信号触发时,详情文字第一行显示真实攻击源 IP(如
External connection from 203.0.113.7),由配置SyncIpToDetail控制开关;RST 信号无归因,使用默认文案 - 动画播放期间不重复触发;触发后进入冷却(
CooldownSeconds,默认 30s,程序强制不小于Duration,两次动画永不重叠) - 托盘右键菜单:立即触发一次覆盖层(跳过冷却,播放中不叠加)/ 修改配置 / 查看日志 / 退出
已知局限:用户态轮询对慢速低流量扫描(nmap -T1)不敏感;单端口高频攻击(distinctPorts 不达标)可能漏报;完整覆盖需管理员权限或 Npcap。
可配置项在 exe 同目录的 IncomingConnectionOverlay.exe.config 的 <appSettings> 中,
缺失或格式错误时回退默认值,程序始终可运行。--watch 模式下可从托盘"修改配置"窗口编辑并保存
(exe.config 不存在时保存会顺带生成一份);保存后下一次覆盖层动画即生效,无需重启:
| 配置项 | 默认值 | 说明 |
|---|---|---|
Duration |
6 |
动画总时长(秒) |
Fade |
0.2 |
淡入/淡出时长(秒) |
BarHeightMax |
120 |
黑条最大高度(px,按 ScaleBase 缩放) |
CenterWidth |
700 |
中央排版区宽(px) |
StripeHeightMax |
24 |
斜纹高度(px) |
StripeSpeed |
1 |
斜纹滚动速度(贴图宽/秒) |
BlinkPeriod |
0.1 |
开场/收尾闪烁周期(秒) |
BlinkOnRatio |
0.5 |
闪烁占空比(0~1) |
Tint |
255,0,0 |
tint 主色(R,G,B,0~255) |
ScaleBase |
1080 |
分辨率缩放基准(屏幕高度 px) |
TitleText |
INCOMING CONNECTION |
标题文字 |
DetailText |
External... |
详情文字( 为换行;watch 注入源 IP 时被覆盖) |
SyncIpToDetail |
true |
watch 检测到扫描时是否把真实源 IP 注入详情文字(true/false) |
ShowNotifications |
true |
是否显示托盘通知:启动气泡 + 检测到攻击气泡(true/false) |
CooldownSeconds |
30 |
watch 触发后冷却时长(秒);程序强制不小于 Duration,防动画重叠 |
手工编辑 config 时,详情文字换行请用
字符引用(属性值里的字面换行会被 XML 规范化为空格);通过"修改配置"窗口编辑则自动处理。
# 构建
dotnet build IncomingConnectionOverlay.slnx
# 发布(产物在 bin\Release\net48\publish\,单 exe)
dotnet publish IncomingConnectionOverlay.slnx -c Release把 publish 目录里的 IncomingConnectionOverlay.exe(可选带 .exe.config)拷给任何人即可运行。
assets/ 目录不入版本库(第三方素材版权不随源码分发),仅含 README.txt 获取指引。
构建前请自行放入以下文件(构建时以 EmbeddedResource 内嵌进 exe,运行时从内存加载,不随 exe 分发):
CautionIcon.png/CautionIconBG.png/StripePattern.png—— 从《Hacknet》游戏解包(或用自有等价素材)beep.wav/doomshock.wav/brightflash.wav—— 提示音与双音效kremlin-1.ttf—— 标题字体(Kremlin)
素材缺失时程序仍可运行(对应元素跳过),但视觉效果不完整。
- 分层窗口:
UpdateLayeredWindow+CreateDIBSection(32bpp ARGB 保留 alpha,避免GetHbitmap丢透明通道);窗口WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_TOOLWINDOW - 动画逻辑:逐行复刻原版
IncomingConnectionOverlay.cs(官方源码),含闪烁/淡入淡出/布局公式;元素尺寸按屏幕高度相对ScaleBase缩放 - 斜纹平铺:
TextureBrush+WrapMode.Tile无缝滚动(DrawImage逐块有 1px 插值接缝) - 文字缩放:
Graphics.Transform等比缩放(避免每帧重建字体导致抖动),绘制前换行符归一为\n - 扫描检测:
GetExtendedTcpTable(入站连接按源 IP 归因 + 连接级去重)、GetTcpStatistics(RST 增量),均无需管理员权限 - 音效:PlaySound 是单通道,多个
Play()会互相打断,故运行时把 beep 与双音效 PCM 混音成一条再内存播放 - 误报说明:360 等国产杀软的启发式规则对"全屏置顶透明窗口 + P/Invoke + 无签名"敏感,属误报(本程序无任何网络与恶意行为);已通过音频纯内存播放、去除临时文件解压、补充版本信息等降低误报面
- 资源解包:XnbConverter、xnb_parse
- 参考:Hacknet 官方源码(IncomingConnectionOverlay / PatternDrawer / TextItem)、BASpark(覆盖层方案参考)