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)
