⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 打开扫描源程序.txt

📁 可以对黑客编程有一定的了解
💻 TXT
字号:
打开扫描源程序(for WIN2K)  


半打开扫描演示程序开发总结

   首先,我要在这里感谢shotgun,他给了我很多的帮助和建议,真的非常感谢!!

   这个程序我写了很长时间,写的过程也非常不平坦,因为我没有找到一份在WIN2K下实现的半打开扫描的源代码,很多人让我参考for linux的源代码,但一些细节在WIN2K和Linux下是不一样的.刚开始时我也以为这个程序应该很好写,毕竟原理大家都知道了,而且for linux的源代码自己也看过,但等到做过后才知道,事情远没有那么简单,只有亲自做过的人才会理解其中的含义.(当然,不排除我不聪明这个原因,可能其他人写起来很轻松吧!) 
 
   下面谈谈我在开发过程中遇到的几个问题. 

   刚开始时,我的思路很简单,建原始套接字->设置IP头选项->填充IP头和TCP头->发送数据->接收数据.因为以前写过一些原始套接字的程序,所以,只花了一两天就写好了,然后,我就开始测试了. 测试时,我发现总是接收不到数据!我以为程序我写错了,所以我反复的调试检查,接连好几天,搞的我头都大了,问题还是没有解决.这同时我还在网上向别人请教,但还是没有任何头绪.差不多一个多星期吧,我收到了shotgun的回帖,他说:使用IPPROTO_RAW创建的套接字只能发数据不能接收数据,并说我可以选择两条路,一是在创建发送套接字的同时,再建一个监听套接字,用来接收数据包;二是不去动IP头,而只处理TCP头.两种方法我都试验了一下,但只成功了第一种.监听套接字的写法大家可以参考shotgun写过的一个sniffer程序,我以前根据自己的需要改造过他的这个程序,所以写起来还是瞒顺手的.

   程序写完了,但还有几个问题我不明白,有谁知道的还请赐教一二.

   一,shotgun提到的第二种方法在WIN2K下能否实现,怎么实现?
   二,socket(AF_INET , SOCK_RAW , IPPROTO_IP)和socket(AF_INET , SOCK_RAW , IPPROTO_RAW)有什么区别没有?(在我的程序中,创建发送数据包的讨教字时这两个都可以).

  注意:以上只是自己的观点,可能会存在错误,请大家批评指正.这段程序也只是起到演示学习的作用,所以不很完善.(监听部分有时会形成死循环,最好另开一个线程)



include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include "mstcpip.h"
#pragma comment(lib,"ws2_32")

#define DEFAULT_DEST_PORT 5
#define DEST_HOST "www.hrbust.edu.cn"
#define SEQ 0x28376839

typedef struct _iphdr 
{
unsigned char h_lenver; //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 _tcphdr //定义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; 

struct //定义TCP伪首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz;
char ptcl; //协议类型
unsigned short tcpl; //TCP长度
}psd_header;

SOCKET sockRaw = INVALID_SOCKET,
sockListen = INVALID_SOCKET;
struct sockaddr_in dest;

//SOCK错误处理程序
void CheckSockError(int iErrorCode, char *pErrorMsg)
{
if(iErrorCode==SOCKET_ERROR) 
{
printf("%s Error:%d\n", pErrorMsg, GetLastError());
closesocket(sockRaw);
ExitProcess(-1);
}

}

//计算检验和
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);
}

//IP解包程序
bool DecodeIPHeader(char *buf, int bytes)
{
IP_HEADER *iphdr;
TCP_HEADER *tcphdr;
  unsigned short iphdrlen;

  iphdr = (IP_HEADER *)buf;
  iphdrlen = sizeof(unsigned long) * (iphdr->h_lenver & 0xf);
  tcphdr = (TCP_HEADER*)(buf + iphdrlen);

//是否来自目标IP
if(iphdr->sourceIP != dest.sin_addr.s_addr) return false;

//序列号是否正确
if((ntohl(tcphdr->th_ack) != (SEQ+1)) && (ntohl(tcphdr->th_ack) != SEQ)) return false;

//RST/ACK - 无服务
if(tcphdr->th_flag == 20)
{
printf(".\n");
return true;
}

//SYN/ACK - 扫描到一个端口
if(tcphdr ->th_flag == 18)
{
printf("%d\n",ntohs(tcphdr->th_sport));
return true;
}

  return true;
}

