package main import ( "encoding/json" "fmt" "net/url" "os" "strings" pkgaes "github.com/perfect-panel/server/pkg/aes" ) func main() { // 通讯密钥 communicationKey := "c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx" // 真实 Nginx 日志数据 - 从用户提供的日志中选取 sampleLogs := []string{ // 加密的下载请求 - 不同平台 `172.245.180.199 - - [02/Feb/2026:04:35:47 +0000] "GET /v1/common/client/download?data=JetaR6P9e8G5lZg2KRiAhV6c%2FdMilBtP78bKmsbAxL8%3D&time=2026-02-02T04:35:15.032000 HTTP/1.1" 200 201 "https://www.hifastvpn.com/" "AdsBot-Google (+http://www.google.com/adsbot.html)"`, `172.245.180.199 - - [02/Feb/2026:04:35:47 +0000] "GET /v1/common/client/download?data=%2FFTAxtcEd%2F8T2MzKdxxrPfWBXk4pNPbQZB3p8Yrl8XQ%3D&time=2026-02-02T04:35:15.031000 HTTP/1.1" 200 181 "https://www.hifastvpn.com/" "AdsBot-Google (+http://www.google.com/adsbot.html)"`, `172.245.180.199 - - [02/Feb/2026:04:35:47 +0000] "GET /v1/common/client/download?data=i18AVRwlVSuFrbf4NmId0RcTbj0tRJIBFHP0MxLjDmI%3D&time=2026-02-02T04:35:15.033000 HTTP/1.1" 200 201 "https://www.hifastvpn.com/" "AdsBot-Google (+http://www.google.com/adsbot.html)"`, `172.245.180.199 - - [02/Feb/2026:04:50:50 +0000] "GET /v1/common/client/download?platform=mac HTTP/1.1" 200 113 "https://gethifast.net/" "Mozilla/5.0 (compatible; AhrefsBot/7.0; +http://ahrefs.com/robot/)"`, `172.245.180.199 - - [02/Feb/2026:04:50:50 +0000] "GET /v1/common/client/download?platform=windows HTTP/1.1" 200 117 "https://gethifast.net/" "Mozilla/5.0 (compatible; AhrefsBot/7.0; +http://ahrefs.com/robot/)"`, `172.245.180.199 - - [02/Feb/2026:05:24:16 +0000] "GET /v1/common/client/download?data=XfZsgEqUUQ0YBTT51ETQp2wheSvE4SRupBfYbiLnJOc%3D&time=2026-02-02T05:24:15.462000 HTTP/1.1" 200 181 "https://www.hifastvpn.com/" "Mozilla/5.0 (X11; CrOS x86_64 14541.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"`, // 真实用户下载 `172.245.180.199 - - [02/Feb/2026:02:15:16 +0000] "GET /v1/common/client/download?data=XIZiz7c4sbUGE7Hl8fY6O2D5QKaZqx%2Fg81uR7kjenSg%3D&time=2026-02-02T02:15:16.337000 HTTP/1.1" 200 201 "https://hifastvpn.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"`, `172.245.180.199 - - [02/Feb/2026:02:18:09 +0000] "GET /v1/common/client/download?data=aB0HistwZTIhxJh6yIds%2B6knoyZC17KyxaXvyd3Z5LY%3D&time=2026-02-02T02:18:06.301000 HTTP/1.1" 200 201 "https://hifastvpn.com/" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Mobile Safari/537.36"`, // 实际文件下载 `111.55.176.116 - - [02/Feb/2026:02:19:02 +0000] "GET /v1/common/client/download/file/android-1.0.0.apk HTTP/2.0" 200 18546688 "https://hifastvpn.com/" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Mobile Safari/537.36"`, `111.249.202.38 - - [02/Feb/2026:03:14:46 +0000] "GET /v1/common/client/download/file/mac-1.0.0.dmg HTTP/2.0" 200 72821392 "https://hifastvpn.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 12.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.7091.96 Safari/537.36"`, // Windows 用户 `172.245.180.199 - - [02/Feb/2026:02:23:55 +0000] "GET /v1/common/client/download?data=t8OIVjnZx1N7w5ras4oVH9V0wz4JYlR7849WYKvbj9E%3D&time=2026-02-02T02:23:56.110000 HTTP/1.1" 200 201 "https://hifastvpn.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.7149.88 Safari/537.36"`, // Mac 用户 `172.245.180.199 - - [02/Feb/2026:03:14:10 +0000] "GET /v1/common/client/download?data=mGKSxZtL7Ptf30MgFzBJPIsURC%2FkOf2lOGaXQOQ5Ft8%3D&time=2026-02-02T03:14:07.667000 HTTP/1.1" 200 181 "https://hifastvpn.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 12.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.7091.96 Safari/537.36"`, // Android 移动端 `172.245.180.199 - - [02/Feb/2026:03:19:41 +0000] "GET /v1/common/client/download?data=y7gttvd%2BoKf9%2BZUeNTsOvuFHwOLFBByrNjkvhPkVykg%3D&time=2026-02-02T03:19:42.192000 HTTP/1.1" 200 201 "https://hifastvpn.com/" "Mozilla/5.0 (Linux; Android 15; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.7559.59 Mobile Safari/537.36"`, `183.171.68.186 - - [02/Feb/2026:03:19:47 +0000] "GET /v1/common/client/download/file/android-1.0.0.apk HTTP/1.1" 200 179890 "https://hifastvpn.com/" "Mozilla/5.0 (Linux; Android 15; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.7559.59 Mobile Safari/537.36"`, } // 如果命令行提供了参数,使用命令行参数 if len(os.Args) > 1 { sampleLogs = os.Args[1:] } fmt.Println("=== Nginx 下载日志解密工具 ===") fmt.Printf("通讯密钥: %s\n\n", communicationKey) // 统计数据 stats := make(map[string]int) successCount := 0 for i, logLine := range sampleLogs { // 提取日志条目 entry := extractLogEntry(logLine) if entry.Data == "" && entry.Platform == "" { fmt.Printf("--- 日志 #%d ---\n", i+1) fmt.Println("⚠️ 跳过: 未找到 data 或 platform 参数\n") continue } // 如果有 platform 参数(非加密),直接使用 if entry.Platform != "" { fmt.Printf("--- 日志 #%d ---\n", i+1) fmt.Printf("📍 IP地址: %s\n", entry.IP) fmt.Printf("🌐 来源: %s\n", entry.Referer) fmt.Printf("🔓 平台: %s (未加密)\n\n", entry.Platform) stats[entry.Platform]++ successCount++ continue } // 处理加密的 data 参数 if entry.Data == "" { continue } // URL 解码 decodedData, err := url.QueryUnescape(entry.Data) if err != nil { fmt.Printf("--- 日志 #%d ---\n", i+1) fmt.Printf("❌ 错误: URL 解码失败: %v\n\n", err) continue } // 提取 nonce (IV) - 从 time 参数转换 nonce := extractNonceFromTime(entry.Time) // AES 解密 plainText, err := pkgaes.Decrypt(decodedData, communicationKey, nonce) if err != nil { fmt.Printf("--- 日志 #%d ---\n", i+1) fmt.Printf("❌ 错误: 解密失败: %v\n", err) fmt.Printf(" IP: %s, Nonce: %s\n\n", entry.IP, nonce) continue } // 解析 JSON 获取平台信息 var result map[string]interface{} if err := json.Unmarshal([]byte(plainText), &result); err == nil { if platform, ok := result["platform"].(string); ok { stats[platform]++ } } fmt.Printf("--- 日志 #%d ---\n", i+1) fmt.Printf("📍 IP地址: %s\n", entry.IP) fmt.Printf("🌐 来源: %s\n", entry.Referer) fmt.Printf("🔓 解密内容: %s\n\n", plainText) successCount++ } // 输出统计信息 if successCount > 0 { fmt.Println("=" + strings.Repeat("=", 50)) fmt.Printf("📊 统计信息 (成功解密: %d)\n", successCount) fmt.Println("=" + strings.Repeat("=", 50)) for platform, count := range stats { fmt.Printf(" %s: %d 次\n", platform, count) } fmt.Println() } } // LogEntry 表示解析后的日志条目 type LogEntry struct { IP string Data string Time string Referer string Platform string } // extractLogEntry 从日志行中提取所有关键信息 func extractLogEntry(logLine string) *LogEntry { entry := &LogEntry{} // 提取 IP 地址(第一个字段) parts := strings.Fields(logLine) if len(parts) > 0 { entry.IP = parts[0] } // 提取 Referer 和 User-Agent // Nginx combined 格式:... "请求" 状态码 字节数 "Referer" "User-Agent" // 需要找到最后两对引号 quotes := []int{} for i := 0; i < len(logLine); i++ { if logLine[i] == '"' { quotes = append(quotes, i) } } // 至少需要 6 个引号: "GET ..." "Referer" "User-Agent" if len(quotes) >= 6 { // 倒数第 4 和第 3 个引号之间是 Referer refererStart := quotes[len(quotes)-4] refererEnd := quotes[len(quotes)-3] entry.Referer = logLine[refererStart+1 : refererEnd] // 倒数第 2 和第 1 个引号之间是 User-Agent // 如果需要也可以提取 // uaStart := quotes[len(quotes)-2] // uaEnd := quotes[len(quotes)-1] // entry.UserAgent = logLine[uaStart+1 : uaEnd] } // 查找 ? 后面的查询字符串 idx := strings.Index(logLine, "?") // 如果没有查询参数,检查是否是直接文件下载 if idx == -1 { // 检查是否包含 /v1/common/client/download/file/ filePrefix := "/v1/common/client/download/file/" fileIdx := strings.Index(logLine, filePrefix) if fileIdx != -1 { // 提取文件名部分 // URL 形式可能是: /v1/common/client/download/file/Hi%E5%BF%ABVPN-windows-1.0.0.exe HTTP/1.1 // 需要截取到空格 pathStart := fileIdx + len(filePrefix) pathEnd := strings.Index(logLine[pathStart:], " ") if pathEnd != -1 { filePath := logLine[pathStart : pathStart+pathEnd] // URL 解码 decodedPath, err := url.QueryUnescape(filePath) if err == nil { // 转换为小写以便匹配 lowerPath := strings.ToLower(decodedPath) if strings.Contains(lowerPath, "windows") || strings.HasSuffix(lowerPath, ".exe") { entry.Platform = "windows" } else if strings.Contains(lowerPath, "mac") || strings.HasSuffix(lowerPath, ".dmg") { entry.Platform = "mac" } else if strings.Contains(lowerPath, "android") || strings.HasSuffix(lowerPath, ".apk") { entry.Platform = "android" } else if strings.Contains(lowerPath, "ios") || strings.HasSuffix(lowerPath, ".ipa") { entry.Platform = "ios" } } } } return entry } queryStr := logLine[idx+1:] // 截取到空格或 HTTP/ endIdx := strings.Index(queryStr, " ") if endIdx != -1 { queryStr = queryStr[:endIdx] } // 解析查询参数 params := strings.Split(queryStr, "&") for _, param := range params { kv := strings.SplitN(param, "=", 2) if len(kv) != 2 { continue } switch kv[0] { case "data": entry.Data = kv[1] case "time": entry.Time = kv[1] case "platform": entry.Platform = kv[1] } } return entry } // extractNonceFromTime 从 time 参数中提取 nonce // time 格式: 2026-02-02T04:35:15.032000 // 需要转换为纳秒时间戳的十六进制 func extractNonceFromTime(timeStr string) string { if timeStr == "" { return "" } // URL 解码 decoded, err := url.QueryUnescape(timeStr) if err != nil { return "" } // 简化处理:直接使用整个时间字符串作为 nonce // 因为原始代码使用 time.Now().UnixNano() 的十六进制 // 但是从日志中我们无法准确还原原始的 nonce // 所以尝试使用 time 字符串本身 return decoded }