基于 libnids和libpcap 还原 tcp stream

#include 
#include 
#include 
#include 

/* Libnids的头文件,必须包含 */
char ascii_string[10000];
char *char_to_ascii(char ch)
/* 此函数的功能主要用于把协议数据进行显示 */
{
    char *string;
    ascii_string[0] = 0;
    string = ascii_string;
    if (isgraph(ch))
     /* 可打印字符 */
    {
        *string++ = ch;
    }
    else if (ch == ' ')
     /* 空格 */
    {
        *string++ = ch;
    }
    else if (ch == '\n' || ch == '\r')
     /* 回车和换行 */
    {
        *string++ = ch;
    }
    else
     /* 其它字符以点"."表示 */
    {
        *string++ = '.';
    }
    *string = 0;
    return ascii_string;
}
/*
 * ====================================================================================
 * 下面的函数是回调函数,用于分析TCP连接,分析TCP连接状态,对TCP协议传输的数据进行分析
 * ====================================================================================
 *  */
void tcp_protocol_callback(struct tcp_stream *tcp_connection, void **arg)
{
    int i;
    char address_string[1024];
    char content[65535];
    char content_urgent[65535];
    struct tuple4 ip_and_port = tcp_connection->addr;
    /* 获取TCP连接的地址和端口对 */
    strcpy(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.saddr))));
    /* 获取源地址 */
    sprintf(address_string + strlen(address_string), " : %i", ip_and_port.source);
    /* 获取源端口 */
    strcat(address_string, " <---> ");
    strcat(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.daddr))));
    /* 获取目的地址 */
    sprintf(address_string + strlen(address_string), " : %i", ip_and_port.dest);
    /* 获取目的端口 */
    strcat(address_string, "\n");
    switch (tcp_connection->nids_state) /* 判断LIBNIDS的状态 */
    {
        case NIDS_JUST_EST:
            /* 表示TCP客户端和TCP服务器端建立连接状态 
 * 在此状态下就可以决定是否对此TCP连接进行数据分析,可以决定是否捕获TCP客户端接收的数据、TCP服务器端接收的数据、TCP客户端接收的紧急数据或者TCP服务器端接收的紧急数据*/
            tcp_connection->client.collect++;
            /* 客户端接收数据 */
            tcp_connection->server.collect++;
            /* 服务器接收数据 */
            tcp_connection->server.collect_urg++;
            /* 服务器接收紧急数据 */
            tcp_connection->client.collect_urg++;
            /* 客户端接收紧急数据 */
            printf("%sTCP连接建立\n", address_string);
            return ;
        case NIDS_CLOSE:
            /* 表示TCP连接正常关闭 */
            printf("--------------------------------\n");
            printf("%sTCP连接正常关闭\n", address_string);
            return ;
        case NIDS_RESET:
            /* 表示TCP连接被重置关闭 */
            printf("--------------------------------\n");
            printf("%sTCP连接被RST关闭\n", address_string);
            return ;
        case NIDS_DATA:
            /* 表示有新的数据到达在这个状态可以判断是否有新的数据到达,如果有就可以把数据存储起来,可以在这个状态之中来分析TCP传输的数据,此数据就存储在half_stream数据结构的缓存之中。 */
            {
                struct half_stream *hlf;
                /* 表示TCP连接的一端的信息,可以是客户端,也可以是服务器端 */
                if (tcp_connection->server.count_new_urg)
                {
                    /* 表示TCP服务器端接收到新的紧急数据 */
                    printf("--------------------------------\n");
                    strcpy(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.saddr))));
                    sprintf(address_string + strlen(address_string), " : %i", ip_and_port.source);
                    strcat(address_string, " urgent---> ");
                    strcat(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.daddr))));
                    sprintf(address_string + strlen(address_string), " : %i", ip_and_port.dest);
                    strcat(address_string, "\n");
                    address_string[strlen(address_string) + 1] = 0;
                    address_string[strlen(address_string)] = tcp_connection->server.urgdata;
                    printf("%s", address_string);
                    return ;
                }
                if (tcp_connection->client.count_new_urg)
                {
                    /* 表示TCP客户端接收到新的紧急数据 */
                    printf("--------------------------------\n");
                    strcpy(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.saddr))));
                    sprintf(address_string + strlen(address_string), " : %i", ip_and_port.source);
                    strcat(address_string, " <--- urgent ");
                    strcat(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.daddr))));
                    sprintf(address_string + strlen(address_string), " : %i", ip_and_port.dest);
                    strcat(address_string, "\n");
                    address_string[strlen(address_string) + 1] = 0;
                    address_string[strlen(address_string)] = tcp_connection->client.urgdata;
                    printf("%s", address_string);
                    return ;
                }
                if (tcp_connection->client.count_new)
                {
                    /* 表示客户端接收到新的数据 */
                    hlf = &tcp_connection->client;
                    /* 此时hlf表示的是客户端的TCP连接信息 */
                    strcpy(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.saddr))));
                    sprintf(address_string + strlen(address_string), ":%i", ip_and_port.source);
                    strcat(address_string, " <--- ");
                    strcat(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.daddr))));
                    sprintf(address_string + strlen(address_string), ":%i", ip_and_port.dest);
                    strcat(address_string, "\n");
                    printf("--------------------------------\n");
                    printf("%s", address_string);
                    memcpy(content, hlf->data, hlf->count_new);
                    content[hlf->count_new] = '\0';
                    printf("客户端接收数据\n");
                    for (i = 0; i < hlf->count_new; i++)
                    {
                        printf("%s", char_to_ascii(content[i]));
                        //输出客户端接收的新的数据,以可打印字符进行显示
                    }
                    printf("\n");
                }
                else
                {                                                                                                               /* 表示服务器端接收到新的数据 */
                       hlf = &tcp_connection->server;
                       /* 此时hlf表示服务器端的TCP连接信息 */
                       strcpy(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.saddr))));
                       sprintf(address_string + strlen(address_string), ":%i", ip_and_port.source);
                       strcat(address_string, " ---> ");
                       strcat(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.daddr))));
                       sprintf(address_string + strlen(address_string), ":%i", ip_and_port.dest);
                       strcat(address_string, "\n");
                       printf("--------------------------------\n");
                       printf("%s", address_string);
                       memcpy(content, hlf->data, hlf->count_new);
                       content[hlf->count_new] = '\0';
                       printf("服务器端接收数据:\n");
                       for (i = 0; i < hlf->count_new; i++)
                       {
                           printf("%s", char_to_ascii(content[i]));
                           //输出服务器接收到的新的数据
                       }
                       printf("\n");
                   }
               }
           default:
               break;
       }
       return ;
}
void main()
{
    struct nids_chksum_ctl temp;
    temp.netaddr = 0;
    temp.mask = 0;
    temp.action = 1;
    nids_register_chksum_ctl(&temp,1);  
    /*这段是相关与计算校验和的,比较新的网卡驱动会自动计算校验和,我们要做的就是把它关掉*/
        nids_params.filename = "/data/wafpackets/waf.pcap";
    if (!nids_init())
    /* Libnids初始化 */
    {
        printf("出现错误:%s\n", nids_errbuf);
        exit(1);
    }
    nids_register_tcp(tcp_protocol_callback);
    /* 注册回调函数 */
    nids_run();
    /* Libnids进入循环捕获数据包状态 */
}

