Jump to content
Nytro

SYN port scanner (source)

Recommended Posts

SYN port scanner (source)

version 1.2

by ithilgore

ithilgore.ryu.L@gmail.com

/****************************************************************************/
/* Creeper - a simple Syn Scanner */
/* minimalistic port scanner for educational purposes */
/* Copyright (C) 2007 ithilgore - ithilgore.ryu.L@gmail.com */
/* */
/* This program is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation, either version 3 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/****************************************************************************/

/****************************************************************************/
/* Creeper */
/* version 1.2 */
/* by ithilgore */
/* ithilgore.ryu.L@gmail.com */
/* */
/* compile with: gcc creeper.c -lpcap -o creeper */
/* some compilers may also need -fpack-struct */
/* */
/* Use of this code is for educational purposes only. I am not responsible */
/* for any illegal or criminal activities performed with this tool or */
/* any modifications of it. */
/* This tool is free and open software. This means you can do anything you */
/* like with it with your own responsibility and with no warranty from me. */
/* to the source. */
/* */
/* This tool has been tested so far and works sucessfully in: */
/* ----Slackware 11 with kernel 2.2.4.33 */
/* ----Arch Linux (Core Dump) kernel 2.6.23 */
/****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <pcap.h>
#include <signal.h>

#define BUFSIZE 65535 //maximum size of any datagram(16 bits the size of identifier)
#define TRUE 1
#define FALSE 0
#define default_low 1
#define default_high 1024


/* change the timeout at will
* it defines how long the scanner will wait for
* an answer from the scanned host
* careful though - testing shows < 4 is bad
* it is just another factor between speed and accuracy
*/
#define DEFAULT_S_TIMEOUT 5


/* default snap length (maximum bytes per packet to capture) */
#define SNAP_LEN 1518

/* ethernet headers are always exactly 14 bytes */
#define SIZE_ETHERNET 14

/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN 6

/* USING TCPDUMP-like header structs */

/* Ethernet header */
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */
u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};

/* IP header */
struct sniff_ip {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip) (((ip)->ip_vhl) >> 4)

/* TCP header */
typedef u_int tcp_seq;

struct sniff_tcp {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
u_char th_offx2; /* data offset, rsvd */
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
};

/* pseudo header used for tcp checksuming
* a not so well documented fact ... in public
*/

struct pseudo_hdr {
u_int32_t src;
u_int32_t dst;
u_char mbz;
u_char proto;
u_int16_t len;
};

/* Global Variables */
int verbose_mode;
int stealth_mode; /* Syn Scanning */
int s_timeout; /* timeout seconds for Syn Scanning */
long int low_port = default_low;
long int high_port = default_high;
char *ipArg = NULL;
pcap_t *session;


/* Function Prototypes */

void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
void print_usage(const char *argv);
int check_Port(long *lport, long *hport, char *optar);
uint16_t checksum_comp(uint16_t *addr, int len);
pcap_t* EnginePreparing(char *vicIP, struct sockaddr_in **ipP, pcap_t *session);
struct hostent* host_resolve(void);
void Syn_Scanning(void);
void Connect_Scanning(void);
void sigfunc(int);

/* Function Prototypes end*/

/********************************MAIN PROGRAM********************************/



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

if ( argc == 1 ) {
print_usage( argv[0] );
exit(0);
}

int opt;
while ( (opt = getopt(argc , argv , "h:vp:S") ) != -1 ) {
switch (opt)
{
case 'h':
ipArg = optarg;
break;
case 'v':
verbose_mode = TRUE;
break;
case 'p':
check_Port (&low_port, &high_port, optarg);
break;
case 'S':
stealth_mode = TRUE;
break;
case '?':
fprintf (stderr, "option inconsistency : -%c \n"
"see usage(no arguments)\n", optopt);
exit(EXIT_FAILURE);
}
}

if (ipArg == NULL){
fprintf(stderr, "No host given-see usage(no arguments)\n" );
exit(EXIT_FAILURE);
}

if (!stealth_mode) {
Connect_Scanning();
}
else {
if (getuid() && geteuid()) {
fprintf(stderr, "Need to be root to initiate Syn Scanning\n");
exit(EXIT_FAILURE);
}
Syn_Scanning();
}
exit(EXIT_SUCCESS);

}


void print_usage(const char *argv) {
fprintf(stdout,
"Port Scanner by ithilgore\n"
"usage: %s -h Host [OPTIONS]\n"
"Host -> IP or Name\n"
"OPTIONS include:\n"
"-v : verbose mode\n"
"-p : port range (eg. -p23 , -p0-1024)\n"
"-S : stealth mode on ( syn scanning )\n"
"more options to be included\n\n"
, argv);
}




