📄 winscan.c
字号:
#include <windows.h>#include <winsock2.h>#include <string.h>#include <signal.h>#include <sys/timeb.h>#include "hping2.h"#include "globals.h"#include "hstring.h"#define SEM_MODE 0777#define MAXPORT 65535extern struct timeb msec_delay;int opt_scan_probes = 8;float avrgms = 0;int avrgcount = 0;/* ---------------------------- data structures ----------------------------- *//* Note that while we don't use any kind of locking, to access * this fields is safe. the 'retry' field is only accessed by the * sendinf half, while the 'active' field is set by the receiver * and tested by the sender so atomicity isn't an issue. */struct portinfo { int active; int retry; time_t sentms; /* Upss... added this that requires locking, FIXME */};/* -------------------------------- misc ----------------------------------- */static char *tcp_strflags(char *s, unsigned int flags){ char *ftab = "FSRPAYXY", *p = s; int bit = 0; memset(s, '.', 8); s[8] = '\0'; while(bit < 8) { if (flags & (1 << bit)) p[bit] = ftab[bit]; bit++; } return s;}static char *port_to_name(int port){ struct servent *se; se = getservbyport(htons(port), NULL); if (!se) return ""; else return se->s_name;}/* ------------------------- shared memory related -------------------------- */static void do_exit(int sid){ exit(0);}/* ----------------------------- ports parsing ------------------------------ */static int parse_ports(struct portinfo *pi, char *ports){ char *args[32], *p = strdup(ports); int argc, j, i; if (!p) { fprintf(stderr, "Out of memory"); return 1; } argc = strftok(",", ports, args, 32); for (j = 0; j < argc; j++) { int neg = 0; char *a = args[j]; /* ports negation */ if (a[0] == '!') { neg = 1; a++; } /* range */ if (strchr(a, '-')) { char *range[2]; int low, high; strftok("-", a, range, 2); if (!strisnum(range[0]) || !strisnum(range[1])) goto err; /* syntax error */ low = strtol(range[0], NULL, 0); high = strtol(range[1], NULL, 0); if (low > high) { int t; t = high; high = low; low = t; } for (i = low; i <= high; i++) pi[i].active = !neg; /* all the ports */ } else if (!strcmp(a, "all")) { for (i = 0; i <= MAXPORT; i++) pi[i].active = !neg; } /* /etc/services ports *//* else if (!strcmp(a, "known")) { struct servent *se; setservent(0); while((se = getservent()) != NULL) { int port = ntohs(se->s_port); if (port < 0 || port > MAXPORT) continue; pi[port].active = !neg; } } */ /* a single port */ else { int port; if (!strisnum(a)) goto err; /* syntax error */ port = strtol(a, NULL, 0); if (port < 0 || port > MAXPORT) goto err; /* syntax error */ pi[port].active = !neg; } } free(p); return 0;err: free(p); return 1;}/* -------------------------------- output ---------------------------------- */DWORD WINAPI sender(LPVOID pi2){ int i, retry = 0; time_t start_time; struct portinfo *pi = (struct portinfo *)pi2; start_time = get_midnight_ut_ms(); while(1) { int active = 0; int recvd = 0; retry ++; for (i = 0; i < MAXPORT; i++) { if (pi[i].active && pi[i].retry) { active++; pi[i].retry--; sequence = -1; dst_port = i; pi[i].sentms = get_midnight_ut_ms(); send_tcp(); if (opt_waitinusec) { if (msec_delay.millitm) sleep(msec_delay.millitm); } else { sleep(sending_wait); } } } avrgms = (float)pi[MAXPORT+1].active; if (retry >= 3) { if (opt_debug) printf("AVRGMS %f\n", avrgms); if (avrgms) sleep((int) (avrgms)); else sleep(1); } for (i = 0; i < MAXPORT; i++) { if (!pi[i].active && pi[i].retry) recvd++; } /* More to scan? */ if (!active) { if (!recvd) sleep(1); fprintf(stderr, "All replies received. Done.\n"); printf("Not responding ports: "); for (i = 0; i < MAXPORT; i++) { if (pi[i].active && !pi[i].retry) { printf("(%d %.11s) ", i, port_to_name(i)); } } printf("\n"); exit(0); } /* Are we sending too fast? */ if ((!recvd && opt_waitinusec && msec_delay.millitm == 0 && (get_midnight_ut_ms() - start_time) > 500) || (opt_scan_probes-retry) <= 2) { if (opt_debug) printf("SLOWING DONW\n"); msec_delay.millitm *= 10; msec_delay.millitm++; } }}/* -------------------------------- input ---------------------------------- */static void receiver(struct portinfo *pi, HANDLE child){ struct myiphdr ip; char packet[IP_MAX_SIZE + linkhdr_size]; while(1) { int len, iplen; len = read_packet(packet, IP_MAX_SIZE + linkhdr_size); if (len == -1) { perror("read_packet"); continue; } /* minimal sanity checks */ if (len < linkhdr_size) continue; iplen = len - linkhdr_size; if (iplen < sizeof(struct myiphdr)) continue; /* copy the ip header in an access-safe place */ memcpy(&ip, packet+linkhdr_size, sizeof(ip)); /* check if the dest IP matches */ if (memcmp(&ip.daddr, &local.sin_addr, sizeof(ip.daddr))) continue; /* check if the source IP matches */ if (ip.protocol != IPPROTO_ICMP && memcmp(&ip.saddr, &remote.sin_addr, sizeof(ip.saddr))) continue; if (ip.protocol == IPPROTO_TCP) { struct mytcphdr tcp; int iphdrlen = ip.ihl << 2; char flags[16]; time_t rttms; int sport; /* more sanity checks */ if ((iplen - iphdrlen) < sizeof(tcp)) continue; /* time to copy the TCP header in a safe place */ memcpy(&tcp, packet+linkhdr_size+iphdrlen, sizeof(tcp)); /* check if the TCP dest port matches */#if 0 printf("SRC: %d DST: %d\n", ntohs(tcp.th_sport), ntohs(tcp.th_dport));#endif if (ntohs(tcp.th_dport) != initsport) continue; sport = htons(tcp.th_sport); if (pi[sport].active == 0) continue; /* Note that we don't care about a wrote RTT * result due to resend on the same port. */ rttms = get_midnight_ut_ms() - pi[sport].sentms; avrgcount++; avrgms = (avrgms*(avrgcount-1)/avrgcount)+(rttms/avrgcount); /* The avrg RTT is shared using shared memory, * no locking... */ pi[MAXPORT+1].active = (int) avrgms; tcp_strflags(flags, tcp.th_flags);#if 0 printf("%5d: %s %3d %5d %5d %10ld (%2d)\n", sport, flags, ip.ttl, ip.id, ntohs(tcp.th_win), (long) rttms, opt_scan_probes-(pi[sport].retry));#endif if ((tcp.th_flags & TH_SYN) || opt_verbose) { printf("%5d %-11.11s: %s %3d %5d %5d\n", sport, port_to_name(sport), flags, ip.ttl, ip.id, ntohs(tcp.th_win)); fflush(stdout); } pi[sport].active = 0; } else if (ip.protocol == IPPROTO_ICMP) { struct myicmphdr icmp; struct myiphdr subip; struct mytcphdr subtcp; int iphdrlen = ip.ihl << 2; unsigned char *p; int port; struct in_addr gwaddr; /* more sanity checks, we are only interested * in ICMP quoting the original packet. */ if ((iplen - iphdrlen) < sizeof(icmp)+sizeof(subip)+sizeof(subtcp)) continue; /* time to copy headers in a safe place */ p = packet+linkhdr_size+iphdrlen; memcpy(&icmp, p, sizeof(subtcp)); p += sizeof(icmp); memcpy(&subip, p, sizeof(ip)); p += sizeof(ip); memcpy(&subtcp, p, sizeof(subtcp)); /* Check if the ICMP quoted packet matches */ /* check if the source IP matches */ if (memcmp(&subip.saddr, &local.sin_addr, sizeof(subip.saddr))) continue; /* check if the destination IP matches */ if (memcmp(&subip.daddr, &remote.sin_addr, sizeof(subip.daddr))) continue; /* check if the quoted TCP packet port matches */ if (ntohs(subtcp.th_sport) != initsport) continue; port = htons(subtcp.th_dport); if (pi[port].active == 0) continue; pi[port].active = 0; memcpy(&gwaddr.s_addr, &ip.saddr, 4); printf("%5d: %3d %5d (ICMP %3d %3d from %s)\n", port, ip.ttl, ntohs(ip.id), icmp.type, icmp.code, inet_ntoa(gwaddr)); } if (WaitForSingleObject(child, 0) == WAIT_OBJECT_0) { do_exit(0); } }}void scanmain(void){ int ports = 0, i; HANDLE childpid; DWORD threadId; struct portinfo *pi; pi = malloc(sizeof(struct portinfo) * (MAXPORT + 2)); if (pi == NULL) { fprintf(stderr, "[malloc] failed: %d\n", GetLastError()); exit(1); } pi[MAXPORT+1].active = 0; /* hold the average RTT */ for (i = 0; i <= MAXPORT; i++) { pi[i].active = 0; pi[i].retry = opt_scan_probes; } if (parse_ports(pi, opt_scanports)) { fprintf(stderr, "Ports syntax error for scan mode\n"); free(pi); exit(1); } for (i = 0; i <= MAXPORT; i++) { if (!pi[i].active) pi[i].retry = 0; } for (i = 0; i <= MAXPORT; i++) ports += pi[i].active; fprintf(stderr, "%d ports to scan, use -V to see all the replies\n", ports); fprintf(stderr, "+----+-----------+---------+---+-----+-----+\n"); fprintf(stderr, "|port| serv name | flags |ttl| id | win |\n"); fprintf(stderr, "+----+-----------+---------+---+-----+-----+\n"); /* We are ready to fork, the input and output parts * are separated processes */ childpid = CreateThread(NULL, 0, sender, pi, 0, &threadId); if (childpid == NULL) { fprintf(stderr, "[CreateThread] failed: %d\n", GetLastError()); free(pi); exit(1); } /* The parent is the receiver, the child the sender. * it's almost the same but this way is simpler * to make it working in pipe with other commands like grep. */ signal(SIGINT, do_exit); signal(SIGTERM, do_exit); receiver(pi, childpid); /* UNREACHED */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -