branching out now to a pipeline design

This commit is contained in:
Jack Halford 2017-10-09 17:13:02 +02:00
parent 14dcfdcafc
commit 3f86775ec2
9 changed files with 284 additions and 123 deletions

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/08 21:27:51 by jhalford ### ########.fr */ /* Updated: 2017/10/09 16:14:18 by jhalford ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -32,33 +32,23 @@
# include "libdill.h" # include "libdill.h"
# define SCAN_TCP (1 << 0)
# define SCAN_SYN (1 << 1)
# define SCAN_NULL (1 << 2)
# define SCAN_ACK (1 << 3)
# define SCAN_FIN (1 << 4)
# define SCAN_XMAS (1 << 5)
# define SCAN_UDP (1 << 6)
# define SCAN_MAX 7
typedef struct s_data t_data; typedef struct s_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 enum e_port_status t_port_status; typedef enum e_port_status t_port_status;
typedef enum e_scan_type t_scan_type;
struct s_data enum e_scan_type
{ {
t_flag flag; SCAN_TCP,
char **av_data; SCAN_SYN,
t_list *host; SCAN_ACK,
SCAN_FIN,
int sock_tcp; SCAN_XMAS,
int threads; SCAN_UDP,
int scan; SCAN_MAX
}; };
struct
enum e_port_status enum e_port_status
{ {
OPEN, OPEN,
@ -68,20 +58,36 @@ enum e_port_status
OPEN_FILTERED, OPEN_FILTERED,
}; };
struct s_data
{
t_flag flag;
char **av_data;
int sock[SCAN_MAX];
struct sockaddr sock_a[SCAN_MAX];
int threads;
t_list *host;
BITFIELD(ports, USHRT_MAX + 1);
BITFIELD(scans, SCAN_MAX);
};
struct s_host struct s_host
{ {
char *host; // user input host (ip or dn) char *host; // user input host (ip or dn)
char *dn; // ai_canonname char *dn; // ai_canonname
char ip[INET6_ADDRSTRLEN]; // readable ip address (4 or 6) char ip[INET6_ADDRSTRLEN]; // humain readable ip address
struct s_target ports[USHRT_MAX + 1];
struct sockaddr *addr; struct sockaddr *addr;
size_t addrlen; size_t addrlen;
int chan[USHRT_MAX + 1][SCAN_MAX];
}; };
struct s_target struct s_target
{ {
int in_channel; t_host *host;
t_port_status results[SCAN_MAX]; uint16_t port;
t_scan_type scan;
#define capture_chan(t) (t.host.chan[t.port][t.scan])
}; };
struct s_tcp_packet struct s_tcp_packet

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/08 12:57:23 by jhalford ### ########.fr */ /* Updated: 2017/10/09 14:46:46 by jhalford ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -36,4 +36,8 @@ size_t ft_lllen_base(long long n, int base);
int ft_addrcmp(void *a, void *b); 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)
extern inline void bitfield_bitoff(t_bitblock field[], uint64_t bit)
extern inline uint64_t bitfield_lsb(t_bitblock field[], uint64_t size)
#endif #endif

View file

@ -0,0 +1,68 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* bitfield.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/09 14:44:16 by jhalford #+# #+# */
/* Updated: 2017/10/09 15:57:25 by jhalford ### ########.fr */
/* */
/* ************************************************************************** */
#include <stdlib.h>
/*
** ==== Wrapper around GCC builtins for ====
** ==== arbitrarily large sized bitfields ====
**
** todo
** - up and down iterator
**
*/
typedef uint64_t t_bitblock;
#define BITFIELD(var, size) t_bitblock var[size / sizeof(t_bitblock)]
#define BLOCKSIZE (8 * sizeof(t_bitblock))
/*
** Turn bit on
*/
extern inline void bitfield_biton(t_bitblock field[], uint64_t bit)
{
field[bit / BLOCKSIZE] |= (1 << bit % BLOCKSIZE);
}
/*
** Turn bit off
*/
extern inline void bitfield_bitoff(t_bitblock field[], uint64_t bit)
{
field[bit / BLOCKSIZE] &= ~(1 << bit % BLOCKSIZE);
}
/*
** Least Significant Bit (rightmost)
*/
extern inline uint64_t bitfield_lsb(t_bitblock field[], uint64_t size)
{
int block = -1;
while (!field[++block])
if ((block+1) * BLOCKSIZE > size)
return (-1);
return (block * BLOCKSIZE + __builtin_ctzll(field[block] ^ (~field[block] + 1)) - 1);
}
/*
** Count the number of 1-bits in field
*/
extern inline uint64_t bitfield_popcount(t_bitblock field[], uint64_t size)
{
int block = -1;
int count = 0;
while (++block * BLOCKSIZE < size)
count += __builtin_popcountll(field[block]);
return (count);
}

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/08 21:21:55 by jhalford ### ########.fr */ /* Updated: 2017/10/09 10:48:18 by jhalford ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

View file

