changed pattern completely, much better

This commit is contained in:
Jack Halford 2017-10-24 21:48:39 +02:00
parent 3f86775ec2
commit 73b7fbcd2a
22 changed files with 1370 additions and 358 deletions

View file

@ -6,7 +6,7 @@
# By: wescande <wescande@student.42.fr> +#+ +:+ +#+ # # By: wescande <wescande@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2016/08/29 21:32:58 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/ OBJ_DIR = objs/
SRC_BASE = \ SRC_BASE = \
main.c\ format.c\
nmap.c\ ip.c\
parser.c\
listener.c\ listener.c\
main.c\
parser.c\
scanners.c
SRCS = $(addprefix $(SRC_DIR), $(SRC_BASE)) SRCS = $(addprefix $(SRC_DIR), $(SRC_BASE))
OBJS = $(addprefix $(OBJ_DIR), $(SRC_BASE:.c=.o)) OBJS = $(addprefix $(OBJ_DIR), $(SRC_BASE:.c=.o))
@ -52,7 +54,7 @@ $(NAME): $(LIBFT_LIB) $(OBJ_DIR) $(OBJS) $(CLIENT_OBJ)
-I $(LIBFT_INC) \ -I $(LIBFT_INC) \
-L $(HOME)/.bin/lib \ -L $(HOME)/.bin/lib \
$(LIBFT_LIB) $(CLIENT_OBJ) $(FLAGS) \ $(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" @printf "\r\033[38;5;117m✓ MAKE $@ \033[0m\033[K\n"
$(LIBFT_LIB): $(LIBFT_LIB):

View file

@ -6,7 +6,7 @@
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */ /* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2017/04/22 14:10:24 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 <net/if.h> # include <net/if.h>
# include <netinet/in.h> # include <netinet/in.h>
# include <netinet/ip.h> # include <netinet/ip.h>
# include <netinet/tcp.h>
# include <netinet/ip_icmp.h> # include <netinet/ip_icmp.h>
# include <netinet/if_ether.h> # include <netinet/if_ether.h>
# include <pcap.h> # include <pcap.h>
@ -30,11 +31,13 @@
# include <pthread.h> # include <pthread.h>
# include <ifaddrs.h> # include <ifaddrs.h>
# include "libdill.h" # include "libmill.h"
typedef struct s_data t_data; typedef struct s_data t_data;
typedef struct s_host t_host; typedef struct s_host t_host;
typedef struct s_tcp_packet t_tcp_packet; 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_port_status t_port_status;
typedef enum e_scan_type t_scan_type; typedef enum e_scan_type t_scan_type;
@ -62,14 +65,6 @@ struct s_data
{ {
t_flag flag; t_flag flag;
char **av_data; 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 struct s_host
@ -79,27 +74,35 @@ struct s_host
char ip[INET6_ADDRSTRLEN]; // humain readable ip address char ip[INET6_ADDRSTRLEN]; // humain readable ip address
struct sockaddr *addr; struct sockaddr *addr;
size_t addrlen; size_t addrlen;
int chan[USHRT_MAX + 1][SCAN_MAX];
}; };
struct s_target struct s_job
{ {
t_host *host; ipaddr dest;
uint16_t port; void (*scan)();
t_scan_type scan;
#define capture_chan(t) (t.host.chan[t.port][t.scan])
}; };
struct s_tcp_packet struct s_result
{ {
struct iphdr iph; ipaddr dest;
struct tcphdr tcph; char scan[4];
}__attribute__((packed)); t_port_status status;
};
static t_cliopts g_opts[]; extern t_cliopts g_opts[];
int nmap_parse(int ac, char **av, t_data *data); extern int g_njobs;
chan nmap_parse(int ac, char **av);
void nmap_format(chan results);
void nmap(t_data *data); coroutine void nmap_scan_tcp(chan results, t_job job);
void nmap_listener(void *arg); 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 #endif

View file

@ -108,6 +108,7 @@ lst/lst_insert_sort.c\
lst/pop.c\ lst/pop.c\
lst/push.c\ lst/push.c\
lst/top.c\ lst/top.c\
math/bitfield.c\
math/ft_addrcmp.c\ math/ft_addrcmp.c\
math/ft_ilen.c\ math/ft_ilen.c\
math/ft_ilen_base.c\ math/ft_ilen_base.c\
@ -138,6 +139,7 @@ net/host.c\
net/ip.c\ net/ip.c\
net/net_get.c\ net/net_get.c\
net/net_send.c\ net/net_send.c\
net/prettypacket.c\
net/reserve_port.c\ net/reserve_port.c\
net/tcp.c\ net/tcp.c\
path/ft_path_notdir.c\ path/ft_path_notdir.c\
@ -204,6 +206,7 @@ str/ft_strstr.c\
str/ft_strsub.c\ str/ft_strsub.c\
str/ft_strtok.c\ str/ft_strtok.c\
str/ft_strtrim.c\ str/ft_strtrim.c\
str/hexstring.c\
sys/open_new.c\ sys/open_new.c\
time/epoch.c time/epoch.c

View file

@ -0,0 +1,36 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* hexstring.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <ctype.h>
# include <stdio.h>
# include <string.h>
# include <assert.h>
# include <stdint.h>
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_ */

View file

@ -6,7 +6,7 @@
/* By: jhalford <marvin@42.fr> +#+ +:+ +#+ */ /* By: jhalford <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2016/11/07 13:49:04 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 "math.h"
# include "mytime.h" # include "mytime.h"
# include "get_next_line.h" # include "get_next_line.h"
# include "net.h"
# include "sys.h" # include "sys.h"
# include "net.h"
# include "prettypacket.h"
struct s_stos struct s_stos
{ {

View file

@ -6,7 +6,7 @@
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */ /* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2017/03/20 15:41:59 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); int ft_addrcmp(void *a, void *b);
void *id(void *data); void *id(void *data);
extern inline void bitfield_biton(t_bitblock field[], uint64_t bit) typedef uint64_t t_bitblock;
extern inline void bitfield_bitoff(t_bitblock field[], uint64_t bit) #define BITFIELD(var, size) t_bitblock var[size / sizeof(t_bitblock) + 1]\
extern inline uint64_t bitfield_lsb(t_bitblock field[], uint64_t size) = {[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 #endif

View file

@ -6,7 +6,7 @@
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */ /* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/07 18:06:12 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 ** utilities
*/ */
int reserve_port(int *port); int reserve_port(int s, struct sockaddr *sa);
unsigned short cksum(void *b, int len); unsigned short cksum(void *b, int len);
int host_format(struct sockaddr *addr); 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); void tcp_hdrinit(struct tcphdr *header);
/*
** prettypacket
*/
int prettypacket(void *pkt, size_t size);
#endif #endif

View file

@ -0,0 +1,98 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* prettypacket.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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__ */

View file

@ -6,10 +6,11 @@
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */ /* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/09 14:44:16 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 <stdlib.h> #include <stdlib.h>
/* /*
@ -20,17 +21,13 @@
** - up and down iterator ** - 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 ** Turn bit on
*/ */
extern inline void bitfield_biton(t_bitblock field[], uint64_t bit) 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) 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) ** 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]) while (!field[++block])
if ((block+1) * BLOCKSIZE > size) if ((block+1) * BLOCKSIZE > size) return (-1);
return (-1);
return (block * BLOCKSIZE + __builtin_ctzll(field[block] ^ (~field[block] + 1)) - 1); return (block * BLOCKSIZE + __builtin_ctzll(field[block] ^ (~field[block] + 1)) - 1);
} }

