C#.CC++.net抓包抓网络协议包(WinPcap),该如何编写,求源码,求注释,求指教!

C#.CC++.net抓包抓网络协议包(WinPcap),该如何编写,求源码,求注释,求指教!,第1张

您好,要添加一个预处理定义,你需要打开Project菜单,选择Settings,然后选择C/C++选项卡,在General类下,你必须在Preprocessor

Definitions下的文本框中添加定义。

要在一个VC++6.0工程中,添加一,个新的库,你必须打开Project菜单,选择Settings,然后选择Link选项卡,然后把新库的名字添加到Object/Library

modules下的文本框中

要向VC++6.0中添加一个新的库所在的路径,你必须打开Tool菜单,选择Options,然后选择Directories选项卡,在Show

directories下拉框中选择Library

files,并且将新的路径添加到Directories中去

要向VC++6.0中添加一个新的包含文件所在的路径,你必须打开Tool菜单,选择Options,然后选择Directories选项卡,在Show

directories下拉框中选择Include

files,并且将新的路径添加到Directories中去

范例程序

我们一共了一些范例程序来显示WinPcap API的用法。这些程序的源代码,以及编译运行这些代码所需的所有文件,都可以在 Developer's

Pack找到。作为教程,在这里,我们提供了浏览器式的代码:这样,在每个函数和变量之间的跳转会比较方便。更多完整的范例程序,请参阅 WinPcap

教程.

// NOTE: remember to include WPCAP and HAVE_REMOTE among

your preprocessor

definitions.

(工程->设置->c/c++->预处理程序定义

中添加WPCAP和HAVE_REMOTE)

如果连接有问题,把lib复制到工程目录下用下面方法:

#pragma

comment(lib,"wpcap.lib")

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

package com.daidai.util

import org.hibernate.Session

import org.hibernate.SessionFactory

import org.hibernate.cfg.Configuration

public class HibernateUtil {

private static SessionFactory sessionFactory

public static SessionFactory getSessionFactory() {

Configuration conf=new Configuration().configure()

sessionFactory=conf.buildSessionFactory()

return sessionFactory

}

public static void setSessionFactory(SessionFactory sessionFactory) {

HibernateUtil.sessionFactory = sessionFactory

}

public static Session getSession(){

return sessionFactory.openSession()

}

}

package com.daidai.util

import java.io.File

import java.io.FileInputStream

import java.io.FileNotFoundException

import java.io.IOException

import java.io.InputStreamReader

import java.io.UnsupportedEncodingException

import jxl.Cell

import jxl.Sheet

import jxl.Workbook

import jxl.write.WritableSheet

import jxl.write.WritableWorkbook

public class Util {

private static String Cellphone_Number

private static String Cellphone_Number1

private static String Cellphone_Number2

private static String Fasten_Telephone

private static String Fasten_Telephone2

private static String name

private static String remarks

public static Sheet rs

public Util(){}

static{

try{

Workbook rwb=Workbook.getWorkbook(new File("Book1.xls"))

rs=rwb.getSheet(0)

int count=rs.getColumns()

System.out.println(count)

int count1=rs.getRows()

System.out.println(count1)

//获取第一行,第一列的值

//count1行

//count列

for(int i=0i<count1i++){

for(int j=0j<countj++){

Cell c00 = rs.getCell(j, i)

String strc00 = c00.getContents()

//获取第一行,第二列的值

Cell c10 = rs.getCell(1, 0)

String strc10 = c10.getContents()

System.out.println(strc00)

System.out.println(strc10)

}

}

}catch(Exception e){

e.printStackTrace()

}

}

public static void main(String[]args){

Util u=new Util()

}

}

<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC

"-//Hibernate/Hibernate Configuration DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

<property name="connection.driver_class"

>com.mysql.jdbc.Driver</property>

<property name="connection.url"

>jdbc:mysql://127.0.0.1:3306/test</property>

<property name="connection.username"

>root</property>

<property name="connection.password"

>daidai</property>

<!-- SQL dialect 数据库方言-->

<property name="dialect"

>org.hibernate.dialect.MySQLDialect</property>

<!-- Echo all executed SQL to stdout -->

<property name="show_sql">true</property>

<property name="hbm2ddl.auto">create</property>

<mapping resource="User.hbm.xml"/>

</session-factory>

</hibernate-configuration>

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.daidai.entity">

<class name="User" table="t_user">

<id name="id">

<generator class="native"/>

</id>

<property name="name" type="java.lang.String" length="15"/>

<property name="Cellphone_Number" type="java.lang.String" length="11"/>

<property name="Cellphone_Number1" type="java.lang.String" length="11"/>

<property name="Cellphone_Number2" type="java.lang.String" length="11"/>

<property name="Fasten_Telephone" type="java.lang.String" length="11"/>

<property name="Fasten_Telephone2" type="java.lang.String" length="11"/>

<property name="remarks" type="java.lang.String"/>

</class>

</hibernate-mapping>

package com.daidai.dao.impl

import com.daidai.util.*

import org.hibernate.HibernateException

