tcp syn scan demo

#include<stdio.h> //printf

#include<stdlib.h> //for exit(0);

#include<time.h>

#include<string.h> //memset

#include<sys/socket.h>

#include<errno.h> //For errno - the error number

#include<pthread.h>

#include<netdb.h> //hostend

#include<arpa/inet.h>

#include<netinet/tcp.h>  //Provides declarations for tcp header

#include<netinet/ip.h>    //Provides declarations for ip header

#include <unistd.h>

void * receive_ack( void *ptr );

void process_packet(unsigned char*, int);

unsigned short csum(unsigned short *, int );

char * hostname_to_ip(char * );

int get_local_ip (char *);

int get_random_sport ();

struct pseudo_header    //needed for checksum calculation

{

    unsigned int source_address;

    unsigned int dest_address;

    unsigned char placeholder;

    unsigned char protocol;

    unsigned short tcp_length;

    struct tcphdr tcp;

};

struct in_addr dest_ip;

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

{

//Create a raw socket

    int s = socket (AF_INET, SOCK_RAW, IPPROTO_TCP);

    if(s < 0)

    {

        printf ("Error creating socket. Error number : %d . Error message : %s \n", errno,strerror(errno));

        exit(0);

    }

    else

    {

        printf("Socket created.\n");

    }

    //Datagram to represent the packet

    char datagram[4096];

    //IP header

    struct iphdr *iph = (struct iphdr *) datagram;

//TCP header

    struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip));

    //socket 目标地址

    struct sockaddr_in  dest;

    //tcp/ip 伪头部

    struct pseudo_header psh;

    char *target = argv[1];

    if(argc < 2)

    {

        printf("Please specify a hostname \n");

        exit(1);

    }

    if( inet_addr( target ) != -1)

    {

        dest_ip.s_addr = inet_addr( target );

    }

    else

    {

        char *ip = hostname_to_ip(target);

        if(ip != NULL)

        {

            printf("%s resolved to %s \n", target, ip);

            //Convert domain name to IP

            dest_ip.s_addr = inet_addr( hostname_to_ip(target) );

        }

        else

        {

            printf("Unable to resolve hostname : %s", target);

            exit(1);

        }

    }

    srand(time(NULL));  // Initialization, should only be called once.

//  int source_port = 32768;

    int source_port = get_random_sport();

    char source_ip[20];

    get_local_ip( source_ip );

    printf("Local source IP is %s \n", source_ip);

    memset (datagram, 0, 4096); /* zero out the buffer */

    //Fill in the IP Header

    iph->ihl = 5;

    iph->version = 4;

    iph->tos = 0;

    iph->tot_len = sizeof (struct ip) + sizeof (struct tcphdr);

    iph->id = htons (54321); //Id of this packet

    iph->frag_off = htons(16384);

    iph->ttl = 64;

    iph->protocol = IPPROTO_TCP;

    iph->check = 0;      //Set to 0 before calculating checksum

    iph->saddr = inet_addr ( source_ip );    //Spoof the source ip address

    iph->daddr = dest_ip.s_addr;

    iph->check = csum ((unsigned short *) datagram, iph->tot_len >> 1);

    //TCP Header

    tcph->source = htons ( source_port );

    tcph->dest = htons (80);

    tcph->seq = htonl(1105024978);

    tcph->ack_seq = 0;

    tcph->doff = sizeof(struct tcphdr) / 4;      //Size of tcp header

    tcph->fin=0;

    tcph->syn=1;

    tcph->rst=0;

    tcph->psh=0;

    tcph->ack=0;

    tcph->urg=0;

    tcph->window = htons ( 14600 );  // maximum allowed window size

    tcph->check = 0; //if you set a checksum to zero, your kernel's IP stack should fill in the correct checksum during transmission

    tcph->urg_ptr = 0;

    //IP_HDRINCL to tell the kernel that headers are included in the packet

    int one = 1;

    const int *val = &one;

    if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)

    {

        printf ("Error setting IP_HDRINCL. Error number : %d . Error message : %s \n", errno, strerror(errno));

        exit(0);

    }

    printf("Starting sniffer thread...\n");

    char *message1 = "Thread 1";

    int  iret1;

    pthread_t sniffer_thread;

    if( pthread_create( &sniffer_thread, NULL,  receive_ack, (void*) message1) < 0)

    {

        printf ("Could not create sniffer thread. Error number : %d . Error message : %s \n",errno, strerror(errno));

        exit(0);

    }

    usleep(1);

    printf("Starting to send syn packets\n");

    int port;

    dest.sin_family = AF_INET;

    dest.sin_addr.s_addr = dest_ip.s_addr;

    for(port = 1; port < 10000 ; port++)

    {

        tcph->dest = htons ( port );

        tcph->check = 0; // if you set a checksum to zero, your kernel's IP stack should fill in the correct checksum during transmission

        psh.source_address = inet_addr( source_ip );

        psh.dest_address = dest.sin_addr.s_addr;

        psh.placeholder = 0;

        psh.protocol = IPPROTO_TCP;

        psh.tcp_length = htons( sizeof(struct tcphdr) );

        memcpy(&psh.tcp, tcph, sizeof (struct tcphdr));

        tcph->check = csum( (unsigned short*) &psh, sizeof (struct pseudo_header));

        //Send the packet

        if ( sendto (s, datagram, sizeof(struct iphdr) + sizeof(struct tcphdr), 0, (struct sockaddr *) &dest, sizeof (dest)) < 0)

        {

            printf ("Error sending syn packet. Error number : %d . Error message : %s \n",errno, strerror(errno));

            exit(0);

        }

    }

    pthread_join( sniffer_thread, NULL);

    printf("%d", iret1);

    return 0;

}