int check_Port (long *lport, long *hport, char *optar) {

char *s1 = optar ; //point to the char after 'p'
errno = 0;
*lport = strtol(s1, (char **)NULL, 10);

if (errno != 0) {
perror ("Port number problem \n");
exit(0);
}

if (!(s1 = index(s1, '-'))) { //if no port range specified (no other '-' found)
*hport = *lport;
return 0;
} else {
*hport = strtol(++s1, NULL, 10) ;
if (errno != 0) {
perror("Port number problem \n");
exit(0);
}
if (low_port > high_port) {
fprintf(stdout, "low_port is higher than high_port: swapping...\n");
*lport ^= *hport;
*hport ^= *lport;
*lport ^= *hport;
}
}

}


struct hostent* host_resolve(void) {
struct hostent *hostname;
extern char * ipArg;

if (!(hostname = gethostbyname(ipArg))) {
fprintf (stderr, "Host name resolution failed for %s \n"
"Try using the nslookup prog to find the IP address\n", ipArg);
exit(EXIT_FAILURE);
}

if (verbose_mode) {
fprintf(stdout, "Host Resolution results:\n"
"Name: %s\n"
"Aliases:", hostname->h_name);
char **alias = hostname->h_aliases;
while(*alias) {
fprintf(stdout, "%s ", *alias);
alias++;
}
char **addrs = hostname->h_addr_list;
fprintf(stdout, "\nIP address/es:\n");
while(*addrs) {
fprintf(stdout, " %s ", inet_ntoa(*(struct in_addr *)*addrs));
addrs++;
}
printf("\n");
}
return hostname;

}


void Connect_Scanning(void) {

int sockfd;
char temp_addr[7];

struct sockaddr_in sockaddr;
struct servent *serv;
struct hostent * hostname;
hostname = (struct hostent *)host_resolve();

char **addr = hostname->h_addr_list;

/* transfer of dotted-decimal IP of first IP from resolving */

strcpy (temp_addr, inet_ntoa(*(struct in_addr *)*addr));

fprintf(stdout, "Initiating Connect() Scan against %s [%ld ports] \n",
temp_addr,
(high_port-low_port+1));

int i = 0;
for (i = low_port; i <= high_port; i++) {

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Socket error");
exit(EXIT_FAILURE);
}
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(i);
inet_pton(AF_INET, temp_addr, &sockaddr.sin_addr);

if (!connect(sockfd, (struct sockaddr*)& sockaddr, sizeof(sockaddr))) {
serv = getservbyport(htons(i), "tcp");
fprintf(stdout, "TCP port %d open , possible service: %s\n", i, serv->s_name);
}

close(sockfd);
}
fprintf(stdout, "Connect Scanning completed\n");
}


void sigfunc(int signum) { /* signal handler */

pcap_breakloop(session);

}


