/*====================================================================== Simple Stealth Ver1.10 HalfOpen and Steath Port Scanner, and OS detection The Shadow Penguin Security (http://shadowpenguin.backsection.net) Written by UNYUN (unewn4th@usa.net) ====================================================================== */ #include #include #include #include #define SRC_PORT 10101 #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_ACK 0x10 struct iphdr{ u_int8_t ihl:4; u_int8_t version:4; u_int8_t tos; u_int16_t tot_len; u_int16_t id; u_int16_t frag_off; u_int8_t ttl; u_int8_t protocol; u_int16_t check; u_int32_t saddr; u_int32_t daddr; }; struct tcphdr{ u_int16_t th_sport; u_int16_t th_dport; u_int32_t th_seq; u_int32_t th_ack; u_int8_t th_x2:4; u_int8_t th_off:4; u_int8_t th_flags; u_int16_t th_win; u_int16_t th_sum; u_int16_t th_urp; }; struct pseudohdr { u_int32_t saddr; u_int32_t daddr; u_int8_t useless; u_int8_t protocol; u_int16_t tcplength; }; unsigned short in_cksum(u_short *addr, int len) { int sum=0; int nleft=len; u_short *w=addr; u_short answer=0; while (nleft > 1){ sum += *w++; nleft -= 2; } if (nleft == 1){ *(u_char *)(&answer) = *(u_char *)w ; sum += answer; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return(answer); } int send_packet(int socket, struct sockaddr_in *target_addr, struct sockaddr_in *your_addr, unsigned char session_flags,unsigned long sequence) { struct iphdr *ip_header; struct tcphdr *tcp_header; struct pseudohdr *pseudo_header; char send_buf[40]; int send_length; int sent_length; memset(send_buf,0,40); ip_header = (struct iphdr *)send_buf; tcp_header = (struct tcphdr *)(send_buf+sizeof(struct iphdr)); pseudo_header = (struct pseudohdr *)((char*)tcp_header-sizeof(struct pseudohdr)); pseudo_header->saddr = your_addr->sin_addr.s_addr; pseudo_header->daddr = target_addr->sin_addr.s_addr; pseudo_header->protocol = IPPROTO_TCP; pseudo_header->tcplength = htons(sizeof(struct tcphdr)); tcp_header->th_sport = your_addr->sin_port; tcp_header->th_dport = target_addr->sin_port; tcp_header->th_off = 5; tcp_header->th_flags = session_flags; tcp_header->th_seq = htonl(sequence); tcp_header->th_ack = htonl(0); tcp_header->th_win = htons(512); tcp_header->th_sum = in_cksum((u_short *)pseudo_header,sizeof(struct pseudohdr)+sizeof(struct tcphdr)); memset(send_buf,0,sizeof(struct iphdr)); ip_header->saddr = your_addr->sin_addr.s_addr; ip_header->daddr = target_addr->sin_addr.s_addr; ip_header->version = 4; ip_header->ihl = 5; ip_header->ttl = 255; ip_header->id = rand()%0xffff; ip_header->protocol = IPPROTO_TCP; ip_header->tot_len = htons(sizeof(struct iphdr)+sizeof(struct tcphdr)); ip_header->check = in_cksum((u_short *)ip_header,sizeof(struct iphdr)); send_length=sizeof(struct iphdr)+sizeof(struct tcphdr); sent_length=sendto(socket,send_buf,send_length,0, (struct sockaddr *)target_addr,sizeof(struct sockaddr)); if (send_length != sent_length) return -1; else return 0; } int main(int argc, char *argv[]) { struct iphdr *ip_header; struct tcphdr *tcp_header; struct sockaddr_in target_info; int target_info_len; fd_set read_fd; int scan_port; unsigned char scan_flag; char recvbuf[5000]; struct sockaddr_in target_addr; struct sockaddr_in your_addr; int raw_socket; int tcp_socket; int result=0; int i; static struct{ unsigned int WindowSize; char OSname[30]; }OSfeatures[]={ /*-----< Checked OS >---------------------------------------*/ {0x9823,"Solaris 2"}, /* Sol7(Intel),2.6,2.5,2.4(Sparc) */ {0x0010,"SunOS 4"}, /* SunOS4.1 (Sparc) */ {0x00f0,"IRIX"}, /* IRIX 5.3(Indy),6.3(O2) */ {0x00c0,"IRIX6.2"}, /* IRIX 6.2(IMPACT) */ {0xe07f,"Linux"}, /* TurboLinux3.0 (Intel) */ {0x0040,"FreeBSD"}, /* FreeBSD 2.2.7 or NetBSD 1.3 */ {0x0080,"Digital"}, /* Digital 4.0 or HP-UX B1.10.20 */ {0x8021,"Windows"}, /* Windows 95/98/NT4 */ {0x5B45,"MacOS"}, /* MacOS 7.5.5 , 8.5 */ /*-----< Thanks! nmap-os-fingerprints >---------------------*/ {0x253f,"AIX 3"}, /* AIX 3 */ {0x433e,"AIX 4"}, /* AIX 4.1 */ {0xafff,"AIX 4"}, /* AIX 4.1 */ {0x253f,"AIX 4"}, /* AIX 4.1 */ {0x1720,"BSD/OS"}, /* BSDI BSD/OS 2.1, 3.0 */ {0x0020,"HP-UX"}, /* HP-UX 9 */ {0x2e40,"FreeBSD"}, /* FreeBSD 2.2.1 - 3.0 */ {0x3d40,"FreeBSD"}, /* FreeBSD 2.2.1 - 3.0 */ {0x5c80,"Digital"}, /* Digital UNIX OSF1 V 4.0,4.0B,4.0D */ {0x0008,"OS/2"}, /* IBM OS/2 V.3 */ {0x2aef,"IRIX5,6"}, /* IRIX 5.3 */ {0x00c0,"IRIX6.4,6.5"},/* IRIX6.4 or 6.5 */ {0x003c,"Linux2028"}, /* Linux 2.0.28 */ {0x007c,"Linux2030"}, /* Linux 2.0.30 */ {0xe07f,"Linux2033-"},/* Linux 2.0.33-36 */ {0x537f,"Linux21xx"}, /* Linux 2.1.122 - 2.1.130 */ {0x870f,"NeXT"}, /* NeXT Mach */ {0xff1f,"NetWare"}, /* Novell Netware 3.12 - 5.00 */ {0x2e40,"OpenBSD"}, /* OpenBSD 2.1-2.3 or WinNT5 Beta */ {0x2332,"Solaris 2"}, /* Solaris2.3-2.5 */ {0x9722,"Sol26-27"}, /* Solaris2.6-2.7 */ {0x1720,"Windows"}, /* Windows 95/98/NT4 */ {0x0000,""}}; if (argc!=5){ printf("[usage] %s [YourIP] [TargetIP] [TargetPort] [mode]\n",argv[0]); printf(" (mode : 's'=SYN scan, 'f'=FIN scan, 'a'=ACK scan)\n"); return -1; } switch(argv[4][0]){ case 's' : scan_flag = TH_SYN; break; case 'f' : scan_flag = TH_FIN; break; case 'a' : scan_flag = TH_ACK; break; default : printf("Invalid mode.\n"); return -1; } scan_port = atoi(argv[3]); ip_header = (struct iphdr *)recvbuf; tcp_header = (struct tcphdr *)(recvbuf+sizeof(struct iphdr)); target_addr.sin_family = AF_INET; target_addr.sin_addr.s_addr = inet_addr(argv[2]); target_addr.sin_port = htons(scan_port); your_addr.sin_addr.s_addr = inet_addr(argv[1]); your_addr.sin_port = htons(SRC_PORT); if ((tcp_socket=socket(AF_INET,SOCK_RAW,IPPROTO_TCP))==-1){ printf("Can not create raw socket.\n"); return -1; } if ((raw_socket=socket(AF_INET,SOCK_RAW,IPPROTO_RAW))==-1){ printf("Can not create raw socket.\n"); return -1; } send_packet(raw_socket,&target_addr,&your_addr,scan_flag,100); FD_ZERO(&read_fd); FD_SET(tcp_socket,&read_fd); select(FD_SETSIZE,&read_fd,NULL,NULL,NULL); for (;;){ if (FD_ISSET(tcp_socket,&read_fd)){ target_info_len = sizeof(target_info); recvfrom(tcp_socket,recvbuf,5000,0, (struct sockaddr *)&target_info,&target_info_len); if (target_info.sin_addr.s_addr == target_addr.sin_addr.s_addr) if (ntohs(tcp_header->th_dport) == SRC_PORT && ntohs(tcp_header->th_sport) == scan_port){ printf("\nReply from %s\n",argv[2]); if (tcp_header->th_flags & TH_RST) printf("RST\n"); if (tcp_header->th_flags & TH_ACK) printf("ACK\n"); if (tcp_header->th_flags & TH_SYN){ printf("SYN\n"); if (scan_flag & TH_SYN){ result=1; for (i=0;;i++){ result=1; if (strlen(OSfeatures[i].OSname)==0) break; if (OSfeatures[i].WindowSize == tcp_header->th_win) printf("\nOS = %s\n",OSfeatures[i].OSname); } } } printf("\nTTL = %d\nTCP window size = %xH\n\n", ip_header->ttl,tcp_header->th_win); if (ip_header->ttl < 65 && tcp_header->th_win > 0 && scan_flag & TH_ACK) result=1; if (result==1) printf("Port %s : open\n\n",argv[3]); else printf("Port %s : close\n\n",argv[3]); if (!(tcp_header->th_flags & TH_RST)) send_packet(raw_socket,&target_addr,&your_addr, TH_RST, 101); break; } } } return(0); }