diff --git a/nmap/Makefile b/nmap/Makefile index ee1854d1..57b7bd69 100644 --- a/nmap/Makefile +++ b/nmap/Makefile @@ -6,7 +6,7 @@ # By: wescande +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2016/08/29 21:32:58 by wescande #+# #+# # -# Updated: 2017/10/08 19:09:21 by jhalford ### ########.fr # +# Updated: 2017/10/24 14:33:26 by jhalford ### ########.fr # # # # **************************************************************************** # @@ -31,10 +31,12 @@ INC_DIR = includes/ OBJ_DIR = objs/ SRC_BASE = \ -main.c\ -nmap.c\ -parser.c\ +format.c\ +ip.c\ listener.c\ +main.c\ +parser.c\ +scanners.c SRCS = $(addprefix $(SRC_DIR), $(SRC_BASE)) OBJS = $(addprefix $(OBJ_DIR), $(SRC_BASE:.c=.o)) @@ -52,7 +54,7 @@ $(NAME): $(LIBFT_LIB) $(OBJ_DIR) $(OBJS) $(CLIENT_OBJ) -I $(LIBFT_INC) \ -L $(HOME)/.bin/lib \ $(LIBFT_LIB) $(CLIENT_OBJ) $(FLAGS) \ - -lm -lpcap -lpthread /usr/local/lib/libdill.a + -lm -lpcap -lpthread $(HOME)/.bin/lib/libmill.a @printf "\r\033[38;5;117m✓ MAKE $@ \033[0m\033[K\n" $(LIBFT_LIB): diff --git a/nmap/includes/nmap.h b/nmap/includes/nmap.h index 00787595..3a0c9449 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/09 16:14:18 by jhalford ### ########.fr */ +/* Updated: 2017/10/24 21:29:35 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,6 +23,7 @@ # include # include # include +# include # include # include # include @@ -30,11 +31,13 @@ # include # include -# include "libdill.h" +# include "libmill.h" typedef struct s_data t_data; typedef struct s_host t_host; typedef struct s_tcp_packet t_tcp_packet; +typedef struct s_job t_job; +typedef struct s_result t_result; typedef enum e_port_status t_port_status; typedef enum e_scan_type t_scan_type; @@ -62,14 +65,6 @@ 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 @@ -79,27 +74,35 @@ struct s_host char ip[INET6_ADDRSTRLEN]; // humain readable ip address struct sockaddr *addr; size_t addrlen; - int chan[USHRT_MAX + 1][SCAN_MAX]; }; -struct s_target +struct s_job { - t_host *host; - uint16_t port; - t_scan_type scan; - #define capture_chan(t) (t.host.chan[t.port][t.scan]) + ipaddr dest; + void (*scan)(); }; -struct s_tcp_packet +struct s_result { - struct iphdr iph; - struct tcphdr tcph; -}__attribute__((packed)); + ipaddr dest; + char scan[4]; + t_port_status status; +}; -static t_cliopts g_opts[]; -int nmap_parse(int ac, char **av, t_data *data); +extern t_cliopts g_opts[]; +extern int g_njobs; +chan nmap_parse(int ac, char **av); +void nmap_format(chan results); -void nmap(t_data *data); -void nmap_listener(void *arg); +coroutine void nmap_scan_tcp(chan results, t_job job); +chan nmap_listener(ipaddr dst, ipaddr src); + +/* +** IP helpers +*/ +uint16_t ipport(ipaddr ip); +uint16_t ipmode(ipaddr ip); +uint16_t ipfamily(ipaddr ip); +ipaddr iplocal_randport(const char *name, int mode, int sock); #endif diff --git a/nmap/libft/Makefile b/nmap/libft/Makefile index 8086a31a..50818e25 100644 --- a/nmap/libft/Makefile +++ b/nmap/libft/Makefile @@ -108,6 +108,7 @@ lst/lst_insert_sort.c\ lst/pop.c\ lst/push.c\ lst/top.c\ +math/bitfield.c\ math/ft_addrcmp.c\ math/ft_ilen.c\ math/ft_ilen_base.c\ @@ -138,6 +139,7 @@ net/host.c\ net/ip.c\ net/net_get.c\ net/net_send.c\ +net/prettypacket.c\ net/reserve_port.c\ net/tcp.c\ path/ft_path_notdir.c\ @@ -204,6 +206,7 @@ str/ft_strstr.c\ str/ft_strsub.c\ str/ft_strtok.c\ str/ft_strtrim.c\ +str/hexstring.c\ sys/open_new.c\ time/epoch.c diff --git a/nmap/libft/includes/hexstring.h b/nmap/libft/includes/hexstring.h new file mode 100644 index 00000000..00f22960 --- /dev/null +++ b/nmap/libft/includes/hexstring.h @@ -0,0 +1,36 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* hexstring.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/24 21:37:32 by jhalford #+# #+# */ +/* Updated: 2017/10/24 21:46:12 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +/** + * HEXSTRING HEADER + * + * Functions used to convert, and manipulate hexstrings. + */ + +#ifndef HEXSTRING_H_ +# define HEXSTRING_H_ + +# include "libft.h" + +# include +# include +# include +# include +# include + + +char *raw_to_hexstr(const char *raw, int size); +char *hexstr_to_raw(const char *hexstr, int *size); +void hex_to_str(uint8_t hex, char *str); +uint8_t str_to_hex(char *str); + +#endif /* HEXSTRING_H_ */ diff --git a/nmap/libft/includes/libft.h b/nmap/libft/includes/libft.h index c8d54967..cb09b1ae 100644 --- a/nmap/libft/includes/libft.h +++ b/nmap/libft/includes/libft.h @@ -6,7 +6,7 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2016/11/07 13:49:04 by jhalford #+# #+# */ -/* Updated: 2017/10/08 15:59:49 by jhalford ### ########.fr */ +/* Updated: 2017/10/24 21:38:26 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ @@ -37,8 +37,9 @@ # include "math.h" # include "mytime.h" # include "get_next_line.h" -# include "net.h" # include "sys.h" +# include "net.h" +# include "prettypacket.h" struct s_stos { diff --git a/nmap/libft/includes/math.h b/nmap/libft/includes/math.h index eeef374c..50907a61 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/09 14:46:46 by jhalford ### ########.fr */ +/* Updated: 2017/10/24 21:04:50 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ @@ -36,8 +36,14 @@ 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) +typedef uint64_t t_bitblock; +#define BITFIELD(var, size) t_bitblock var[size / sizeof(t_bitblock) + 1]\ + = {[0] = size} +#define BLOCKSIZE (8 * sizeof(t_bitblock)) + + +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[]); #endif diff --git a/nmap/libft/includes/net.h b/nmap/libft/includes/net.h index b568ceba..f5a2d81a 100644 --- a/nmap/libft/includes/net.h +++ b/nmap/libft/includes/net.h @@ -6,7 +6,7 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/10/07 18:06:12 by jhalford #+# #+# */ -/* Updated: 2017/10/08 16:52:48 by jhalford ### ########.fr */ +/* Updated: 2017/10/24 20:55:02 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ @@ -32,7 +32,7 @@ ** utilities */ -int reserve_port(int *port); +int reserve_port(int s, struct sockaddr *sa); unsigned short cksum(void *b, int len); int host_format(struct sockaddr *addr); @@ -64,4 +64,10 @@ void ip_load_icmp(struct icmp *icmp, void *buf); */ void tcp_hdrinit(struct tcphdr *header); + +/* +** prettypacket +*/ +int prettypacket(void *pkt, size_t size); + #endif diff --git a/nmap/libft/includes/prettypacket.h b/nmap/libft/includes/prettypacket.h new file mode 100644 index 00000000..585a3f61 --- /dev/null +++ b/nmap/libft/includes/prettypacket.h @@ -0,0 +1,98 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* prettypacket.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/24 21:38:38 by jhalford #+# #+# */ +/* Updated: 2017/10/24 21:41:44 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef __PRETTYPACKET_H__ +#define __PRETTYPACKET_H__ + +#include +#include +#include +#include "hexstring.h" + +/** + * Enable disable colored output (enabled by default) + */ +static int colored_output = 1; + +/** + * List of available colors + */ +static const char *colors[] = { + /// Black + "\\e[0;30m", + /// Red + "\\e[0;31m", + /// Green + "\\e[0;32m", + /// Yellow + "\\e[0;33m", + /// Blue + "\\e[0;34m", + /// Purple + "\\e[0;35m", + /// Cyan + "\\e[0;36m", + /// White + "\\e[0;37m", +}; + +/** + * Reset color + */ +static const char *color_reset = "\\e[0m"; + +/** + * Default terminal rows + */ +static const int rows = 24; + +/** + * Default terminal columns + */ +static const int cols = 80; + +/** + * Example ARP packet + */ +static const char arp_packet[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xAA\x00\x04\x00\x0A\x04\x08\x06\x00\x01\x08\x00\x06\x04\x00\x01\xAA\x00\x04\x00\x0A\x04\xC0\xA8\x01\x09\x00\x00\x00\x00\x00\x00\xC0\xA8\x01\x04"; + +/** + * Example TCP packet + */ +static const char tcp_packet[] = "\x1C\xAF\xF7\x6B\x0E\x4D\xAA\x00\x04\x00\x0A\x04\x08\x00\x45\x00\x00\x34\x5A\xAE\x40\x00\x40\x06\x5E\x67\xC0\xA8\x01\x09\x58\xBF\x67\x3E\x9B\x44\x00\x50\x8E\xB5\xC6\xAC\x15\x93\x47\x9E\x80\x10\x00\x58\xA5\xA0\x00\x00\x01\x01\x08\x0A\x00\x09\xC3\xB2\x42\x5B\xFA\xD6"; + +/** + * Example ICMP packet + */ +static const char icmp_packet[] = "\x1C\xAF\xF7\x6B\x0E\x4D\xAA\x00\x04\x00\x0A\x04\x08\x00\x45\x00\x00\x54\x00\x00\x40\x00\x40\x01\x54\x4E\xC0\xA8\x01\x09\xC0\xA8\x64\x01\x08\x00\x34\x98\xD7\x10\x00\x01\x5B\x68\x98\x4C\x00\x00\x00\x00\x2D\xCE\x0C\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37"; + +/** + * Example UDP packet + */ +static const char udp_packet[] = "\x1C\xAF\xF7\x6B\x0E\x4D\xAA\x00\x04\x00\x0A\x04\x08\x00\x45\x00\x00\x3C\x9B\x23\x00\x00\x40\x11\x70\xBC\xC0\xA8\x01\x09\xD0\x43\xDC\xDC\x91\x02\x00\x35\x00\x28\x6F\x0B\xAE\x9C\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\x77\x77\x77\x06\x67\x6F\x6F\x67\x6C\x65\x03\x63\x6F\x6D\x00\x00\x01\x00\x01"; + +/** + * Example IGMP packet + */ +static const char igmp_packet[] = "\x1C\xAF\xF7\x6B\x0E\x4D\xAA\x00\x04\x00\x0A\x04\x08\x00\x45\x00\x00\x1C\x00\x00\x40\x00\x40\x02\x54\x4E\xC0\xA8\x01\x09\xC0\xA8\x64\x01\x11\xFF\x0D\xFF\xE0\x00\x00\x01"; + +/** + * Example Spanning Tree Protocol (STP) packet + */ +static const char stp_packet[]="\x01\x80\xc2\x00\x00\x00\x00\x1c\x0e\x87\x85\x04\x00\x26\x42\x42\x03\x00\x00\x00\x00\x00\x80\x64\x00\x1c\x0e\x87\x78\x00\x00\x00\x00\x04\x80\x64\x00\x1c\x0e\x87\x85\x00\x80\x04\x01\x00\x14\x00\x02\x00\x0f\x00"; + +// functions that need prototypes +void layer_2_dispatcher(const char *, int, uint64_t); +void layer_3_dispatcher(const char *, int, uint64_t); +void layer_4_dispatcher(const char *, int, uint64_t); + +#endif /* __PRETTYPACKET_H__ */ diff --git a/nmap/libft/srcs/math/bitfield.c b/nmap/libft/srcs/math/bitfield.c index c62cf8f2..af9290ae 100644 --- a/nmap/libft/srcs/math/bitfield.c +++ b/nmap/libft/srcs/math/bitfield.c @@ -6,10 +6,11 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/10/09 14:44:16 by jhalford #+# #+# */ -/* Updated: 2017/10/09 15:57:25 by jhalford ### ########.fr */ +/* Updated: 2017/10/24 21:04:39 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ +#include "libft.h" #include /* @@ -20,17 +21,13 @@ ** - 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); + field[bit / BLOCKSIZE + 1] |= (1 << (bit % BLOCKSIZE)); } /* @@ -38,19 +35,21 @@ extern inline void bitfield_biton(t_bitblock field[], uint64_t bit) */ extern inline void bitfield_bitoff(t_bitblock field[], uint64_t bit) { - field[bit / BLOCKSIZE] &= ~(1 << bit % BLOCKSIZE); + field[bit / BLOCKSIZE + 1] &= ~(1 << bit % BLOCKSIZE); } /* ** Least Significant Bit (rightmost) */ -extern inline uint64_t bitfield_lsb(t_bitblock field[], uint64_t size) +extern inline uint64_t bitfield_lsb(t_bitblock field[]) { - int block = -1; + int block; + uint64_t size; + block = 0; + size = field[0]; while (!field[++block]) - if ((block+1) * BLOCKSIZE > size) - return (-1); + if ((block+1) * BLOCKSIZE > size) return (-1); return (block * BLOCKSIZE + __builtin_ctzll(field[block] ^ (~field[block] + 1)) - 1); } diff --git a/nmap/libft/srcs/net/ip.c b/nmap/libft/srcs/net/ip.c index 85bd9213..e3584952 100644 --- a/nmap/libft/srcs/net/ip.c +++ b/nmap/libft/srcs/net/ip.c @@ -6,7 +6,7 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/10/07 18:02:39 by jhalford #+# #+# */ -/* Updated: 2017/10/08 15:52:39 by jhalford ### ########.fr */ +/* Updated: 2017/10/24 12:44:35 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/nmap/libft/srcs/net/prettypacket.c b/nmap/libft/srcs/net/prettypacket.c new file mode 100644 index 00000000..1dcd5e47 --- /dev/null +++ b/nmap/libft/srcs/net/prettypacket.c @@ -0,0 +1,666 @@ +/* + * prettypacket.c + * + * Created on: 03/dec/2012 + * Author: Acri Emanuele + * + * Disassemble network packet and print their fields. + * Uses the stdin to receive raw packet data. Prints on stdout. + */ + +#include +#include +#include + +#include "prettypacket.h" + +#define VERSION "1.5" + +#define BUFFER_SIZE 8192 +/** + * Byte multiplier: a printed byte uses 3 characters + */ +#define BYTE_MULT 3 + +/** + * Packet type arguments + */ +enum packet_type { + no_type = 0, + tcp, + udp, + icmp, + igmp, + arp, + stp +}; + +/* +** Packets disassembling loop +** layer 2: isl, llc1, llc2, ethenet or payload +** layer 3: IPv4, IPv6, arp or payload +** layer 4: icmp, igmp, tcp, udp or payload +*/ +int prettypacket(void *pkt, size_t size) +{ + + layer_2_dispatcher(pkt, size, 0); + puts("\n ----------- "); + fflush(stdout); + return 0; +} + +/** + * Return the successive color iterating on colors + * + * @return pointer to the next color string + */ +const char *next_color() { + static int total_colors = sizeof(colors)/sizeof(char *); + static int index = -1; + + return colors[ (++index) % total_colors ]; +} + +/** + * Extract protocol number (8bit version) + * + * @param packet_buffer raw packet captured from the network + * @param counter protocol number offset + * @return protocol number in host format + */ +static inline uint8_t protocol_8bit_extract(const char *packet_buffer, int counter) { + return *(packet_buffer + counter); +} + +/** + * Extract protocol number (16bit version) + * + * @param packet_buffer raw packet captured from the network + * @param counter protocol number offset + * @return protocol number in host format + */ +static inline uint16_t protocol_16bit_extract(const char *packet_buffer, int counter) { + return ntohs(*((uint16_t *)(packet_buffer + counter))); +} + +/** + * Extract protocol type from ethernet Destination MAC Address (48bit) + * @param packet_buffer raw packet captured from the network + * @param counter protocol number offset + * @return protocol number in host format + */ +static inline uint64_t protocol_48bit_extract(const char *packet_buffer, int counter) { + uint64_t value = 0; + + int i; + for(i=0; i < 6; i++) { + uint8_t byte = *((uint8_t *)(packet_buffer + counter + i)); + + value = byte + (value * 256); + } + + return value; +} + +/** + * Diplay a single field of an header + * + * @param packet_buffer raw packet captured from the network, starting at the part to process + * @param field_size size in bytes of the field to print + * @param counter read bytes counter + * @param field_text description of the field + */ +static inline void field_print (const char *packet_buffer, int field_size, + int *counter, const char *field_text) { + + char *tmp_hexstr = raw_to_hexstr(packet_buffer + *counter, field_size); + *counter += field_size; + + printf(" %-24s %s\n", tmp_hexstr, field_text); + + free(tmp_hexstr); +} + +/** + * Print the payload part of the packet + * + * @param packet_buffer raw packet captured from the network, starting at the part to process + * @param size packet_buffer size + */ +void payload_print (const char *packet_buffer, int size) { + + if (size < 1) { + return; + } + + puts("\nPayload or Trailer:"); + + int bytes_per_row = cols / BYTE_MULT; + + int i, j=0; + + // new line + while (j < size) { + + // bytes in the line + for (i = 0; (i < bytes_per_row) && (j < size); i++, j++) { // columns + char str[BYTE_MULT]; + + hex_to_str(packet_buffer[j], str); + + printf(" %s", str); + } + + puts(""); + } + +} + +/** + * Print the TCP header of the packet + * + * @param packet_buffer raw packet captured from the network, starting at the part to process + * @param size packet_buffer size + */ +void tcp_print (const char *packet_buffer, int size) { + int counter = 0; + + puts("\nTCP Header:"); + + if (size < 8) { + puts (" invalid header size"); + return; + } + + // print header fields + field_print(packet_buffer, 2, &counter, "Source port"); + field_print(packet_buffer, 2, &counter, "Destination port"); + field_print(packet_buffer, 4, &counter, "Sequence number"); + field_print(packet_buffer, 4, &counter, "Acknowledgement number"); + field_print(packet_buffer, 1, &counter, "Header length"); + field_print(packet_buffer, 1, &counter, "Flags"); + field_print(packet_buffer, 2, &counter, "Window"); + field_print(packet_buffer, 2, &counter, "Checksum"); + field_print(packet_buffer, 2, &counter, "Urgent pointer"); + + // print remaining payload + payload_print(packet_buffer + counter, size - counter); +} + +/** + * Print the UDP header of the packet + * + * @param packet_buffer raw packet captured from the network, starting at the part to process + * @param size packet_buffer size + */ +void udp_print (const char *packet_buffer, int size) { + int counter = 0; + + puts("\nUDP Header:"); + + if (size < 8) { + puts (" invalid header size"); + return; + } + + // print header fields + field_print(packet_buffer, 2, &counter, "Source port"); + field_print(packet_buffer, 2, &counter, "Destination port"); + field_print(packet_buffer, 2, &counter, "Length"); + field_print(packet_buffer, 2, &counter, "Checksum"); + + // print remaining payload + payload_print(packet_buffer + counter, size - counter); +} + +/** + * Print the ICMP header of the packet + * + * @param packet_buffer raw packet captured from the network, starting at the part to process + * @param size packet_buffer size + */ +void icmp_print (const char *packet_buffer, int size) { + int counter = 0; + + puts("\nICMP Header:"); + + if (size < 8) { + puts (" invalid header size"); + return; + } + + // print header fields + field_print(packet_buffer, 1, &counter, "Type"); + field_print(packet_buffer, 1, &counter, "Code"); + field_print(packet_buffer, 2, &counter, "Checksum"); + field_print(packet_buffer, 2, &counter, "ID"); + field_print(packet_buffer, 2, &counter, "Sequence number"); + + // print remaining payload + payload_print(packet_buffer + counter, size - counter); +} + +/** + * Print the IGMP header of the packet + * + * @param packet_buffer raw packet captured from the network, starting at the part to process + * @param size packet_buffer size + */ +void igmp_print (const char *packet_buffer, int size) { + int counter = 0; + + puts("\nIGMP Header:"); + + if (size < 8) { + puts (" invalid header size"); + return; + } + + // print header fields + field_print(packet_buffer, 1, &counter, "Type"); + field_print(packet_buffer, 1, &counter, "Max response time"); + field_print(packet_buffer, 2, &counter, "Checksum"); + field_print(packet_buffer, 4, &counter, "Group address"); + + // print remaining payload + payload_print(packet_buffer + counter, size - counter); +} + +/** + * Print the IP header of the packet + * + * @param packet_buffer raw packet captured from the network, starting at the part to process + * @param size packet_buffer size + */ +void ip_print (const char *packet_buffer, int size) { + int counter = 0; + + puts("\nIP Header:"); + + if (size < 20) { + puts (" invalid header size"); + return; + } + + // print header fields + field_print(packet_buffer, 1, &counter, "Version / Header length"); + field_print(packet_buffer, 1, &counter, "ToS / DFS"); + field_print(packet_buffer, 2, &counter, "Total length"); + field_print(packet_buffer, 2, &counter, "ID"); + field_print(packet_buffer, 2, &counter, "Flags / Fragment offset"); + field_print(packet_buffer, 1, &counter, "TTL"); + + int next_protocol = protocol_8bit_extract(packet_buffer, counter); + field_print(packet_buffer, 1, &counter, "Protocol"); + + field_print(packet_buffer, 2, &counter, "Checksum"); + field_print(packet_buffer, 4, &counter, "Source address"); + field_print(packet_buffer, 4, &counter, "Destination address"); + + // go up to the next layer + layer_4_dispatcher(packet_buffer + counter, size - counter, next_protocol); +} + +/** + * Print the ARP header of the packet + * + * @param packet_buffer raw packet captured from the network, starting at the part to process + * @param size packet_buffer size + */ +void arp_print (const char *packet_buffer, int size) { + int counter = 0; + + puts("\nARP Header:"); + + if (size < 28) { + puts (" invalid header size"); + return; + } + + // print header fields + field_print(packet_buffer, 2, &counter, "Hardware type"); + field_print(packet_buffer, 2, &counter, "Protocol type"); + + int hs = *(packet_buffer + counter); + field_print(packet_buffer, 1, &counter, "Hardware size"); + + int ps = *(packet_buffer + counter); + field_print(packet_buffer, 1, &counter, "Protocol size"); + + field_print(packet_buffer, 2, &counter, "Opcode"); + + field_print(packet_buffer, hs, &counter, "Sender hardware address"); + field_print(packet_buffer, ps, &counter, "Sender protocol address"); + field_print(packet_buffer, hs, &counter, "Target hardware address"); + field_print(packet_buffer, ps, &counter, "Target protocol address"); + + // print remaining payload + payload_print(packet_buffer + counter, size - counter); +} + +/** + * Print the ETHERNET header of the packet + * + * @param packet_buffer raw packet captured from the network, starting at the part to process + * @param size packet_buffer size + */ +void ethernet_print (const char *packet_buffer, int size) { + int counter = 0; + + puts("\nEthernet Header:"); + + if (size < 14) { + puts (" invalid header size"); + return; + } + + // print header fields + uint64_t dst_mac = protocol_48bit_extract(packet_buffer, counter); + field_print(packet_buffer, 6, &counter, "Destination hardware address"); + field_print(packet_buffer, 6, &counter, "Source hardware address"); + + int next_protocol = protocol_16bit_extract(packet_buffer, counter); + field_print(packet_buffer, 2, &counter, "Lenght/Type"); + + /* + * if the last field value is less or equal to 1500 is a lenght + * otherwise is a protocol type (check IEEE 802.3 documentation...) + */ + + if (next_protocol > 1500) { + + // go up to the next layer + layer_3_dispatcher(packet_buffer + counter, size - counter, next_protocol); + + } else { + + // remain on the same layer + layer_2_dispatcher(packet_buffer + counter, size - counter, dst_mac); + + } +} + +/** + * Print the ISL header of the packet + * + * @param packet_buffer raw packet captured from the network, starting at the part to process + * @param size packet_buffer size + */ +void isl_print (const char *packet_buffer, int size) { + int counter = 0; + + puts("\nISL Header:"); + + if (size < 30) { + puts (" invalid header size"); + return; + } + + // print header fields + field_print(packet_buffer, 5, &counter, "Destination"); + + + int next_protocol = protocol_8bit_extract(packet_buffer, counter); + next_protocol >>= 4; + + field_print(packet_buffer, 1, &counter, "Type/User"); + field_print(packet_buffer, 6, &counter, "Source"); + field_print(packet_buffer, 2, &counter, "Length"); + field_print(packet_buffer, 1, &counter, "DSAP"); + field_print(packet_buffer, 1, &counter, "SSAP"); + field_print(packet_buffer, 1, &counter, "Control"); + field_print(packet_buffer, 3, &counter, "HSA"); + field_print(packet_buffer, 2, &counter, "Vlan ID/BPDU"); + field_print(packet_buffer, 2, &counter, "Index"); + field_print(packet_buffer, 2, &counter, "RES"); + + /* + * Note: we subtrack 4 to the size of the packet to exclude + * the final frame check sequence + */ + + if (next_protocol == 0) { + + // go up to the next layer + ethernet_print(packet_buffer + counter, size - counter - 4); + + } else { + + // go up to the next layer + payload_print(packet_buffer + counter, size - counter - 4); + + } + + counter = size - 4; + + puts("\nISL Header (end):"); + + field_print(packet_buffer, 4, &counter, "Frame check seq."); +} + +/** + * Print the DTP header of the packet + * + * @param packet_buffer raw packet captured from the network, starting at the part to process + * @param size packet_buffer size + */ +void dtp_print (const char *packet_buffer, int size) { + int counter = 0; + + puts("\nDinamic Trunking Protocol Header:"); + + if (size < 29) { + puts (" invalid header size"); + return; + } + + // print header fields + field_print(packet_buffer, 1, &counter, "Version"); + field_print(packet_buffer, 8, &counter, "Domain"); + + field_print(packet_buffer, 5, &counter, "Status"); + field_print(packet_buffer, 5, &counter, "DTP Type"); + + field_print(packet_buffer, 8, &counter, "Neighbor"); + field_print(packet_buffer, 2, &counter, ""); // splitted since too long... + + // print remaining payload + payload_print(packet_buffer + counter, size - counter); +} + +/** + * Print the STP header of the packet + * + * @param packet_buffer raw packet captured from the network, starting at the part to process + * @param size packet_buffer size + */ +void stp_print (const char *packet_buffer, int size) { + int counter = 0; + + puts("\nSpanning Tree Protocol Header:"); + + if (size < 38) { + puts (" invalid header size"); + return; + } + + // print header fields + field_print(packet_buffer, 2, &counter, "Protocol Identifier"); + field_print(packet_buffer, 1, &counter, "Protocol Version Identifier"); + + field_print(packet_buffer, 1, &counter, "BPDU Type"); + field_print(packet_buffer, 1, &counter, "BPDU Flags"); + + field_print(packet_buffer, 2, &counter, "Root Priority/System ID Extension"); + field_print(packet_buffer, 6, &counter, "Root System ID"); + + field_print(packet_buffer, 4, &counter, "Root Path Cost"); + + field_print(packet_buffer, 2, &counter, "Bridge Priority/System ID Extension"); + field_print(packet_buffer, 6, &counter, "Bridge System ID"); + + field_print(packet_buffer, 2, &counter, "Port Identifier"); + field_print(packet_buffer, 2, &counter, "Message Age"); + field_print(packet_buffer, 2, &counter, "Max Age"); + field_print(packet_buffer, 2, &counter, "Hello Time"); + field_print(packet_buffer, 2, &counter, "Forward Delay"); + + // print remaining payload + payload_print(packet_buffer + counter, size - counter); +} + +/** + * Print the LLC header of the packet + * + * @param packet_buffer raw packet captured from the network, starting at the part to process + * @param size packet_buffer size + */ +void llc_print (const char *packet_buffer, int size) { + int counter = 0; + + puts("\nLogical-Link Control Header:"); + + if (size < 3) { + puts (" invalid header size"); + return; + } + + // print header fields + int dsap = protocol_8bit_extract(packet_buffer, counter); + field_print(packet_buffer, 1, &counter, "DSAP"); + + int ssap = protocol_8bit_extract(packet_buffer, counter); + field_print(packet_buffer, 1, &counter, "SSAP"); + + field_print(packet_buffer, 1, &counter, "Control field"); + + if (dsap == 0x42 && ssap == 0x42) { + + // spanning tree protocol + stp_print(packet_buffer + counter, size - counter); + + } else if (dsap == 0xaa && ssap == 0xaa) { + + if (size < 8) { + puts (" invalid header size"); + return; + } + + // continue printing LLC fields + field_print(packet_buffer, 3, &counter, "Organization code"); + + int pid = protocol_16bit_extract(packet_buffer, counter); + field_print(packet_buffer, 2, &counter, "PID"); + + if (pid == 0x2004) { + + // dinamic trunking protocol + dtp_print(packet_buffer + counter, size - counter); + + } else { + + // print remaining payload + payload_print(packet_buffer + counter, size - counter); + + } + + } + +} + +/** + * Determine the packet type and call the appropriate function to disassemble it. + * Operates on layer 2 (OSI model) packet's headers. + * + * @param packet_buffer raw packet captured from the network, starting at layer 2 + * @param size packet_buffer size + * @param protocol protocol number + */ +void layer_2_dispatcher (const char *packet_buffer, int size, uint64_t protocol) { + + uint64_t llc1 = 0x0180C20000LLU, llc2 = 0x01000CCCCCCCLLU; + + if (size < 1) { + return; + } + + if (memcmp(packet_buffer, "\x01\x00\x0C\x00\x00", 5)==0 || + memcmp(packet_buffer, "\x03\x00\x0c\x00\x00", 5)==0 ) { + + isl_print(packet_buffer, size); + + } else if ((protocol / 256) == llc1) { + + llc_print(packet_buffer, size); // spanning tree + + } else if (protocol == llc2) { + + llc_print(packet_buffer, size); + + } else { + + ethernet_print(packet_buffer, size); + + } +} + +/** + * Determine the packet type and call the appropriate function to disassemble it. + * Operates on layer 3 (OSI model) packet's headers. + * + * @param packet_buffer raw packet captured from the network, starting at layer 3 + * @param size packet_buffer size + * @param protocol protocol number + */ +void layer_3_dispatcher (const char *packet_buffer, int size, uint64_t protocol) { + + if (size < 1) { + return; + } + + /* + * if the last field value (of an ethernet header) is less or equal to 1500 + * then is a lenght otherwise is a protocol type (check IEEE 802.3 documentation...) + */ + + if (protocol <= 0xffff) { // check if it's a 16bit field + // (i.e. last ethernet field was a protocol) + switch (protocol) { + + case 0x0800: ip_print(packet_buffer, size); break; + case 0x0806: arp_print(packet_buffer, size); break; + + default: payload_print(packet_buffer, size); + + } + + } else { + payload_print(packet_buffer, size); + } + +} + +/** + * Determine the packet type and call the appropriate function to disassemble it. + * Operates on layer 4 (OSI model) packet's headers. + * + * @param packet_buffer raw packet captured from the network, starting at layer 4 + * @param size packet_buffer size + * @param protocol protocol number + */ +void layer_4_dispatcher (const char *packet_buffer, int size, uint64_t protocol) { + + if (size < 1) { + return; + } + + switch (protocol) { + case 1: icmp_print(packet_buffer, size); break; + case 2: igmp_print(packet_buffer, size); break; + case 6: tcp_print(packet_buffer, size); break; + case 17: udp_print(packet_buffer, size); break; + default: payload_print(packet_buffer, size); + } +} + diff --git a/nmap/libft/srcs/net/reserve_port.c b/nmap/libft/srcs/net/reserve_port.c index cb664dea..6c3bf493 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/09 10:48:18 by jhalford ### ########.fr */ +/* Updated: 2017/10/24 17:30:41 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,7 +19,7 @@ int reserve_port(int s, struct sockaddr *sa) i = 49152; while (i < 65535) { - sa->sin_port = htons(i); + ((struct sockaddr_in*)sa)->sin_port = htons(i); if (bind(s, sa, sizeof(sa)) == 0) return (0); ++i; diff --git a/nmap/libft/srcs/net/tcp.c b/nmap/libft/srcs/net/tcp.c index 83c0d746..434ac9bd 100644 --- a/nmap/libft/srcs/net/tcp.c +++ b/nmap/libft/srcs/net/tcp.c @@ -6,7 +6,7 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/10/07 18:02:34 by jhalford #+# #+# */ -/* Updated: 2017/10/08 15:54:16 by jhalford ### ########.fr */ +/* Updated: 2017/10/24 20:24:09 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/nmap/libft/srcs/printing/hexdump.c b/nmap/libft/srcs/printing/hexdump.c index de933085..cdb9588d 100644 --- a/nmap/libft/srcs/printing/hexdump.c +++ b/nmap/libft/srcs/printing/hexdump.c @@ -6,7 +6,7 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/10/07 17:56:14 by jhalford #+# #+# */ -/* Updated: 2017/10/07 17:56:40 by jhalford ### ########.fr */ +/* Updated: 2017/10/24 14:33:28 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/nmap/libft/srcs/str/hexstring.c b/nmap/libft/srcs/str/hexstring.c new file mode 100644 index 00000000..2306b5e9 --- /dev/null +++ b/nmap/libft/srcs/str/hexstring.c @@ -0,0 +1,202 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* hexstring.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/24 21:42:59 by jhalford #+# #+# */ +/* Updated: 2017/10/24 21:47:58 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "hexstring.h" + +/** + * Byte multiplier: a printed byte uses 3 characters + */ +#define BYTE_MULT 3 + +/** + * Convert a 2-bytes string to an uint8_t integer (e.g. "1A\0" -> 0x1A) + * + * @param str hexstring to convert, of expected size BYTE_MULT + * @return converted uint8_t integer + */ +uint8_t str_to_hex(char *str) { + + assert(str != NULL); + + uint8_t hex = 0; + + if(isdigit(str[0])) { + hex |= (str[0] & 0x0F) << 4; + } else { + hex |= ((str[0]+0x09) & 0x0F) << 4; + } + + if(isdigit(str[1])) { + hex |= (str[1] & 0x0F); + } else { + hex |= ((str[1]+0x09) & 0x0F); + } + + return hex; +} + +/** + * Convert an uint8_t integer to a 2-bytes hexstring (e.g. 0x1A -> "1A\0") + * + * @param hex uint8_t integer to convert + * @param str destination hexstring, of expected size BYTE_MULT + */ +void hex_to_str(uint8_t hex, char *str) { + + assert(str != NULL); + + str[0] = (hex & 0xF0) >> 4; + str[1] = (hex & 0x0F); + str[2] = '\0'; + + if(str[0]<0x0A) { + str[0] |= 0x30; + } else { + str[0] |= 0x40; + str[0] -= 0x09; + } + + if(str[1]<0x0A) { + str[1] |= 0x30; + } else { + str[1] |= 0x40; + str[1] -= 0x09; + } +} + +/** + * Check if the character is hexadecimal. + * + * @param c character to check + * @return + * - 1 if hexadecimal + * - 0 if not hexadecimal + */ +int is_hex(char c) { + if ((c >= 'A' && c <= 'F') || (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) + return 1; + return 0; +} + +/** + * Return the length of the hexstring. + * + * @param hexstr input string + * @return hexstr length + */ +int hexstr_size(const char *hexstr) { + + assert(hexstr != NULL); + + int size = 0; + const char *p = hexstr; + + /* + * Parse an hexstring and calculate it's size. + * Analyze three bytes at a time, in this format: HEX HEX (SPACE|NULL) + * (Ex. "FF ", "2A ", "EE") + */ + while ( is_hex(p[0]) && is_hex(p[1]) && (p[2] == ' ' || p[2] == '\n' || p[2] == '\0') ) { + //printf("p[0] = %c, p[1] = %c, p[2] = %c\n", p[0], p[1], p[2] == '\0' ? 'N' : p[2]); + + size++; + p += BYTE_MULT; + } + + return size; +} + +/** + * Create a raw buffer from an hexstring. The buffer must be manually free()d. + * + * @param hexstr hexstring to convert + * @param size hexstring size + * @return pointer to the converted raw buffer + */ +char *hexstr_to_raw(const char *hexstr, int *size) { + + assert(hexstr != NULL); + assert(size != NULL); + + char *raw = NULL; + const char *p = hexstr; + + *size = hexstr_size(hexstr); + raw = (char *) malloc(*size); // malloc the raw buffer + + char hex[BYTE_MULT]; + int i = 0; + + /* + * Parse an hexstring. + * Analyze three bytes at a time, in this format: HEX HEX (SPACE|NULL) + * (Ex. "FF ", "2A ", "EE") + */ + while ( is_hex(p[0]) && is_hex(p[1]) && (p[2] == ' ' || p[2] == '\n' || p[2] == '\0') ) { + //printf("p[0] = %c, p[1] = %c, p[2] = %c\n", p[0], p[1], p[2] == '\0' ? 'N' : p[2]); + + // extract a single byte + hex[0] = p[0]; + hex[1] = p[1]; + hex[2] = '\0'; + + raw[i] = str_to_hex(hex); + + i++; + p += BYTE_MULT; + } + + //hex_dump(raw, size); + + return raw; +} + +/** + * Create an hexstring from a raw buffer. The hexstring must be manually free()d. + * + * @param raw raw buffer to convert + * @param size raw buffer size + * @return converted hexstring + */ +char *raw_to_hexstr(const char *raw, int size) { + + assert(raw != NULL); + if(size == 0) return NULL; + + char *hexstr = NULL; + + hexstr = (char *) malloc(size*BYTE_MULT); // malloc the hexstring + + char hex[BYTE_MULT]; + int i = 0; + char *p = hexstr; + + /* + * Parse an hexstring. + * Analyze three bytes at a time, in this format: HEX HEX (SPACE|NULL) + * (Ex. "FF ", "2A ", "EE") + */ + for (i=0; i +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/24 15:07:14 by jhalford #+# #+# */ +/* Updated: 2017/10/24 21:48:03 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "nmap.h" + +int g_njobs; +char g_port_status[][20] = +{ + "OPEN", + "FILTERED", + "CLOSED", + "UNFILTERED", + "OPEN_FILTERED", +}; + +void nmap_format(chan results) +{ + t_result result; + char buf[IPADDR_MAXSTRLEN]; + int i; + + i = 0; + while (i++ < g_njobs) + { + result = chr(results, t_result); + printf("%s:%i %s(%s)\n", + ipaddrstr(result.dest, buf), + ipport(result.dest), + g_port_status[result.status], + result.scan); + } + printf("finished reading %i jobs\n", g_njobs); +} diff --git a/nmap/srcs/ip.c b/nmap/srcs/ip.c new file mode 100644 index 00000000..fb929ff8 --- /dev/null +++ b/nmap/srcs/ip.c @@ -0,0 +1,52 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ip.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/24 17:22:16 by jhalford #+# #+# */ +/* Updated: 2017/10/24 21:36:52 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "nmap.h" + +/* +** some libmill ip extensions +*/ + +uint16_t ipport(ipaddr ip) +{ + return (ntohs(((struct sockaddr_in*)&ip)->sin_port)); +} + +uint16_t ipfamily(ipaddr ip) +{ + return (((struct sockaddr*)&ip)->sa_family); +} + +uint16_t ipmode(ipaddr ip) +{ + if (((struct sockaddr*)&ip)->sa_family == AF_INET) + return (IPADDR_IPV4); + else + return (IPADDR_IPV6); +} + +ipaddr iplocal_randport(const char *name, int mode, int sock) +{ + unsigned short port; + ipaddr ip; + + port = 49152; + while (port < 65535) + { + ip = iplocal(name, port, mode); + if (bind(sock, (struct sockaddr*)&ip, sizeof(ip)) == 0) + return (ip); + ++port; + } + errno = EBUSY; + return (ip); +} diff --git a/nmap/srcs/listener.c b/nmap/srcs/listener.c index 482f329e..e6484dbe 100644 --- a/nmap/srcs/listener.c +++ b/nmap/srcs/listener.c @@ -1,33 +1,54 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* listener.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/23 19:16:39 by jhalford #+# #+# */ +/* Updated: 2017/10/24 21:28:44 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + #include "nmap.h" -static pcap_t *pcap_obj = NULL; +#define PCAP_FILTER\ + "src host %s and src port %i and dst host %s and dst port %i" -static void packet_callback(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet) +static void packet_callback(u_char *arg, const struct pcap_pkthdr *pkthdr, + const u_char *packet) { (void)pkthdr; (void)packet; - t_data *data = (t_data*)arg; + chan ch = (chan)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); + prettypacket((void*)packet, pkthdr->len); + (void)ch; + /* chs(ch, struct tcphdr, *(t_tcp_packet*)packet); */ } -coroutine void nmap_listener(t_data *data) +coroutine void listener_loop(chan ch, pcap_t *pcap_obj) { - t_data *data; - char errbuf[PCAP_ERRBUF_SIZE]; - bpf_u_int32 netp; - bpf_u_int32 maskp; - struct bpf_program fp; - char *str; + ft_printf("listener loop\n"); + if (pcap_loop(pcap_obj, -1, packet_callback, (u_char*)ch) == -1) + { + ft_printf("pcap_loop fail\n"); + exit(EXIT_FAILURE); + } +} - data = (t_data*)arg; +chan nmap_listener(ipaddr dst, ipaddr src) +{ + char errbuf[PCAP_ERRBUF_SIZE]; + pcap_t *pcap_obj; + bpf_u_int32 netp; + bpf_u_int32 maskp; + struct bpf_program fp; + char str[100]; + chan pkts; + + pkts = chmake(struct tcphdr, 10); if (pcap_lookupnet("any", &netp, &maskp, errbuf) == -1) { exit(EXIT_FAILURE); @@ -37,24 +58,13 @@ coroutine void nmap_listener(t_data *data) fprintf(stderr, "pcap_open_live: %s", errbuf); exit(EXIT_FAILURE); } - if (!(str = ft_str3join("host ", ((t_host*)data->host->content)->ip, " and (tcp or icmp)"))) - { + if (!(sprintf(str, PCAP_FILTER, ipaddrstr(dst, str), ipport(dst), + ipaddrstr(src, str), ipport(src)))) exit(EXIT_FAILURE); - } if (pcap_compile(pcap_obj, &fp, str, 1, netp) == -1) - { exit(EXIT_FAILURE); - } if (pcap_setfilter(pcap_obj, &fp) == -1) - { exit(EXIT_FAILURE); - } - /* signal(SIGALRM, sigalrm_handler); */ - ft_printf("listener loop\n"); - if (pcap_loop(pcap_obj, -1, packet_callback, (u_char*)data) == -1) - { - ft_printf("pcap_loop fail\n"); - exit(EXIT_FAILURE); - } - free(str); + go(listener_loop(pkts, pcap_obj)); + return (chdup(pkts)); } diff --git a/nmap/srcs/main.c b/nmap/srcs/main.c index 38131124..07f2a46a 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/09 15:58:02 by jhalford ### ########.fr */ +/* Updated: 2017/10/24 20:08:00 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,52 +15,53 @@ #define NMAP_USAGE1 " [--ip HOST] [--file FILE]" #define NMAP_USAGE2 " [--ports PORTS] [--speedup [NUMBER]] [--scan [TYPE]] HOST" -/* -** only IPv4 -** only default network if -** one per port per scan type -*/ -int fill_ports(t_data *data) -{ - int i; +t_data *g_data; - i = -1; - while (++i < SCAN_MAX) +coroutine void jobs_loop(chan jobs, chan results) +{ + t_job job; + chan copy; + int i; + + i = 0; + while (true) { - 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); - } + job = chr(jobs, t_job); + if (job.scan == NULL) + break ; + copy = chdup(results); + go(job.scan(copy, job)); + i++; } + printf("finished starting jobs\n"); } -int main(int ac, char **av) +static chan nmap(chan jobs) { - t_data data; + chan results; - if (getuid() != 0) - { - fprintf(stderr, "You must have root privileges to use nmap!\n"); - return(1); - } - if (nmap_parse(ac, av, &data)) + results = chmake(t_result, 0); + go(jobs_loop(jobs, results)); + return (results); +} + +int main(int ac, char **av) +{ + chan jobs; + chan results; + + /* if (getuid() != 0) */ + /* { */ + /* fprintf(stderr, "You must have root privileges to use nmap!\n"); */ + /* return(1); */ + /* } */ + if ((jobs = nmap_parse(ac, av)) < 0) { printf("usage: nmap --help\n"); printf("or nmap"NMAP_USAGE1 NMAP_USAGE2"\n"); exit(1); } - fill_ports(&data); - go(nmap_listener(&data)); - int chan = nmap(&data); + results = nmap(jobs); + nmap_format(results); return (0); } diff --git a/nmap/srcs/nmap.c b/nmap/srcs/nmap.c deleted file mode 100644 index 770d69e8..00000000 --- a/nmap/srcs/nmap.c +++ /dev/null @@ -1,116 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* nmap.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: jhalford +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2017/10/08 19:10:07 by jhalford #+# #+# */ -/* Updated: 2017/10/09 17:12:31 by jhalford ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "nmap.h" - -t_scanner g_scanners[SCAN_MAX] -{ - scan_tcp, - NULL, - NULL, - NULL, - NULL, - NULL, - /* scan_syn, */ - /* scan_ack, */ - /* scan_fin, */ - /* scan_xmas, */ - /* scan_udp, */ -} - -coroutine void nmap_scan_port(int ch, t_data *data, t_target target) -{ - int fan_in; - int fan_in_local; - int scan; - - fan_in = chmake(sizeof(t_scan_result)); - while (scan = bitfield_lsb(data.scans, USHRT_MAX + 1)) - { - data.scans &= ~scan; - fan_in_local = hdup(fan_in); - scanner = g_scanners[scan]; - go(scanner(fan_in_local, sock, target)); - } - - 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; - int nhost; - int fan_in_local; - struct chclause clause[ft_lstsize(data->host)]; - int buf; - - nhost = 0; - for (t_list *list = data->host; list != NULL; list = list->next) - { - 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 efb0d07d..ab20595c 100644 --- a/nmap/srcs/parser.c +++ b/nmap/srcs/parser.c @@ -6,62 +6,62 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/10/08 19:10:05 by jhalford #+# #+# */ -/* Updated: 2017/10/09 14:51:21 by jhalford ### ########.fr */ +/* Updated: 2017/10/24 21:00:10 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ #include "nmap.h" -static t_cliopts g_opts[] = -{ - {'h', "host", 0, 0, nmap_get_host, 0}, - /* {'f', "file", 0, 0, nmap_get_file, 0}, */ - /* {'p', "ports", 0, 0, nmap_get_ports, 0}, */ - {'t', "threads", 0, 0, nmap_get_threads, 0}, - {'s', "scan", 0, 0, nmap_get_scan, 0}, - {0, 0, 0, 0, 0, 0}, -}; +extern int g_njobs; -static int nmap_get_host(char *node, t_data *data) -{ - t_host host; - struct addrinfo *servinfo, hints; +/* static t_cliopts g_opts[] = */ +/* { */ +/* {'h', "host", 0, 0, nmap_get_host, 0}, */ +/* /1* {'f', "file", 0, 0, nmap_get_file, 0}, *1/ */ +/* /1* {'p', "ports", 0, 0, nmap_get_ports, 0}, *1/ */ +/* {'t', "threads", 0, 0, nmap_get_threads, 0}, */ +/* {'s', "scan", 0, 0, nmap_get_scan, 0}, */ +/* {0, 0, 0, 0, 0, 0}, */ +/* }; */ - memset (&hints, 0, sizeof (hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_RAW; - hints.ai_flags = AI_CANONNAME; +/* static t_host nmap_get_host(char *node) */ +/* { */ +/* t_host host; */ +/* struct addrinfo *servinfo, hints; */ - if (getaddrinfo(node, NULL, &hints, &servinfo)) - { - fprintf(stderr, "Failed to resolve \"%s\"\n", node); - return (1); - } - host.addr = servinfo->ai_addr; - host.addrlen = servinfo->ai_addrlen; - host.host = node; - host.dn = servinfo->ai_canonname; +/* memset (&hints, 0, sizeof (hints)); */ +/* hints.ai_family = PF_UNSPEC; */ +/* hints.ai_socktype = SOCK_RAW; */ +/* hints.ai_flags = AI_CANONNAME; */ - void *addr; - if (servinfo->ai_family == AF_INET) { // IPv4 - struct sockaddr_in *ipv4 = (struct sockaddr_in *)servinfo->ai_addr; - addr = &(ipv4->sin_addr); - } else { // IPv6 - struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)servinfo->ai_addr; - addr = &(ipv6->sin6_addr); - } +/* if (getaddrinfo(node, NULL, &hints, &servinfo)) */ +/* { */ +/* fprintf(stderr, "Failed to resolve \"%s\"\n", node); */ +/* return (host); */ +/* } */ +/* host.addr = servinfo->ai_addr; */ +/* host.addrlen = servinfo->ai_addrlen; */ +/* host.host = node; */ +/* host.dn = servinfo->ai_canonname; */ - // convert the IP to a string and print it: - inet_ntop(servinfo->ai_family, addr, host.ip, sizeof(host.ip)); +/* void *addr; */ +/* if (servinfo->ai_family == AF_INET) { // IPv4 */ +/* struct sockaddr_in *ipv4 = (struct sockaddr_in *)servinfo->ai_addr; */ +/* addr = &(ipv4->sin_addr); */ +/* } else { // IPv6 */ +/* struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)servinfo->ai_addr; */ +/* addr = &(ipv6->sin6_addr); */ +/* } */ - printf("dn=%s, ip=%s\n", host.dn, host.ip); +/* // convert the IP to a string and print it: */ +/* inet_ntop(servinfo->ai_family, addr, host.ip, sizeof(host.ip)); */ - /* MUST DO rDNS search here */ - /* printf("rDNS record for %s: %s\n", addrstr, DOMAIN NAME WITH RDNS); */ +/* printf("dn=%s, ip=%s\n", host.dn, host.ip); */ - ft_lsteadd(&data->host, ft_lstnew(&host, sizeof(host))); - return (0); -} +/* /1* MUST DO rDNS search here *1/ */ +/* /1* printf("rDNS record for %s: %s\n", addrstr, DOMAIN NAME WITH RDNS); *1/ */ +/* return (host); */ +/* } */ /* int nmap_get_file(char *opt_arg, t_data *data) */ /* { */ @@ -71,65 +71,64 @@ static int nmap_get_host(char *node, t_data *data) /* { */ /* } */ -static int nmap_get_threads(char *opt_arg, t_data *data) +/* static int nmap_get_threads(char *opt_arg, t_data *data) */ +/* { */ +/* data->threads = ft_atoi(opt_arg); */ +/* return (0); */ +/* } */ + +/* static int nmap_get_scan(char *opt_arg, t_data *data) */ +/* { */ +/* while (*opt_arg) */ +/* { */ +/* if (*opt_arg == 'T') */ +/* bitfield_biton(data->scans, SCAN_TCP); */ +/* else if (*opt_arg == 'S') */ +/* bitfield_biton(data->scans, SCAN_SYN); */ +/* else if (*opt_arg == 'A') */ +/* bitfield_biton(data->scans, SCAN_ACK); */ +/* else if (*opt_arg == 'F') */ +/* bitfield_biton(data->scans, SCAN_FIN); */ +/* else if (*opt_arg == 'X') */ +/* bitfield_biton(data->scans, SCAN_XMAS); */ +/* else if (*opt_arg == 'U') */ +/* bitfield_biton(data->scans, SCAN_UDP); */ +/* else */ +/* return (1); */ +/* opt_arg++; */ +/* } */ +/* return (0); */ +/* } */ + +coroutine void coarse_dispatcher(chan jobs) { - data->threads = ft_atoi(opt_arg); - return (0); + t_job job; + + job.scan = nmap_scan_tcp; + + job.dest = ipremote("scanme.nmap.org", 80, IPADDR_IPV4, -1); + chs(jobs, t_job, job); + job.dest = ipremote("scanme.nmap.org", 81, IPADDR_IPV4, -1); + chs(jobs, t_job, job); + + job.scan = 0; + chdone(jobs, t_job, job); + chclose(jobs); } -static int nmap_get_scan(char *opt_arg, t_data *data) +chan nmap_parse(int ac, char **av) { - while (*opt_arg) - { - if (*opt_arg == 'T') - bitfield_biton(data->scans, SCAN_TCP); - else if (*opt_arg == 'S') - bitfield_biton(data->scans, SCAN_SYN); - else if (*opt_arg == 'A') - bitfield_biton(data->scans, SCAN_ACK); - else if (*opt_arg == 'F') - bitfield_biton(data->scans, SCAN_FIN); - else if (*opt_arg == 'X') - bitfield_biton(data->scans, SCAN_XMAS); - else if (*opt_arg == 'U') - bitfield_biton(data->scans, SCAN_UDP); - else - return (1); - opt_arg++; - } - return (0); -} - -int nmap_parse(int ac, char **av, t_data *data) -{ - struct ifaddrs *ifaddrs, *ifa_first; (void)ac; - data->host = NULL; - bzero(data->ports, sizeof(data->ports)); - data->threads = 0; - data->scan = 0; + (void)av; + /* if (cliopts_get(av, g_opts, data)) */ + /* return (ft_perror("nmap")); */ + /* if (!data->host && data->av_data && data->av_data) */ + /* nmap_get_host(*data->av_data, data); */ - if (cliopts_get(av, g_opts, data)) - return (ft_perror("nmap")); - if (!data->host && data->av_data && data->av_data) - nmap_get_host(*data->av_data, data); - if (!data->scan) - data->scan = SCAN_TCP; - getifaddrs(&ifa_first); - for (ifaddrs = ifa_first; ifaddrs && ifaddrs->ifa_flags & IFF_LOOPBACK; ifaddrs = ifaddrs->ifa_next) - ; - if (ifaddrs) - { - ifaddrs=ifaddrs->ifa_next; - printf("if=%s\n", ifaddrs->ifa_name); - data->source_addr = *ifaddrs->ifa_addr; - } - else - { - fprintf(stderr, "couldn't find an internet interface\n"); - exit(1); - } - freeifaddrs(ifa_first); - bitfield_biton(data->ports, 80); - return (0); + chan jobs; + jobs = chmake(t_job, 0); + go(coarse_dispatcher(jobs)); + g_njobs = 2; + + return (jobs); } diff --git a/nmap/srcs/scanners.c b/nmap/srcs/scanners.c index db99c0fc..038457c5 100644 --- a/nmap/srcs/scanners.c +++ b/nmap/srcs/scanners.c @@ -6,42 +6,44 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2017/10/09 15:28:42 by jhalford #+# #+# */ -/* Updated: 2017/10/09 16:14:35 by jhalford ### ########.fr */ +/* Updated: 2017/10/24 21:48:11 by jhalford ### ########.fr */ /* */ /* ************************************************************************** */ #include "nmap.h" -coroutine void nmap_scan_tcp(int ch, t_data *data, t_target target) +coroutine void nmap_scan_tcp(chan results, t_job job) { - int listen; - t_scan_result res; - t_tcp_packet pkt; + t_result result; + chan pkts; + ipaddr src; + int sock; - listen = capture_chan(target); + sock = socket(ipfamily(job.dest), SOCK_STREAM, IPPROTO_TCP); + src = iplocal_randport(NULL, ipmode(job.dest), sock); + pkts = nmap_listener(job.dest, src); - iphdr_init(&pkt.iph); + result.dest = job.dest; + ft_strcpy(result.scan, "TCP"); - 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)); + struct tcphdr pkt; + result.status = CLOSED; - tcphdr_init(&pkt.tcph); - packet.tcph.dest = htons(target.port); - packet.tcph.check = cksum(&packet, sizeof(t_tcp_packet)); + tcp_hdrinit(&pkt); + pkt.th_dport = htons(ipport(job.dest)); + pkt.th_sport = htons(ipport(src)); + /* pkt.th_flags = 0; */ + pkt.th_sum = cksum(&pkt, sizeof(pkt)); - if (sendto(sock, &packet, sizeof(packet), 0, - host->addr, host->addrlen) < 0) + if (sendto(sock, &pkt, sizeof(pkt), 0, + (struct sockaddr*)&job.dest, sizeof(job.dest)) < 0) { perror("sendto"); exit(1); } - /* chrecv(channel, &buf, sizeof()) */ - hexdump(&packet, sizeof(packet)); + pkt = chr(pkts, struct tcphdr); - - chsend(ch, res, sizeof(res), -1); - printf("result sent\n"); - hclose(ch); + chs(results, t_result, result); + chclose(results); + return ; }