void Syn_Scanning(void) {

s_timeout = DEFAULT_S_TIMEOUT; /* global var for timeout */
int sockfd;
int timeout = 0; /* check if timeout with return from dispatch */
char temp_addr[16];

struct sockaddr_in sin;
struct servent *serv;
struct hostent *hostname;
struct sockaddr_in *ipP; /* local ip storage */

hostname = (struct hostent *)host_resolve();

char **addr = hostname->h_addr_list;
strncpy(temp_addr, inet_ntoa(*(struct in_addr *)*addr), 16);

char datagram[4096]; // buffer for datagrams
struct sniff_ip *iph = (struct sniff_ip *)datagram;
/* tcp header begins right after the end of the ip header */
/* can it work in reverse ? Of course not */
struct sniff_tcp *tcph = (struct sniff_tcp *)(datagram + sizeof(struct sniff_ip));

struct sigaction act;
act.sa_handler = sigfunc;
sigemptyset(&act.sa_mask);
act.sa_flags = 0; /* read man of libpcap -> SA_RESTART MUST BE OFF */

/* Prepare the Sniffing Engine */
session = (pcap_t *)EnginePreparing(temp_addr, &ipP, session);


fprintf(stdout, "Initiating Syn Scanning against %s [%ld ports] \n", temp_addr, (high_port-low_port+1));
int i = 0;
for (i = low_port; i <= high_port; i++) {

if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {
perror("sock:");
exit(EXIT_FAILURE);
}

sin.sin_family = AF_INET;

inet_pton(AF_INET, temp_addr, &sin.sin_addr);

memset(datagram, 0, 4096); /* zero out the buffer */
iph->ip_vhl = 0x45; /* version=4,header_length=5 (no data) */
iph->ip_tos = 0; /* type of service -not needed */
iph->ip_len = sizeof (struct sniff_ip) + sizeof (struct sniff_tcp); /* no payload */
iph->ip_id = htonl(54321); /* simple id */
iph->ip_off = 0; /* no fragmentation */
iph->ip_ttl = 255; /* time to live - set max value */
iph->ip_p = IPPROTO_TCP; /* 6 as a value - see /etc/protocols/ */
iph->ip_src.s_addr = ipP->sin_addr.s_addr; /*local device IP */
iph->ip_dst.s_addr = sin.sin_addr.s_addr; /* dest addr */
iph->ip_sum = /* no need for ip sum actually */
checksum_comp( (unsigned short *)iph,
sizeof(struct sniff_ip));

tcph->th_sport = htons(1234); /* arbitrary port */
tcph->th_dport = htons(i); /* scanned dest port */
tcph->th_seq = random(); /* the random SYN sequence */
tcph->th_ack = 0; /* no ACK needed */
tcph->th_offx2 = 0x50; /* 50h (5 offset) ( 8 0s reserverd )*/
tcph->th_flags = TH_SYN; /* initial connection request */
tcph->th_win = (65535); /* maximum allowed window size */
tcph->th_sum = 0; /* will compute later */
tcph->th_urp = 0; /* no urgent pointer */

/* pseudo header for tcp checksum */
struct pseudo_hdr *phdr = (struct pseudo_hdr *) (datagram +
sizeof(struct sniff_ip) + sizeof(struct sniff_tcp));
phdr->src = iph->ip_src.s_addr;
phdr->dst = iph->ip_dst.s_addr;
phdr->mbz = 0;
phdr->proto = IPPROTO_TCP;
phdr->len = ntohs(0x14); /* in bytes the tcp segment length */
/*- WhyTF is it network byte saved by default ????*/


tcph->th_sum = htons(checksum_comp((unsigned short *)tcph,
sizeof(struct pseudo_hdr)+
sizeof(struct sniff_tcp)));

int one = 1;
const int *val = &one;
if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
fprintf(stderr, "Warning: Cannot set HDRINCL for port %d\n",i);


if (sendto(sockfd, datagram, iph->ip_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
fprintf(stderr, "Error sending datagram for port %d\n", i);
break;
}

sigaction (SIGALRM, &act, 0);
alarm(s_timeout);

// give port as argument to callback function
timeout = pcap_dispatch(session, -1, got_packet, (u_char *)i);
alarm(0); /* trigger off alarm for this loop */

if (verbose_mode && timeout == -2) {
fprintf(stdout, "timeout for port %d\n", i);
}

}

fprintf(stdout, "SYN Scanning completed\n");
}


uint16_t checksum_comp (uint16_t *addr, int len) { /* compute TCP header checksum */
/* with the usual algorithm a bit changed */
/* for byte ordering problem resolving */
/* see RFC 1071 for more info */
/* Compute Internet Checksum for "count" bytes
* beginning at location "addr".
*/
register long sum = 0;
int count = len;
uint16_t temp;

while (count > 1) {
temp = htons(*addr++); // in this line:added -> htons
sum += temp;
count -= 2;
}

/* Add left-over byte, if any */
if(count > 0)
sum += *(unsigned char *)addr;

/* Fold 32-bit sum to 16 bits */
while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);

uint16_t checksum = ~sum;
return checksum;
}