View file

@ -6,7 +6,7 @@
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */ /* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/07 18:02:39 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 */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

View file

@ -0,0 +1,666 @@
/*
* prettypacket.c
*
* Created on: 03/dec/2012
* Author: Acri Emanuele <crossbower@gmail.com>
*
* Disassemble network packet and print their fields.
* Uses the stdin to receive raw packet data. Prints on stdout.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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);
}
}

View file

@ -6,7 +6,7 @@
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */ /* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/07 18:02:55 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; i = 49152;
while (i < 65535) while (i < 65535)
{ {
sa->sin_port = htons(i); ((struct sockaddr_in*)sa)->sin_port = htons(i);
if (bind(s, sa, sizeof(sa)) == 0) if (bind(s, sa, sizeof(sa)) == 0)
return (0); return (0);
++i; ++i;

View file

@ -6,7 +6,7 @@
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */ /* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/07 18:02:34 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 */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

View file

@ -6,7 +6,7 @@
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */ /* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/07 17:56:14 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 */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

View file

@ -0,0 +1,202 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* hexstring.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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<size; i++, p+=BYTE_MULT) {
// extract a single byte
hex_to_str(raw[i], hex);
p[0] = hex[0];
p[1] = hex[1];
p[2] = ' ';
}
hexstr[(size*BYTE_MULT)-1] = '\0';
return hexstr;
}

42
nmap/srcs/format.c Normal file
View file

@ -0,0 +1,42 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* format.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}