/*

    Method to sniff incoming packets and look for Ack replies

*/

void * receive_ack( void *ptr )

{

    //Start the sniffer thing

    start_sniffer();

}

int start_sniffer()

{

    int sock_raw;

    int saddr_size, data_size;

    struct sockaddr saddr;

    unsigned char *buffer = (unsigned char *)malloc(65536); //Its Big!

    printf("Sniffer initialising...\n");

    fflush(stdout);

    //Create a raw socket that shall sniff

    sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);

    if(sock_raw < 0)

    {

        printf("Socket Error\n");

        fflush(stdout);

        return 1;

    }

    saddr_size = sizeof saddr;

    struct timeval tv;

    tv.tv_sec = 2;

    tv.tv_usec = 0;

    if (setsockopt(sock_raw, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)

    {

        printf("socket option  SO_RCVTIMEO not support\n");

        return 1;

    }

    while(1)

    {

        //Receive a packet

        data_size = recvfrom(sock_raw, buffer, 65536, 0, &saddr, &saddr_size);

        if(data_size <0 )

        {

            printf("Recvfrom error , failed to get packets\n");

            fflush(stdout);

            return 1;

        }

        //Now process the packet

        process_packet(buffer, data_size);

    }

    close(sock_raw);

    printf("Sniffer finished.");

    fflush(stdout);

    return 0;

}

void process_packet(unsigned char* buffer, int size)

{

    //Get the IP Header part of this packet

    struct iphdr *iph = (struct iphdr*)buffer;

    struct sockaddr_in source,dest;

    unsigned short iphdrlen;

    if(iph->protocol == 6)

    {

        struct iphdr *iph = (struct iphdr *)buffer;

        iphdrlen = iph->ihl*4;

        struct tcphdr *tcph=(struct tcphdr*)(buffer + iphdrlen);

        memset(&source, 0, sizeof(source));

        source.sin_addr.s_addr = iph->saddr;

        memset(&dest, 0, sizeof(dest));

        dest.sin_addr.s_addr = iph->daddr;

        if(tcph->syn == 1 && tcph->ack == 1 && source.sin_addr.s_addr == dest_ip.s_addr )

        {

            printf("ip %s \t Port %d open \n", inet_ntoa(source.sin_addr),ntohs(tcph->source));

            fflush(stdout);

        }

        else

        {

            printf("ip %s \t Port %d close \n", inet_ntoa(source.sin_addr),ntohs(tcph->source));

        }

    }

}

/*

Checksums - IP and TCP

*/

unsigned short csum(unsigned short *ptr,int nbytes)

{

    register long sum;

    unsigned short oddbyte;

    register short answer;

    sum=0;

    while(nbytes>1)

    {

        sum+=*ptr++;

        nbytes-=2;

    }

    if(nbytes==1)

    {

        oddbyte=0;

        *((u_char*)&oddbyte)=*(u_char*)ptr;

        sum+=oddbyte;

    }

    sum = (sum>>16)+(sum & 0xffff);

    sum = sum + (sum>>16);

    answer=(short)~sum;

    return(answer);

}

/*

    Get ip from domain name

*/

char* hostname_to_ip(char * hostname)

{

    struct hostent *he;

    struct in_addr **addr_list;

    int i;

    if ( (he = gethostbyname( hostname ) ) == NULL)

    {

        // get the host info

        herror("gethostbyname");

        return NULL;

    }

    addr_list = (struct in_addr **) he->h_addr_list;

    for(i = 0; addr_list[i] != NULL; i++)

    {

        //Return the first one;

        return inet_ntoa(*addr_list[i]) ;

    }

    return NULL;

}

/*

Get source IP of system , like 192.168.0.6 or 192.168.1.2

*/

int get_local_ip ( char * buffer)

{

    int sock = socket ( AF_INET, SOCK_DGRAM, 0);

    const char* kGoogleDnsIp = "8.8.8.8";

    int dns_port = 53;

    struct sockaddr_in serv;

    memset( &serv, 0, sizeof(serv) );

    serv.sin_family = AF_INET;

    serv.sin_addr.s_addr = inet_addr(kGoogleDnsIp);

    serv.sin_port = htons( dns_port );

    int err = connect( sock, (const struct sockaddr*) &serv, sizeof(serv) );

    struct sockaddr_in name;

    socklen_t namelen = sizeof(name);

    err = getsockname(sock, (struct sockaddr*) &name, &namelen);

    const char *p = inet_ntop(AF_INET, &name.sin_addr, buffer, 100);

    close(sock);

}

int get_random_sport()

{

    int sport=32768;

    sport =sport + rand()%28000;

    return sport;

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354