//主函数
int main(int argc,char **argv)
{
int iErrorCode;
int datasize;
struct hostent *hp;
IP_HEADER ip_header;
TCP_HEADER tcp_header;
char SendBuf[128]={0};
char RecvBuf[65535]={0};

//初始化SOCKET
WSADATA wsaData;
iErrorCode = WSAStartup(MAKEWORD(2,2),&wsaData);
CheckSockError(iErrorCode, "WSAStartup()");
sockRaw = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
CheckSockError(sockRaw, "socket()");
sockListen = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
CheckSockError(sockListen, "socket");

//设置IP头操作选项
BOOL bOpt = true;
iErrorCode = setsockopt(sockRaw,IPPROTO_IP,IP_HDRINCL,(char *)&bOpt,sizeof(bOpt));
CheckSockError(iErrorCode, "setsockopt()"); 

//获得本地IP
SOCKADDR_IN sa;
unsigned char LocalName[256];

iErrorCode = gethostname((char*)LocalName,sizeof(LocalName)-1);
CheckSockError(iErrorCode, "gethostname()");
if((hp = gethostbyname((char*)LocalName)) == NULL)
{
CheckSockError(SOCKET_ERROR, "gethostbyname()");
}
memcpy(&sa.sin_addr.S_un.S_addr,hp->h_addr_list[0],hp->h_length);
sa.sin_family = AF_INET;
sa.sin_port = htons(7000);
iErrorCode = bind(sockListen, (PSOCKADDR)&sa, sizeof(sa));
CheckSockError(iErrorCode, "bind");

//设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包
DWORD dwBufferLen[10] ;
DWORD dwBufferInLen = 1 ; 
DWORD dwBytesReturned = 0 ;
iErrorCode=WSAIoctl(sockListen, SIO_RCVALL,&dwBufferInLen, sizeof(dwBufferInLen),       
            &dwBufferLen, sizeof(dwBufferLen),&dwBytesReturned , NULL , NULL );
CheckSockError(iErrorCode, "Ioctl");

//获得目标主机IP
memset(&dest,0,sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(DEFAULT_DEST_PORT);
if((dest.sin_addr.s_addr = inet_addr(DEST_HOST)) == INADDR_NONE)
{
if((hp = gethostbyname(DEST_HOST)) != NULL)
{
memcpy(&(dest.sin_addr),hp->h_addr_list[0],hp->h_length);
dest.sin_family = hp->h_addrtype;
printf("dest.sin_addr = %s\n",inet_ntoa(dest.sin_addr));
}
else
{
CheckSockError(SOCKET_ERROR, "gethostbyname()");
}
}

//填充IP首部
ip_header.h_lenver=(4<<4 | sizeof(ip_header)/sizeof(unsigned long));
//高四位IP版本号,低四位首部长度
ip_header.total_len=htons(sizeof(IP_HEADER)+sizeof(TCP_HEADER)); //16位总长度(字节)
ip_header.ident=1; //16位标识
ip_header.frag_and_flags=0; //3位标志位
ip_header.ttl=128; //8位生存时间TTL
ip_header.proto=IPPROTO_TCP; //8位协议(TCP,UDP…)
ip_header.checksum=0; //16位IP首部校验和
ip_header.sourceIP=sa.sin_addr.s_addr; //32位源IP地址
ip_header.destIP=dest.sin_addr.s_addr; //32位目的IP地址

//填充TCP首部
tcp_header.th_sport=htons(7000); //源端口号
tcp_header.th_dport=htons(DEFAULT_DEST_PORT); //目的端口号
tcp_header.th_seq=htonl(SEQ); //SYN序列号
tcp_header.th_ack=0; //ACK序列号置为0
tcp_header.th_lenres=(sizeof(TCP_HEADER)/4<<4|0); //TCP长度和保留位
tcp_header.th_flag=2; //SYN 标志
tcp_header.th_win=htons(16384); //窗口大小
tcp_header.th_urp=0; //偏移
tcp_header.th_sum=0; //校验和

//填充TCP伪首部(用于计算校验和,并不真正发送)
psd_header.saddr=ip_header.sourceIP;
psd_header.daddr=ip_header.destIP;
psd_header.mbz=0;
psd_header.ptcl=IPPROTO_TCP;
psd_header.tcpl=htons(sizeof(tcp_header));

//计算TCP校验和,计算校验和时需要包括TCP pseudo header 
memcpy(SendBuf,&psd_header,sizeof(psd_header)); 
memcpy(SendBuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header));
tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header));

//计算IP校验和
memcpy(SendBuf,&ip_header,sizeof(ip_header));
memcpy(SendBuf+sizeof(ip_header),&tcp_header,sizeof(tcp_header));
memset(SendBuf+sizeof(ip_header)+sizeof(tcp_header),0,4);
datasize=sizeof(ip_header)+sizeof(tcp_header);
ip_header.checksum=checksum((USHORT *)SendBuf,datasize);

//填充发送缓冲区
memcpy(SendBuf,&ip_header,sizeof(ip_header));

