GOLEMWORKS/port_scanner
GitHub: GOLEMWORKS/port_scanner
一款支持 SYN 隐蔽扫描、服务版本探测与 banner 抓取的高性能多线程端口扫描工具,并提供 C 共享库与 JSON 导出能力。
Stars: 0 | Forks: 0
# 端口扫描器 v2.0 (MVP)
一款支持 SYN scan、version detection、banner grabbing 以及导出为 JSON 的渗透测试工具。
## 功能特性
- **TCP Connect Scan** — 通过 connect() 进行标准扫描
- **SYN Scan** — 通过 raw sockets 进行隐蔽扫描(需要 root/CAP_NET_RAW 权限)
- **Version Detection** — 识别服务版本(SSH、FTP、SMTP、HTTP、Memcached 等)
- **Banner Grabbing** — 抓取服务 banner
- **SSL/TLS Detection** — 自动识别 SSL 端口
- **JSON Export** — 将结果导出为 JSON(无外部依赖)
- **Graceful Degradation** — 如果 SYN 不可用,自动回退到 connect scan
- **Multi-threaded** — 高性能多线程扫描
## 编译
### 用于 C API 的 Shared library:
```
g++ -std=c++17 -shared -fPIC -o libport_scanner.so port_scanner.cpp -pthread
```
### CLI 版本:
```
g++ -std=c++17 -o port_scanner_cli port_scanner_cli.cpp -L. -lport_scanner -pthread
```
### 使用 main.cpp (standalone):
```
g++ -std=c++17 -o port_scanner main.cpp -pthread
```
## CLI 使用方法
```
./port_scanner_cli [опции]
```
### 主要选项
- `-h, --host ` — 要扫描的主机(默认:localhost)。可指定多次
- `-f, --file ` — 包含主机列表的文件(每行一个主机)
- `-s, --start ` — 起始端口(默认:1)
- `-e, --end ` — 结束端口(默认:1024)
- `-t, --timeout ` — 超时时间,单位为毫秒(默认:1000)
- `-T, --threads ` — 线程数(默认:10)
- `-r, --range ` — 端口范围(-s 和 -e 的替代方案)
### 新选项 (v2.0)
- `--syn` — 使用 SYN scan 代替 connect scan(需要 root)
- `--version-detect` — 启用服务版本检测
- `--banner-grab` — 启用 banner 抓取
- `--json ` — 将扫描结果导出到 JSON 文件
- `--all-scans` — 启用所有功能(SYN + version + banner)
### 预设方案
```
# 快速扫描 (connect scan, 前 100 个端口)
./port_scanner_cli --start 1 --end 100
# Stealth 扫描 (SYN scan, 前 1024 个端口)
./port_scanner_cli --syn --start 1 --end 1024
# 包含所有检查的完整扫描
./port_scanner_cli --all-scans --host 192.168.1.1
```
### SYN Scan
SYN scan(也称为“半开扫描”)是一种比完整 TCP 连接更高效、更隐蔽的扫描方法。
**工作原理:**
1. 发送 TCP SYN 数据包(连接请求)
2. 如果端口开放 — 目标服务器回复 SYN+ACK,扫描器发送 RST 并断开连接,不完成 3 次握手
3. 如果端口关闭 — 服务器回复 RST
4. 如果被防火墙过滤 — 超时
**SYN scan 的优势:**
- **隐蔽性**:不完成 TCP 连接,在日志中更难被发现
- **速度**:无需等待连接完全建立
- **效率**:可以在单位时间内扫描更多端口
**要求:**
- **root** 权限或 Capability `CAP_NET_RAW` (Linux)
- 在 macOS 上 raw sockets 的工作方式不同 — 会自动回退到 connect scan
**用法:**
```
# 基本 SYN scan (需要 sudo)
sudo ./port_scanner_cli --syn --host 192.168.1.1 --range 1-1024
# 带服务版本检测的 SYN scan
sudo ./port_scanner_cli --syn --version-detect --host example.com --range 1-1024
# 带所有检查的 SYN scan (version + banner grabbing)
sudo ./port_scanner_cli --syn --all-scans --host target.com --range 1-65535
# 带结果导出的 SYN scan
sudo ./port_scanner_cli --syn --version-detect --banner-grab --json report.json --host target.com
```
**回退到 Connect Scan:**
如果进程没有权限使用 raw sockets,程序会自动切换到 connect scan 并输出警告:
```
[WARN] Raw sockets unavailable (need root/CAP_NET_RAW). Falling back to connect scan for target.com
```
### 示例
基础扫描:
```
./port_scanner_cli
./port_scanner_cli --host 192.168.1.1 --host 192.168.1.2
./port_scanner_cli --file hosts.txt
```
带版本检测的 SYN scan:
```
sudo ./port_scanner_cli --syn --version-detect --host example.com
```
完整扫描并导出为 JSON:
```
sudo ./port_scanner_cli --all-scans --json report.json --host 192.168.1.1 --range 1-1024
```
## 工作原理
### TCP Connect Scan
1. 程序创建一个 TCP socket 并尝试与目标端口建立完整连接
2. 如果成功 — 端口开放;如果失败 — 端口关闭或不可达
### SYN Scan ( 隐蔽 )
1. 创建 raw socket 以在 IP 层发送数据包
2. 发送带有随机 source port 的 TCP SYN 数据包
3. 响应情况:
- **SYN+ACK** → 端口开放,发送 RST 断开连接(隐蔽)
- **RST** → 端口关闭
- **ICMP error** → 端口不可达/filtered
4. **Graceful Degradation**:如果 raw sockets 不可用(无 root 权限),自动切换到 connect scan
### Version Detection
对每个开放端口发送 protocol-specific probe:
- **SSH** (22):发送 "SSH-2.0-PortScanner",解析响应
- **FTP** (21):FEAT 命令 (RFC 2389)
- **HTTP** (80):HEAD 请求,解析 Server header
- **SMTP** (25):EHLO 命令
- **Memcached** (11211):"version" 命令
- 结果按 key (host:port) 缓存
### Banner Grabbing
1. 连接到开放端口
2. 等待 500ms 获取自动发送的 banner
3. 返回 banner 的第一行(最多 1024 字节)
### 导出为 JSON
- 手动序列化,无外部依赖
- 包含 scan_info、hosts(包含端口、版本、banner)以及 summary
- 对字符串中的特殊字符进行转义
## 技术细节
- **SYN Scan**:raw sockets (IPPROTO_TCP),手动构建 TCP header,RFC 793 checksum
- **Connect Scan**:使用 SO_RCVTIMEO/SO_SNDTIMEO 的标准 socket()+connect()
- **DNS Resolution**:配合 AF_INET 使用 getaddrinfo()
- **Thread Safety**:使用 mutex 处理队列、结果和输出;使用 atomic 处理进度
- **Cross-platform**:兼容 macOS(针对 raw sockets 提供 SO_CONNECT_TIME 回退)
## 在 Flutter 中使用
可以通过 FFI 调用 C API,从而在 Flutter 应用中使用端口扫描器。
### 为 macOS 编译 shared library
```
g++ -std=c++17 -shared -fPIC -o libport_scanner.dylib port_scanner.cpp -pthread
```
### 为 Android 编译 shared library
Android 需要 NDK。以下是为各种架构编译的示例:
**arm64-v8a:**
```
$NDK/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android21-clang++ \
-std=c++17 -shared -fPIC \
-o libport_scanner_arm64-v8a.so \
port_scanner.cpp \
-pthread
```
**armeabi-v7a:**
```
$NDK/toolchains/llvm/prebuilt/darwin-x86_64/bin/armv7a-linux-androideabi21-clang++ \
-std=c++17 -shared -fPIC \
-o libport_scanner_armeabi-v7a.so \
port_scanner.cpp \
-pthread
```
建议配置 CMakeLists.txt 以便自动为所有目标架构进行编译。
### Dart API (通过 FFI)
```
import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
final DynamicLibrary _lib = Platform.isAndroid
? DynamicLibrary.open('libport_scanner.so')
: DynamicLibrary.open('libport_scanner.dylib');
typedef ScannerCreateFn = Pointer Function(
Pointer> hosts, Int32 hostsCount,
Int32 startPort, Int32 endPort,
Int32 timeoutMs, Int32 maxThreads);
typedef ScannerCreate = Pointer Function(
Pointer> hosts, Int32 hostsCount,
Int32 startPort, Int32 endPort,
Int32 timeoutMs, Int32 maxThreads);
typedef ScannerDestroyFn = Void Function(Pointer scanner);
typedef ScannerDestroy = Void Function(Pointer scanner);
typedef ScannerScanFn = Void Function(Pointer scanner);
typedef ScannerScan = Void Function(Pointer scanner);
typedef ScannerGetResultCountFn = Int32 Function(Pointer scanner);
typedef ScannerGetResultCount = Int32 Function(Pointer scanner);
typedef ScannerGetResultFn = PortResult Function(Pointer scanner, Int32 index);
typedef ScannerGetResult = PortResult Function(Pointer scanner, Int32 index);
typedef ScannerGetHostStatusFn = HostStatus Function(Pointer scanner, Int32 index);
typedef ScannerGetHostStatus = HostStatus Function(Pointer scanner, Int32 index);
final scannerCreate = _lib.lookupFunction('scanner_create');
final scannerDestroy = _lib.lookupFunction('scanner_destroy');
final scannerScan = _lib.lookupFunction('scanner_scan');
final scannerGetResultCount = _lib.lookupFunction('scanner_get_result_count');
final scannerGetResult = _lib.lookupFunction('scanner_get_result');
final scannerGetHostStatus = _lib.lookupFunction('scanner_get_host_status');
@ ffi struct
class HostStatus extends ffi.Struct {
external int value;
}
@ffi.struct
class PortResult extends ffi.Struct {
external Pointer host;
external int port;
external int is_open;
external Pointer service;
}
Future
- >> scanPorts({
required List
标签:C++, 云存储安全, 内核驱动, 插件系统, 数据擦除, 数据统计, 端口扫描, 网络协议, 网络扫描