编译
gcc parser.c -lnids -o pcap

python 版本 基于 pynids

#!/usr/bin/env python2

import os, pwd
import sys
import nids
import socket

NOROOT = "nobody"
end_states = (nids.NIDS_CLOSE, nids.NIDS_TIMEOUT, nids.NIDS_RESET)
SERVER_PORT = 80
TCP_STREAM = {}

def sendToServer(data):
        ip_port = ('192.168.68.175', 6666)
        sk = socket.socket()
        sk.connect(ip_port)

        sk.sendall(data)
        reply = sk.recv(1024)
        print(reply)
        sk.close()
        sys.exit(1)

def handleTcpStream(tcp):
        print "tcps -", str(tcp.addr), " state:", tcp.nids_state

        ((src, sport), (dst, dport)) = tcp.addr
        if tcp.nids_state == nids.NIDS_JUST_EST:
                # new to us, but do we care?
                key = src + ":" + str(sport) + "-" + dst + ":" + str(dport)
                TCP_STREAM[key] = {}

                print tcp.addr
                if dport in (80, 8000, 8080, SERVER_PORT):
                        print "collecting ..."
                        tcp.client.collect = 1
                        tcp.server.collect = 1

        elif tcp.nids_state == nids.NIDS_DATA:
                # keep all of the stream's new data
                print tcp.server.data[:tcp.server.count] 
                tcp.discard(0)

        elif tcp.nids_state in end_states:
                print "addr:", tcp.addr
                sys.exit(1)
                #print "addr:", tcp.addr
                #print "To server:"
                #print tcp.server.data[:tcp.server.count] 
                #print "TO client:"
                #print tcp.client.data[:tcp.client.count]
                serverData = tcp.server.data[:tcp.server.count]
                sendToServer(serverData)

def main():
        #nids.param("pcap_filter", "tcp")

        nids.param("scan_num_hosts", 0)
        nids.chksum_ctl([('0.0.0.0/0', False)])

        if len(sys.argv) == 2:
                nids.param("filename", sys.argv[1])

        nids.init()

        #(uid, gid) = pwd.getpwnam(NOROOT)[2:4]
        #os.setgroups([gid, ])
        #os.setgid(gid)
        #os.setuid(uid)
        #if 0 in [os.getuid(), os.getgid()] + list(os.getgroups):
        #       print "error - drop root, please!"
        #       sys.exit(1)

        nids.register_tcp(handleTcpStream)
        print "pid", os.getpid()

        # Loop forever (network device), or until EOF (pcap file)
        # Note that an exception in the callback will break the loop!
        try:
                nids.run()
        except nids.error, e:
                print "nids/pcap error:", e
        except Exception, e:
                print "misc, exception (runtime error in user callback?):", e

if __name__ == '__main__':
        main()

你可能感兴趣的:(网络)