//发送TCP报文
iErrorCode=sendto(sockRaw,SendBuf,datasize,0,(struct sockaddr*) &dest,
sizeof(dest));
CheckSockError(iErrorCode, "sendto()");

//接收数据
DWORD timeout = 2000;
DWORD start = GetTickCount();
while(true)
{
//计时,2s超时
if((GetTickCount() - start) >= timeout) break;

memset(RecvBuf, 0, sizeof(RecvBuf));
iErrorCode = recv(sockListen, RecvBuf, sizeof(RecvBuf), 0);
CheckSockError(iErrorCode, "recv");

if(DecodeIPHeader(RecvBuf,iErrorCode)) break;
}

//退出前清理
if(sockRaw != INVALID_SOCKET) closesocket(sockRaw);
WSACleanup();
return 0;
} 



修改了部分地方:

while(true)
{
//计时,2s超时
if((GetTickCount() - start) >= timeout) break;

memset(RecvBuf, 0, sizeof(RecvBuf));
iErrorCode = recv(sockListen, RecvBuf, sizeof(RecvBuf), 0);
CheckSockError(iErrorCode, "recv");

if(int i = DecodeIPHeader(RecvBuf,iErrorCode))
{
if(i == 1) break;
tcp_header.th_flag=4; //RST 标志
//计算TCP校验和,计算校验和时需要包括TCP pseudo header 
memcpy(SendBuf,&psd_header,sizeof(psd_header)); 
memcpy(SendBuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header));
tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header));

//计算IP校验和
memcpy(SendBuf,&ip_header,sizeof(ip_header));
memcpy(SendBuf+sizeof(ip_header),&tcp_header,sizeof(tcp_header));
memset(SendBuf+sizeof(ip_header)+sizeof(tcp_header),0,4);
datasize=sizeof(ip_header)+sizeof(tcp_header);
ip_header.checksum=checksum((USHORT *)SendBuf,datasize);

//填充发送缓冲区
memcpy(SendBuf,&ip_header,sizeof(ip_header));

//发送TCP报文
iErrorCode=sendto(sockRaw,SendBuf,datasize,0,(struct sockaddr*) &dest,
sizeof(dest));
CheckSockError(iErrorCode, "sendto()");

break;
}
}


//IP解包程序
int DecodeIPHeader(char *recvbuf, int bytes)
{
IP_HEADER *iphdr;
TCP_HEADER *tcphdr;
  unsigned short iphdrlen;

  iphdr = (IP_HEADER *)recvbuf;
  iphdrlen = sizeof(unsigned long) * (iphdr->h_lenver & 0xf);
  tcphdr = (TCP_HEADER*)(recvbuf + iphdrlen);

//是否来自目标IP
if(iphdr->sourceIP != dest.sin_addr.s_addr) return 0;

//序列号是否正确
if((ntohl(tcphdr->th_ack) != (SEQ+1)) && (ntohl(tcphdr->th_ack) != SEQ)) return 0;

//RST/ACK - 无服务
if(tcphdr->th_flag == 20)
{
printf(".\n");
return 1;
}

//SYN/ACK - 扫描到一个端口
if(tcphdr ->th_flag == 18)
{ 
printf("%d\n",ntohs(tcphdr->th_sport));
return 2;
}

  return 1;
}

其他地方不变!!


 临渊羡鱼不如退而结网!!  
小海的EMAIL 


 补充日期: 2001-05-30 15:13:06

// Copyright (C) Microsoft Corporation, 1996-1999
#if _MSC_VER > 1000
#pragma once
#endif

/* Argument structure for SIO_KEEPALIVE_VALS */

struct tcp_keepalive {
  u_long onoff;
  u_long keepalivetime;
  u_long keepaliveinterval;
};

// New WSAIoctl Options

#define SIO_RCVALL      _WSAIOW(IOC_VENDOR,1)
#define SIO_RCVALL_MCAST   _WSAIOW(IOC_VENDOR,2)
#define SIO_RCVALL_IGMPMCAST _WSAIOW(IOC_VENDOR,3)
#define SIO_KEEPALIVE_VALS  _WSAIOW(IOC_VENDOR,4)
#define SIO_ABSORB_RTRALERT  _WSAIOW(IOC_VENDOR,5)
#define SIO_UCAST_IF     _WSAIOW(IOC_VENDOR,6)
#define SIO_LIMIT_BROADCASTS _WSAIOW(IOC_VENDOR,7)
#define SIO_INDEX_BIND    _WSAIOW(IOC_VENDOR,8)
#define SIO_INDEX_MCASTIF   _WSAIOW(IOC_VENDOR,9)
#define SIO_INDEX_ADD_MCAST  _WSAIOW(IOC_VENDOR,10)
#define SIO_INDEX_DEL_MCAST  _WSAIOW(IOC_VENDOR,11)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -