A Port Scanner in C
The following port scanner C code checks approximately 65535 ports in about 15 seconds on-network.
#include <stdio.h> #include <stdlib.h> #include <netinet/in.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <netdb.h> #include <sys/types.h> #include <sys/time.h> #include <sys/ioctl.h> #include <sys/wait.h> #define MAX_PORTS 65535 #define MAX_SOCKETS 1023 // gcc -o portscanner portscanner.c int scan_port(const char* host, int port) { struct sockaddr_in server; int sock; sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { perror("socket"); return -1; } server.sin_addr.s_addr = inet_addr(host); server.sin_family = AF_INET; server.sin_port = htons(port); int flags = fcntl(sock, F_GETFL, 0); fcntl(sock, F_SETFL, flags | O_NONBLOCK); if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == -1) { if (errno != EINPROGRESS) { perror("connect"); return -1; } } fd_set fdset; struct timeval tv; FD_ZERO(&fdset); FD_SET(sock, &fdset); tv.tv_sec = 0; tv.tv_usec = 200000; // Timeout of 200ms int select_ret = select(sock + 1, NULL, &fdset, NULL, &tv); if (select_ret == -1) { perror("select"); return -1; } else if (select_ret == 0) { close(sock); return 0; } // Connection successful, port is open close(sock); return 1; } void scan_ports(const char* host, int start_port, int end_port) { int num_sockets = 0; int port; for (port = start_port; port <= end_port; port++) { pid_t pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } else if (pid == 0) { // Child process int result = scan_port(host, port); if (result == 1) { printf("Port %d is open\n", port); } exit(EXIT_SUCCESS); } else { // Parent process num_sockets++; if (num_sockets >= MAX_SOCKETS) { wait(NULL); num_sockets--; } } } } int main(int argc, char* argv[]) { if (argc < 3 || argc > 4) { printf("Usage: %s <host> <port/start_port> [end_port]\n", argv[0]); return 1; } const char* host = argv[1]; int start_port = atoi(argv[2]); int end_port; if (argc == 4) { end_port = atoi(argv[3]); if (start_port < 1 || start_port > MAX_PORTS || end_port < 1 || end_port > MAX_PORTS || start_port > end_port) { printf("Invalid port range.\n"); return 1; } } else { end_port = start_port; if (start_port < 1 || start_port > MAX_PORTS) { printf("Invalid port.\n"); return 1; } } printf("Scanning ports %d to %d on host %s...\n", start_port, end_port, host); scan_ports(host, start_port, end_port); return 0; }
Here is a Windows version; it is much slower.
// CFLAGS="-static-libgcc -static-libstdc++ -03" // i686-w64-mingw32-gcc -o portscanner.exe portscanner_win32.c -lws2_32 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <winsock2.h> #include <ws2tcpip.h> #include <process.h> #pragma comment(lib, "ws2_32.lib") #define MAX_PORTS 65535 typedef struct { const char* host; int start_port; int end_port; } ScanParams; int scan_port(const char* host, int port) { WSADATA wsaData; SOCKET sock; struct sockaddr_in server; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { perror("WSAStartup"); return -1; } sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { perror("socket"); WSACleanup(); return -1; } server.sin_addr.s_addr = inet_addr(host); server.sin_family = AF_INET; server.sin_port = htons(port); u_long nonblocking = 1; if (ioctlsocket(sock, FIONBIO, &nonblocking) != 0) { perror("ioctlsocket"); closesocket(sock); WSACleanup(); return -1; } if (connect(sock, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) { int error = WSAGetLastError(); if (error != WSAEWOULDBLOCK) { perror("connect"); closesocket(sock); WSACleanup(); return -1; } } fd_set fdset; struct timeval tv; FD_ZERO(&fdset); FD_SET(sock, &fdset); tv.tv_sec = 0; tv.tv_usec = 200000; // Timeout of 200ms int select_ret = select(0, NULL, &fdset, NULL, &tv); if (select_ret == SOCKET_ERROR) { perror("select"); closesocket(sock); WSACleanup(); return -1; } else if (select_ret == 0) { closesocket(sock); WSACleanup(); return 0; } // Connection successful, port is open closesocket(sock); WSACleanup(); return 1; } unsigned int __stdcall scan_ports_thread(void* params) { ScanParams* scanParams = (ScanParams*)params; const char* host = scanParams->host; int start_port = scanParams->start_port; int end_port = scanParams->end_port; int port; for (port = start_port; port <= end_port; port++) { int result = scan_port(host, port); if (result == 1) { printf("Port %d is open\n", port); } } _endthreadex(0); return 0; } void scan_ports(const char* host, int start_port, int end_port, int num_threads) { int ports_per_thread = (end_port - start_port + 1) / num_threads; int remaining_ports = (end_port - start_port + 1) % num_threads; int thread; HANDLE* scanThreads = malloc(num_threads * sizeof(HANDLE)); ScanParams* scanParams = malloc(num_threads * sizeof(ScanParams)); for (thread = 0; thread < num_threads; thread++) { scanParams[thread].host = host; scanParams[thread].start_port = start_port + thread * ports_per_thread; scanParams[thread].end_port = scanParams[thread].start_port + ports_per_thread - 1; if (thread == num_threads - 1) { // Assign remaining ports to the last thread scanParams[thread].end_port += remaining_ports; } scanThreads[thread] = (HANDLE)_beginthreadex(NULL, 0, scan_ports_thread, &scanParams[thread], 0, NULL); } // Wait for all threads to finish WaitForMultipleObjects(num_threads, scanThreads, TRUE, INFINITE); free(scanThreads); free(scanParams); } int main(int argc, char* argv[]) { if (argc < 3 || argc > 5) { printf("Usage: %s <host> <port/start_port> [end_port] [num_threads]\n", argv[0]); return 1; } const char* host = argv[1]; int start_port = atoi(argv[2]); int end_port; int num_threads = 25; if (argc >= 4) { end_port = atoi(argv[3]); if (argc == 5) { num_threads = atoi(argv[4]); } } else { end_port = start_port; } if (start_port < 1 || start_port > MAX_PORTS || end_port < 1 || end_port > MAX_PORTS || start_port > end_port) { printf("Invalid port range.\n"); return 1; } printf("Scanning ports %d to %d on host %s using %d thread(s)...\n", start_port, end_port, host, num_threads); scan_ports(host, start_port, end_port, num_threads); return 0; }
Visited 1 times, 1 visit(s) today
Leave a Reply