检测主机tcp端口是否开放的程序

时间:2021-07-09 15:25:25

1,做网络安全有几个月时间了,每天都在忙于事物性工作搞技术研究的时间相对比较少。但是还是接触了不少网络安全知识。

      工作中经常要用到扫描工具对主机漏洞进行扫描或端口扫描。所以自己也想写个主机漏扫工具及端口扫描工具,写漏扫工具很复杂本人还做不到

      呵呵就从端口扫描工具写起,首先实现TCP端口扫描,由于UDP是无连接的,端口扫描相对难点以后再实现。

2,本程序界面部分是用GTK写的,采用多线程对端口扫描,设置了TCP套接字接收超时选项为500ms,这样500ms内没收到,syn ack报文就认为端口没有开放。

这样为了节省TCP扫描时间,不然如果不设置超时时间扫65536个端口需要几天的时间不现实。

我扫描的是10000以内的端口大概20分钟,6万多个端口的话大概2个小时可以扫完。

本程序在linux下编译运行。GCC编译选项:`pkg-config --libs --cflags gtk+-2.0 gthread-2.0`

3,以下为程序代码

#include <gtk/gtk.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


GtkWidget *entry_port,*entry_ip;
GtkWidget *window;
//int sock_fd;
//int dip;
struct in_addr dip;

void show_warning(const char *message, gpointer window)
{
        GtkWidget *dialog;
        dialog = gtk_message_dialog_new(window,
            GTK_DIALOG_DESTROY_WITH_PARENT,
            GTK_MESSAGE_WARNING,
            GTK_BUTTONS_OK,
            message);
        gtk_window_set_title(GTK_WINDOW(dialog), "Warning");
        gtk_dialog_run(GTK_DIALOG(dialog));
        gtk_widget_destroy(dialog);
}

void test_port(gpointer port){
    struct sockaddr_in s_in;
    int sock_fd;
    s_in.sin_family = AF_INET;
        s_in.sin_port = htons(*(short int*)port);
    s_in.sin_addr=dip;
    struct timeval timeout={0,500000};
    char buf[10]="";
    if((sock_fd=socket(AF_INET,SOCK_STREAM,0))<0){
        printf("socket error\n");
        g_thread_exit(NULL);
    }
    setsockopt(sock_fd,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));
    if(connect(sock_fd,(struct sockaddr *)&s_in,sizeof(s_in))){
        printf("connect error\n");
    }else{
//        gdk_threads_enter(); //进入
        sprintf(buf,"%d;",*(short int*)port);
        gtk_entry_append_text(GTK_ENTRY(entry_port),buf);
//        gdk_threads_leave();    //离开
    }
    close(sock_fd);
    while(gtk_events_pending()){
                gtk_main_iteration();
        }
//        gtk_widget_set_sensitive(widget,TRUE);

    g_thread_exit(NULL);
//    

}

void check_port(GtkWidget *widget,gpointer data){
    gchar *p_ip;
//    struct in_addr dip;
//    int sock_fd;
    short int i;
    short int p_port[65535];
    GThread *thread1,*thread2,*thread3,*thread4,*thread5,*thread6;
    p_ip=gtk_entry_get_text(GTK_ENTRY(entry_ip));
    if(inet_aton(p_ip,&dip)==0){
        show_warning("无效的ip地址",window);
        return;        
    }
    gtk_entry_set_text(GTK_ENTRY(entry_port),"");
    gtk_widget_set_sensitive(widget,FALSE);
//    sock_fd=socket(AF_INET,SOCK_STREAM,0);
    for(i=10;i<=10000;i++){                                      //前10个端口基本不会对外开放所以都不用扫描了          
        p_port[i]=i;
        thread1=g_thread_create((GThreadFunc)test_port,&p_port[i],TRUE,NULL);
        i++;
        p_port[i]=i;
        thread2=g_thread_create((GThreadFunc)test_port,&p_port[i],TRUE,NULL);
        i++;
        p_port[i]=i;
        thread3=g_thread_create((GThreadFunc)test_port,&p_port[i],TRUE,NULL);
        i++;
        p_port[i]=i;
        thread4=g_thread_create((GThreadFunc)test_port,&p_port[i],TRUE,NULL);
        i++;
                p_port[i]=i;
                thread5=g_thread_create((GThreadFunc)test_port,&p_port[i],TRUE,NULL);
        i++;
                p_port[i]=i;
                thread6=g_thread_create((GThreadFunc)test_port,&p_port[i],TRUE,NULL);

        
        if(thread1!=NULL)
            g_thread_join(thread1);
        if(thread2!=NULL)
            g_thread_join(thread2);
        if(thread3!=NULL)
            g_thread_join(thread3);
        if(thread4!=NULL)
            g_thread_join(thread4);
        if(thread5!=NULL)
            g_thread_join(thread5);
        if(thread6!=NULL)
            g_thread_join(thread6);

//        sock_fd=socket(AF_INET,SOCK_STREAM,0);
//        test_port(i);
        while(gtk_events_pending()){
                     gtk_main_iteration();
            }
//        close(sock_fd);
    }
/*
    while(gtk_events_pending()){
               gtk_main_iteration();
           }
*/
    gtk_widget_set_sensitive(widget,TRUE);
    return;
//    close(sock_fd);    
}

int main(int argc,char *argv[]){
//    GtkWidget *window;
        GtkWidget *table,*button,*label;
//    GtkWidget *entry_port,*entry_ip;
    if(!g_thread_supported())
                g_thread_init(NULL);
      gtk_init(&argc,&argv);
        window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
        //window=gtk_window_new(GTK_WINDOW_POPUP);
        gtk_window_set_title(GTK_WINDOW(window),"端口扫描");
    gtk_widget_set_size_request(window,300,150);
    gtk_window_set_resizable((GtkWindow *)window,FALSE);
    gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
    //gtk_window_
    gtk_container_set_border_width(GTK_CONTAINER(window),10);
    table=gtk_table_new(4,2,TRUE);
    gtk_container_add(GTK_CONTAINER(window),table);
    label=gtk_label_new("主机IP");
    entry_ip=gtk_entry_new();
    gtk_table_attach_defaults(GTK_TABLE(table),label, 0 , 1, 0,1);
    gtk_table_attach_defaults(GTK_TABLE(table),entry_ip, 1 , 2, 0,1);
    button=gtk_button_new_with_label("确定");
    label=gtk_label_new("开放的端口数");
    entry_port=gtk_entry_new();
    
    gtk_table_attach_defaults(GTK_TABLE(table),button, 0 , 2, 1,2);
    gtk_table_attach_defaults(GTK_TABLE(table),label, 0 , 2, 2,3);
    gtk_table_attach_defaults(GTK_TABLE(table),entry_port, 0 , 2, 3,4);

    
    g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(check_port),NULL);
    g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL);
    gtk_widget_show_all(window);
        gdk_threads_enter();//
        gtk_main();
        gdk_threads_leave();//
        return FALSE;
}

4,程序运行截图

                                                                           检测主机tcp端口是否开放的程序