编写ARP扫描器探测局域网活动主机
文/图 暗夜舞者
现在大多上网用户用的是小区宽带,这就为我们的入侵活动提供了方便。行动之前我们要做好充分的准备,比如扫描。
对目标主机进行网络扫描时,首先要进行的工作是判断目标主机是否存活或在线。传统的探测远程主机是否存活的方法是通过ICMP协议中的回显应答报文来探测(Ping)。随着对安全的越来越多的了解和重视,很多主机为了避免被扫描器探测,通过防火墙将ICMP包屏蔽,从而达到在网络中隐藏的目的。这时,Ping返回的结果一般是“Request timed out”,表明目标主机没有处于活动状态,但其实目标主机在线。
利用ARP探测活动主机可以达到避开防火墙探测活动主机的目的。ARP协议的作用是将IP地址转换成物理地址(MAC地址)。攻击者向目标主机发送一个ARP请求,如果目标主机处于活动状态,则会返回其MAC地址,这样就可以达到探测活动主机的目的了。我实现这个想法的源代码如下。
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <iphlpapi.h>
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"iphlpapi.lib")
char StartIP[20]; //扫描起始IP地址
char EndIP[20]; //扫描结束IP地址
int ProgressTag=0; //进度条标志位
上面的代码主要包含了相关头文件,加载了必需的库文件,并且定义了全局变量StartIP和EndIP。变量StartIP表示扫描起始地址,变量EndIP表示扫描结束地址。注意,由于程序要用SendARP函数,所以要包含头文件iphlpapi.h和加载库文件iphlpapi.lib。
// 解析命令行
void ParseCmd(int argc, char **argv)
{
if(argc != 2)
{
printf("usage : ActiveHostScan.exe [StartIP-EndIP]");
exit(0);
}
char *pdest;
int result;
ZeroMemory(StartIP,20);
ZeroMemory(EndIP,20);
int ch = -; //分隔符
pdest = strchr( argv[1], ch );
result = pdest - argv[1] + 1; //寻找“-”的位置
strncpy(StartIP,argv[1],result-1); //提取起始IP地址
strncpy(EndIP,argv[1]+result,strlen(argv[1])-result); //提取结束IP地址
}
上面的代码实现解析用户输入命令的函数。参数argc是字符串个数;argv表示用户输入命令。程序流程是:先判断输入的命令个数是否符合要求,然后调用strchr函数搜寻“-”的位置,最后找到相应位置将用户输入的起始IP和结束IP赋值给StartIP和EndIP。
//定义进度提示函数
void ProgressShow(void)
{
//进度条
char *progressbar[12]=
{
"|","/","-","\","|","/","-","\","|","/","-","\",
};
printf(" =%s=",progressbar[ProgressTag]);
ProgressTag=(ProgressTag==11)?0:ProgressTag+1;
Sleep(2);
}
//扫描目标主机是否存活
int ScanHostState(char *ip)
{
HRESULT hr;
IPAddr ipAddr;
ULONG pulMac[2];//MAC地址
ULONG ulLen;
char *szMac;
//转换成网络字节顺序
ipAddr = inet_addr (ip);
//设置MAC地址为广播地址xff
memset (pulMac, 0xff, sizeof (pulMac));
ulLen = 6;
hr = SendARP (ipAddr, 0, pulMac, &ulLen);
//如果返回无错则表明指定目标主机存活
if(hr == NO_ERROR)
{
size_t i, j;
szMac = new char[ulLen*3];
PBYTE pbHexMac = (PBYTE) pulMac;
//转换MAC地址为字符串格式以便输出
for (i = 0, j = 0; i < ulLen - 1; ++i) {
j += sprintf (szMac + j, "%02X:", pbHexMac[i]);
}
sprintf (szMac + j, "%02X", pbHexMac[i]);
printf ("主机%s 响应! MAC地址:%s
",ip, szMac);
delete [] szMac;
return 1;
}
return 0;
}
上面的代码实现用ARP数据包探测指定主机是否存活的函数,参数ip表示目标IP。
//主函数
int main(int argc, char **argv)
{
//解析命令行
ParseCmd(argc,argv);
struct in_addr targetaddr;
//目标机地址结构
unsigned long ips=inet_addr(StartIP);
//计算起始IP地址的网络字节
unsigned long ipe=inet_addr(EndIP);
//计算结束IP地址的网络字节
ips=ntohl(ips);
//计算起始IP地址的主机字节
ipe=ntohl(ipe);
//计算结束IP地址的主机字节
DWORD dwStart = GetTickCount();
//记录开始时间
//开始循环探测主机
for(int k=ips;k<=ipe;k++)
{
ProgressShow();
targetaddr.S_un.S_addr=htonl(k);
//探测指定主机是否存活
ScanHostState(inet_ntoa(targetaddr));
Sleep(10);
}
printf("
探测消耗时间:%d ms
",GetTickCount()-dwStart);
return 0;
}
我们运行一下,在命令提示符下输入“activehostscan.exe 124.93.27.1-124.93.27.200”,结果如图1所示,可以看到利用ARP不仅能探测主机是否存活,还可以探测其MAC地址。
图1
以上程序只是一个构架,希望大家可以得到一些提示,在此基础上添加更多的功能来完善它
补充:综合编程 , 其他综合 ,