1- use crate :: utils:: { get_format_info, ScanInfo } ;
1+ use crate :: {
2+ utils:: { get_favicon_url, get_fofa_iconhash, get_format_info} ,
3+ FINGER_DATA ,
4+ } ;
5+ use crossbeam:: queue:: SegQueue ;
26use reqwest:: { header, Client } ;
7+ use serde:: Serialize ;
38use std:: time:: Duration ;
4- use crossbeam:: queue:: SegQueue ;
59
610pub const USER_AGENT : & str =
711 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:128.0) Gecko/20100101 Firefox/128.0" ;
812
13+ #[ derive( Debug , Serialize , Clone ) ]
14+ pub struct PrintInfo {
15+ pub url : String ,
16+ pub status_code : u16 ,
17+ pub title : String ,
18+ pub server : String ,
19+ pub jump_url : String ,
20+ pub content_length : usize ,
21+ pub cms : Vec < String > ,
22+ }
23+
924// 创建http客户端
1025pub fn create_http_client ( timeout : usize , proxy : Option < String > ) -> Client {
1126 let mut headers = header:: HeaderMap :: new ( ) ;
@@ -63,7 +78,7 @@ pub async fn send_request(
6378 url : & str ,
6479 u16_vec : Vec < u16 > ,
6580 path : & str ,
66- seg_queue : & SegQueue < ScanInfo > ,
81+ seg_queue : & SegQueue < PrintInfo > ,
6782) -> Result < String , reqwest:: Error > {
6883 // 解析URL,如果path为空,则默认为/,如果有值,则加上,还需要处理url有没有/
6984 let url = if path. is_empty ( ) {
@@ -79,7 +94,7 @@ pub async fn send_request(
7994
8095 let response = client. get ( url. as_str ( ) ) . send ( ) . await ?;
8196
82- let scan_info = get_format_info ( response, url) ;
97+ let scan_info = get_format_info ( response, url) ;
8398 let scan_info = scan_info. await ;
8499
85100 let url = scan_info. url ;
@@ -88,19 +103,66 @@ pub async fn send_request(
88103 let content_length = scan_info. content_length ;
89104 let server = scan_info. server ;
90105 let jump_url = scan_info. jump_url ;
106+ let body = scan_info. body ;
107+ let header = scan_info. header ;
108+
109+ // 处理url 变为 协议 + 域名 + 端口 + /favicon.ico
110+ let favicon_url = get_favicon_url ( & url) . unwrap_or_else ( |_| "" . to_string ( ) ) ;
111+
112+ // 获取 icon
113+ let icon_hash = get_fofa_iconhash ( favicon_url, client)
114+ . await
115+ . unwrap_or_else ( |_| "" . to_string ( ) ) ;
116+ let mut cms_list: Vec < String > = Vec :: new ( ) ;
117+
118+ // 然后进行指纹匹配,如果能匹配到,则返回cms,遍历指纹
119+ for finger in & * FINGER_DATA {
120+ let method = finger. method . to_string ( ) ;
121+ let location = finger. location . to_string ( ) ;
122+ let keyword = finger. keyword . clone ( ) ;
123+
124+ if method == "keyword" {
125+ // 说明为关键词匹配
126+ if location == "body" {
127+ // 说明是body匹配,keyword 词组都在 body中
128+ let all_found = keyword. iter ( ) . all ( |s| body. contains ( s) ) ;
129+ if all_found {
130+ // 说明匹配成功
131+ cms_list. push ( finger. cms . to_string ( ) ) ;
132+ }
133+ } else if location == "header" {
134+ // 说明是header匹配
135+ let all_found = keyword. iter ( ) . all ( |s| header. contains ( s) ) ;
136+ if all_found {
137+ // 说明匹配成功
138+ cms_list. push ( finger. cms . to_string ( ) ) ;
139+ }
140+ }
141+ } else if method == "faviconhash" {
142+ // 说明是faviconhash匹配
143+ if icon_hash == finger. keyword [ 0 ] {
144+ // 说明匹配成功
145+ cms_list. push ( finger. cms . to_string ( ) ) ;
146+ }
147+ }
148+ }
149+
150+ // 对 cms_list 进行去重
151+ cms_list. dedup ( ) ;
91152
92153 if u16_vec. contains ( & status_code) {
93- seg_queue. push ( ScanInfo {
154+ seg_queue. push ( PrintInfo {
94155 url : url. to_string ( ) ,
95156 status_code,
96157 title : title. to_string ( ) ,
97158 server : server. to_string ( ) ,
98159 jump_url : jump_url. to_string ( ) ,
99160 content_length,
161+ cms : cms_list. clone ( ) ,
100162 } ) ;
101163 Ok ( format ! (
102- "{} [{}] [{}] [{}] [{}] [{}]" ,
103- url, status_code, title, server, jump_url, content_length
164+ "{} [{}] [{}] [{}] [{}] [{}] {:?} " ,
165+ url, status_code, title, server, jump_url, content_length, cms_list
104166 ) )
105167 } else {
106168 Ok ( "" . to_string ( ) )
0 commit comments