52
nmap/srcs/ip.c Normal file
View file

@ -0,0 +1,52 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ip.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}

View file

@ -1,33 +1,54 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* listener.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/23 19:16:39 by jhalford #+# #+# */
/* Updated: 2017/10/24 21:28:44 by jhalford ### ########.fr */
/* */
/* ************************************************************************** */
#include "nmap.h" #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)pkthdr;
(void)packet; (void)packet;
t_data *data = (t_data*)arg; chan ch = (chan)arg;
ft_printf("received packet !!!\n"); ft_printf("received packet !!!\n");
hexdump(&packet, sizeof(packet)); prettypacket((void*)packet, pkthdr->len);
host = extract_host(pkt); (void)ch;
dport = extract_dport(pkt); /* chs(ch, struct tcphdr, *(t_tcp_packet*)packet); */
sport = extract_sport(pkt);
chan = get_chan(host, dport, sport);
chsend(ch, &pkt, sizeof(pkt), -1);
} }
coroutine void nmap_listener(t_data *data) coroutine void listener_loop(chan ch, pcap_t *pcap_obj)
{ {
t_data *data; ft_printf("listener loop\n");
char errbuf[PCAP_ERRBUF_SIZE]; if (pcap_loop(pcap_obj, -1, packet_callback, (u_char*)ch) == -1)
bpf_u_int32 netp; {
bpf_u_int32 maskp; ft_printf("pcap_loop fail\n");
struct bpf_program fp; exit(EXIT_FAILURE);
char *str; }
}
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) if (pcap_lookupnet("any", &netp, &maskp, errbuf) == -1)
{ {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -37,24 +58,13 @@ coroutine void nmap_listener(t_data *data)
fprintf(stderr, "pcap_open_live: %s", errbuf); fprintf(stderr, "pcap_open_live: %s", errbuf);
exit(EXIT_FAILURE); 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); exit(EXIT_FAILURE);
}
if (pcap_compile(pcap_obj, &fp, str, 1, netp) == -1) if (pcap_compile(pcap_obj, &fp, str, 1, netp) == -1)
{
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
}
if (pcap_setfilter(pcap_obj, &fp) == -1) if (pcap_setfilter(pcap_obj, &fp) == -1)
{
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} go(listener_loop(pkts, pcap_obj));
/* signal(SIGALRM, sigalrm_handler); */ return (chdup(pkts));
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);
} }

View file

