




已阅读5页,还剩18页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
需求对一个特定的文件进行分片发送,构造数据包,发送数据包,接收数据包并提取有效数据,对数据组合还原为原文件。设计当前,基于socket的网络编程已成为当今不可替代的编程方法,它将网络通讯当作文件描述符进行处理,把对这个“网络文件”(即socket套接字)的操作抽象成一种类似于文件操作的方式进行。从实现细节上,这种工作方式根据TCP/IP的网络通讯模型,封装了一系列的实现,使得我们只需要使用一个指定的参数,就可以实现在基于所需协议的数据的发送和接收。 但是,如果我们对那些系统自动给我们做的工作感兴趣,希望与发送的数据作“面对面”的接触,根据需求,传统的socket只能实现传输层之上的数据传输,不能自己构造数据包,而且这里需要更底层的操作,比如网络层和数据链路层,故不可用。方案一:Libnet + libpcap 这个方案基于C语言实现,对于一个特定的文件,得到其HEX数据,根据需求分成若干个部分,前面每个部分大小一致,剩余作为最后一个部分,将这个数据分别利用libnet组包发送包,利用libpcap抓包解析包,得到后取其有效数据,也就是HEX数据,对其组装,得到最后的文件,整个过程结束。libnetlibnet是UNIX系统同台上网络安全工具开发的重要的库,它和libpcap、libnids一起,给网络安全工具的开发人员提供了一组丰富而且完全的武器,使之得以很方便地编写出结构化强、健壮性好、可移植性高等特点的程序。libnet提供一系列的接口函数,实现和封装了数据包的构造和发送过程。利用它可以亲自构造从应用层到链路层的各层协议的数据包头,并将这些包头与有效数据有序地组合在一起发送出去。当然,它也是基于tcp/ip协议族模型的。利用libnet函数库开发应用程序的基本步骤非常简单: 1、数据包内存初始化; 2、构造数据包; 3、发送数据; 4、释放资源; libnet提供的接口函数按其作用可分为四类:* 内存管理(分配和释放)函数* 地址解析函数* 数据包构造函数* 数据包发送函数接口函数及其功能以下分别列出这些接口函数及其功能内存管理函数单数据包内存初始化:int libnet_init_packet(u_short packet_size, u_char *buf);单数据包内存释放:void libnet_destroy_packet(u_char *buf);多数据包内存初始化:int libnet_init_packet_arena(struct libnet_arena *arena,u_short packet_num, u_short packet_size);访问多数据包内存中的下一个数据包:u_char *libnet_next_packet_from_arena(struct libnet_arena *arena,u_short packet_size);多数据包内存释放:void libnet_destroy_packet_arena(struct libnet_arena *arena);地址解析函数解析主机名:u_char *libnet_host_lookup(u_long ip, u_short use_name);解析主机名(可重入函数):void libnet_host_lookup_r(u_long ip, u_short use_name, u_char *buf);域名解析:u_long libnet_name_resolve(u_char *ip, u_short use_name);获取接口设备IP地址:u_long libnet_get_ipaddr(struct libnet_link_int *l,const u_char *device, const u_char *ebuf);获取接口设备硬件地址:struct ether_addr *libnet_get_hwaddr(struct libnet_link_int *l,const u_char *device,const u_char *ebuf);数据包构造函数(数据包类型多样,这里太多,列几个主要的)ARP协议数据包:int libnet_build_arp(u_short hrdw, u_short prot, u_short h_len,u_short p_len, u_short op, u_char *s_ha,u_char *s_pa, u_char *t_ha, u_char *t_pa,const u_char *payload, int payload_len,u_char *packet_buf);以太网协议数据包:int libnet_build_ethernet(u_char *daddr, u_char *saddr, u_short id,const u_char *payload, int payload_len,u_char *packet_buf);IP协议数据包:int libnet_build_ip(u_short len, u_char tos, u_short ip_id, u_short frag,u_char ttl, u_char protocol, u_long saddr,u_long daddr, const u_char *payload, int payload_len,u_char *packet_buf);TCP协议数据包:int libnet_build_tcp(u_short th_sport, u_short th_dport, u_long th_seq,u_long th_ack, u_char th_flags, u_short th_win,u_short th_urg, const u_char *payload,int payload_len, u_char *packet_buf);UDP协议数据包:int libnet_build_udp(u_short sport, u_short dport, const u_char *payload,int payload_len, u_char *packet_buf);IP协议数据包选项:int libnet_insert_ipo(struct ipoption *opt, u_char opt_len,u_char *packet_buf);TCP协议数据包选项:int libnet_insert_tcpo(struct tcpoption *opt, u_char opt_len,u_char *packet_buf);数据包发送函数打开raw socket:int libnet_open_raw_sock(int protocol);关闭raw socket:int libnet_close_raw_sock(int socket);选择接口设备:int libnet_select_device(struct sockaddr_in *sin,u_char *device, u_char *ebuf);打开链路层接口设备:struct libnet_link_int *libnet_open_link_interface(char *device,char *ebuf);关闭链路层接口设备:int libnet_close_link_interface(struct libnet_link_int *l);发送IP数据包:int libnet_write_ip(int socket, u_char *packet, int packet_size);发送链路层数据包:int libnet_write_link_layer(struct libnet_link_int *l,const u_char *device, u_char *packet,int packet_size);检验和计算:int libnet_do_checksum(u_char *packet, int protocol, int packet_size);相关的支持函数随机数种子生成器:int libnet_seed_prand();获取随机数:u_long libnet_get_prand(int modulus);16进制数据输出:void libnet_hex_dump(u_char * buf, int len, int swap, FILE *stream);端口列表链初始化:int libnet_plist_chain_new(struct libnet_plist_chain *plist,char *token_list);获取端口列表链的下一项(端口范围):int libnet_plist_chain_next_pair(struct libnet_plist_chain *plist,u_short *bport, u_short *eport);端口列表链输出显示:int libnet_plist_chain_dump(struct libnet_plist_chain *plist);获取端口列表链:u_char *libnet_plist_chain_dump_string(struct libnet_plist_chain *plist);端口列表链内存释放:void libnet_plist_chain_free(struct libnet_plist_chain *plist);libpcaplibpcap是一个网络数据包捕获函数库,功能非常强大,Linux下著名的tcpdump就是以它为基础的。如何使用libpcap:首先要使用libpcap,我们必须包含pcap.h头文件,可以在/usr/local/include/pcap/pcap.h找到,其中包含了每个类型定义的详细说明。1.获取网络接口首先我们需要获取监听的网络接口:我们可以手动指定或让libpcap自动选择,先介绍如何让libpcap自动选择:char * pcap_lookupdev(char * errbuf)上面这个函数返回第一个合适的网络接口的字符串指针,如果出错,则errbuf存放出错信息字符串,errbuf至少应该是PCAP_ERRBUF_SIZE个字节长度的。注意,很多libpcap函数都有这个参数。pcap_lookupdev()一般可以在跨平台的,且各个平台上的网络接口名称都不相同的情况下使用。如果我们手动指定要监听的网络接口,则这一步跳过,我们在第二步中将要监听的网络接口字符串硬编码在pcap_open_live里。2.释放网络接口在操作为网络接口后,我们应该要释放它:void pcap_close(pcap_t * p)该函数用于关闭pcap_open_live()获取的pcap_t的网络接口对象并释放相关资源。3.打开网络接口获取网络接口后,我们需要打开它:pcap_t * pcap_open_live(const char * device, int snaplen, int promisc, int to_ms, char * errbuf)上面这个函数会返回指定接口的pcap_t类型指针,后面的所有操作都要使用这个指针。第一个参数是第一步获取的网络接口字符串,可以直接使用硬编码。第二个参数是对于每个数据包,从开头要抓多少个字节,我们可以设置这个值来只抓每个数据包的头部,而不关心具体的内容。典型的以太网帧长度是1518字节,但其他的某些协议的数据包会更长一点,但任何一个协议的一个数据包长度都必然小于65535个字节。第三个参数指定是否打开混杂模式(Promiscuous Mode),0表示非混杂模式,任何其他值表示混合模式。如果要打开混杂模式,那么网卡必须也要打开混杂模式,可以使用如下的命令打开eth0混杂模式:ifconfig eth0 promisc第四个参数指定需要等待的毫秒数,超过这个数值后,第3步获取数据包的这几个函数就会立即返回。0表示一直等待直到有数据包到来。第五个参数是存放出错信息的数组。4.获取数据包打开网络接口后就已经开始监听了,那如何知道收到了数据包呢?有下面3种方法:a)u_char * pcap_next(pcap_t * p, struct pcap_pkthdr * h)如果返回值为NULL,表示没有抓到包第一个参数是第2步返回的pcap_t类型的指针第二个参数是保存收到的第一个数据包的pcap_pkthdr类型的指针pcap_pkthdr类型的定义如下:cpp view plain copystruct pcap_pkthdr struct timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ ; 注意这个函数只要收到一个数据包后就会立即返回.b)int pcap_loop(pcap_t * p, int cnt, pcap_handler callback, u_char * user)第一个参数是第2步返回的pcap_t类型的指针第二个参数是需要抓的数据包的个数,一旦抓到了cnt个数据包,pcap_loop立即返回。负数的cnt表示pcap_loop永远循环抓包,直到出现错误。第三个参数是一个回调函数指针,它必须是如下的形式:void callback(u_char * userarg, const struct pcap_pkthdr * pkthdr, const u_char * packet)第一个参数是pcap_loop的最后一个参数,当收到足够数量的包后pcap_loop会调用callback回调函数,同时将pcap_loop()的user参数传递给它第二个参数是收到的数据包的pcap_pkthdr类型的指针第三个参数是收到的数据包数据c)int pcap_dispatch(pcap_t * p, int cnt, pcap_handler callback, u_char * user)这个函数和pcap_loop()非常类似,只是在超过to_ms毫秒后就会返回(to_ms是pcap_open_live()的第4个参数)5.分析数据包我们既然已经抓到数据包了,那么我们要开始分析了,这部分留给读者自己完成,具体内容可以参考相关的网络协议说明。在本文的最后,我会示范性的写一个分析arp协议的sniffer,仅供参考。要特别注意一点,网络上的数据是网络字节顺序的,因此分析前需要转换为主机字节顺序(ntohs()函数)。6.过滤数据包我们抓到的数据包往往很多,如何过滤掉我们不感兴趣的数据包呢?几乎所有的操作系统(BSD, AIX, Mac OS, Linux等)都会在内核中提供过滤数据包的方法,主要都是基于BSD Packet Filter(BPF)结构的。libpcap利用BPF来过滤数据包。过滤数据包需要完成3件事:a) 构造一个过滤表达式b) 编译这个表达式c) 应用这个过滤器a)BPF使用一种类似于汇编语言的语法书写过滤表达式,不过libpcap和tcpdump都把它封装成更高级且更容易的语法了,具体可以man tcpdump,以下是一些例子:src host 77只接收源ip地址是77的数据包dst port 80只接收tcp/udp的目的端口是80的数据包not tcp只接收不使用tcp协议的数据包tcp13 = 0x02 and (dst port 22 or dst port 23)只接收SYN标志位置位且目标端口是22或23的数据包(tcp首部开始的第13个字节)icmpicmptype = icmp-echoreply or icmpicmptype = icmp-echo只接收icmp的ping请求和ping响应的数据包ehter dst 00:e0:09:c1:0e:82只接收以太网mac地址是00:e0:09:c1:0e:82的数据包ip8 = 5只接收ip的ttl=5的数据包(ip首部开始的第8个字节)b)构造完过滤表达式后,我们需要编译它,使用如下函数:int pcap_compile(pcap_t * p, struct bpf_program * fp, char * str, int optimize, bpf_u_int32 netmask)fp:这是一个传出参数,存放编译后的bpfstr:过滤表达式optimize:是否需要优化过滤表达式metmask:简单设置为0即可c)最后我们需要应用这个过滤表达式:int pcap_setfilter(pcap_t * p, struct bpf_program * fp)第二个参数fp就是前一步pcap_compile()的第二个参数应用完过滤表达式之后我们便可以使用pcap_loop()或pcap_next()等抓包函数来抓包了。方案2.1:可以使用sendip发送数据包,接收方式同样采用libpcap.在正常的网络环境中,很难产生错误的IP 包,也很难产生我们想要的错误的IP 包,为此,要完成对产品的测试,我们必须自己来制造各种各样错误的IP 包,本篇的目的就是介绍如何利用各种发包工具来制造自己想要的错误的IP 包。SENDIP 是一个LINUX 下的命令行工具,可以通过命令行参数的方式发送各种格式的IP 包,它有大量的命令行参数来规定各种协议的头格式,目前可支持NTP, BGP, RIP, RIPng,TCP, UDP, ICMP 或raw IPv4 和IPv6 包格式,并且可以随意在包中添加数据。方案2.2:pcap4j(/kaitoy/pcap4j)Pcap4J is a Java library for capturing, crafting and sending packets. Pcap4J wraps a native packet capture library (libpcap or WinPcap) via JNA and provides you Java-Oriented APIs.1、 方案2.3:scapy(/secdev/scapy)scapy是python写的一个功能强大的交互式数据包处理程序,可用来发送、嗅探、解析和伪造网络数据包,常常被用到网络攻击和测试中实现方案一:#define BUF_SIZE 256 /定义单个数据包携带的数据大小,单位是字节/*函数实现将数据装入数据包,构造数据包(这里以tcp为例),发送数据包的工作,这里可以指定以太网头、ip头,tcp头各个元组的值,从哪个网卡发送以及源和目的ip地址和物理地址。*/int func_package(u_char payload,int bytes_in) libnet_t *handle; /* Libnet句柄 */ int packet_size; /* 构造的数据包大小 */ char *device = eth0; /* 设备名字,也支持点十进制的IP地址,会自己找到匹配的设备 */ char *src_ip_str = 19; /* 源IP地址字符串 */ char *dst_ip_str = 01; /* 目的IP地址字符串 */ u_char src_mac6 = 0x00, 0x0c, 0x29, 0x4b, 0x76, 0x97; /* 源MAC */ u_char dst_mac6 = 0x20, 0x7c, 0x8f, 0x72, 0x34, 0x06; /* 目的MAC */ u_long dst_ip, src_ip; /* 网路序的目的IP和源IP */ char errorLIBNET_ERRBUF_SIZE; /* 出错信息 */ libnet_ptag_t eth_tag, ip_tag, tcp_tag, tcp_op_tag; /* 各层build函数返回值 */ u_short proto = IPPROTO_TCP; /* 传输层协议 */ u_long payload_s = 0; /* 承载数据的长度,初值为0 */ /* 把目的IP地址字符串转化成网络序 */ dst_ip = libnet_name2addr4(handle, dst_ip_str, LIBNET_RESOLVE); /* 把源IP地址字符串转化成网络序 */ src_ip = libnet_name2addr4(handle, src_ip_str, LIBNET_RESOLVE); /* 初始化Libnet */ if ( (handle = libnet_init(LIBNET_LINK, device, error) = NULL ) printf(libnet_init failuren); return (-1); ; /strncpy(payload, testtesttest, sizeof(payload)-1); /* 构造负载的内容 */ /payload_s = strlen(payload); /* 计算负载内容的长度 */ payload_s = bytes_in; /* 计算负载内容的长度 */#if 0 /* 构建TCP的选项,通常在第一个TCP通信报文中设置MSS */ tcp_op_tag = libnet_build_tcp_options( payload, payload_s, handle, 0 ); if (tcp_op_tag = -1) printf(build_tcp_options failuren); return (-2); ;#endif tcp_tag = libnet_build_tcp( 30330, /* 源端口 */ 30331, /* 目的端口 */ 8888, /* 序列号 */ 8889, /* 确认号 */ TH_PUSH | TH_ACK, /* Control flags */ 14600, /* 窗口尺寸 */ 0, /* 校验和,0为自动计算 */ bytes_in, /* 紧急指针 */ LIBNET_TCP_H + payload_s, /* 长度 */ payload, /* 负载内容 */ payload_s, /* 负载内容长度 */ handle, /* libnet句柄 */ 0 /* 新建包 */ ); if (tcp_tag = -1) printf(libnet_build_tcp failuren); return (-3); ; /* 构造IP协议块,返回值是新生成的IP协议快的一个标记 */ ip_tag = libnet_build_ipv4( LIBNET_IPV4_H + LIBNET_TCP_H + payload_s, /* IP协议块的总长,*/ 0, /* tos */ (u_short) libnet_get_prand(LIBNET_PRu16), /* id,随机产生065535 */ 0, /* frag 片偏移 */ (u_int8_t)libnet_get_prand(LIBNET_PR8), /* ttl,随机产生0255 */ proto, /* 上层协议 */ 0, /* 校验和,此时为0,表示由Libnet自动计算 */ src_ip, /* 源IP地址,网络序 */ dst_ip, /* 目标IP地址,网络序 */ NULL, /* 负载内容或为NULL */ 0, /* 负载内容的大小*/ handle, /* Libnet句柄 */ 0 /* 协议块标记可修改或创建,0表示构造一个新的*/ ); if (ip_tag = -1) printf(libnet_build_ipv4 failuren); return (-4); ; /* 构造一个以太网协议块,只能用于LIBNET_LINK */ eth_tag = libnet_build_ethernet( dst_mac, /* 以太网目的地址 */ src_mac, /* 以太网源地址 */ ETHERTYPE_IP, /* 以太网上层协议类型,此时为IP类型 */ NULL, /* 负载,这里为空 */ 0, /* 负载大小 */ handle, /* Libnet句柄 */ 0 /* 协议块标记,0表示构造一个新的 */ ); if (eth_tag = -1) printf(libnet_build_ethernet failuren); return (-5); ; packet_size = libnet_write(handle); /* 发送已经构造的数据包*/ libnet_destroy(handle); /* 释放句柄 */ return 0;/*主函数完成文件分片组合*/int main() /u_char payload255 = 0; /* 承载数据的数组,初值为空 */ /strncpy(payload, fanshuquan, sizeof(payload)-1); /* 构造负载的内容 */ /func_package(payload); FILE *in_file; FILE *out_file; u_char dataBUF_SIZE; size_t bytes_in; size_t bytes_out; long len = 0;char* old = o;char* n = n; int i=0,j=0; if ( (in_file = fopen(old, rb) = NULL ) printf(old file errorn); return 2; if ( (out_file = fopen(n, wb) = NULL ) printf(new file errorn); return 3; while ( (bytes_in = fread(data, 1, BUF_SIZE, in_file) 0 ) /func_package(u_char *)bytes_in); for(i=0; ibytes_in; +i) printf( %02x, datai); if( (i + 1) % 16 = 0 ) printf(n); func_package(data,bytes_in); printf(%dn,strlen(data); printf(%d*n,bytes_in); bytes_out = fwrite(data, 1, bytes_in, out_file);/* bytes_out = fwrite(data, 1, bytes_in, out_file); if ( bytes_in != bytes_out ) printf(Fatal write error.n); return 4; len += bytes_out; printf(copying file . %d bytes copyn, len);*/ printf(%dn,j+); /for(i=0;iBUF_SIZE;+i)datai=;strcpy(data,end_of_file);func_package(data,11); fclose(in_file); /fclose(out_file); return 0;/定义bpf过滤器规则#define FILTER dst host 01 and ether dst host 20:7c:8f:72:34:06 and dst port 30331 and tcp/实现抓包并组合数据void fun_pcap(FILE * out_file) char errBufPCAP_ERRBUF_SIZE, *devStr; devStr = pcap_lookupdev(errBuf); if(devStr) printf(success: device: %sn, devStr); else printf(error: %sn, errBuf); exit(1); pcap_t * device = pcap_open_live(devStr, 63335, 1, 0, errBuf); if(!device) printf(error: pcap_open_live(): %sn, errBuf); exit(1); struct bpf_program filter; pcap_compile(device, &filter, FILTER, 1, 0); pcap_setfilter(device, &filter); struct pcap_pkthdr packet; const u_char * pktStr; int j=0; while(pktStr = pcap_next(device, &packet) printf(%dn,j+); int i,bytes_in, bytes_out; u_char dataBUF_SIZE; bytes_in = pktStr52*256 + pktStr53; for(i=54; i54+bytes_in; +i) datai-54 = pktStri; if(data0=0x65)&(data1=0x6e)&(data2=0x64)&(data3=0x5f)&(data4=0x6f)&(data5=0x66)&(data6=0x5f)&(data7=0x66)&(data8=0x69)&(data9=0x6c)&(data10=0x65) fclose(out_file); printf(end of
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025贵州生态渔业有限责任公司面向社会招聘综合笔试历年参考题库附带答案详解
- 2025证大集团招聘15名工作人员笔试历年参考题库附带答案详解
- 2025福建福州地铁2号线校园招聘笔试历年参考题库附带答案详解
- 2025福建省海峡人才报社有限责任公司招聘全媒体业务工作人员3人笔试历年参考题库附带答案详解
- 2025福建安溪城市建设发展有限公司招募职业经理人笔试历年参考题库附带答案详解
- 2025甘肃平凉灵台县绿色果品有限责任公司招聘4人笔试历年参考题库附带答案详解
- 2025湖南怀化市中方县产业投资发展集团有限公司招聘8人笔试历年参考题库附带答案详解
- 2025安徽岳西县事业单位引进急需紧缺专业人才3人模拟试卷及答案详解(网校专用)
- 2025年滨州水务发展集团有限公司权属公司公开招聘国有企业工作人员笔试笔试历年参考题库附带答案详解
- 2025山东日照经济技术开发区区属国有企业招聘工作人员拟聘用人员(二)笔试历年参考题库附带答案详解
- 人美版美术六年级上册全册教案
- GB/T 21499-2024粮油检验稻谷和糙米潜在出米率测定方法
- (版)科学道德与学风建设题库
- GB/Z 44314-2024生物技术生物样本保藏动物生物样本保藏要求
- 2023年全国职业院校技能大赛-融媒体内容策划与制作赛项规程
- 《电力建设施工企业安全生产标准化实施规范》
- 糖尿病周围神经病变知多少课件
- 新概念英语青少版入门 A-Unit-1课件(共98张)
- 儿童肺炎支原体肺炎诊疗指南(2023年版)解读
- 个人履职考核情况表
- 中小学消防安全、交通安全、食品安全、防溺水、防欺凌系统安全教育主题课件
评论
0/150
提交评论