@ -10,6 +10,12 @@ static void packet_callback(u_char *arg, const struct pcap_pkthdr *pkthdr, const
t_data *data = (t_data*)arg; t_data *data = (t_data*)arg;
ft_printf("received packet !!!\n"); ft_printf("received packet !!!\n");
hexdump(&packet, sizeof(packet)); hexdump(&packet, sizeof(packet));
host = extract_host(pkt);
dport = extract_dport(pkt);
sport = extract_sport(pkt);
chan = get_chan(host, dport, sport);
chsend(ch, &pkt, sizeof(pkt), -1);
} }
coroutine void nmap_listener(t_data *data) coroutine void nmap_listener(t_data *data)

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/08 21:27:57 by jhalford ### ########.fr */ /* Updated: 2017/10/09 15:58:02 by jhalford ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -15,7 +15,34 @@
#define NMAP_USAGE1 " [--ip HOST] [--file FILE]" #define NMAP_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"
int nmap_ports(t_data *data, int ch) /*
** only IPv4
** only default network if
** one per port per scan type
*/
int fill_ports(t_data *data)
{
int i;
i = -1;
while (++i < SCAN_MAX)
{
if ((data->sock[i] = socket(AF_INET, SOCK_RAW, 0)) < 0)
{
perror("socket");
exit(1);
}
/* if (setsockopt(data->sock[i], IPPROTO_IP, IP_HDRINCL, (int[]){1}, sizeof(val)) == -1) */
/* return (1); */
data->sock_a[i].sin_family = AF_INET;
data->sock_a[i].sin_addr.s_addr = INADDR_ANY;
if (reserve_port(data.sock[i], &data.sock_a[i]))
{
fprintf(stderr, "couldn't reserve port\n");
exit(1);
}
}
}
int main(int ac, char **av) int main(int ac, char **av)
{ {
@ -32,19 +59,8 @@ int main(int ac, char **av)
printf("or nmap"NMAP_USAGE1 NMAP_USAGE2"\n"); printf("or nmap"NMAP_USAGE1 NMAP_USAGE2"\n");
exit(1); exit(1);
} }
fill_ports(&data);
// single tcp port
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = INADDR_ANY;
if (reserve_port(data.sock_tcp, &sa))
{
fprintf(stderr, "couldn't reserve port\n");
exit(1);
}
go(nmap_listener(&data)); go(nmap_listener(&data));
int chan = nmap(&data); int chan = nmap(&data);
nmap_collector(chan, &data);
return (0); return (0);
} }

View file

