无需客户端扫描局域网抓取返回信息

上一个章节中和大家讨论了如何编写一个程序获取到本机的Windows 系统安装了哪些HotFix(补丁程序)、开放了哪些端口、哪些共享;之后我们会讨论如何再开发一个管理端,由管理端网络指令命令客户端程序自我扫描后把结果返回回来。这里需要一些储备知识关于WinSocket 的。
昨天晚上有看客与我讨论,有没有可能不通过客户端程序(即不用在客户机上事先安装特定的程序)就能扫描到客户机的主要信息。实际上木马本身也是一种客户端程序,工作原理和正常用途的客户端程序没有什么区别。但是在没有客户端程序的情况爬取客户机信息从技术层面不无可能,可以说微软Windows 本身也支持,RPC 服务就为此而生。但是前提是你有这台机器的管理权,如果是利用某些漏洞绕过了权限的检查或获取到了管理员权限直接从你的电脑管理别人的电脑是微软本身支持的功能。但这不是今天要聊的话题。
首先拟定一下目标:远程抓取客户机信息;
前提:不需要在局域网中的其他电脑中安装客户端程序。只通过远程扫描方式。
探测出局域网上哪些机器是存活的,并得到MAC 地址、机器名
对指定的活动机器IP 端口进行试探性连接,判断其某些端口是不是开放了。
 
因为不是开发黑客木马程序,更多的前提条件不谈了,作为管理员肯定清楚你要扫的网络的IP 分配范围,比如我现在想扫描 192.168.50.1 – 192.168.50.254 ;
要判断一台机器是不是活的,常用的方法是PING ,PING 使用的是ICMP 协议,在程序代码里通过Socket 实现ICMP 协议非常简单,但是ICMP 有一个严重的问题就是太慢了,探测一个IP 要几十毫秒不等的时间,而且很多时候用户如果开启了以防火墙中禁制ICMP 出站规则你就有可能PING 不通它,但它的确是活的。因此这次可以采用ARP 协议,向对方的客户机发送一个ARP 包(不可用于伪装包攻击包),通过毫秒级的回包中就可以取到对方IP 的网卡MAC ,如果采用多线程的情况下,探测 254 个IP 时间不到 1秒。如果没有收到回包就可能对方的机器未开机不是活动状态。
 
CString ipTools::IPToMAC( CStringIpAddStr  )
{
 
         BYTEbyMAC[6];
         ZeroMemory(byMAC,6);
 
         DWORDdwLen = 6;
         intiReturn = SendARP( IPStrToNaddress(IpAddStr), 0, (PULONG) &byMAC,&dwLen);
 
         if( iReturn == NO_ERROR)
         {
                   CStringtmp;
                   tmp.Format(_T("%.2X-%.2X-%.2X-%.2X-%.2X-%.2X"),
                            byMAC[0],
                            byMAC[1],
                            byMAC[2],
                            byMAC[3],
                            byMAC[4],
                            byMAC[5]);
 
                   returntmp;              
         }
         else
         {
                   return_T("00-00-00-00-00-00");
         }
 
}

对于活动IP 就可以通过IP 获取其机器名,WinSocket中提供了一个函数getnameinfo   可以根据IP 返回机器名,但是这个函数执行非常慢,正常情况下调用这个函数取机器名,返回需要 1 -2 秒(是秒哦不是毫秒啊)这种效率是难以接受的,因而我们可以更一种方案人为构建一个NetBiosNs 的数据包,发向目标IP ,NETBIOS协议是由IBM公司开发,该协议是一种在局域网上的程序可以使用的应用程序编程接口,为程序提供了请求低级服务的统一的命令集,作用是为了给局域网提供网络以及其他特殊功能。系统可以利用WINS服务、广播及Lmhost文件等多种模式将NetBIOS名(特指基于NETBIOS协议获得计算机名称)解析为相应IP地址,实现信息通讯。


