|
| 1 | +# Spray SDK |
| 2 | + |
| 3 | +Spray SDK 提供了简洁的 Go API,用于 HTTP URL 检测和路径暴力破解。 |
| 4 | + |
| 5 | +## 核心概念 |
| 6 | + |
| 7 | +SDK 由两部分组成: |
| 8 | + |
| 9 | +1. **SprayEngine**: 管理持久化状态(指纹库等) |
| 10 | +2. **两个核心 API**: |
| 11 | + - `CheckStream`: URL 批量检测,返回 channel |
| 12 | + - `BruteStream`: 路径暴力破解,返回 channel |
| 13 | + |
| 14 | +其他 API(`Check`、`Brute`)都是对 Stream API 的简单封装,你也可以根据需要自行封装。 |
| 15 | + |
| 16 | +## 快速开始 |
| 17 | + |
| 18 | +```go |
| 19 | +import "github.com/chainreactors/spray/sdk" |
| 20 | + |
| 21 | +// 1. 创建 SprayEngine |
| 22 | +engine := sdk.NewSprayEngine(nil) |
| 23 | + |
| 24 | +// 2. 初始化(加载指纹库等) |
| 25 | +engine.Init() |
| 26 | + |
| 27 | +// 3. 使用 |
| 28 | +ctx := context.Background() |
| 29 | + |
| 30 | +// URL 检测 |
| 31 | +urls := []string{"http://example.com", "http://httpbin.org"} |
| 32 | +resultCh, _ := engine.CheckStream(ctx, urls) |
| 33 | +for result := range resultCh { |
| 34 | + fmt.Printf("%s [%d]\n", result.UrlString, result.Status) |
| 35 | +} |
| 36 | + |
| 37 | +// 路径暴力破解 |
| 38 | +wordlist := []string{"admin", "api", "test"} |
| 39 | +resultCh, _ := engine.BruteStream(ctx, "http://example.com", wordlist) |
| 40 | +for result := range resultCh { |
| 41 | + fmt.Printf("%s [%d]\n", result.UrlString, result.Status) |
| 42 | +} |
| 43 | +``` |
| 44 | + |
| 45 | +## 配置 |
| 46 | + |
| 47 | +### 使用默认配置 |
| 48 | + |
| 49 | +```go |
| 50 | +engine := sdk.NewSprayEngine(nil) |
| 51 | +``` |
| 52 | + |
| 53 | +默认配置针对 SDK 场景优化:静默模式、无进度条、单 pool、20 线程。 |
| 54 | + |
| 55 | +### 自定义配置 |
| 56 | + |
| 57 | +```go |
| 58 | +opt := sdk.DefaultConfig() |
| 59 | +opt.Threads = 100 |
| 60 | +opt.Timeout = 10 |
| 61 | +opt.Filter = "current.Status == 404" // 过滤 404 |
| 62 | +opt.Headers = []string{"Authorization: Bearer token"} |
| 63 | + |
| 64 | +engine := sdk.NewSprayEngine(opt) |
| 65 | +``` |
| 66 | + |
| 67 | +### 运行时修改 |
| 68 | + |
| 69 | +```go |
| 70 | +engine.SetThreads(50) |
| 71 | +engine.SetTimeout(10) |
| 72 | +``` |
| 73 | + |
| 74 | +## API 参考 |
| 75 | + |
| 76 | +### SprayEngine |
| 77 | + |
| 78 | +```go |
| 79 | +// 创建实例 |
| 80 | +engine := sdk.NewSprayEngine(opt) // opt 为 nil 时使用默认配置 |
| 81 | + |
| 82 | +// 初始化(必须调用) |
| 83 | +engine.Init() |
| 84 | + |
| 85 | +// 设置参数 |
| 86 | +engine.SetThreads(threads) |
| 87 | +engine.SetTimeout(timeout) |
| 88 | +``` |
| 89 | + |
| 90 | +### 核心 API |
| 91 | + |
| 92 | +```go |
| 93 | +// URL 检测(流式) |
| 94 | +CheckStream(ctx, urls) -> channel |
| 95 | + |
| 96 | +// 暴力破解(流式) |
| 97 | +BruteStream(ctx, baseURL, wordlist) -> channel |
| 98 | +``` |
| 99 | + |
| 100 | +### 便捷 API |
| 101 | + |
| 102 | +```go |
| 103 | +// URL 检测(批量) |
| 104 | +Check(ctx, urls) -> []result |
| 105 | + |
| 106 | +// 暴力破解(批量) |
| 107 | +Brute(ctx, baseURL, wordlist) -> []result |
| 108 | +``` |
| 109 | + |
| 110 | +## 配置选项 |
| 111 | + |
| 112 | +`core.Option` 包含所有 spray 的配置项,常用的有: |
| 113 | + |
| 114 | +**请求配置** |
| 115 | +- `Method`: HTTP 方法 |
| 116 | +- `Timeout`: 超时时间(秒) |
| 117 | +- `Threads`: 线程数 |
| 118 | +- `Headers`: 自定义请求头 |
| 119 | +- `MaxBodyLength`: 最大响应体长度(KB) |
| 120 | + |
| 121 | +**模式配置** |
| 122 | +- `Mod`: 扫描模式(`path` 或 `host`) |
| 123 | +- `Filter`: 过滤规则(expr 表达式) |
| 124 | +- `Match`: 匹配规则(expr 表达式) |
| 125 | +- `BlackStatus`: 黑名单状态码 |
| 126 | +- `WhiteStatus`: 白名单状态码 |
| 127 | +- `RateLimit`: 速率限制(请求/秒) |
| 128 | + |
| 129 | +**插件配置** |
| 130 | +- `Finger`: 启用指纹识别 |
| 131 | +- `CrawlPlugin`: 启用爬虫 |
| 132 | +- `BakPlugin`: 启用备份文件检测 |
| 133 | + |
| 134 | +完整配置项参考 `core.Option` 结构体。 |
| 135 | + |
| 136 | +## 结果结构 |
| 137 | + |
| 138 | +```go |
| 139 | +type SprayResult struct { |
| 140 | + UrlString string // URL |
| 141 | + Status int // HTTP 状态码 |
| 142 | + BodyLength int // 响应体长度 |
| 143 | + Title string // 页面标题 |
| 144 | + IsValid bool // 是否有效 |
| 145 | + Frameworks common.Frameworks // 识别的框架 |
| 146 | + Extracts map[string][]string // 提取的信息 |
| 147 | +} |
| 148 | +``` |
| 149 | + |
| 150 | +## 完整示例 |
| 151 | + |
| 152 | +### 示例 1: URL 批量检测 |
| 153 | + |
| 154 | +```go |
| 155 | +package main |
| 156 | + |
| 157 | +import ( |
| 158 | + "context" |
| 159 | + "fmt" |
| 160 | + "github.com/chainreactors/spray/sdk" |
| 161 | +) |
| 162 | + |
| 163 | +func main() { |
| 164 | + engine := sdk.NewSprayEngine(nil) |
| 165 | + engine.Init() |
| 166 | + engine.SetThreads(50) |
| 167 | + |
| 168 | + urls := []string{ |
| 169 | + "http://example.com", |
| 170 | + "http://httpbin.org/get", |
| 171 | + } |
| 172 | + |
| 173 | + ctx := context.Background() |
| 174 | + results, _ := engine.Check(ctx, urls) |
| 175 | + |
| 176 | + for _, r := range results { |
| 177 | + if r.IsValid { |
| 178 | + fmt.Printf("[+] %s [%d] %s\n", r.UrlString, r.Status, r.Title) |
| 179 | + } |
| 180 | + } |
| 181 | +} |
| 182 | +``` |
| 183 | + |
| 184 | +### 示例 2: 路径暴力破解(流式) |
| 185 | + |
| 186 | +```go |
| 187 | +package main |
| 188 | + |
| 189 | +import ( |
| 190 | + "context" |
| 191 | + "fmt" |
| 192 | + "github.com/chainreactors/spray/sdk" |
| 193 | +) |
| 194 | + |
| 195 | +func main() { |
| 196 | + opt := sdk.DefaultConfig() |
| 197 | + opt.Threads = 100 |
| 198 | + opt.Filter = "current.Status == 404" |
| 199 | + |
| 200 | + engine := sdk.NewSprayEngine(opt) |
| 201 | + engine.Init() |
| 202 | + |
| 203 | + wordlist := []string{"admin", "api", "test", ".git"} |
| 204 | + ctx := context.Background() |
| 205 | + |
| 206 | + resultCh, _ := engine.BruteStream(ctx, "http://example.com", wordlist) |
| 207 | + for result := range resultCh { |
| 208 | + fmt.Printf("[+] %s [%d] %d bytes\n", |
| 209 | + result.UrlString, result.Status, result.BodyLength) |
| 210 | + } |
| 211 | +} |
| 212 | +``` |
| 213 | + |
| 214 | +### 示例 3: 多实例共享指纹库 |
| 215 | + |
| 216 | +```go |
| 217 | +package main |
| 218 | + |
| 219 | +import ( |
| 220 | + "context" |
| 221 | + "github.com/chainreactors/spray/sdk" |
| 222 | +) |
| 223 | + |
| 224 | +func main() { |
| 225 | + // 第一个实例初始化指纹库 |
| 226 | + engine1 := sdk.NewSprayEngine(nil) |
| 227 | + engine1.Init() |
| 228 | + |
| 229 | + // 第二个实例共享已加载的指纹库 |
| 230 | + opt2 := sdk.DefaultConfig() |
| 231 | + opt2.Threads = 100 |
| 232 | + engine2 := sdk.NewSprayEngine(opt2) |
| 233 | + // 不需要再次 Init |
| 234 | + |
| 235 | + ctx := context.Background() |
| 236 | + |
| 237 | + // 并发使用 |
| 238 | + go engine1.Check(ctx, urls1) |
| 239 | + go engine2.Check(ctx, urls2) |
| 240 | +} |
| 241 | +``` |
| 242 | + |
| 243 | +## 注意事项 |
| 244 | + |
| 245 | +1. **必须初始化**: 创建 `SprayEngine` 后必须调用 `Init()` 加载指纹库 |
| 246 | +2. **配置克隆**: SDK 内部会克隆配置,避免并发修改 |
| 247 | +3. **共享状态**: 多个 `SprayEngine` 实例共享已加载的指纹库 |
| 248 | +4. **自动清理**: Stream 模式会自动清理资源 |
| 249 | + |
| 250 | +## 许可证 |
| 251 | + |
| 252 | +MIT License |
0 commit comments