@ -6,83 +6,111 @@
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */ /* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/08 19:10:07 by jhalford #+# #+# */ /* Created: 2017/10/08 19:10:07 by jhalford #+# #+# */
/* Updated: 2017/10/08 21:27:50 by jhalford ### ########.fr */ /* Updated: 2017/10/09 17:12:31 by jhalford ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "nmap.h" #include "nmap.h"
unsigned short cksum(void *b, int len) t_scanner g_scanners[SCAN_MAX]
{ {
unsigned short *buf = b; scan_tcp,
unsigned int sum=0; NULL,
NULL,
for (sum = 0; len > 1; len -= 2) NULL,
sum += *((unsigned short*)buf++); NULL,
if (len == 1) NULL,
sum += *(unsigned char*)buf; /* scan_syn, */
/* scan_ack, */
sum = (sum >> 16) + (sum & 0xFFFF); /* scan_fin, */
return (~(sum + (sum >> 16))); /* scan_xmas, */
/* scan_udp, */
} }
coroutine void nmap_scan_node(t_host *host, struct iphdr *iph, int port) coroutine void nmap_scan_port(int ch, t_data *data, t_target target)
{ {
int channel; int fan_in;
t_tcp_packet packet; int fan_in_local;
int scan;
channel = host.channels[port]; fan_in = chmake(sizeof(t_scan_result));
while (scan = bitfield_lsb(data.scans, USHRT_MAX + 1))
packet.iph = *iph;
tcphdr_init(&packet.tcph);
packet.tcph.dest = htons(port);
packet.tcph.source = ;
/* packet.tcph.syn = 1; */
packet.tcph.check = cksum(&packet, sizeof(t_tcp_packet));
if ((host.sock_tcp = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
perror("server: socket");
int val = 1;
if (setsockopt(host.sock_tcp, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val)) == -1)
return (1);
if (sendto(data->sock_tcp, &packet, sizeof(packet), 0,
host->addr, host->addrlen) < 0)
{ {
perror("sendto"); data.scans &= ~scan;
exit(1); fan_in_local = hdup(fan_in);
scanner = g_scanners[scan];
go(scanner(fan_in_local, sock, target));
} }
/* chrecv(channel, &buf, sizeof()) */
printf("packet sent\n"); while (nport)
hexdump(&packet, sizeof(packet)); {
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) void nmap(t_data *data)
{ {
t_list *list; t_list *list;
t_host *host; t_host *host;
struct iphdr iph; int nhost;
int fan_in_local;
struct chclause clause[ft_lstsize(data->host)];
int buf;
iphdr_init(&iph); nhost = 0;
iph.protocol = IPPROTO_TCP;
iph.daddr = *(uint32_t*)&((struct sockaddr_in*)host->addr)->sin_addr;
iph.saddr = *(uint32_t*)&((struct sockaddr_in*)&data->source_addr)->sin_addr;
iph.tot_len = htons(sizeof(t_tcp_packet));
int fan_in = chmake(sizeof());
for (t_list *list = data->host; list != NULL; list = list->next) for (t_list *list = data->host; list != NULL; list = list->next)
{ {
t_host *host = list->content; host = list->content;
printf("scanning %s...\n", host->dn); fan_in_local = hdup(fan_in);
for (port = 1; port < USHRT_MAX; port++;) target.host = host;
{ go(nmap_scan_host(fan_in_local, data, target));
if (data.ports[port]) nhost++;
{
int fan_in_local = hdup(fan_in);
go(nmap_scan_node(data, iph, port, fan_in_local));
}
}
} }
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); return (fan_in);
} }

View file

@ -6,7 +6,7 @@
/* 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/08 21:05:14 by jhalford ### ########.fr */ /* Updated: 2017/10/09 14:51:21 by jhalford ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -82,19 +82,17 @@ static int nmap_get_scan(char *opt_arg, t_data *data)
while (*opt_arg) while (*opt_arg)
{ {
if (*opt_arg == 'T') if (*opt_arg == 'T')
data->scan |= SCAN_TCP; bitfield_biton(data->scans, SCAN_TCP);
else if (*opt_arg == 'S') else if (*opt_arg == 'S')
data->scan |= SCAN_SYN; bitfield_biton(data->scans, SCAN_SYN);
else if (*opt_arg == 'N')
data->scan |= SCAN_NULL;
else if (*opt_arg == 'A') else if (*opt_arg == 'A')
data->scan |= SCAN_ACK; bitfield_biton(data->scans, SCAN_ACK);
else if (*opt_arg == 'F') else if (*opt_arg == 'F')
data->scan |= SCAN_FIN; bitfield_biton(data->scans, SCAN_FIN);
else if (*opt_arg == 'X') else if (*opt_arg == 'X')
data->scan |= SCAN_XMAS; bitfield_biton(data->scans, SCAN_XMAS);
else if (*opt_arg == 'U') else if (*opt_arg == 'U')
data->scan |= SCAN_UDP; bitfield_biton(data->scans, SCAN_UDP);
else else
return (1); return (1);
opt_arg++; opt_arg++;
@ -107,7 +105,7 @@ int nmap_parse(int ac, char **av, t_data *data)
struct ifaddrs *ifaddrs, *ifa_first; struct ifaddrs *ifaddrs, *ifa_first;
(void)ac; (void)ac;
data->host = NULL; data->host = NULL;
bzero(data->ports, USHRT_MAX + 1); bzero(data->ports, sizeof(data->ports));
data->threads = 0; data->threads = 0;
data->scan = 0; data->scan = 0;
@ -132,18 +130,6 @@ int nmap_parse(int ac, char **av, t_data *data)
exit(1); exit(1);
} }
freeifaddrs(ifa_first); freeifaddrs(ifa_first);
bitfield_biton(data->ports, 80);
for (t_list *list = data->host; list != NULL; list = list->next)
{
t_host *host = list->content;
printf("scanning %s...\n", host->dn);
for (port = 1; port < USHRT_MAX; port++;)
{
if (data.ports[port])
host->channels[port] = chmake(sizeof(t_tcp_packet));
}
}
return (0); return (0);
} }

47
nmap/srcs/scanners.c Normal file
View file

@ -0,0 +1,47 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* scanners.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2017/10/09 15:28:42 by jhalford #+# #+# */
/* Updated: 2017/10/09 16:14:35 by jhalford ### ########.fr */
/* */
/* ************************************************************************** */
#include "nmap.h"
coroutine void nmap_scan_tcp(int ch, t_data *data, t_target target)
{
int listen;
t_scan_result res;
t_tcp_packet pkt;
listen = capture_chan(target);
iphdr_init(&pkt.iph);
pkt.iph.protocol = IPPROTO_TCP;
pkt.iph.saddr = *(uint32_t*)&((struct sockaddr_in*)&data->out_sa[target.scan])->sin_addr;
pkt.iph.daddr = *(uint32_t*)&((struct sockaddr_in*)target.host->addr)->sin_addr;
pkt.iph.tot_len = htons(sizeof(t_tcp_packet));
tcphdr_init(&pkt.tcph);
packet.tcph.dest = htons(target.port);
packet.tcph.check = cksum(&packet, sizeof(t_tcp_packet));
if (sendto(sock, &packet, sizeof(packet), 0,
host->addr, host->addrlen) < 0)
{
perror("sendto");
exit(1);
}
/* chrecv(channel, &buf, sizeof()) */
hexdump(&packet, sizeof(packet));
chsend(ch, res, sizeof(res), -1);
printf("result sent\n");
hclose(ch);
}