Forerunner 库是一个快速、轻量且可扩展的网络库,旨在帮助开发健壮的网络中心型应用程序,例如:IP 扫描器、端口敲门工具、客户端、服务器等。在目前的状态下,Forerunner 库能够同步和异步地扫描和端口敲门 IP 地址,以获取该端点设备的相关信息,例如:IP 是否在线、物理 MAC 地址等。该库完全面向对象且基于事件,因此扫描数据被包含在专门定制的“扫描”对象中,这些对象设计用于处理从结果到异常的所有数据。
| 方法 | 描述 | 用法 |
|---|---|---|
| Scan | 扫描单个 IP 以获取信息 | Scan("192.168.1.1"); |
| ScanRange | 扫描一段 IP 范围以获取信息 | ScanRange("192.168.1.1", "192.168.1.255") |
| ScanList | 扫描一个 IP 列表以获取信息 | ScanList("192.168.1.1, 192.168.1.2, 192.168.1.3") |
| PortKnock | Ping 单个 IP 的所有端口 | PortKnock("192.168.1.1"); |
| PortKnockRange | Ping 一段 IP 范围内的所有端口 | PortKnockRange("192.168.1.1", "192.168.1.255"); |
| PortKnockList | Ping 一个 IP 列表的所有端口 | PortKnockList("192.198.1.1, 192.168.1.2, 192.168.1.3"); |
| IsHostAlive | Ping 一个主机 N 次,每次等待 X 毫秒 | IsHostAlive("192.168.1.1", 5, 1000); |
| GetAveragePingResponse | 获取主机的平均 Ping 响应时间 | GetAveragePingResponse("192.168.1.1", 5, 1000); |
| IsPortOpen | 通过 TCP & UDP Ping 单个端口 | IsPortOpen("192.168.1.1", 45000, new TimeSpan(1000), false); |
在这个数字时代,扫描网络是一项常见任务,因此我特意让未来的程序员能够以最简单的方式完成这项工作。Forerunner 库完全面向对象,非常适合即插即用场景;用于 IP 扫描的对象称为 IPScanObject,它实际上包含多个属性:
了解了这个对象之后,让我们尝试创建一个新对象并使用它执行扫描。有几种方法可以实现,但最简单的入门方法是先创建一个新的 Scanner 对象,以便访问扫描方法。然后,创建一个 IPScanObject,并将其设置为 Scan 方法,传入你想要枚举的 IP;例如:
using System;
using Forerunner; // 记得导入我们的库。
namespace Example
{
class Program
{
static void Main(string[] args)
{
// 我们要扫描的 IP。
string ip = "192.168.1.1";
// 创建一个新的扫描器对象。
Scanner s = new Scanner();
// 创建一个新的扫描对象并执行扫描。
IPScanObject result = s.Scan(ip);
// 输出扫描完成的信息。
if (result.Errors != null)
Console.WriteLine("[x] 扫描过程中发生错误。");
else
Console.WriteLine("[+] " + ip + " 已成功扫描!");
// 允许用户随时退出。
Console.Read();
}
}
}
另一种方法,也是我偏好的操作方式,是创建一个 Scanner 对象,并订阅 ScanAsyncProgressChanged 或 ScanAsyncComplete 等事件处理器,这样我就能完全控制异步方法;我可以控制它们的状态如何影响我的应用程序等等;例如:
using System;
using System.Threading.Tasks;
using Forerunner; // 记得导入我们的库。
namespace Example
{
class Program
{
static void Main(string[] args)
{
// 我们要扫描的 IP。
string ip = "192.168.1.1";
// 设置我们的扫描器对象。
Scanner s = new Scanner();
s.ScanAsyncProgressChanged += new ScanAsyncProgressChangedHandler(ScanAsyncProgressChanged);
s.ScanAsyncComplete += new ScanAsyncCompleteHandler(ScanAsyncComplete);
// 使用我们的 IP 启动一个新的扫描任务。
TaskFactory task = new TaskFactory();
task.StartNew(() => s.ScanAsync(ip));
// 允许用户随时退出。
Console.Read();
}
static void ScanAsyncProgressChanged(object sender, ScanAsyncProgressChangedEventArgs e)
{
// 在此处使用 e.Progress 做些事情,或者你可以不订阅此事件,从而什么都不做。
}
static void ScanAsyncComplete(object sender, ScanAsyncCompleteEventArgs e)
{
// 使用 IPScanObject(即 e.Result)做些事情。
if (e.Result.Errors != null)
Console.WriteLine("[x] 扫描过程中发生错误。");
else
Console.WriteLine("[+] " + e.Result.IP + " 已成功扫描!");
}
}
}
我知道你在想什么。端口敲门?是的,也不完全是。这个术语并不指传统意义上的通过一组预定义端口连接,而仅仅是检查是否有端口是开放的。从字面意义上讲,就是通过尝试连接每个端口并发送数据来“敲门”。与 IP 扫描一样,端口敲门使用一个自定义对象,称为“Port Knock Scan Object”或简写 PKScanObject。PKScanObject 实际上包含一个 PKServiceObject 列表,这些对象又包含我们的端口数据;服务对象包含以下属性:
端口敲门的方式与 IP 扫描类似。首先,创建一个 Scanner 对象。然后,创建一个新的 PKScanObject,并将其设置为 PortKnock 方法,传入你选择的 IP,然后显示结果;例如:
using System;
using Forerunner; // 记得导入我们的库。
namespace Example
{
class Program
{
static void Main(string[] args)
{
// 我们要扫描的 IP。
string ip = "192.168.1.1";
// 创建一个新的扫描器对象。
Scanner s = new Scanner();
// 创建一个新的扫描对象并执行扫描。
PKScanObject result = s.PortKnock(ip);
// 输出扫描完成的信息。
if (result.Errors != null)
Console.WriteLine("[x] 扫描过程中发生错误。");
else
Console.WriteLine("[+] " + ip + " 已成功扫描!");
// 显示我们的结果。
foreach (PKServiceObject port in result.Services)
{
Console.WriteLine("[+] IP: " + port.IP + " | " +
"Port: " + port.Port.ToString() + " | " +
"Protocol: " + port.Protocol.ToString() + " | " +
"Status: " + port.Status.ToString());
}
// 允许用户随时退出。
Console.Read();
}
}
}
最后,我将向你展示一个异步端口敲门的简单示例。它与同步端口敲门基本相同,只是你可以利用事件。你可以获取进度更新,而无需担心 UI 崩溃或系统处于锁定状态;例如:
using System;
using System.Threading.Tasks;
using Forerunner; // 记得导入我们的库。
namespace Example
{
class Program
{
static void Main(string[] args)
{
// 我们要扫描的 IP。
string ip = "192.168.1.1";
// 设置我们的扫描器对象。
Scanner s = new Scanner();
s.PortKnockAsyncProgressChanged += new PortKnockAsyncProgressChangedHandler(PortKnockAsyncProgressChanged);
s.PortKnockAsyncComplete += new PortKnockAsyncCompleteHandler(PortKnockAsyncComplete);
// 使用我们的 IP 启动一个新的扫描任务。
TaskFactory task = new TaskFactory();
task.StartNew(() => s.PortKnockAsync(ip));
// 允许用户随时退出。
Console.Read();
}
static void PortKnockAsyncProgressChanged(object sender, PortKnockAsyncProgressChangedEventArgs e)
{
// 显示我们的进度,以便我们知道预计剩余时间。
if (e.Progress == 99)
{
Console.Write(e.Progress.ToString() + "%...");
Console.WriteLine("100%!");
}
else
Console.Write(e.Progress.ToString() + "%...");
}
static void PortKnockAsyncComplete(object sender, PortKnockAsyncCompleteEventArgs e)
{
// 告诉用户端口敲门已完成。
Console.WriteLine("[+] 端口敲门完成!");
// 检查是否解析出错误。
if (e.Result == null)
Console.WriteLine("[X] 端口敲门没有返回任何数据!");
else
{
// 检查是否有记录到端口。
if (e.Result.Services.Count == 0)
Console.WriteLine("[!] 敲门期间没有端口开放。");
else
{
// 显示我们的端口及其详细信息。
foreach (PKServiceObject port in e.Result.Services)
{
Console.WriteLine("[+] IP: " + port.IP + " | " +
"Port: " + port.Port.ToString() + " | " +
"Protocol: " + port.Protocol.ToString() + " | " +
"Status: " + port.Status.ToString());
}
}
}
}
}
}
图标: monkik
https://www.flaticon.com/authors/monkik
版权所有 © ∞ Jason Drawdy
保留所有权利。
MIT 许可证(MIT)
特此免费授予任何获得本软件及相关文档文件(以下简称“软件”)副本的人,不受限制地处理本软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售本软件副本的权利,并允许获得本软件的人这样做,但须符合以下条件:
上述版权声明和本许可声明应包含在所有副本或实质部分中。
本软件按“原样”提供,不作任何明示或暗示的保证,包括但不限于适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有人均不对因本软件或本软件的使用或其他交易而产生的任何索赔、损害或其他责任负责,无论是合同诉讼、侵权行为还是其他行为。
除本声明外,未经上述版权持有人事先书面授权,不得在广告或其他推广活动中使用其名称,以宣传本软件的销售、使用或其他交易。