From dd5fc8e09151a5cd5f6369e5e7301d99aeb559a4 Mon Sep 17 00:00:00 2001 From: Eviden <1538279017@qq.com> Date: Thu, 19 Mar 2026 17:10:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=94=B9wappalyzer=E5=BC=95?= =?UTF-8?q?=E6=93=8E=E7=9A=84=E7=BB=93=E6=9E=84=E4=BD=93=E4=BB=A5=E9=80=82?= =?UTF-8?q?=E9=85=8D=E6=9C=80=E6=96=B0=E7=9A=84wappalyzer=E6=8C=87?= =?UTF-8?q?=E7=BA=B9;=E5=A2=9E=E5=8A=A0Dom,Icon=E4=B8=A4=E4=B8=AA=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E4=BB=A5=E5=AE=8C=E5=85=A8=E4=BD=BF=E7=94=A8wappalyze?= =?UTF-8?q?rgo=E7=9A=84=E8=83=BD=E5=8A=9B!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- engine_test.go | 18 +++++------ wappalyzer/fingerprints.go | 62 +++++++++++++++++++++++++++++--------- wappalyzer/wappalyzer.go | 1 + 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/engine_test.go b/engine_test.go index 2ba6030..e454090 100644 --- a/engine_test.go +++ b/engine_test.go @@ -30,17 +30,17 @@ func TestEngine(t *testing.T) { } fmt.Println(engine.String()) - //client := &http.Client{ + // client := &http.Client{ // Transport: &http.Transport{ // TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // }, - //} - //resp, err := client.Get("https://boce.aliyun.com/detect/http") - //if err != nil { + // } + // resp, err := client.Get("https://boce.aliyun.com/detect/http") + // if err != nil { // panic(err) - //} - //start := time.Now() - //content := httputils.ReadRaw(resp) + // } + // start := time.Now() + // content := httputils.ReadRaw(resp) // 调用 DetectContent @@ -54,7 +54,7 @@ func TestEngine(t *testing.T) { } // 打印执行时间 - //println("耗时: " + time.Since(start).String()) + // println("耗时: " + time.Since(start).String()) fmt.Println(frames.String()) // 打印内存分配 @@ -220,7 +220,7 @@ func TestEngine_Wappalyzer(t *testing.T) { t.Error(err) return } - resp, err := http.Get("http://127.0.0.1:8000") + resp, err := http.Get("https://www.thinkphp.cn/") if err != nil { return } diff --git a/wappalyzer/fingerprints.go b/wappalyzer/fingerprints.go index 37beb13..591aade 100644 --- a/wappalyzer/fingerprints.go +++ b/wappalyzer/fingerprints.go @@ -1,6 +1,7 @@ package wappalyzer import ( + "encoding/json" "github.com/chainreactors/fingers/common" "regexp" "strconv" @@ -13,21 +14,46 @@ type Fingerprints struct { Apps map[string]*Fingerprint `json:"apps"` } +// UnmarshalJSON supports both normalized (apps) and upstream (technologies) keys. +func (f *Fingerprints) UnmarshalJSON(data []byte) error { + var payload struct { + Apps map[string]*Fingerprint `json:"apps"` + Technologies map[string]*Fingerprint `json:"technologies"` + } + + if err := json.Unmarshal(data, &payload); err != nil { + return err + } + + switch { + case len(payload.Apps) > 0: + f.Apps = payload.Apps + case len(payload.Technologies) > 0: + f.Apps = payload.Technologies + default: + f.Apps = map[string]*Fingerprint{} + } + + return nil +} + // Fingerprint is a single piece of information about a tech validated and normalized type Fingerprint struct { - Cats []int `json:"cats"` - CSS []string `json:"css"` - Cookies map[string]string `json:"cookies"` - JS []string `json:"js"` - Headers map[string]string `json:"headers"` - HTML []string `json:"html"` - Script []string `json:"scripts"` - ScriptSrc []string `json:"scriptSrc"` - Meta map[string][]string `json:"meta"` - Implies []string `json:"implies"` - Description string `json:"description"` - Website string `json:"website"` - CPE string `json:"cpe"` + Cats []int `json:"cats"` + CSS []string `json:"css"` + Cookies map[string]string `json:"cookies"` + Dom map[string]map[string]interface{} `json:"dom"` + JS map[string]string `json:"js"` + Headers map[string]string `json:"headers"` + HTML []string `json:"html"` + Script []string `json:"scripts"` + ScriptSrc []string `json:"scriptSrc"` + Meta map[string][]string `json:"meta"` + Implies []string `json:"implies"` + Description string `json:"description"` + Website string `json:"website"` + CPE string `json:"cpe"` + Icon string `json:"icon"` } // CompiledFingerprints contains a map of fingerprints for tech detection @@ -47,6 +73,8 @@ type CompiledFingerprint struct { description string // website contains a URL associated with the fingerprint website string + // icon contains icon identifier from fingerprint source + icon string // cookies contains fingerprints for target cookies cookies map[string]*versionRegex // js contains fingerprints for the js file @@ -81,6 +109,7 @@ type AppInfo struct { Description string Website string CPE string + Icon string } // CatsInfo contains basic information about an App. @@ -128,6 +157,7 @@ func (v *versionRegex) MatchString(value string) (bool, string) { if v.skipRegex { return true, "" } + value = strings.ToLower(value) matches := v.regex.FindAllStringSubmatch(value, -1) if len(matches) == 0 { return false, "" @@ -163,6 +193,7 @@ func compileFingerprint(app string, fingerprint *Fingerprint) *CompiledFingerpri implies: fingerprint.Implies, description: fingerprint.Description, website: fingerprint.Website, + icon: fingerprint.Icon, cookies: make(map[string]*versionRegex), js: make([]*versionRegex, 0, len(fingerprint.JS)), headers: make(map[string]*versionRegex), @@ -181,7 +212,10 @@ func compileFingerprint(app string, fingerprint *Fingerprint) *CompiledFingerpri compiled.cookies[header] = fingerprint } - for _, pattern := range fingerprint.JS { + for property, pattern := range fingerprint.JS { + if pattern == "" { + pattern = regexp.QuoteMeta(property) + } fingerprint, err := newVersionRegex(pattern) if err != nil { continue diff --git a/wappalyzer/wappalyzer.go b/wappalyzer/wappalyzer.go index 092b17a..b2e49b3 100644 --- a/wappalyzer/wappalyzer.go +++ b/wappalyzer/wappalyzer.go @@ -159,6 +159,7 @@ func (engine *Wappalyze) FingerprintWithInfo(headers map[string][]string, body [ Description: fingerprint.description, Website: fingerprint.website, CPE: fingerprint.cpe, + Icon: fingerprint.icon, } } }