import org.hibernate.Session

import com.daidai.dao.UserDAO

import com.daidai.entity.User

public class UserDAOImpl implements UserDAO {

public Session session=null

public void save(User user) {

try {

session=HibernateUtil.getSession()

session.getTransaction().begin()

session.save(user)

session.getTransaction().commit()

} catch (HibernateException e) {

session.getTransaction().rollback()

e.printStackTrace()

throw e

}

}

}

package com.daidai.dao

import com.daidai.entity.User

public interface UserDAO {

public void save(User user)

}

第一法则:站在巨人肩膀上 &&不要重复造轮子。

对于这种复杂的过程,第一选择是使用现成的,节约时间,提升效率。

Wireshark(前称Ethereal)是一个网络封包分析软件。网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料。Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换。

网络封包分析软件的功能可想像成 "电工技师使用电表来量测电流、电压、电阻" 的工作 - 只是将场景移植到网络上,并将电线替换成网络线。在过去,网络封包分析软件是非常昂贵,或是专门属于营利用的软件。Ethereal的出现改变了这一切。在GNUGPL通用许可证的保障范围底下,使用者可以以免费的代价取得软件与其源代码,并拥有针对其源代码修改及客制化的权利。Ethereal是目前全世界最广泛的网络封包分析软件之一。

第二法则:学习 &&提升。

如果是单纯的学习知识,可以直接尝试写一些具有部分功能的程序,过程会有点艰难,但非常有意义。学习网络编程,需要了解 开放系统互连参考模型的的七层每一层的意义以及现实当中实现的四层的网络协议。然后就可以知道抓包的包位于模型当中的传输层协议,包括UDP和TCP的协议。进一步要学习每种协议的格式,表头,数据包等等。一句话,冰冻三尺非一日之寒。

Windows下的抓包及简单的编程。

Windows2000在TCP/IP协议组件上做了很多改进,功能也有增强。比如在协议栈上的调整,增大了默认窗口大小,以及高延迟链接新算法。同时在安全性上,可应用IPSec加强安全性,比NT下有不少的改进。

 Microsoft TCP/IP 组件包含“核心协议”、“服务”及两者之间的“接口”。传输驱动程序接口 (TDI) 与网络设备接口规范 (NDIS) 是公用的。 此外,还有许多用户模型应用程序的更高级接口。最常用的接口是 Windows Sockets、远程过程调用 (RPC) 和 NetBIOS。

 Windows Sockets 是一个编程接口,它是在加州大学伯克利分校开发的套接字接口的基础上定义的。它包括了一组扩展件,以充分利用 Microsoft Windows 消息驱动的特点。规范的 1.1 版是在 1993 年 1 月发行的,2.2.0 版在 1996 年 5 月发行。Windows 2000 支持 Winsock 2.2 版。在Winsock2中,支持多个传输协议的原始套接字,重叠I/O模型、服务质量控制等。

这里介绍Windows Sockets的一些关于原始套接字(Raw Socket)的编程。同Winsock1相比,最明显的就是支持了Raw Socket套接字类型,通过原始套接字,我们可以更加自如地控制Windows下的多种协议,而且能够对网络底层的传输机制进行控制。

1、创建一个原始套接字,并设置IP头选项。

SOCKET sock

sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP)

或者:

s = WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED)

 这里,我们设置了SOCK_RAW标志,表示我们声明的是一个原始套接字类型。创建原始套接字后,IP头就会包含在接收的数据中,如果我们设定 IP_HDRINCL 选项,那么,就需要自己来构造IP头。注意,如果设置IP_HDRINCL 选项,那么必须具有 administrator权限,要不就必须修改注册表:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Afd\Parameter\

修改键:DisableRawSecurity(类型为DWORD),把值修改为 1。如果没有,就添加。

BOOL blnFlag=TRUE

setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&blnFlag, sizeof(blnFlag)

 对于原始套接字在接收数据报的时候,要注意这么几点:

a、如果接收的数据报中协议类型和定义的原始套接字匹配,那么,接收的所有数据就拷贝到套接字中。

b、如果绑定了本地地址,那么只有接收数据IP头中对应的远端地址匹配,接收的数据就拷贝到套接字中。

c、如果定义的是外部地址,比如使用connect(),那么,只有接收数据IP头中对应的源地址匹配,接收的数据就拷贝到套接字中。

2、构造IP头和TCP头

这里,提供IP头和TCP头的结构:

// Standard TCP flags

#define URG 0x20

#define ACK 0x10

#define PSH 0x08

#define RST 0x04

#define SYN 0x02

#define FIN 0x01

typedef struct _iphdr //定义IP首部

