C# 服务器安全检查工具

检查日志

复制代码
--------------------------------------------------------------
----------------------当前已启用来宾帐号------------------------
--------------------------------------------------------------
帐号: ***** 供来宾访问计算机或访问域的内置帐户 供来宾访问计算机或访问域的内置帐户
--------------------------------------------------------------
----------------------当前已启用管理员帐号------------------------
--------------------------------------------------------------
帐号: ****** 管理计算机(域)的内置帐户 管理计算机(域)的内置帐户
--------------------------------------------------------------
---------------------------已开放端口-------------------------
--------------------------------------------------------------
已开放端口:0.0.0.0:135
已开放端口:0.0.0.0:445
已开放端口:0.0.0.0:1433
已开放端口:0.0.0.0:2121
已开放端口:0.0.0.0:3389
已开放端口:0.0.0.0:5040
已开放端口:0.0.0.0:7680
已开放端口:0.0.0.0:19303
已开放端口:0.0.0.0:47546
已开放端口:0.0.0.0:49664
已开放端口:0.0.0.0:49665
已开放端口:0.0.0.0:49666
已开放端口:0.0.0.0:49667
已开放端口:0.0.0.0:49668
已开放端口:0.0.0.0:49675
已开放端口:0.0.0.0:49683
已开放端口:127.0.0.1:1434
已开放端口:127.0.0.1:49735
已开放端口:127.0.0.1:65001
已开放端口:192.168.*.*:139
已开放端口:[::]:135
已开放端口:[::]:445
已开放端口:[::]:1433
已开放端口:[::]:3389
已开放端口:[::]:7680
已开放端口:[::]:47546
已开放端口:[::]:49664
已开放端口:[::]:49665
已开放端口:[::]:49666
已开放端口:[::]:49667
已开放端口:[::]:49668
已开放端口:[::]:49675
已开放端口:[::]:49683
已开放端口:[::1]:1434
已开放端口:[::1]:49679
已连接:192.168.*.*:33538->52.168.112.67:443(美国->加利福尼亚州圣克拉拉Microsoft公司) Established
已连接:192.168.*.*:35348->180.163.150.166:443(上海市->电信) Established
已连接:192.168.*.*:35446->116.62.230.66:443(浙江省杭州市->阿里云) Established
已连接:192.168.*.*:35581->180.163.150.33:443(上海市->电信) Established
已连接:192.168.*.*:35659->101.37.113.127:443(浙江省杭州市->阿里云) Established
已连接:192.168.*.*:35661->116.207.174.105:443(湖北省宜昌市->电信) Established
已连接:192.168.*.*:35662->180.163.150.169:443(上海市->电信) Established
已连接:192.168.*.*:35664->120.55.196.147:443(浙江省杭州市->阿里云BGP数据中心) Established
已连接:192.168.*.*:35665->180.163.150.38:443(上海市->电信) Established
--------------------------------------------------------------
----------------------当前已连接服务器------------------------
--------------------------------------------------------------
TCP 192.168.*.*:33538->52.168.112.67:443(美国->加利福尼亚州圣克拉拉Microsoft公司) C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\PerfWatson2.exe
TCP 192.168.*.*:35348->180.163.150.166:443(上海市->电信) D:\Program Files\SogouExplorer\SogouExplorer.exe
TCP 192.168.*.*:35446->116.62.230.66:443(浙江省杭州市->阿里云) D:\Program Files\SogouExplorer\SogouExplorer.exe
TCP 192.168.*.*:35581->180.163.150.33:443(上海市->电信) D:\Program Files\SogouExplorer\SogouExplorer.exe
TCP 192.168.*.*:35659->101.37.113.127:443(浙江省杭州市->阿里云) D:\Program Files\SogouExplorer\SogouExplorer.exe
TCP 192.168.*.*:35661->116.207.174.105:443(湖北省宜昌市->电信) D:\Program Files\SogouExplorer\SogouExplorer.exe
TCP 192.168.*.*:35662->180.163.150.169:443(上海市->电信) D:\Program Files\SogouExplorer\SogouExplorer.exe
--------------------------------------------------------------
----------------------当前已开启共享------------------------
--------------------------------------------------------------
共享磁盘: H:\ 请检查
--------------------------------------------------------------
----------------------当前防火墙状态------------------------
--------------------------------------------------------------
防火墙状态:已启用
--------------------------------------------------------------
----------------------当前防火墙开放规则------------------------
--------------------------------------------------------------
规则:[68] --------------- 核心网络 - 动态主机配置协议(DHCP-Out)
规则:[80] --------------- 万维网服务(HTTP 流量入站)
规则:[546] --------------- 核心网络 - IPv6 的动态主机配置协议(DHCPV6-Out)
规则:[5353] --------------- Microsoft Edge (mDNS-In)
规则:[7235] --------------- WFD ASP 协调协议(UDP 输出)
--------------------------------------------------------------
---------------------------系统安全日志-----------------------
--------------------------------------------------------------
安全日志:2022-11-05 16:24:46 [****]:审核日志已被清除。
--------------------------------------------------------------
-------------------------应用安全日志-------------------------
--------------------------------------------------------------
--------------------------------------------------------------
---------------------------全部执行完成-----------------------
--------------------------------------------------------------
复制代码

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
using NetFwTypeLib;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.DirectoryServices;
using System.IO;
using System.Linq;
using System.Management;
using System.Net.NetworkInformation;
 