void ipTools::InitNetBiosNs(TNetBiosNS*nbns)
{
         nbns->tID=0x0000;
         nbns->Flags=0x1000;
         nbns->Questions=0x0100;
         nbns->AnswerRRs=0x0000;
         nbns->AuthorityRRs=0x0000;
         nbns->AdditionalRRs=0x0000;
         nbns->Name[0]=0x20;
         nbns->Name[1]=0x43;
         nbns->Name[2]=0x4b;
         for(inti=3;i<33;i++)
           nbns->Name[i]=0x41;
         nbns->Name[33]=0x00;
         nbns->tType=0x2100;
         nbns->tClass=0x0100;
}
 
 
CString ipTools::IPGetPCName( CStringipAddStr  )
{
         //获取远程机器名
         WSADatawsadata;
         WSAStartup(MAKEWORD(2,2),&wsadata);
         SOCKETudpClient = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
         sockaddr_inSrvAddr;      
         USES_CONVERSION;
         SrvAddr.sin_addr.S_un.S_addr= inet_addr(T2A(ipAddStr));// IpStrToNadd(ipAddStr);//inet_addr((LPSTR)(LPCTSTR)ipAddStr);
         SrvAddr.sin_family=AF_INET;
         SrvAddr.sin_port=htons(137);
         //if(connect(udpClient,(SOCKADDR*)&SrvAddr,sizeof(SOCKADDR))== SOCKET_ERROR)
         //      goto err;
         TNetBiosNSnbns;
         InitNetBiosNs(&nbns);
         if(sendto(udpClient,(char*)&nbns,sizeof(nbns),0,(SOCKADDR*)&SrvAddr,sizeof(SOCKADDR))== SOCKET_ERROR)
                   gotoerr;
         charrecvBuf[512];
         ZeroMemory(recvBuf,512);
         intlen = sizeof(SOCKADDR);
         if(recvfrom(udpClient,recvBuf,512,0,(SOCKADDR*)&SrvAddr,&len)== SOCKET_ERROR)
                   gotoerr;
         closesocket(udpClient);
         WSACleanup();
 
         for(inti=57;i<57+18;i++)
                   if(recvBuf[i]<0x20)
                            recvBuf[i]=0;
 
         return(CString)&recvBuf[57];
 
         err:
                   CStringErrorCode;
                   ErrorCode.Format(_T("%d"),GetLastError());
                   return_T("Error: " + ErrorCode );
        
}

 
为了提高扫描的效率非常有必要采用多线程技术,可以建立一个任务池对于现在硬件配置电脑64 位的PC 系统上同时开启254 个线程序应该是毫无压力的。不过发得太快也可能丢包哦,这个要看具体情况来调试了。
 
voidCMFCApplication1Dlg::OnBnClickedButton1()
{
         //TODO: 在此添加控件通知处理程序代码
 
         ipToolstest;
 
         inti = test.IP2Count(_T("192.168.50.1"),_T("192.168.50.254"));
 
          CString sIP = _T("192.168.50.1");
        
         for(int j=0;jIpStr = sIP;
 
     CloseHandle(CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)AddList,(LPVOID)AddIP,0,0));
 
           sIP = test.NextIPaddress( sIP ); 
                  
}
 
DWORD WINAPI AddList( LPVOID ip )
{
  ipTools test;
 
  //CString tmp = *(CString*)ip;
 
  AddIPRecord* AddIP = (AddIPRecord*)ip;
 
  CString host =_T("");
  //AfxMessageBox(  AddIP->IpStr);
  CString mac = test.IPToMAC( AddIP->IpStr );
  host = test.IPGetPCName( AddIP->IpStr );
   if(  mac !=_T("00-00-00-00-00-00") )
   {
     ((CMFCApplication1Dlg*)AfxGetApp()->m_pMainWnd)->ListBox1.AddString(AddIP->IpStr  +_T("::") +mac +_T("::") +host );
 
  }   
 
  delete AddIP;
  return 0;
 
}





你可能感兴趣的:(远程管控相关,VC++)