@ -6,7 +6,7 @@
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */ /* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/08 19:10:04 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_USAGE1 " [--ip HOST] [--file FILE]"
#define NMAP_USAGE2 " [--ports PORTS] [--speedup [NUMBER]] [--scan [TYPE]] HOST" #define NMAP_USAGE2 " [--ports PORTS] [--speedup [NUMBER]] [--scan [TYPE]] HOST"
/* t_data *g_data;
** only IPv4
** only default network if coroutine void jobs_loop(chan jobs, chan results)
** one per port per scan type
*/
int fill_ports(t_data *data)
{ {
t_job job;
chan copy;
int i; int i;
i = -1; i = 0;
while (++i < SCAN_MAX) while (true)
{ {
if ((data->sock[i] = socket(AF_INET, SOCK_RAW, 0)) < 0) job = chr(jobs, t_job);
{ if (job.scan == NULL)
perror("socket"); break ;
exit(1); copy = chdup(results);
} go(job.scan(copy, job));
/* if (setsockopt(data->sock[i], IPPROTO_IP, IP_HDRINCL, (int[]){1}, sizeof(val)) == -1) */ i++;
/* 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);
}
} }
printf("finished starting jobs\n");
} }
int main(int ac, char **av) static chan nmap(chan jobs)
{ {
t_data data; chan results;
if (getuid() != 0) results = chmake(t_result, 0);
{ go(jobs_loop(jobs, results));
fprintf(stderr, "You must have root privileges to use nmap!\n"); return (results);
return(1); }
}
if (nmap_parse(ac, av, &data)) 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("usage: nmap --help\n");
printf("or nmap"NMAP_USAGE1 NMAP_USAGE2"\n"); printf("or nmap"NMAP_USAGE1 NMAP_USAGE2"\n");
exit(1); exit(1);
} }
fill_ports(&data); results = nmap(jobs);
go(nmap_listener(&data)); nmap_format(results);
int chan = nmap(&data);
return (0); return (0);
} }

View file

@ -1,116 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* nmap.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}

View file

@ -6,62 +6,62 @@
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */ /* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/08 19:10:05 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" #include "nmap.h"
static t_cliopts g_opts[] = extern int g_njobs;
{
{'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},
};
static int nmap_get_host(char *node, t_data *data) /* static t_cliopts g_opts[] = */
{ /* { */
t_host host; /* {'h', "host", 0, 0, nmap_get_host, 0}, */
struct addrinfo *servinfo, hints; /* /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)); /* static t_host nmap_get_host(char *node) */
hints.ai_family = PF_UNSPEC; /* { */
hints.ai_socktype = SOCK_RAW; /* t_host host; */
hints.ai_flags = AI_CANONNAME; /* struct addrinfo *servinfo, hints; */
if (getaddrinfo(node, NULL, &hints, &servinfo)) /* memset (&hints, 0, sizeof (hints)); */
{ /* hints.ai_family = PF_UNSPEC; */
fprintf(stderr, "Failed to resolve \"%s\"\n", node); /* hints.ai_socktype = SOCK_RAW; */
return (1); /* hints.ai_flags = AI_CANONNAME; */
}
host.addr = servinfo->ai_addr;
host.addrlen = servinfo->ai_addrlen;
host.host = node;
host.dn = servinfo->ai_canonname;
void *addr; /* if (getaddrinfo(node, NULL, &hints, &servinfo)) */
if (servinfo->ai_family == AF_INET) { // IPv4 /* { */
struct sockaddr_in *ipv4 = (struct sockaddr_in *)servinfo->ai_addr; /* fprintf(stderr, "Failed to resolve \"%s\"\n", node); */
addr = &(ipv4->sin_addr); /* return (host); */
} else { // IPv6 /* } */
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)servinfo->ai_addr; /* host.addr = servinfo->ai_addr; */
addr = &(ipv6->sin6_addr); /* host.addrlen = servinfo->ai_addrlen; */
} /* host.host = node; */
/* host.dn = servinfo->ai_canonname; */
// convert the IP to a string and print it: /* void *addr; */
inet_ntop(servinfo->ai_family, addr, host.ip, sizeof(host.ip)); /* 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("dn=%s, ip=%s\n", host.dn, host.ip); */
/* printf("rDNS record for %s: %s\n", addrstr, DOMAIN NAME WITH RDNS); */
ft_lsteadd(&data->host, ft_lstnew(&host, sizeof(host))); /* /1* MUST DO rDNS search here *1/ */
return (0); /* /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) */ /* 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); t_job job;
return (0);
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; (void)ac;
data->host = NULL; (void)av;
bzero(data->ports, sizeof(data->ports)); /* if (cliopts_get(av, g_opts, data)) */
data->threads = 0; /* return (ft_perror("nmap")); */
data->scan = 0; /* if (!data->host && data->av_data && data->av_data) */
/* nmap_get_host(*data->av_data, data); */
if (cliopts_get(av, g_opts, data)) chan jobs;
return (ft_perror("nmap")); jobs = chmake(t_job, 0);
if (!data->host && data->av_data && data->av_data) go(coarse_dispatcher(jobs));
nmap_get_host(*data->av_data, data); g_njobs = 2;
if (!data->scan)
data->scan = SCAN_TCP; return (jobs);
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);
} }

View file

@ -6,42 +6,44 @@
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */ /* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/09 15:28:42 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" #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_result result;
t_scan_result res; chan pkts;
t_tcp_packet pkt; 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; struct tcphdr pkt;
pkt.iph.saddr = *(uint32_t*)&((struct sockaddr_in*)&data->out_sa[target.scan])->sin_addr; result.status = CLOSED;
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); tcp_hdrinit(&pkt);
packet.tcph.dest = htons(target.port); pkt.th_dport = htons(ipport(job.dest));
packet.tcph.check = cksum(&packet, sizeof(t_tcp_packet)); pkt.th_sport = htons(ipport(src));
/* pkt.th_flags = 0; */
pkt.th_sum = cksum(&pkt, sizeof(pkt));
if (sendto(sock, &packet, sizeof(packet), 0, if (sendto(sock, &pkt, sizeof(pkt), 0,
host->addr, host->addrlen) < 0) (struct sockaddr*)&job.dest, sizeof(job.dest)) < 0)
{ {
perror("sendto"); perror("sendto");
exit(1); exit(1);
} }
/* chrecv(channel, &buf, sizeof()) */ pkt = chr(pkts, struct tcphdr);
hexdump(&packet, sizeof(packet));
chs(results, t_result, result);
chsend(ch, res, sizeof(res), -1); chclose(results);
printf("result sent\n"); return ;
hclose(ch);
} }