namespace 服务器安全检查
{
    internal class Program
    {
 
        private static string ipPath = AppDomain.CurrentDomain.BaseDirectory +  "qqwry.dat" ;
        public static IPCheck.QQWry myIP =  new IPCheck.QQWry(ipPath);
        static void Main( string [] args)
        {
            DirectoryEntry localMachine =  new DirectoryEntry( "WinNT://" + Environment.MachineName);
 
            WriteLog( "--------------------------------------------------------------" );
            WriteLog( "----------------------当前已启用来宾帐号------------------------" );
            WriteLog( "--------------------------------------------------------------" );
 
            foreach ( object groupMember  in (IEnumerable)localMachine.Children.Find( "Guests" "group" ).Invoke( "members" null ))
            {
 
                DirectoryEntry member =  new DirectoryEntry(groupMember);
                var state = member.Properties[ "UserFlags" ].Value;
                WriteLog( "帐号: " + member.Name +  " " + member.Properties[ "Description" ].Value +  " " + member.Properties[ "Description" ].Value);
            }
 
            WriteLog( "--------------------------------------------------------------" );
            WriteLog( "----------------------当前已启用管理员帐号------------------------" );
            WriteLog( "--------------------------------------------------------------" );
 
            foreach ( object groupMember  in (IEnumerable)localMachine.Children.Find( "Administrators" "group" ).Invoke( "members" null ))
            {
                DirectoryEntry member =  new DirectoryEntry(groupMember);
                WriteLog( "帐号: " + member.Name +  " " + member.Properties[ "Description" ].Value +  " " + member.Properties[ "Description" ].Value);
 
            }
 
 
 
            //using (var machineContext = new PrincipalContext(ContextType.Machine))
            //using (var gpSeach = new PrincipalSearcher(new GroupPrincipal(machineContext)))
            //{
            //    foreach (GroupPrincipal gp in gpSeach.FindAll())//.Where(gp => gp.SamAccountName == "Administrators")
            //    {
            //        if (gp.SamAccountName == "Administrators" || gp.SamAccountName == "Guests" || gp.SamAccountName == "Users" || gp.SamAccountName == "IIS_IUSRS" || gp.SamAccountName == "Remote Desktop Users" || gp.SamAccountName == "Remote Management Users")
            //        {
            //            foreach (var member in gp.Members)
            //            {
            //                if (member.Name.ToLower().Contains("administrator") || member.Name.ToLower().Contains("admin"))
            //                    WriteLog("帐号: " + member.Name + "(" + gp.SamAccountName + ") " + member.Description + " 是否禁用 不安全");
            //                else
            //                    WriteLog("帐号: " + member.Name + "(" + gp.SamAccountName + ") " + member.Description + "  安全");
            //            }
            //        }
            //    }
            //}
 
 
            WriteLog( "--------------------------------------------------------------" );
            WriteLog( "---------------------------已开放端口-------------------------" );
            WriteLog( "--------------------------------------------------------------" );
 
            IPGlobalProperties properti = IPGlobalProperties.GetIPGlobalProperties();
 
            var ipEndPoints = properti.GetActiveTcpListeners();
            foreach ( var ip  in ipEndPoints)
            {
                WriteLog( "已开放端口:" + ip.ToString());
            }
 
            //当前已建立连接
            var tcps = properti.GetActiveTcpConnections().ToList().Where(f => !f.RemoteEndPoint.Address.ToString().Contains( "127.0" ) && !f.RemoteEndPoint.Address.ToString().Contains( "192.168" ) && f.State == TcpState.Established).OrderBy(f => f.LocalEndPoint.Port);
            foreach ( var ip  in tcps)
            {
                if (ip.LocalEndPoint.Port != 80)
                {
                    WriteLog( "已连接:" + ip.LocalEndPoint.ToString() +  "->" + ip.RemoteEndPoint.ToString() +  "(" + myIP.SearchIPLocationStr(ip.RemoteEndPoint.ToString()) +  ") " + ip.State.ToString());
                }
            }
 
 
            WriteLog( "--------------------------------------------------------------" );
            WriteLog( "----------------------当前已连接服务器------------------------" );
            WriteLog( "--------------------------------------------------------------" );
 
            System.Diagnostics.Process p =  new System.Diagnostics.Process();
            p.StartInfo.FileName =  "cmd.exe" ;
            p.StartInfo.UseShellExecute =  false ;     //是否使用操作系统shell启动
            p.StartInfo.RedirectStandardInput =  true ; //接受来自调用程序的输入信息
            p.StartInfo.RedirectStandardOutput =  true ; //由调用程序获取输出信息
            p.StartInfo.RedirectStandardError =  true ; //重定向标准错误输出
            p.StartInfo.CreateNoWindow =  true ; //不显示程序窗口
            p.Start(); //启动程序
 
            //向cmd窗口发送输入信息
            p.StandardInput.WriteLine( "netstat -ano&exit" );
            p.StandardInput.AutoFlush =  true ;
            //获取cmd窗口的输出信息
            string output = p.StandardOutput.ReadToEnd();
            p.WaitForExit(); //等待程序执行完退出进程
            p.Close();
 
            string [] lines = output.Remove(0, output.IndexOf( "PID" ) + 3).Replace( "  " " " ).Replace( "  " " " ).Replace( "  " " " ).Replace( "  " " " ).Split( new string [] {  "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            foreach ( string str  in lines)
            {
                string line = str.Trim();
                if (line.StartsWith( "TCP" , StringComparison.OrdinalIgnoreCase))
                {
                    string [] arr = line.Split( ' ' );
 
                    if (arr.Length == 5 && arr[3] ==  "ESTABLISHED" )
                    {
                        if (arr[1].Split( ':' )[1] ==  "80" continue ;
 
                        int pid = Int32.Parse(arr[4]);
 
                        Process pro80 = Process.GetProcessById(pid);
 
                        string fullPath =  "" ;
                        string wmiQuery =  string .Format( "select CommandLine,ExecutablePath from Win32_Process where ProcessId={0}" , pid);
                        using (ManagementObjectSearcher searcher2 =  new ManagementObjectSearcher(wmiQuery))
                        {
                            using (ManagementObjectCollection retObjectCollection = searcher2.Get())
                            {
                                foreach (ManagementObject retObject  in retObjectCollection)
                                {
                                    //if (retObject["CommandLine"] != null)
                                    //{
                                    //    string s = (string.Format("[{0}]", retObject["CommandLine"]));
                                    //    string k = s.Substring(s.IndexOf("EXE") + 3);
                                    //    k = k.Remove(k.IndexOf("]"));
                                    //    return k;
                                    //}
                                    fullPath = ( string )retObject[ "ExecutablePath" ];
                                    break ;
                                }
                            }
                        }
 
                        if ( string .IsNullOrWhiteSpace(fullPath))
                            WriteLog( string .Format( "{0} {1}->{2} {3}" , arr[0], arr[1], arr[2] +  "(" + myIP.SearchIPLocationStr(arr[2]) +  ")" , pro80.ProcessName +  ".exe" ));
                        else
                            WriteLog( string .Format( "{0} {1}->{2} {3}" , arr[0], arr[1], arr[2] +  "(" + myIP.SearchIPLocationStr(arr[2]) +  ")" , fullPath));
                    }
                }
            }
 
            WriteLog( "--------------------------------------------------------------" );
            WriteLog( "----------------------当前已开启共享------------------------" );
            WriteLog( "--------------------------------------------------------------" );
 
            ManagementObjectSearcher searcher =  new ManagementObjectSearcher( "select * from win32_share" );
            foreach (ManagementObject share  in searcher.Get())
            {
                string type = share[ "Type" ].ToString();
                string name = share[ "Name" ].ToString();  //getting share name
                string path = share[ "Path" ].ToString();  //getting share path
                string caption = share[ "Caption" ].ToString();  //getting share description
 
                if (type ==  "0" // 0 = DiskDrive (1 = Print Queue, 2 = Device, 3 = IPH)
                {
                    WriteLog( "共享磁盘: " + path +  " 请检查" );
                }
                else if (type ==  "3" // 0 = DiskDrive (1 = Print Queue, 2 = Device, 3 = IPH)               
                {
                    WriteLog( "共享IPH: " + name +  " 请检查" );
                }
                else if (type ==  "1" // 0 = DiskDrive (1 = Print Queue, 2 = Device, 3 = IPH)               
                {
                    WriteLog( "共享打印机: " + name +  " 请检查" );
                }
                //else
                //{
                //    WriteLog("默认共享: " + name + " 请检查");
                //}
 
                //share.InvokeMethod("Delete", null, null);//删除共享
            }
 
            WriteLog( "--------------------------------------------------------------" );
            WriteLog( "----------------------当前防火墙状态------------------------" );
            WriteLog( "--------------------------------------------------------------" );
 
            INetFwMgr netFwMgr = (INetFwMgr)Activator.CreateInstance(Type.GetTypeFromProgID( "HNetCfg.FwMgr" ));
            WriteLog( "防火墙状态:" + (netFwMgr.LocalPolicy.CurrentProfile.FirewallEnabled ?  "已启用" "未启用" ));
 
            WriteLog( "--------------------------------------------------------------" );
            WriteLog( "----------------------当前防火墙开放规则------------------------" );
            WriteLog( "--------------------------------------------------------------" );
            INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID( "HNetCfg.FwPolicy2" ));
 
            Dictionary< int string > dic =  new Dictionary< int string >();
 
            //检查是否有同名规则
            foreach (INetFwRule item  in firewallPolicy.Rules)
            {
                int port = 0;
                int .TryParse(item.LocalPorts,  out port);
                if (port > 0)
                {
                    if (item.Enabled && item.Action != NET_FW_ACTION_.NET_FW_ACTION_BLOCK) //阻止连接
                    {
                        if (dic.ContainsKey(port))
                        {
                            if (dic[port] != item.Name)
                                dic[port] = item.Name +  "," + dic[port];
                        }
                        else
                        {
                            dic.Add(port, item.Name);
                        }
                    }
                }
            }
 
            foreach ( var item  in dic.OrderBy(o => o.Key))
            {
                WriteLog( "规则:[" + item.Key +  "] --------------- " + item.Value);
            }
 
            WriteLog( "--------------------------------------------------------------" );
            WriteLog( "---------------------------系统安全日志-----------------------" );
            WriteLog( "--------------------------------------------------------------" );
 
            //List list = new List();
            //foreach (var eventLog2 in EventLog.GetEventLogs())
            //{
            //    if (!list.Contains(eventLog2.Log))
            //        list.Add(eventLog2.Log);
            //    foreach (EventLogEntry entry in eventLog2.Entries)
            //    {
            //        //Debug.WriteLine(entry.Message);
            //    }
            //}
            //Console.WriteLine(string.Join("\r\n",list.ToArray()));
 
            //Application
            //HardwareEvents
            //Internet Explorer
            //Key Management Service
            //Kingsoft Internet Security
            //Security
            //System
            //Visual Studio
            //Windows Azure
            //Windows PowerShell
 
            //读取安全日志
            foreach (EventLogEntry entry  in new EventLog( "Security" ).Entries)
            {
                string msg =  string .Join( "," , entry.ReplacementStrings);
 
                string [] m = entry.Message.Split( new string [] {  "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
 
                if (entry.ReplacementStrings.Length == 14 && entry.ReplacementStrings[12] !=  "-" )
                {
                    WriteLog( "安全日志:" + entry.TimeGenerated +  " [" + myIP.SearchIPLocationStr(entry.ReplacementStrings[12]) +  "]尝试用1[" + entry.ReplacementStrings[5] +  "]登录 结果:" + m[0]);
                }
                else if (entry.ReplacementStrings.Length == 21 && entry.ReplacementStrings[19] !=  "-" )
                {
                    WriteLog( "安全日志:" + entry.TimeGenerated +  " [" + entry.ReplacementStrings[19] +  "(" + myIP.SearchIPLocationStr(entry.ReplacementStrings[19]) +  ")" "]尝试用2[" + entry.ReplacementStrings[5] +  "]登录 结果:" + m[0]);
                }
                else if (entry.ReplacementStrings.Length == 4 && !m[0].Contains( "计算机试图验证帐户的凭据" ))
                {
                    WriteLog( "安全日志:" + entry.TimeGenerated +  " [" + entry.ReplacementStrings[1] +  "]:" + m[0]);
                }
                else if (entry.ReplacementStrings.Length == 6 && !entry.ReplacementStrings[4].StartsWith( "S-" ))
                {
                    WriteLog( "安全日志:" + entry.TimeGenerated +  " [" + entry.ReplacementStrings[5] +  "][" + myIP.SearchIPLocationStr(entry.ReplacementStrings[4]) +  "]尝试用3[" + entry.ReplacementStrings[0] +  "]登录 结果:" + m[0]);
                }
                else
                {
                    if (entry.Message.Contains( "客户端地址:" ))
                    {
 
                    }
                    else
                    {
 
                    }
                }
            }
 
            WriteLog( "--------------------------------------------------------------" );
            WriteLog( "-------------------------应用安全日志-------------------------" );
            WriteLog( "--------------------------------------------------------------" );
 
 
            foreach (EventLogEntry entry  in new EventLog( "Application" ).Entries)
            {
                string msg =  string .Join( "," , entry.ReplacementStrings);
 
                string [] m = entry.Message.Split( new string [] {  "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
 
                if (entry.Message.Contains( "登录失败" ) && !entry.Message.Contains( "SQL 跟踪" ))
                {
                    if (entry.ReplacementStrings.Length == 30)
                    {
                        WriteLog( "安全日志:" + entry.TimeGenerated +  " [" + myIP.SearchIPLocationStr(entry.ReplacementStrings[12]) +  "]尝试访问[" + entry.ReplacementStrings[19] +  "][" + entry.ReplacementStrings[11] +  "]登录 结果:" + entry.ReplacementStrings[18]);
 
                    }
                    else
                    {
                        WriteLog( "应用日志:" + entry.TimeGenerated +  " " + entry.Message);
                    }
                }
                else
                {
                }
            }
 
            WriteLog( "--------------------------------------------------------------" );
            WriteLog( "---------------------------全部执行完成-----------------------" );
            WriteLog( "--------------------------------------------------------------" );
 
            Console.ReadKey();
        }
 
 
        ///
        /// 输出日志并保存文件
        ///
        ///
        public static void WriteLog( string value)
        {
            try
            {
                if ( string .IsNullOrWhiteSpace(value))  return ;
 
                Console.WriteLine(value);
 
                string path = DateTime.Now.ToString( "yyyy-MM-dd-HH" ) +  ".config" ;
                StreamWriter streamWriter =  new StreamWriter(path,  true );
                streamWriter.WriteLine(value);
                streamWriter.Close();
            }
            catch
            {
            }
        }
 
    }
}

  

复制代码
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Web;
using System.Configuration;

namespace IPCheck
{

    /*
    使用方法:

    例子:
    QQWry qq=new QQWry("d:\\QQWry.Dat");
    IPLocation ip=qq.SearchIPLocation("127.0.0.1");//这里添写IP地址
    Console.WriteLine(ip.country);//国家
    Console.WriteLine(ip.area);//地区
    */

    //以下是类文件
    //根据LumaQQ改写而成.

    /**/
    ///<summary>
    /// QQWry 的摘要说明。
    ///</summary>
    public class QQWry
    {
        //第一种模式
        #region 第一种模式
        /**/
        ///<summary>
        ///第一种模式
        ///</summary>
        #endregion
        private const byte REDIRECT_MODE_1 = 0x01;

        //第二种模式
        #region 第二种模式
        /**/
        ///<summary>
        ///第二种模式
        ///</summary>
        #endregion
        private const byte REDIRECT_MODE_2 = 0x02;

        //每条记录长度
        #region 每条记录长度
        /**/
        ///<summary>
        ///每条记录长度
        ///</summary>
        #endregion
        private const int IP_RECORD_LENGTH = 7;

        //数据库文件
        #region 数据库文件
        /**/
        ///<summary>
        ///文件对象
        ///</summary>
        #endregion
        private FileStream ipFile;

        private const string unCountry = "未知国家";
        private const string unArea = "未知地区";

        //索引开始位置
        #region 索引开始位置
        /**/
        ///<summary>
        ///索引开始位置
        ///</summary>
        #endregion
        private long ipBegin;

        //索引结束位置
        #region 索引结束位置
        /**/
        ///<summary>
        ///索引结束位置
        ///</summary>
        #endregion
        private long ipEnd;

        //IP地址对象
        #region IP地址对象
        /**/
        ///<summary>
        /// IP对象
        ///</summary>
        #endregion
        private IPLocation loc;

        //存储文本内容
        #region 存储文本内容
        /**/
        ///<summary>
        ///存储文本内容
        ///</summary>
        #endregion
        private byte[] buf;

        //存储3字节
        #region 存储3字节
        /**/
        ///<summary>
        ///存储3字节
        ///</summary>
        #endregion
        private byte[] b3;

        //存储4字节
        #region 存储4字节
        /**/
        ///<summary>
        ///存储4字节IP地址
        ///</summary>
        #endregion
        private byte[] b4;

        //构造函数
        #region 构造函数
        /**/
        ///<summary>
        ///构造函数
        ///</summary>
        ///<param name="ipfile">IP数据库文件绝对路径</param>
        #endregion
        public QQWry(string ipfile)
        {

            buf = new byte[100];
            b3 = new byte[3];
            b4 = new byte[4];
            try
            {
                ipFile = new FileStream(ipfile, FileMode.Open);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            ipBegin = readLong4(0);
            ipEnd = readLong4(4);
            loc = new IPLocation();
        }

        //根据IP地址搜索
        #region 根据IP地址搜索
        /**/
        ///<summary>
        ///搜索IP地址搜索
        ///</summary>
        ///<param name="ip"></param>
        ///<returns></returns>
        #endregion
        public IPLocation SearchIPLocation(string ip)
        {
            ip = ip.Split(':')[0];

            //将字符IP转换为字节
            string[] ipSp = ip.Split('.');
            if (ipSp.Length != 4)
            {
                return new IPLocation();
                throw new ArgumentOutOfRangeException("不是合法的IP地址!");
            }
            byte[] IP = new byte[4];
            for (int i = 0; i < IP.Length; i++)
            {
                IP[i] = (byte)(Int32.Parse(ipSp[i]) & 0xFF);
            }

            IPLocation local = null;
            long offset = locateIP(IP);

            if (offset != -1)
            {
                local = getIPLocation(offset);
            }

            if (local == null)
            {
                local = new IPLocation();
                local.area = unArea;
                local.country = unCountry;
            }
            return local;
        }

        public string SearchIPLocationStr(string strIp)
        {
            IPLocation ip = SearchIPLocation(strIp);
            if (ip != null)
                return ip.country + "->" + ip.area;

            return strIp;
        }

        //取得具体信息
        #region 取得具体信息
        /**/
        ///<summary>
        ///取得具体信息
        ///</summary>
        ///<param name="offset"></param>
        ///<returns></returns>
        #endregion
        private IPLocation getIPLocation(long offset)
        {
            ipFile.Position = offset + 4;
            //读取第一个字节判断是否是标志字节
            byte one = (byte)ipFile.ReadByte();
            if (one == REDIRECT_MODE_1)
            {
                //第一种模式
                //读取国家偏移
                long countryOffset = readLong3();
                //转至偏移处
                ipFile.Position = countryOffset;
                //再次检查标志字节
                byte b = (byte)ipFile.ReadByte();
                if (b == REDIRECT_MODE_2)
                {
                    loc.country = readString(readLong3());
                    ipFile.Position = countryOffset + 4;
                }
                else
                    loc.country = readString(countryOffset);

                //读取地区标志
                loc.area = readArea(ipFile.Position);

            }
            else if (one == REDIRECT_MODE_2)
            {
                //第二种模式
                loc.country = readString(readLong3());
                loc.area = readArea(offset + 8);
            }
            else
            {
                //普通模式
                loc.country = readString(--ipFile.Position);
                loc.area = readString(ipFile.Position);
            }
            return loc;
        }

        //取得地区信息
        #region 取得地区信息
        /**/
        ///<summary>
        ///读取地区名称
        ///</summary>
        ///<param name="offset"></param>
        ///<returns></returns>
        #endregion
        private string readArea(long offset)
        {
            ipFile.Position = offset;
            byte one = (byte)ipFile.ReadByte();
            if (one == REDIRECT_MODE_1 || one == REDIRECT_MODE_2)
            {
                long areaOffset = readLong3(offset + 1);
                if (areaOffset == 0)
                    return unArea;
                else
                {
                    return readString(areaOffset);
                }
            }
            else
            {
                return readString(offset);
            }
        }

        //读取字符串
        #region 读取字符串
        /**/
        ///<summary>
        ///读取字符串
        ///</summary>
        ///<param name="offset"></param>
        ///<returns></returns>
        #endregion
        private string readString(long offset)
        {
            ipFile.Position = offset;
            int i = 0;
            for (i = 0, buf[i] = (byte)ipFile.ReadByte(); buf[i] != (byte)(0); buf[++i] = (byte)ipFile.ReadByte()) ;

            if (i > 0)
                return Encoding.Default.GetString(buf, 0, i);
            else
                return "";
        }

        //查找IP地址所在的绝对偏移量
        #region 查找IP地址所在的绝对偏移量
        /**/
        ///<summary>
        ///查找IP地址所在的绝对偏移量
        ///</summary>
        ///<param name="ip"></param>
        ///<returns></returns>
        #endregion
        private long locateIP(byte[] ip)
        {
            long m = 0;
            int r;

            //比较第一个IP项
            readIP(ipBegin, b4);
            r = compareIP(ip, b4);
            if (r == 0)
                return ipBegin;
            else if (r < 0)
                return -1;
            //开始二分搜索
            for (long i = ipBegin, j = ipEnd; i < j;)
            {
                m = this.getMiddleOffset(i, j);
                readIP(m, b4);
                r = compareIP(ip, b4);
                if (r > 0)
                    i = m;
                else if (r < 0)
                {
                    if (m == j)
                    {
                        j -= IP_RECORD_LENGTH;
                        m = j;
                    }
                    else
                    {
                        j = m;
                    }
                }
                else
                    return readLong3(m + 4);
            }
            m = readLong3(m + 4);
            readIP(m, b4);
            r = compareIP(ip, b4);
            if (r <= 0)
                return m;
            else
                return -1;
        }

        //读出4字节的IP地址
        #region 读出4字节的IP地址
        /**/
        ///<summary>
        ///从当前位置读取四字节,此四字节是IP地址
        ///</summary>
        ///<param name="offset"></param>
        ///<param name="ip"></param>
        #endregion
        private void readIP(long offset, byte[] ip)
        {
            ipFile.Position = offset;
            ipFile.Read(ip, 0, ip.Length);
            byte tmp = ip[0];
            ip[0] = ip[3];
            ip[3] = tmp;
            tmp = ip[1];
            ip[1] = ip[2];
            ip[2] = tmp;
        }

        //比较IP地址是否相同
        #region 比较IP地址是否相同
        /**/
        ///<summary>
        ///比较IP地址是否相同
        ///</summary>
        ///<param name="ip"></param>
        ///<param name="beginIP"></param>
        ///<returns>0:相等,1:ip大于beginIP,-1:小于</returns>
        #endregion
        private int compareIP(byte[] ip, byte[] beginIP)
        {
            for (int i = 0; i < 4; i++)
            {
                int r = compareByte(ip[i], beginIP[i]);
                if (r != 0)
                    return r;
            }
            return 0;
        }

        //比较两个字节是否相等
        #region 比较两个字节是否相等
        /**/
        ///<summary>
        ///比较两个字节是否相等
        ///</summary>
        ///<param name="bsrc"></param>
        ///<param name="bdst"></param>
        ///<returns></returns>
        #endregion
        private int compareByte(byte bsrc, byte bdst)
        {
            if ((bsrc & 0xFF) > (bdst & 0xFF))
                return 1;
            else if ((bsrc ^ bdst) == 0)
                return 0;
            else
                return -1;
        }

        //根据当前位置读取4字节
        #region 根据当前位置读取4字节
        /**/
        ///<summary>
        ///从当前位置读取4字节,转换为长整型
        ///</summary>
        ///<param name="offset"></param>
        ///<returns></returns>
        #endregion
        private long readLong4(long offset)
        {
            long ret = 0;
            ipFile.Position = offset;
            ret |= (ipFile.ReadByte() & 0xFF);
            ret |= ((ipFile.ReadByte() << 8) & 0xFF00);
            ret |= ((ipFile.ReadByte() << 16) & 0xFF0000);
            ret |= ((ipFile.ReadByte() << 24) & 0xFF000000);
            return ret;
        }

        //根据当前位置,读取3字节
        #region 根据当前位置,读取3字节
        /**/
        ///<summary>
        ///根据当前位置,读取3字节
        ///</summary>
        ///<param name="offset"></param>
        ///<returns></returns>
        #endregion
        private long readLong3(long offset)
        {
            long ret = 0;
            ipFile.Position = offset;
            ret |= (ipFile.ReadByte() & 0xFF);
            ret |= ((ipFile.ReadByte() << 8) & 0xFF00);
            ret |= ((ipFile.ReadByte() << 16) & 0xFF0000);
            return ret;
        }

        //从当前位置读取3字节
        #region 从当前位置读取3字节
        /**/
        ///<summary>
        ///从当前位置读取3字节
        ///</summary>
        ///<returns></returns>
        #endregion
        private long readLong3()
        {
            long ret = 0;
            ret |= (ipFile.ReadByte() & 0xFF);
            ret |= ((ipFile.ReadByte() << 8) & 0xFF00);
            ret |= ((ipFile.ReadByte() << 16) & 0xFF0000);
            return ret;
        }

        //取得begin和end之间的偏移量
        #region 取得begin和end之间的偏移量
        /**/
        ///<summary>
        ///取得begin和end中间的偏移
        ///</summary>
        ///<param name="begin"></param>
        ///<param name="end"></param>
        ///<returns></returns>
        #endregion
        private long getMiddleOffset(long begin, long end)
        {
            long records = (end - begin) / IP_RECORD_LENGTH;
            records >>= 1;
            if (records == 0)
                records = 1;
            return begin + records * IP_RECORD_LENGTH;
        }
    } //class QQWry

    public class IPLocation
    {
        public String country;
        public String area;

        public IPLocation()
        {
            country = area = "";
        }

        public IPLocation getCopy()
        {
            IPLocation ret = new IPLocation();
            ret.country = country;
            ret.area = area;
            return ret;
        }
    }
}
复制代码

 

posted @   懒人境界  阅读(243)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示