pcap_t* EnginePreparing (char * vicIP, struct sockaddr_in **ipP, pcap_t *session) {

char *dev;
char errbuf[PCAP_ERRBUF_SIZE];
bpf_u_int32 devip, netmask;
struct pcap_pkthdr header;
struct bpf_program filter; /* compiled filter */
char filter_exp[30] = "src host "; /* we filter the traffic to the victim */
pcap_if_t *alldev;

/* yes some numbers are HARDCODED as they should be */
/* guess why and then try exploiting it */

strncpy((char *)filter_exp+9, vicIP, 16);
fprintf(stdout, "filter exp: %s \n ", filter_exp);

if ((pcap_findalldevs(&alldev, errbuf)) == -1) {
fprintf (stderr, "%s\n", errbuf);
exit(EXIT_FAILURE);
}

struct pcap_addr *address = alldev->addresses;
address = address->next; /*first address is U(F)O*/
struct sockaddr_in * ip;

while (address) {
if (address->addr) {
ip = (struct sockaddr_in *) address->addr;
fprintf (stdout, "Local IP: %s \n", inet_ntoa(ip->sin_addr));
}
address = address->next;
}

*ipP = (struct sockaddr_in *)alldev->addresses->next->addr; /* local ip to be used in the raw datagram */
/* choose the first you find -there was some problem when choosing the last
* ip since the last found might be 0.0.0.0 and thus chaos would occur */
dev = alldev->name;

/*if ( (dev = pcap_lookupdev(errbuf)) == NULL) {
printf ( "%s\n" , errbuf ) ;
printf ( "Using default eth0 \n");
dev = "eth0" ;
}*/

if (verbose_mode) {
fprintf (stdout, "Using local IP: %s \n", inet_ntoa((*ipP)->sin_addr));
fprintf(stdout, "Using local Device: %s\n", dev);
}

if ((session = pcap_open_live (dev, BUFSIZE, 0, 0, errbuf)) == NULL) {
fprintf (stderr, "Could not open device %s: error: %s \n ", dev, errbuf);
exit (EXIT_FAILURE);
}


if (pcap_compile(session, &filter, filter_exp, 0, 0) == -1) {
fprintf (stderr, "Couldn't parse filter %s: %s \n ", filter_exp, pcap_geterr(session));
exit (EXIT_FAILURE);
}

if (pcap_setfilter(session, &filter) == -1) {
fprintf (stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(session));
exit (EXIT_FAILURE);
}

return session;
}




void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {

const struct sniff_tcp *tcp;
const struct sniff_ip *ip;
const struct sniff_ethernet *ether;
struct servent *serv;

int size_ip;
int size_tcp;

ether = (struct sniff_ethernet*) (packet);
ip = (struct sniff_ip *) (packet + SIZE_ETHERNET);

size_ip = IP_HL(ip)*4;
if (size_ip < 20) {
fprintf (stderr, "Invalid IP header length: %u bytes \n", size_ip);
return;
}

if (ip->ip_p != IPPROTO_TCP) {
fprintf (stderr, "Returned Packet is not TCP protocol \n");
return;
}

tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
size_tcp = TH_OFF(tcp)*4;
if (size_tcp < 20) {
fprintf (stderr, " * Invalid TCP header length: %u bytes\n", size_tcp);
return;
}


/* the actual SYN scanning (heh) : we examine if the SYN flag is on at the receiving packet(port open) */

if (((tcp->th_flags & 0x02) == TH_SYN) && (tcp->th_flags & 0x10) == TH_ACK) {
serv = getservbyport ( htons((int)args), "tcp" );
fprintf (stdout, "TCP port %d open , possible service: %s\n", args, serv->s_name);
// RST is sent by kernel automatically
}
else if ((tcp->th_flags & 0x04 ) == TH_RST && verbose_mode) {
//fprintf (stdout, "TCP port %d closed\n", args ); too much info on screen

}
else if (verbose_mode) {
//fprintf (stdout, "Port %d state unknown/filtered \n", args);
}
}

Sursa:

http://sock-raw.org/papers/syn_scanner

Link to comment
Share on other sites

Daca nu ma insel, nu se compileaza pe windows. Cel putin nu in forma respectiva.

Eu acum citeam despre sock_row din aceeasi sursa, si vad ca pune accent mult pe bsd si linux, deci pe windows probabil e nevoie de ceva modificari.

Eu insa spre exemplu am gasit spre exemplu(cu code blocks instalat) "#include <sys/types.h>" , asta fara sa caut prea mult.

Link to comment
Share on other sites

Trebuie folosit winsock2.h. La inceput trebuie apelata functia WSAStartUp, la sfarsit trebuie apelata WSACleanup... Problema poate fi aici:

sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)

Din cate stiu eu nu se pot crea RAW sockets pe Windows din motive de "securitate". In rest, pe langa cateva functii specifice Linux, se poate porta. Functiile pentru retea, desi Windows are versiuni specifice ale acestor functii, exista si in Windows Sockets API si nu ar trebui sa fie probleme.

Edit: Pe Windows 7 cred ca merge:

#include <stdio.h>
#include <winsock2.h>

int main()
{
WSADATA wsaData;
SOCKET hSock;

WSAStartup(MAKEWORD(2, 2), &wsaData);

// Cream socketul

hSock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);

printf("Handlerul socketului: %d\r\n", hSock);

closesocket(hSock);

WSACleanup();

return 0;
}

Mai pe seara daca nu am ce face, incerc sa il portez.

Edited by Nytro
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...