github.com/chainreactors/fingers@v1.2.1/engine_test.go (about)

     1  package fingers
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/tls"
     6  	"fmt"
     7  	"net/http"
     8  	"os"
     9  	"strconv"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/chainreactors/fingers/common"
    14  	"github.com/chainreactors/fingers/ehole"
    15  	"github.com/chainreactors/fingers/fingerprinthub"
    16  	"github.com/chainreactors/fingers/fingers"
    17  	"github.com/chainreactors/fingers/goby"
    18  	"github.com/chainreactors/fingers/resources"
    19  	"github.com/chainreactors/fingers/wappalyzer"
    20  	"github.com/chainreactors/utils/httputils"
    21  )
    22  
    23  func TestEngine(t *testing.T) {
    24  	if testing.Short() {
    25  		t.Skip("skipping test requiring local file in short mode")
    26  	}
    27  	engine, err := NewEngine()
    28  	if err != nil {
    29  		panic(err)
    30  	}
    31  	fmt.Println(engine.String())
    32  
    33  	//client := &http.Client{
    34  	//	Transport: &http.Transport{
    35  	//		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    36  	//	},
    37  	//}
    38  	//resp, err := client.Get("https://boce.aliyun.com/detect/http")
    39  	//if err != nil {
    40  	//	panic(err)
    41  	//}
    42  	//start := time.Now()
    43  	//content := httputils.ReadRaw(resp)
    44  
    45  	// 调用 DetectContent
    46  
    47  	content, err := os.ReadFile("1.raw")
    48  	if err != nil {
    49  		return
    50  	}
    51  	frames, err := engine.DetectContent(content)
    52  	if err != nil {
    53  		return
    54  	}
    55  
    56  	// 打印执行时间
    57  	//println("耗时: " + time.Since(start).String())
    58  	fmt.Println(frames.String())
    59  
    60  	// 打印内存分配
    61  	for _, f := range frames {
    62  		fmt.Println("cpe: ", f.CPE(), "||||", f.String())
    63  	}
    64  }
    65  
    66  func TestEngine_Match(t *testing.T) {
    67  	if testing.Short() {
    68  		t.Skip("skipping live network test in short mode")
    69  	}
    70  	engine, err := NewEngine()
    71  	if err != nil {
    72  		panic(err)
    73  	}
    74  	resp, err := http.Get("http://nc.scsstjt.com:8090/index.jsp")
    75  	if err != nil {
    76  		panic(err)
    77  	}
    78  	frames := engine.Match(resp)
    79  	fmt.Println(frames.String())
    80  }
    81  
    82  func TestFavicon(t *testing.T) {
    83  	if testing.Short() {
    84  		t.Skip("skipping live network test in short mode")
    85  	}
    86  	engine, err := NewEngine()
    87  	if err != nil {
    88  		panic(err)
    89  	}
    90  	resp, err := http.Get("http://baidu.com/favicon.ico")
    91  	if err != nil {
    92  		return
    93  	}
    94  	content := httputils.ReadRaw(resp)
    95  	body, _, _ := httputils.SplitHttpRaw(content)
    96  	frame := engine.DetectFavicon(body)
    97  	fmt.Println(frame)
    98  }
    99  
   100  func TestFingersEngine(t *testing.T) {
   101  	if testing.Short() {
   102  		t.Skip("skipping live network test in short mode")
   103  	}
   104  	engine, err := fingers.NewFingersEngine(resources.FingersHTTPData, resources.FingersSocketData, resources.PortData)
   105  	if err != nil {
   106  		t.Error(err)
   107  		return
   108  	}
   109  
   110  	// 模拟比较真实的浏览器请求头
   111  	headers := http.Header{
   112  		"User-Agent": []string{
   113  			"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
   114  		},
   115  		"Accept": []string{
   116  			"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
   117  		},
   118  		"Accept-Language": []string{"zh-CN,zh;q=0.9,en;q=0.8"},
   119  		"Accept-Encoding": []string{"gzip, deflate"},
   120  		"Connection":      []string{"keep-alive"},
   121  		// 如果目标网站有严格的 referer 检查,可以加上
   122  		// "Referer": []string{"https://www.google.com/"},
   123  	}
   124  
   125  	client := &http.Client{
   126  		Transport: &http.Transport{
   127  			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   128  		},
   129  	}
   130  
   131  	req, err := http.NewRequest("GET", "http://nc.scsstjt.com:8090/login/login.php", nil)
   132  	if err != nil {
   133  		t.Fatal(err)
   134  	}
   135  
   136  	// 一次性设置所有 header
   137  	req.Header = headers
   138  
   139  	resp, err := client.Do(req)
   140  	if err != nil {
   141  		t.Log(err)
   142  		return
   143  	}
   144  	defer resp.Body.Close()
   145  
   146  	content := httputils.ReadRaw(resp)
   147  	frames := engine.WebMatch(content)
   148  
   149  	for _, frame := range frames {
   150  		t.Log(frame)
   151  	}
   152  }
   153  
   154  func TestEngine_MatchWithEngines(t *testing.T) {
   155  	if testing.Short() {
   156  		t.Skip("skipping live network test in short mode")
   157  	}
   158  	engine, err := NewEngine()
   159  	if err != nil {
   160  		t.Error(err)
   161  	}
   162  	resp, err := http.Get("http://127.0.0.1")
   163  	if err != nil {
   164  		return
   165  	}
   166  
   167  	need := []string{FingersEngine, FingerPrintEngine}
   168  	frames := engine.MatchWithEngines(resp, need...)
   169  	for _, frame := range frames {
   170  		t.Log(frame)
   171  	}
   172  }
   173  
   174  func TestFingerPrintHubsEngine(t *testing.T) {
   175  	if testing.Short() {
   176  		t.Skip("skipping live network test in short mode")
   177  	}
   178  	engine, err := fingerprinthub.NewFingerPrintHubEngine(resources.FingerprinthubWebData, resources.FingerprinthubServiceData)
   179  	if err != nil {
   180  		t.Error(err)
   181  	}
   182  	resp, err := http.Get("http://127.0.0.1")
   183  	if err != nil {
   184  		return
   185  	}
   186  
   187  	content := httputils.ReadRaw(resp)
   188  	frames := engine.WebMatch(content)
   189  	for _, frame := range frames {
   190  		t.Log(frame)
   191  	}
   192  }
   193  
   194  func TestEHoleEngine(t *testing.T) {
   195  	if testing.Short() {
   196  		t.Skip("skipping live network test in short mode")
   197  	}
   198  	engine, err := ehole.NewEHoleEngine(resources.EholeData)
   199  	if err != nil {
   200  		t.Error(err)
   201  	}
   202  	resp, err := http.Get("http://127.0.0.1:8089")
   203  	if err != nil {
   204  		return
   205  	}
   206  
   207  	content := httputils.ReadRaw(resp)
   208  	header, body, ok := httputils.SplitHttpRaw(content)
   209  	if ok {
   210  		frames := engine.MatchWithHeaderAndBody(string(header), string(body))
   211  		for _, frame := range frames {
   212  			t.Log(frame)
   213  		}
   214  	}
   215  }
   216  
   217  func TestGobyEngine(t *testing.T) {
   218  	if testing.Short() {
   219  		t.Skip("skipping live network test in short mode")
   220  	}
   221  	engine, err := goby.NewGobyEngine(resources.GobyData)
   222  	if err != nil {
   223  		t.Error(err)
   224  	}
   225  	resp, err := http.Get("https://baidu.com")
   226  	if err != nil {
   227  		return
   228  	}
   229  
   230  	content := httputils.ReadRaw(resp)
   231  	content = bytes.ToLower(content)
   232  	start := time.Now()
   233  	frames := engine.WebMatch(content)
   234  	fmt.Println(frames)
   235  	fmt.Println(time.Since(start).String())
   236  }
   237  
   238  func TestEngine_Wappalyzer(t *testing.T) {
   239  	if testing.Short() {
   240  		t.Skip("skipping live network test in short mode")
   241  	}
   242  	engine, err := wappalyzer.NewWappalyzeEngine(resources.WappalyzerData)
   243  	if err != nil {
   244  		t.Error(err)
   245  		return
   246  	}
   247  	resp, err := http.Get("http://127.0.0.1:8000")
   248  	if err != nil {
   249  		return
   250  	}
   251  
   252  	content := httputils.ReadBody(resp)
   253  	start := time.Now()
   254  	frames := engine.Fingerprint(resp.Header, content)
   255  	fmt.Println(frames)
   256  	fmt.Println(time.Since(start).String())
   257  }
   258  
   259  func TestAlias(t *testing.T) {
   260  	engine, err := NewEngine(FingersEngine, FingerPrintEngine)
   261  	if err != nil {
   262  		t.Fatal(err)
   263  	}
   264  	fmt.Println(engine.FindAny("cdncache_server"))
   265  	fmt.Println(engine.Aliases.Aliases["cdn-cache-server"])
   266  	fmt.Println(engine.Aliases.Map["fingers"]["cdn-cache-server"])
   267  }
   268  
   269  func TestNmapEngine(t *testing.T) {
   270  	if testing.Short() {
   271  		t.Skip("skipping live network test in short mode")
   272  	}
   273  	engine, err := NewEngine(NmapEngine)
   274  	if err != nil {
   275  		t.Error(err)
   276  		return
   277  	}
   278  
   279  	nmapEngine := engine.Nmap()
   280  	if nmapEngine == nil {
   281  		t.Error("nmap engine not found")
   282  		return
   283  	}
   284  
   285  	fmt.Printf("nmap engine loaded with %d fingerprints\n", nmapEngine.Len())
   286  
   287  	// 测试Service指纹匹配 - 使用common包的默认实现
   288  	testServiceSender := common.NewServiceSender(3 * time.Second)
   289  
   290  	testServiceCallback := func(result *common.ServiceResult) {
   291  		if result.Framework != nil {
   292  			t.Logf("detected service: %s", result.Framework.String())
   293  		}
   294  	}
   295  
   296  	result := nmapEngine.ServiceMatch("127.0.0.1", "80", 1, testServiceSender, testServiceCallback)
   297  	if result != nil && result.Framework != nil {
   298  		t.Logf("service result: %s", result.Framework.String())
   299  	}
   300  
   301  	// 测试引擎能力
   302  	capability := nmapEngine.Capability()
   303  	if !capability.SupportService {
   304  		t.Error("nmap engine should support service fingerprinting")
   305  	}
   306  	if capability.SupportWeb {
   307  		t.Error("nmap engine should not support web fingerprinting")
   308  	}
   309  
   310  	// 测试WebMatch应该返回空结果
   311  	webFrames := nmapEngine.WebMatch([]byte("test"))
   312  	if len(webFrames) != 0 {
   313  		t.Error("nmap engine WebMatch should return empty results")
   314  	}
   315  }
   316  
   317  // TestServiceEngine 测试Service引擎的能力
   318  func TestServiceEngine(t *testing.T) {
   319  	if testing.Short() {
   320  		t.Skip("skipping live network test in short mode")
   321  	}
   322  	engine, err := NewEngine(NmapEngine)
   323  	if err != nil {
   324  		t.Error(err)
   325  		return
   326  	}
   327  
   328  	// 测试获取支持Service的引擎
   329  	serviceEngines := engine.GetEnginesByType(common.ServiceFingerprint)
   330  	expectedServiceEngines := []string{NmapEngine}
   331  
   332  	if len(serviceEngines) != len(expectedServiceEngines) {
   333  		t.Errorf("Expected %d service engines, got %d", len(expectedServiceEngines), len(serviceEngines))
   334  	}
   335  
   336  	for _, expected := range expectedServiceEngines {
   337  		found := false
   338  		for _, actual := range serviceEngines {
   339  			if actual == expected {
   340  				found = true
   341  				break
   342  			}
   343  		}
   344  		if !found {
   345  			t.Errorf("Expected service engine %s not found", expected)
   346  		}
   347  	}
   348  
   349  	// 测试DetectService API
   350  	testSender := common.NewServiceSender(3 * time.Second)
   351  
   352  	ports := []int{80, 443, 445, 135, 1080, 3306, 1433, 1521}
   353  	for _, port := range ports {
   354  		results, err := engine.DetectService("127.0.0.1", strconv.Itoa(port), 9, testSender, nil)
   355  		if err != nil {
   356  			t.Logf("DetectService error: %v", err)
   357  		}
   358  		if len(results) > 0 && results[0].Framework != nil {
   359  			fmt.Printf("DetectService result: %s\n", results[0].Framework.String())
   360  		}
   361  	}
   362  }