/** * @brief Send a TCP segment to libntoh */ void send_tcp_segment ( struct ip *iphdr , pntoh_tcp_callback_t callback ) { ppeer_info_t pinfo; ntoh_tcp_tuple5_t tcpt5; pntoh_tcp_stream_t stream; struct tcphdr *tcp; size_t size_ip; size_t total_len; size_t size_tcp; size_t size_payload; unsigned char *payload; int ret; unsigned int error; size_ip = iphdr->ip_hl * 4; total_len = ntohs( iphdr->ip_len ); tcp = (struct tcphdr*)((unsigned char*)iphdr + size_ip); if ( (size_tcp = tcp->th_off * 4) < sizeof(struct tcphdr) ) return; payload = (unsigned char *)iphdr + size_ip + size_tcp; size_payload = total_len - ( size_ip + size_tcp ); ntoh_tcp_get_tuple5 ( (void*)iphdr , tcp , &tcpt5 ); /* find the stream or creates a new one */ if ( !( stream = ntoh_tcp_find_stream( tcp_session , &tcpt5 ) ) ) if ( ! ( stream = ntoh_tcp_new_stream( tcp_session , &tcpt5, callback , 0 , &error , 1 , 1 ) ) ) { fprintf ( stderr , "\n[e] Error %d creating new stream: %s" , error , ntoh_get_errdesc ( error ) ); return; } if ( size_payload > 0 ) pinfo = get_peer_info ( payload , size_payload , &tcpt5 ); else pinfo = 0; /* add this segment to the stream */ switch ( ( ret = ntoh_tcp_add_segment( tcp_session , stream, (void*)iphdr, total_len, (void*)pinfo ) ) ) { case NTOH_OK: break; case NTOH_SYNCHRONIZING: free_peer_info ( pinfo ); break; default: fprintf( stderr, "\n[e] Error %d adding segment: %s", ret, ntoh_get_retval_desc( ret ) ); free_peer_info ( pinfo ); break; } return; }
/** * @brief Sends a IPv4 fragment to libntoh */ void send_ipv4_fragment ( struct ip *iphdr , pipv4_dfcallback_t callback ) { ntoh_ipv4_tuple4_t ipt4; pntoh_ipv4_flow_t flow; int ret; unsigned int error; ntoh_ipv4_get_tuple4 ( iphdr , &ipt4 ); if ( !( flow = ntoh_ipv4_find_flow( ipv4_session , &ipt4 ) ) ) if ( ! (flow = ntoh_ipv4_new_flow( ipv4_session , &ipt4, callback, 0 , &error )) ) { fprintf ( stderr , "\n[e] Error %d creating new IPv4 flow: %s" , error , ntoh_get_errdesc ( error ) ); return; } if ( ( ret = ntoh_ipv4_add_fragment( ipv4_session , flow, iphdr ) ) ) fprintf( stderr, "\n[e] Error %d adding IPv4: %s", ret, ntoh_get_retval_desc( ret ) ); return; }
int main ( int argc , char *argv[] ) { /* parameters parsing */ int c; /* pcap */ char errbuf[PCAP_ERRBUF_SIZE]; struct bpf_program fp; char filter_exp[] = "ip and tcp"; char *source = 0; char *filter = filter_exp; const unsigned char *packet = 0; struct pcap_pkthdr header; /* packet dissection */ struct ip *ip; unsigned int error; /* extra */ unsigned int ipf,tcps; fprintf( stderr, "\n###########################" ); fprintf( stderr, "\n# libntoh Example #" ); fprintf( stderr, "\n# ----------------------- #" ); fprintf( stderr, "\n# Written by Chema Garcia #" ); fprintf( stderr, "\n# ----------------------- #" ); fprintf( stderr, "\n# http://safetybits.net #" ); fprintf( stderr, "\n# [email protected] #" ); fprintf( stderr, "\n###########################\n" ); fprintf( stderr, "\n[i] libntoh version: %s\n", ntoh_version() ); if ( argc < 3 ) { fprintf( stderr, "\n[+] Usage: %s <options>\n", argv[0] ); fprintf( stderr, "\n+ Options:" ); fprintf( stderr, "\n\t-i | --iface <val> -----> Interface to read packets from" ); fprintf( stderr, "\n\t-f | --file <val> ------> File path to read packets from" ); fprintf( stderr, "\n\t-F | --filter <val> ----> Capture filter (default: \"ip and tcp\")" ); fprintf( stderr, "\n\t-c | --client ----------> Receive client data"); fprintf( stderr, "\n\t-s | --server ----------> Receive server data\n\n"); exit( 1 ); } /* check parameters */ while ( 1 ) { int option_index = 0; static struct option long_options[] = { { "iface" , 1 , 0 , 'i' } , { "file" , 1 , 0 , 'f' } , { "filter" , 1 , 0 , 'F' } , { "client" , 0 , 0 , 'c' }, { "server" , 0 , 0 , 's' }, { 0 , 0 , 0 , 0 } }; if ( ( c = getopt_long( argc, argv, "i:f:F:cs", long_options, &option_index ) ) < 0 ) break; switch ( c ) { case 'i': source = optarg; handle = pcap_open_live( optarg, 65535, 1, 0, errbuf ); break; case 'f': source = optarg; handle = pcap_open_offline( optarg, errbuf ); break; case 'F': filter = optarg; break; case 'c': receive |= RECV_CLIENT; break; case 's': receive |= RECV_SERVER; break; } } if ( !receive ) receive = (RECV_CLIENT | RECV_SERVER); if ( !handle ) { fprintf( stderr, "\n[e] Error loading %s: %s\n", source, errbuf ); exit( -1 ); } if ( pcap_compile( handle, &fp, filter, 0, 0 ) < 0 ) { fprintf( stderr, "\n[e] Error compiling filter \"%s\": %s\n\n", filter, pcap_geterr( handle ) ); pcap_close( handle ); exit( -2 ); } if ( pcap_setfilter( handle, &fp ) < 0 ) { fprintf( stderr, "\n[e] Cannot set filter \"%s\": %s\n\n", filter, pcap_geterr( handle ) ); pcap_close( handle ); exit( -3 ); } pcap_freecode( &fp ); /* verify datalink */ if ( pcap_datalink( handle ) != DLT_EN10MB ) { fprintf ( stderr , "\n[e] libntoh is independent from link layer, but this example only works with ethernet link layer\n"); pcap_close ( handle ); exit ( -4 ); } fprintf( stderr, "\n[i] Source: %s / %s", source, pcap_datalink_val_to_description( pcap_datalink( handle ) ) ); fprintf( stderr, "\n[i] Filter: %s", filter ); fprintf( stderr, "\n[i] Receive data from client: "); if ( receive & RECV_CLIENT ) fprintf( stderr , "Yes"); else fprintf( stderr , "No"); fprintf( stderr, "\n[i] Receive data from server: "); if ( receive & RECV_SERVER ) fprintf( stderr , "Yes"); else fprintf( stderr , "No"); signal( SIGINT, &shandler ); signal( SIGTERM, &shandler ); /*******************************************/ /** libntoh initialization process starts **/ /*******************************************/ ntoh_init (); if ( ! (tcp_session = ntoh_tcp_new_session ( 0 , 0 , &error ) ) ) { fprintf ( stderr , "\n[e] Error %d creating TCP session: %s" , error , ntoh_get_errdesc ( error ) ); exit ( -5 ); } fprintf ( stderr , "\n[i] Max. TCP streams allowed: %d" , ntoh_tcp_get_size ( tcp_session ) ); if ( ! (ipv4_session = ntoh_ipv4_new_session ( 0 , 0 , &error )) ) { ntoh_tcp_free_session ( tcp_session ); fprintf ( stderr , "\n[e] Error %d creating IPv4 session: %s" , error , ntoh_get_errdesc ( error ) ); exit ( -6 ); } fprintf ( stderr , "\n[i] Max. IPv4 flows allowed: %d\n\n" , ntoh_ipv4_get_size ( ipv4_session ) ); /* capture starts */ while ( ( packet = pcap_next( handle, &header ) ) != 0 ) { /* get packet headers */ ip = (struct ip*) ( packet + sizeof ( struct ether_header ) ); if ( (ip->ip_hl * 4 ) < sizeof(struct ip) ) continue; /* it is an IPv4 fragment */ if ( NTOH_IPV4_IS_FRAGMENT(ip->ip_off) ) send_ipv4_fragment ( ip , &ipv4_callback ); /* or a TCP segment */ else if ( ip->ip_p == IPPROTO_TCP ) send_tcp_segment ( ip , &tcp_callback ); } tcps = ntoh_tcp_count_streams( tcp_session ); ipf = ntoh_ipv4_count_flows ( ipv4_session ); /* no streams left */ if ( ipf + tcps > 0 ) { fprintf( stderr, "\n\n[+] There are currently %i stored TCP stream(s) and %i IPv4 flow(s). You can wait them to get closed or press CTRL+C\n" , tcps , ipf ); pause(); } shandler( 0 ); //dummy return return 0; }
/** * @brief Send a TCP segment to libntoh */ void send_tcp_segment ( struct ip *iphdr , pntoh_tcp_callback_t callback ) { ppeer_info_t pinfo; ntoh_tcp_tuple5_t tcpt5; pntoh_tcp_stream_t stream; struct tcphdr *tcp; size_t size_ip; size_t total_len; size_t size_tcp; size_t size_payload; unsigned char *payload; int32_t ret; unsigned int error; size_ip = iphdr->ip_hl * 4; total_len = ntohs( iphdr->ip_len ); tcp = (struct tcphdr*)((unsigned char*)iphdr + size_ip); if ( (size_tcp = tcp->th_off * 4) < sizeof(struct tcphdr) ) { return; } payload = (unsigned char *)iphdr + size_ip + size_tcp; size_payload = total_len - ( size_ip + size_tcp ); ntoh_tcp_get_tuple5 ( iphdr , tcp , &tcpt5 ); /* find the stream or creates a new one */ if ( !( stream = ntoh_tcp_find_stream( tcp_session , &tcpt5 ) ) ) { if ( ! ( stream = ntoh_tcp_new_stream( tcp_session , &tcpt5, callback , 0 , &error , 1 , 1 ) ) ) { if (DEBUG) { fprintf ( stderr , "\n[e] Error %d creating new stream: %s" , error , ntoh_get_errdesc ( error ) ); } return; } } if ( size_payload > 0 ) { pinfo = get_peer_info ( payload , size_payload , &tcpt5 ); } else { pinfo = 0; } if (pinfo != 0) { /* HERE - determine if this is a packet type we're interested in */ //if (Contains((char *)payload, "HTTP") && (Contains((char *)payload, "GET") || Contains((char *)payload, "POST") || Contains((char *)payload, "HEAD"))) if (ntohs(tcpt5.dport) == 80) { pending_more_hdr_data = extractHttpHdr((const char *)(payload)); if (pending_more_hdr_data == 0) { size_t l = (strlen((const char *)(pinfo->path))); i = 0; while (i < l) { snc.mem.t5s[(snc.smem.shm[CTL][POS]) - 1][i] = (sig_atomic_t)(pinfo->path[i]); i++; } snc.mem.t5s[(snc.smem.shm[CTL][POS]) - 1][i] = (sig_atomic_t)((const char)'\0'); if (DEBUG) { write(2, "\n\t[i] --- tcp tuple 5 --- ", 27); write(2, (const char *)(pinfo->path), strlen((const char *)(pinfo->path))); fflush(stderr); } extractSig(); ret = dumpToShm(); if(ret != 0) { if (DEBUG) { fprintf(stderr, "\n\t[Error] --- Unable to dump HTTP header to shared memory\n\t\tReason: %s\n", ret == CRING ? "CRING" : (ret == PWING ? "PWING" : "Unknown")); } } else { if (DEBUG) { write(2, "\n\tSuccessfully dumped signature to shared memory\n", 49); } } ret = 0; } } } /* add this segment to the stream */ switch ( ( ret = ntoh_tcp_add_segment( tcp_session , stream, iphdr, total_len, (void*)pinfo ) ) ) { case NTOH_OK: break; case NTOH_SYNCHRONIZING: free_peer_info ( pinfo ); break; default: if (DEBUG) { fprintf( stderr, "\n[e] Error %d adding segment: %s", ret, ntoh_get_retval_desc( ret ) ); } free_peer_info ( pinfo ); break; } return; }
int main (int argc , char *argv[]) { signal( SIGINT, &shandler ); signal( SIGTERM, &shandler ); signal( SIGSEGV, &shandler ); write(2, "\n\t\t######################################", 41); write(2, "\n\t\t# Dump HTTP Sigs #", 41); write(2, "\n\t\t# ---------------------------------- #", 41); write(2, "\n\t\t# Written by Ernest Richards #", 41); write(2, "\n\t\t# Based on code from Chema Garcia #", 41); write(2, "\n\t\t# ---------------------------------- #", 41); write(2, "\n\t\t# Github.com/ernesto341/ais-research #", 41); write(2, "\n\t\t######################################\n", 42); write(2, "\n\t\tX ----- Active ----- X\n\n", 43); if (DEBUG) { sprintf(buf, "\n[i] libntoh version: %s\n", ntoh_version()); write(2, buf, strlen(buf)); } if ( argc < 3 ) { sprintf(buf, "\n[+] Usage: %s <options>\n", argv[0]); write(2, buf, strlen(buf)); write(2, "\n+ Options:", 11); // 28 write(2, "\n\t-i | --iface <val> -----> Interface to read packets from", 58); write(2, "\n\t-f | --file <val> ------> File path to read packets from", 58); write(2, "\n\t-F | --filter <val> ----> Capture filter (must contain \"tcp\" or \"ip\")", 71); write(2, "\n\t-c | --client ----------> Receive client data only", 52); write(2, "\n\t-s | --server ----------> Receive server data only\n\n", 54); exit(1); } /* parameters parsing */ int32_t c = 0; /* pcap */ char errbuf[PCAP_ERRBUF_SIZE]; struct bpf_program fp; char filter_exp[] = "ip"; char *source = 0; char *filter = filter_exp; const unsigned char *packet = 0; struct pcap_pkthdr header; /* packet dissection */ struct ip *ip; uint32_t error = 0; /* extra */ uint32_t ipf, tcps; /* check parameters */ while ( c >= 0 ) { int32_t option_index = 0; static struct option long_options[] = { { "iface" , 1 , 0 , 'i' }, { "file" , 1 , 0 , 'f' }, { "filter" , 1 , 0 , 'F' }, { "client" , 0 , 0 , 'c' }, { "server" , 0 , 0 , 's' }, { 0 , 0 , 0 , 0 } }; c = getopt_long( argc, argv, "i:f:F:cs", long_options, &option_index ); if (c >= 0) { switch ( c ) { case 'i': source = optarg; handle = pcap_open_live( optarg, 65535, 1, 0, errbuf ); break; case 'f': source = optarg; handle = pcap_open_offline( optarg, errbuf ); break; case 'F': filter = optarg; break; case 'c': receive |= RECV_CLIENT; break; case 's': receive |= RECV_SERVER; break; } } } if ( !receive ) { receive = (RECV_CLIENT | RECV_SERVER); } if ( !handle ) { if (DEBUG) { fprintf( stderr, "\n[e] Error loading %s: %s\n", source, errbuf ); } exit( -1 ); } if ( pcap_compile( handle, &fp, filter, 0, 0 ) < 0 ) { if (DEBUG) { fprintf( stderr, "\n[e] Error compiling filter \"%s\": %s\n\n", filter, pcap_geterr( handle ) ); } pcap_close( handle ); exit( -2 ); } if ( pcap_setfilter( handle, &fp ) < 0 ) { if (DEBUG) { fprintf( stderr, "\n[e] Cannot set filter \"%s\": %s\n\n", filter, pcap_geterr( handle ) ); } pcap_close( handle ); exit( -3 ); } pcap_freecode( &fp ); /* verify datalink */ if ( pcap_datalink( handle ) != DLT_EN10MB ) { if (DEBUG) { fprintf ( stderr , "\n[e] libntoh is independent from link layer, but this code only works with ethernet link layer\n"); } pcap_close ( handle ); exit ( -4 ); } if (DEBUG) { fprintf( stderr, "\n[i] Source: %s / %s", source, pcap_datalink_val_to_description( pcap_datalink( handle ) ) ); fprintf( stderr, "\n[i] Filter: %s", filter ); fprintf( stderr, "\n[i] Receive data from client: "); if ( receive & RECV_CLIENT ) { fprintf( stderr , "Yes"); } else { fprintf( stderr , "No"); } fprintf( stderr, "\n[i] Receive data from server: "); if ( receive & RECV_SERVER ) { fprintf( stderr , "Yes"); } else { fprintf( stderr , "No"); } } /*******************************************/ /** libntoh initialization process starts **/ /*******************************************/ initMem(&snc); /* fork and exec retrieve in retdir */ char *null_args[] = {NULL}; char *null_envp[] = {NULL}; if ((ret_pid = fork()) == 0) /* child */ { if (execve((char *)"./retdir/retrieve\0", null_args, null_envp) < 0) { perror("execve()"); shandler(-1); } } else { if ((t5Convert = (sig_atomic_t *)malloc(sizeof(sig_atomic_t) * t5TplLen)) < (sig_atomic_t *)0) { write(2, "\n\t[e] --- Unable to allocate sufficient memory\n", 47); fflush(stderr); _exit(-1); } ntoh_init (); if ( ! (tcp_session = ntoh_tcp_new_session ( 0 , 0 , &error ) ) ) { if (DEBUG) { fprintf ( stderr , "\n[e] Error %d creating TCP session: %s" , error , ntoh_get_errdesc ( error ) ); } exit ( -5 ); } if (DEBUG) { fprintf ( stderr , "\n[i] Max. TCP streams allowed: %d" , ntoh_tcp_get_size ( tcp_session ) ); } if ( ! (ipv4_session = ntoh_ipv4_new_session ( 0 , 0 , &error )) ) { ntoh_tcp_free_session ( tcp_session ); if (DEBUG) { fprintf ( stderr , "\n[e] Error %d creating IPv4 session: %s" , error , ntoh_get_errdesc ( error ) ); } exit ( -6 ); } if (DEBUG) { fprintf ( stderr , "\n[i] Max. IPv4 flows allowed: %d\n\n" , ntoh_ipv4_get_size ( ipv4_session ) ); fflush(stderr); } /* capture starts */ /* accept signal from consumer to quit */ while ( ( packet = pcap_next( handle, &header ) ) != 0 && snc.smem.shm[CTL][FLAGS] != CDONE) { static int pc = 0; fprintf(stdout, "Packet %d\n", ++pc); fflush(stdout); /* get packet headers */ ip = (struct ip*) ( packet + sizeof ( struct ether_header ) ); if ( (ip->ip_hl * 4 ) < (int)sizeof(struct ip) ) { continue; } /* it is an IPv4 fragment */ if ( NTOH_IPV4_IS_FRAGMENT(ip->ip_off) ) { send_ipv4_fragment ( ip , &ipv4_callback ); } /* or a TCP segment */ else if ( ip->ip_p == IPPROTO_TCP ) { send_tcp_segment ( ip , &tcp_callback ); } } if (snc.smem.shm[CTL][FLAGS] == CDONE) { shandler( 0 ); } tcps = ntoh_tcp_count_streams( tcp_session ); ipf = ntoh_ipv4_count_flows ( ipv4_session ); /* no streams left */ if ( ipf + tcps > 0 ) { if (DEBUG) { fprintf( stderr, "\n\n[+] There are currently %i stored TCP stream(s) and %i IPv4 flow(s). You can wait for them to get closed or press CTRL+C\n" , tcps , ipf ); pause(); } } shandler( 0 ); } //dummy return, should never be called return (0); }
/** * @brief Sends a IPv4 fragment to libntoh */ void send_ipv4_fragment ( struct ip *iphdr , pipv4_dfcallback_t callback ) { ntoh_ipv4_tuple4_t ipt4; pntoh_ipv4_flow_t flow; size_t total_len; int32_t ret; uint32_t error; total_len = ntohs( iphdr->ip_len ); ntoh_ipv4_get_tuple4 ( iphdr , &ipt4 ); if ( !( flow = ntoh_ipv4_find_flow( ipv4_session , &ipt4 ) ) ) { if ( ! (flow = ntoh_ipv4_new_flow( ipv4_session , &ipt4, callback, 0 , &error )) ) { if (DEBUG) { fprintf ( stderr , "\n[e] Error %d creating new IPv4 flow: %s" , error , ntoh_get_errdesc ( error ) ); } return; } } if ( ( ret = ntoh_ipv4_add_fragment( ipv4_session , flow, iphdr, total_len ) ) ) { if (DEBUG) { fprintf( stderr, "\n[e] Error %d adding IPv4: %s", ret, ntoh_get_retval_desc( ret ) ); } } return; }