{

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 psd_hdr //定义TCP伪首部

{

unsigned long saddr//源地址

unsigned long daddr//目的地址

char mbz

char ptcl//协议类型

unsigned short tcpl//TCP长度

}PSD_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

TCP伪首部并不是真正存在的,只是用于计算检验和。校验和函数:

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头部和TCP头部的时候,就同时需要自己计算他们的检验和。

3、发送原始套接字数据报

 填充这些头部稍微麻烦点,发送就相对简单多了。只需要使用sendto()就OK。

sendto(sock, (char*)&tcpHeader, sizeof(tcpHeader), 0, (sockaddr*)&addr_in,sizeof(addr_in))

下面是一个示例程序,可以作为SYN扫描的一部分。

#include <stdio.h>

#include <winsock2.h>

#include <ws2tcpip.h>

#define SOURCE_PORT 7234

#define MAX_RECEIVEBYTE 255

typedef struct ip_hdr //定义IP首部

{

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地址

}IPHEADER

typedef struct tsd_hdr //定义TCP伪首部

{

unsigned long saddr//源地址

unsigned long daddr//目的地址

char mbz

char ptcl//协议类型

unsigned short tcpl//TCP长度

}PSDHEADER

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位紧急数据偏移量

}TCPHEADER

//CheckSum:计算校验和的子函数

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 useage()

{

printf("******************************************\n")

printf("TCPPing\n")

printf("\t Written by Refdom\n")

printf("\t Email: refdom@263.net\n")

printf("Useage: TCPPing.exe Target_ip Target_port \n")

printf("*******************************************\n")

}

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

{

WSADATA WSAData

SOCKET sock

SOCKADDR_IN addr_in

IPHEADER ipHeader

TCPHEADER tcpHeader

PSDHEADER psdHeader

char szSendBuf[60]={0}

BOOL flag

int rect,nTimeOver

useage()

if (argc!= 3)

{ return false}

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

{

printf("WSAStartup Error!\n")

return false

}

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

{

printf("Socket Setup Error!\n")

return false

}

flag=true

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

{

printf("setsockopt IP_HDRINCL error!\n")

return false

}

nTimeOver=1000

if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOver, sizeof(nTimeOver))==SOCKET_ERROR)

{

printf("setsockopt SO_SNDTIMEO error!\n")

return false

}

addr_in.sin_family=AF_INET

addr_in.sin_port=htons(atoi(argv[2]))

addr_in.sin_addr.S_un.S_addr=inet_addr(argv[1])

//

//

//填充IP首部

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

// ipHeader.tos=0

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

ipHeader.ident=1

ipHeader.frag_and_flags=0

ipHeader.ttl=128

ipHeader.proto=IPPROTO_TCP

ipHeader.checksum=0

ipHeader.sourceIP=inet_addr("本地地址")

ipHeader.destIP=inet_addr(argv[1])

//填充TCP首部

tcpHeader.th_dport=htons(atoi(argv[2]))

tcpHeader.th_sport=htons(SOURCE_PORT)//源端口号

tcpHeader.th_seq=htonl(0x12345678)

tcpHeader.th_ack=0

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

tcpHeader.th_flag=2//修改这里来实现不同的标志位探测,2是SYN,1是FIN,16是ACK探测 等等

tcpHeader.th_win=htons(512)

tcpHeader.th_urp=0

tcpHeader.th_sum=0

psdHeader.saddr=ipHeader.sourceIP

psdHeader.daddr=ipHeader.destIP

psdHeader.mbz=0

psdHeader.ptcl=IPPROTO_TCP

psdHeader.tcpl=htons(sizeof(tcpHeader))

//计算校验和

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

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

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

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))

rect=sendto(sock, szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader),

0, (struct sockaddr*)&addr_in, sizeof(addr_in))

if (rect==SOCKET_ERROR)

{

printf("send error!:%d\n",WSAGetLastError())

return false

}

else

printf("send ok!\n")

closesocket(sock)

WSACleanup()

return 0

}

4、接收数据

 和发送原始套接字数据相比,接收就比较麻烦了。因为在WIN我们不能用recv()来接收raw socket上的数据,这是因为,所有的IP包都是先递交给系统核心,然后再传输到用户程序,当发送一个raws socket包的时候(比如syn),核心并不知道,也没有这个数据被发送或者连接建立的记录,因此,当远端主机回应的时候,系统核心就把这些包都全部丢掉,从而到不了应用程序上。所以,就不能简单地使用接收函数来接收这些数据报。

 要达到接收数据的目的,就必须采用嗅探,接收所有通过的数据包,然后进行筛选,留下符合我们需要的。可以再定义一个原始套接字,用来完成接收数据的任务,需要设置SIO_RCVALL,表示接收所有的数据。

SOCKET sniffersock

sniffsock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED)

DWORD lpvBuffer = 1

DWORD lpcbBytesReturned = 0

WSAIoctl(sniffersock, SIO_RCVALL, &lpvBuffer, sizeof(lpvBuffer), NULL, 0, &lpcbBytesReturned, NULL, NULL)

 创建一个用于接收数据的原始套接字,我们可以用接收函数来接收数据包了。然后在使用一个过滤函数达到筛选的目的,接收我们需要的数据包。

如果在XP以上的 *** 作系统,微软封杀了Raw Soccket,只能用wincpap之类的开发包了。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12048465.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-20
下一篇 2023-05-20

发表评论

登录后才能评论

评论列表(0条)

保存