Nmap Development mailing list archives
[nmap] set source port in unprivileged mode
From: Simone Chiarelli <simchi88 () gmail com>
Date: Sat, 3 Jan 2015 03:47:56 +0100
It’s possible to set source port in tcp/connect scan mode even while unprivileged (for ports higher than 1023). Would it be feasible to add such feature to nmap? Following code is PoC: #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <unistd.h> #include <errno.h> #include <fcntl.h> typedef unsigned short port; typedef char * host; typedef int sock; int timeval_subtract(struct timeval *x, struct timeval *y, struct timeval *result); int socket_wait(int sock, long sec, int usec, int r, int w); int main(int argc, char *argv[]){ int errn = EXIT_SUCCESS; if(argc-1 < 4){ fprintf(stderr, "%s <srcport> <target> <port> <timeout ms>\n", argv[0]); exit(EXIT_FAILURE); } port srcPort = atoi(argv[1]); host targetHost = argv[2]; port dstPort = atoi(argv[3]); int usecTimeOut = atoi(argv[4])*1000; //Resolve host struct hostent *endPointEntry = gethostbyname(targetHost); if(endPointEntry == NULL){ herror(targetHost); exit(EXIT_FAILURE); } struct in_addr *targetAddr = (struct in_addr *)*endPointEntry->h_addr_list; // printf("Resolved Address: %s\n", inet_ntoa(*targetAddr)); //Create socket sock endPointSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(endPointSocket == -1){ perror("Could not create socket"); exit(EXIT_FAILURE); } //Set socket options int on = 1; if(setsockopt(endPointSocket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1){ perror("setsockopt"); errn = EXIT_FAILURE; goto cleanAndExit; } if(setsockopt(endPointSocket, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) == -1){ perror("setsockopt"); errn = EXIT_FAILURE; goto cleanAndExit; } //Set lingering in order to send rst after successfull connection struct linger lingerOpt = {0}; lingerOpt.l_onoff = 1; lingerOpt.l_linger = 0; if (setsockopt(endPointSocket, SOL_SOCKET, SO_LINGER, (const char *) &lingerOpt, sizeof(lingerOpt)) != 0){ perror("setsockopt"); errn = EXIT_FAILURE; goto cleanAndExit; } //Set non-blocking if(fcntl(endPointSocket, F_SETFL, O_NONBLOCK) == -1){ perror("fcntl"); errn = EXIT_FAILURE; goto cleanAndExit; } struct sockaddr_in bindAddr = {0}; bindAddr.sin_family = AF_INET; bindAddr.sin_addr.s_addr = htonl(INADDR_ANY); bindAddr.sin_port = htons(srcPort); if(bind(endPointSocket, (struct sockaddr *) &bindAddr, sizeof(bindAddr)) == -1){ fprintf(stderr, "Could not bind to INADDR_ANY:%hu (err: %s)\n", srcPort, strerror(errno)); errn = EXIT_FAILURE; goto cleanAndExit; } // printf("Bound to INADDR_ANY:%hu\n", srcPort); struct sockaddr_in endPointAddr = {0}; endPointAddr.sin_family = AF_INET; endPointAddr.sin_addr = *targetAddr; endPointAddr.sin_port = htons(dstPort); // struct timeval start = {0}; // if(gettimeofday(&start, NULL) != 0){ // perror("gettimeofday"); // errn = EXIT_FAILURE; // goto cleanAndExit; // } connect(endPointSocket, (struct sockaddr *) &endPointAddr, sizeof(endPointAddr)); int werr = socket_wait(endPointSocket, 0, usecTimeOut, 1, 1); errn = errno; // struct timeval end = {0}; // gettimeofday(&end, NULL); // struct timeval lapse = {0}; // timeval_subtract(&end, &start, &lapse); // printf("Elapsed: %ld.%06d sec(s)\n", lapse.tv_sec, lapse.tv_usec); if(werr < 0){ fprintf(stderr, "Could not connect to %s:%hu (err: %s)\n", targetHost, dstPort, strerror(errn)); errn = EXIT_FAILURE; goto cleanAndExit; } printf("Connected to %s:%hu\n", targetHost, dstPort); cleanAndExit: close(endPointSocket); return errn; } int socket_wait(int sock, long sec, int usec, int r, int w) { struct timeval tv = {0,0}; fd_set fdset; fd_set *rfds, *wfds; int n, so_error; unsigned so_len; FD_ZERO (&fdset); FD_SET (sock, &fdset); tv.tv_sec = sec; tv.tv_usec = usec; if (r) rfds = &fdset; else rfds = NULL; if (w) wfds = &fdset; else wfds = NULL; while ((n = select (sock+1, rfds, wfds, NULL, &tv)) == -1 && errno == EINTR); switch (n) { case 0: //perror ("wait timed out"); return -errno; case -1: perror ("error during wait"); return -errno; default: so_len = sizeof(so_error); so_error = 0; getsockopt (sock, SOL_SOCKET, SO_ERROR, &so_error, &so_len); if (so_error == 0) return 0; errno = so_error; return -errno; } } int timeval_subtract(struct timeval *x, struct timeval *y, struct timeval *result) { if (x->tv_usec < y->tv_usec) { int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; y->tv_usec -= 1000000 * nsec; y->tv_sec += nsec; } if (x->tv_usec - y->tv_usec > 1000000) { int nsec = (x->tv_usec - y->tv_usec) / 1000000; y->tv_usec += 1000000 * nsec; y->tv_sec -= nsec; } result->tv_sec = x->tv_sec - y->tv_sec; result->tv_usec = x->tv_usec - y->tv_usec; return x->tv_sec < y->tv_sec; } _______________________________________________ Sent through the dev mailing list http://nmap.org/mailman/listinfo/dev Archived at http://seclists.org/nmap-dev/
Current thread:
- [nmap] set source port in unprivileged mode Simone Chiarelli (Jan 05)