diff --git a/nmap/includes/nmap.h b/nmap/includes/nmap.h index efd1bc14..00787595 100644 --- a/nmap/includes/nmap.h +++ b/nmap/includes/nmap.h @@ -6,7 +6,7 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/04/22 14:10:24 by jhalford #+# #+# */ -/* Updated: 2017/10/08 21:27:51 by jhalford ### ########.fr */ +/* Updated: 2017/10/09 16:14:18 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ @@ -32,33 +32,23 @@ # include "libdill.h" -# define SCAN_TCP (1 << 0) -# define SCAN_SYN (1 << 1) -# define SCAN_NULL (1 << 2) -# define SCAN_ACK (1 << 3) -# define SCAN_FIN (1 << 4) -# define SCAN_XMAS (1 << 5) -# define SCAN_UDP (1 << 6) -# define SCAN_MAX 7 - typedef struct s_data t_data; typedef struct s_host t_host; typedef struct s_tcp_packet t_tcp_packet; typedef enum e_port_status t_port_status; +typedef enum e_scan_type t_scan_type; -struct s_data +enum e_scan_type { - t_flag flag; - char **av_data; - t_list *host; - - int sock_tcp; - int threads; - int scan; + SCAN_TCP, + SCAN_SYN, + SCAN_ACK, + SCAN_FIN, + SCAN_XMAS, + SCAN_UDP, + SCAN_MAX }; -struct - enum e_port_status { OPEN, @@ -68,20 +58,36 @@ enum e_port_status OPEN_FILTERED, }; +struct s_data +{ + t_flag flag; + char **av_data; + + int sock[SCAN_MAX]; + struct sockaddr sock_a[SCAN_MAX]; + int threads; + + t_list *host; + BITFIELD(ports, USHRT_MAX + 1); + BITFIELD(scans, SCAN_MAX); +}; + struct s_host { - char *host; // user input host (ip or dn) - char *dn; // ai_canonname - char ip[INET6_ADDRSTRLEN]; // readable ip address (4 or 6) - struct s_target ports[USHRT_MAX + 1]; + char *host; // user input host (ip or dn) + char *dn; // ai_canonname + char ip[INET6_ADDRSTRLEN]; // humain readable ip address struct sockaddr *addr; size_t addrlen; + int chan[USHRT_MAX + 1][SCAN_MAX]; }; struct s_target { - int in_channel; - t_port_status results[SCAN_MAX]; + t_host *host; + uint16_t port; + t_scan_type scan; + #define capture_chan(t) (t.host.chan[t.port][t.scan]) }; struct s_tcp_packet diff --git a/nmap/libft/includes/math.h b/nmap/libft/includes/math.h index a42049e1..eeef374c 100644 --- a/nmap/libft/includes/math.h +++ b/nmap/libft/includes/math.h @@ -6,7 +6,7 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/03/20 15:41:59 by jhalford #+# #+# */ -/* Updated: 2017/10/08 12:57:23 by jhalford ### ########.fr */ +/* Updated: 2017/10/09 14:46:46 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ @@ -36,4 +36,8 @@ size_t ft_lllen_base(long long n, int base); int ft_addrcmp(void *a, void *b); void *id(void *data); +extern inline void bitfield_biton(t_bitblock field[], uint64_t bit) +extern inline void bitfield_bitoff(t_bitblock field[], uint64_t bit) +extern inline uint64_t bitfield_lsb(t_bitblock field[], uint64_t size) + #endif diff --git a/nmap/libft/srcs/math/bitfield.c b/nmap/libft/srcs/math/bitfield.c new file mode 100644 index 00000000..c62cf8f2 --- /dev/null +++ b/nmap/libft/srcs/math/bitfield.c @@ -0,0 +1,68 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* bitfield.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/09 14:44:16 by jhalford #+# #+# */ +/* Updated: 2017/10/09 15:57:25 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +/* +** ==== Wrapper around GCC builtins for ==== +** ==== arbitrarily large sized bitfields ==== +** +** todo +** - up and down iterator +** +*/ +typedef uint64_t t_bitblock; + +#define BITFIELD(var, size) t_bitblock var[size / sizeof(t_bitblock)] +#define BLOCKSIZE (8 * sizeof(t_bitblock)) + +/* +** Turn bit on +*/ +extern inline void bitfield_biton(t_bitblock field[], uint64_t bit) +{ + field[bit / BLOCKSIZE] |= (1 << bit % BLOCKSIZE); +} + +/* +** Turn bit off +*/ +extern inline void bitfield_bitoff(t_bitblock field[], uint64_t bit) +{ + field[bit / BLOCKSIZE] &= ~(1 << bit % BLOCKSIZE); +} + +/* +** Least Significant Bit (rightmost) +*/ +extern inline uint64_t bitfield_lsb(t_bitblock field[], uint64_t size) +{ + int block = -1; + + while (!field[++block]) + if ((block+1) * BLOCKSIZE > size) + return (-1); + return (block * BLOCKSIZE + __builtin_ctzll(field[block] ^ (~field[block] + 1)) - 1); +} + +/* +** Count the number of 1-bits in field +*/ +extern inline uint64_t bitfield_popcount(t_bitblock field[], uint64_t size) +{ + int block = -1; + int count = 0; + + while (++block * BLOCKSIZE < size) + count += __builtin_popcountll(field[block]); + return (count); +} diff --git a/nmap/libft/srcs/net/reserve_port.c b/nmap/libft/srcs/net/reserve_port.c index 24eb3cd9..cb664dea 100644 --- a/nmap/libft/srcs/net/reserve_port.c +++ b/nmap/libft/srcs/net/reserve_port.c @@ -6,7 +6,7 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/10/07 18:02:55 by jhalford #+# #+# */ -/* Updated: 2017/10/08 21:21:55 by jhalford ### ########.fr */ +/* Updated: 2017/10/09 10:48:18 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/nmap/srcs/listener.c b/nmap/srcs/listener.c index b71f7cbe..482f329e 100644 --- a/nmap/srcs/listener.c +++ b/nmap/srcs/listener.c @@ -10,6 +10,12 @@ static void packet_callback(u_char *arg, const struct pcap_pkthdr *pkthdr, const t_data *data = (t_data*)arg; ft_printf("received packet !!!\n"); hexdump(&packet, sizeof(packet)); + host = extract_host(pkt); + dport = extract_dport(pkt); + sport = extract_sport(pkt); + + chan = get_chan(host, dport, sport); + chsend(ch, &pkt, sizeof(pkt), -1); } coroutine void nmap_listener(t_data *data) diff --git a/nmap/srcs/main.c b/nmap/srcs/main.c index 2e9ec60d..38131124 100644 --- a/nmap/srcs/main.c +++ b/nmap/srcs/main.c @@ -6,7 +6,7 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/10/08 19:10:04 by jhalford #+# #+# */ -/* Updated: 2017/10/08 21:27:57 by jhalford ### ########.fr */ +/* Updated: 2017/10/09 15:58:02 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,7 +15,34 @@ #define NMAP_USAGE1 " [--ip HOST] [--file FILE]" #define NMAP_USAGE2 " [--ports PORTS] [--speedup [NUMBER]] [--scan [TYPE]] HOST" -int nmap_ports(t_data *data, int ch) +/* +** only IPv4 +** only default network if +** one per port per scan type +*/ +int fill_ports(t_data *data) +{ + int i; + + i = -1; + while (++i < SCAN_MAX) + { + if ((data->sock[i] = socket(AF_INET, SOCK_RAW, 0)) < 0) + { + perror("socket"); + exit(1); + } + /* if (setsockopt(data->sock[i], IPPROTO_IP, IP_HDRINCL, (int[]){1}, sizeof(val)) == -1) */ + /* return (1); */ + data->sock_a[i].sin_family = AF_INET; + data->sock_a[i].sin_addr.s_addr = INADDR_ANY; + if (reserve_port(data.sock[i], &data.sock_a[i])) + { + fprintf(stderr, "couldn't reserve port\n"); + exit(1); + } + } +} int main(int ac, char **av) { @@ -32,19 +59,8 @@ int main(int ac, char **av) printf("or nmap"NMAP_USAGE1 NMAP_USAGE2"\n"); exit(1); } - - // single tcp port - struct sockaddr_in sa; - sa.sin_family = AF_INET; - sa.sin_addr.s_addr = INADDR_ANY; - if (reserve_port(data.sock_tcp, &sa)) - { - fprintf(stderr, "couldn't reserve port\n"); - exit(1); - } - + fill_ports(&data); go(nmap_listener(&data)); int chan = nmap(&data); - nmap_collector(chan, &data); return (0); } diff --git a/nmap/srcs/nmap.c b/nmap/srcs/nmap.c index 4071982e..770d69e8 100644 --- a/nmap/srcs/nmap.c +++ b/nmap/srcs/nmap.c @@ -6,83 +6,111 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/10/08 19:10:07 by jhalford #+# #+# */ -/* Updated: 2017/10/08 21:27:50 by jhalford ### ########.fr */ +/* Updated: 2017/10/09 17:12:31 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ #include "nmap.h" -unsigned short cksum(void *b, int len) +t_scanner g_scanners[SCAN_MAX] { - unsigned short *buf = b; - unsigned int sum=0; - - for (sum = 0; len > 1; len -= 2) - sum += *((unsigned short*)buf++); - if (len == 1) - sum += *(unsigned char*)buf; - - sum = (sum >> 16) + (sum & 0xFFFF); - return (~(sum + (sum >> 16))); + scan_tcp, + NULL, + NULL, + NULL, + NULL, + NULL, + /* scan_syn, */ + /* scan_ack, */ + /* scan_fin, */ + /* scan_xmas, */ + /* scan_udp, */ } -coroutine void nmap_scan_node(t_host *host, struct iphdr *iph, int port) +coroutine void nmap_scan_port(int ch, t_data *data, t_target target) { - int channel; - t_tcp_packet packet; + int fan_in; + int fan_in_local; + int scan; - channel = host.channels[port]; - - packet.iph = *iph; - tcphdr_init(&packet.tcph); - packet.tcph.dest = htons(port); - packet.tcph.source = ; - /* packet.tcph.syn = 1; */ - packet.tcph.check = cksum(&packet, sizeof(t_tcp_packet)); - - if ((host.sock_tcp = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1) - perror("server: socket"); - - int val = 1; - if (setsockopt(host.sock_tcp, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val)) == -1) - return (1); - - - if (sendto(data->sock_tcp, &packet, sizeof(packet), 0, - host->addr, host->addrlen) < 0) + fan_in = chmake(sizeof(t_scan_result)); + while (scan = bitfield_lsb(data.scans, USHRT_MAX + 1)) { - perror("sendto"); - exit(1); + data.scans &= ~scan; + fan_in_local = hdup(fan_in); + scanner = g_scanners[scan]; + go(scanner(fan_in_local, sock, target)); } - /* chrecv(channel, &buf, sizeof()) */ - printf("packet sent\n"); - hexdump(&packet, sizeof(packet)); + + while (nport) + { + int res; + if ((res = choose(clauses, nport, -1)) < 0) + printf("choose failed\n"); + nhost--; + printf("finished scanning port %i\n", res); + } + + chsend(ch, &host, sizeof(host), -1); + hclose(ch); +} + +coroutine void nmap_scan_host(int ch, t_data *data, t_target target) +{ + int fan_in; + int fan_in_local; + t_target target; + int port; + + fan_in = chmake(sizeof(t_scan_result * SCAN_MAX)); + while (port = bitfield_lsb(data.ports, USHRT_MAX + 1)) + { + data.ports &= ~port; + fan_in_local = hdup(fan_in); + target.port = port; + go(nmap_scan_port(fan_in_local, data, port)); + } + + while (nport) + { + int res; + if ((res = choose(clauses, nport, -1)) < 0) + printf("choose failed\n"); + nhost--; + printf("finished scanning port #%i\n", res); + } + + chsend(ch, &host, sizeof(host), -1); + hclose(ch); } void nmap(t_data *data) { - t_list *list; - t_host *host; - struct iphdr iph; + t_list *list; + t_host *host; + int nhost; + int fan_in_local; + struct chclause clause[ft_lstsize(data->host)]; + int buf; - iphdr_init(&iph); - iph.protocol = IPPROTO_TCP; - iph.daddr = *(uint32_t*)&((struct sockaddr_in*)host->addr)->sin_addr; - iph.saddr = *(uint32_t*)&((struct sockaddr_in*)&data->source_addr)->sin_addr; - iph.tot_len = htons(sizeof(t_tcp_packet)); - int fan_in = chmake(sizeof()); + nhost = 0; for (t_list *list = data->host; list != NULL; list = list->next) { - t_host *host = list->content; - printf("scanning %s...\n", host->dn); - for (port = 1; port < USHRT_MAX; port++;) - { - if (data.ports[port]) - { - int fan_in_local = hdup(fan_in); - go(nmap_scan_node(data, iph, port, fan_in_local)); - } - } + host = list->content; + fan_in_local = hdup(fan_in); + target.host = host; + go(nmap_scan_host(fan_in_local, data, target)); + nhost++; } + + while (nhost) + { + int res; + if ((res = choose(clauses, nhost, -1)) < 0) + printf("choose failed\n"); + nhost--; + printf("host %s has finished scanning\n", host->dn); + } + printf("nmap has finished\n"); return (fan_in); } diff --git a/nmap/srcs/parser.c b/nmap/srcs/parser.c index 4e4cc31b..efb0d07d 100644 --- a/nmap/srcs/parser.c +++ b/nmap/srcs/parser.c @@ -6,7 +6,7 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/10/08 19:10:05 by jhalford #+# #+# */ -/* Updated: 2017/10/08 21:05:14 by jhalford ### ########.fr */ +/* Updated: 2017/10/09 14:51:21 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ @@ -82,19 +82,17 @@ static int nmap_get_scan(char *opt_arg, t_data *data) while (*opt_arg) { if (*opt_arg == 'T') - data->scan |= SCAN_TCP; + bitfield_biton(data->scans, SCAN_TCP); else if (*opt_arg == 'S') - data->scan |= SCAN_SYN; - else if (*opt_arg == 'N') - data->scan |= SCAN_NULL; + bitfield_biton(data->scans, SCAN_SYN); else if (*opt_arg == 'A') - data->scan |= SCAN_ACK; + bitfield_biton(data->scans, SCAN_ACK); else if (*opt_arg == 'F') - data->scan |= SCAN_FIN; + bitfield_biton(data->scans, SCAN_FIN); else if (*opt_arg == 'X') - data->scan |= SCAN_XMAS; + bitfield_biton(data->scans, SCAN_XMAS); else if (*opt_arg == 'U') - data->scan |= SCAN_UDP; + bitfield_biton(data->scans, SCAN_UDP); else return (1); opt_arg++; @@ -107,7 +105,7 @@ int nmap_parse(int ac, char **av, t_data *data) struct ifaddrs *ifaddrs, *ifa_first; (void)ac; data->host = NULL; - bzero(data->ports, USHRT_MAX + 1); + bzero(data->ports, sizeof(data->ports)); data->threads = 0; data->scan = 0; @@ -132,18 +130,6 @@ int nmap_parse(int ac, char **av, t_data *data) exit(1); } freeifaddrs(ifa_first); - - for (t_list *list = data->host; list != NULL; list = list->next) - { - t_host *host = list->content; - printf("scanning %s...\n", host->dn); - for (port = 1; port < USHRT_MAX; port++;) - { - if (data.ports[port]) - host->channels[port] = chmake(sizeof(t_tcp_packet)); - } - } - + bitfield_biton(data->ports, 80); return (0); } - diff --git a/nmap/srcs/scanners.c b/nmap/srcs/scanners.c new file mode 100644 index 00000000..db99c0fc --- /dev/null +++ b/nmap/srcs/scanners.c @@ -0,0 +1,47 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* scanners.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/09 15:28:42 by jhalford #+# #+# */ +/* Updated: 2017/10/09 16:14:35 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "nmap.h" + +coroutine void nmap_scan_tcp(int ch, t_data *data, t_target target) +{ + int listen; + t_scan_result res; + t_tcp_packet pkt; + + listen = capture_chan(target); + + iphdr_init(&pkt.iph); + + pkt.iph.protocol = IPPROTO_TCP; + pkt.iph.saddr = *(uint32_t*)&((struct sockaddr_in*)&data->out_sa[target.scan])->sin_addr; + pkt.iph.daddr = *(uint32_t*)&((struct sockaddr_in*)target.host->addr)->sin_addr; + pkt.iph.tot_len = htons(sizeof(t_tcp_packet)); + + tcphdr_init(&pkt.tcph); + packet.tcph.dest = htons(target.port); + packet.tcph.check = cksum(&packet, sizeof(t_tcp_packet)); + + if (sendto(sock, &packet, sizeof(packet), 0, + host->addr, host->addrlen) < 0) + { + perror("sendto"); + exit(1); + } + /* chrecv(channel, &buf, sizeof()) */ + hexdump(&packet, sizeof(packet)); + + + chsend(ch, res, sizeof(res), -1); + printf("result sent\n"); + hclose(ch); +}