diff --git a/.gitignore b/.gitignore index 4dd5c54..9d73907 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ obj ft_nmap .cache compile_commands.json +tags diff --git a/include/packet.h b/include/packet.h new file mode 100644 index 0000000..3217e0a --- /dev/null +++ b/include/packet.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include "scan.h" + +struct pshdr { + uint32_t src_addr; + uint32_t dst_addr; + uint8_t placeholder; + uint8_t protocol; + uint16_t tcp_length; +}; + +int send_packets(const struct scan *data, int sockfd); +unsigned short checksum(void *data, int len); diff --git a/src/checksum.c b/src/checksum.c new file mode 100644 index 0000000..3e6cab9 --- /dev/null +++ b/src/checksum.c @@ -0,0 +1,13 @@ +#include + +unsigned short checksum(void *data, int len) +{ + unsigned short *cpy = data; + unsigned int sum = 0; + + for (int i = 0; i < len; i += 2) + sum += *cpy++; + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + return ~sum; +} diff --git a/src/main.c b/src/main.c index db71588..4faa132 100644 --- a/src/main.c +++ b/src/main.c @@ -34,9 +34,11 @@ int main(int ac, char **av) struct thread *single_thread = malloc(sizeof(struct thread)); if (get_interface_name(&single_thread->host) < 0) return 1; - single_thread->port_start = 1; + single_thread->dest_addr = ip_addr; + single_thread->port_start = 21; single_thread->port_end = 1024; single_thread->responses = responses; + single_thread->type = SCAN_SYN; if (routine(single_thread) == NULL) { dprintf(2, "ft_nmap: failed to scan ports\n"); return 1; diff --git a/src/packet.c b/src/packet.c new file mode 100644 index 0000000..d2c2051 --- /dev/null +++ b/src/packet.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "packet.h" +#include "scan.h" + +void create_udp_packet(struct udphdr *udphdr, const struct scan *data) +{ + udphdr->source = htons(1234); + udphdr->dest = htons(data->port); + udphdr->len = sizeof(struct udphdr); + udphdr->check = 0; + udphdr->check = checksum(udphdr, sizeof(struct udphdr)); +} + +int create_tcp_packet(struct tcphdr *tcphdr, const struct scan *data) +{ + tcphdr->source = htons(1234); + tcphdr->dest = htons(data->port); + tcphdr->seq = 0; + tcphdr->ack_seq = 0; + tcphdr->doff = sizeof(struct tcphdr) / sizeof(int); + tcphdr->fin = data->type == SCAN_XMAS || data->type == SCAN_FIN; + tcphdr->syn = data->type == SCAN_SYN; + tcphdr->rst = 0; + tcphdr->psh = data->type == SCAN_XMAS; + tcphdr->ack = data->type == SCAN_ACK; + tcphdr->urg = data->type == SCAN_XMAS; + tcphdr->window = htons(5840); + tcphdr->check = 0; + tcphdr->urg_ptr = 0; + + struct pshdr pshdr; + pshdr.src_addr = inet_addr(data->host->ip); + pshdr.dst_addr = inet_addr(data->dest_addr); + pshdr.placeholder = 0; + pshdr.protocol = IPPROTO_TCP; + pshdr.tcp_length = htons(sizeof(struct tcphdr)); + + size_t pseudogram_size = sizeof(struct pshdr) + sizeof(struct tcphdr); + void *pseudogram = malloc(pseudogram_size); + if (!pseudogram) + return -1; + memcpy(pseudogram, &pshdr, sizeof(pshdr)); + memcpy(pseudogram + sizeof(pshdr), tcphdr, sizeof(struct tcphdr)); + tcphdr->check = checksum(pseudogram, pseudogram_size); + free(pseudogram); + + return 0; +} + +static void *create_packet(const struct scan *data, size_t packet_size) +{ + const bool isudp = data->type == SCAN_UDP; + void *packet = malloc(packet_size); + if (!packet) { + dprintf(2, + "ft_nmap: allocation failed during packet creation\n"); + return NULL; + } + + struct iphdr *iphdr = packet; + iphdr->ihl = sizeof(struct iphdr) / sizeof(int); + iphdr->version = 4; + iphdr->tos = 0; + iphdr->tot_len = packet_size; + iphdr->id = htons(54321); + iphdr->frag_off = 0; + iphdr->ttl = 48; + iphdr->protocol = isudp ? IPPROTO_UDP : IPPROTO_TCP; + iphdr->check = 0; + iphdr->saddr = inet_addr(data->host->ip); + iphdr->daddr = inet_addr(data->dest_addr); + + iphdr->check = checksum(packet, packet_size); + + // this is starnakin stuff + switch ((int)isudp) { + case true: + create_udp_packet(packet + sizeof(struct iphdr), data); + break; + default: + create_tcp_packet(packet + sizeof(struct iphdr), data); + } + + return packet; +} + +int send_packets(const struct scan *data, int sockfd) +{ + struct sockaddr_in conn_addr; + + size_t packet_size = sizeof(struct iphdr) + + (data->type == SCAN_UDP ? sizeof(struct udphdr) + : sizeof(struct tcphdr)); + void *packet = create_packet(data, packet_size); + sendto(sockfd, packet, packet_size, 0, (struct sockaddr *)&conn_addr, + sizeof(struct sockaddr_in)); + free(packet); + + return 0; +} diff --git a/src/scan.c b/src/scan.c index 5e29a10..cf3e145 100644 --- a/src/scan.c +++ b/src/scan.c @@ -8,6 +8,7 @@ #include #include +#include "packet.h" #include "response.h" #include "scan.h" @@ -18,6 +19,8 @@ static void dispatch_callback(u_char *user, const struct pcap_pkthdr *h, const struct iphdr *iphdr = (struct iphdr *)(bytes + sizeof(struct ether_header)); + printf("uwu\n"); + if (iphdr->protocol == IPPROTO_TCP && h->caplen >= sizeof(struct ether_header) + sizeof(struct iphdr) + sizeof(struct tcphdr)) { @@ -43,8 +46,8 @@ static void dispatch_callback(u_char *user, const struct pcap_pkthdr *h, int scan(const struct scan *data) { - int sockfd = socket( - AF_INET, data->type == SCAN_UDP ? SOCK_DGRAM : SOCK_STREAM, 0); + int sockfd = socket(AF_INET, SOCK_RAW, + data->type == SCAN_UDP ? IPPROTO_UDP : IPPROTO_TCP); if (sockfd < 0) { dprintf(2, "ft_nmap: failed to create socket"); return -1; @@ -71,7 +74,7 @@ int scan(const struct scan *data) data->dest_addr, data->port, data->host->ip); if (pcap_compile(handle, &fp, pcap_expr, 0, mask) < 0) { - dprintf(2, "ft_nmap: failed to lookup net/mask\n"); + dprintf(2, "ft_nmap: failed to compile pcap expression\n"); pcap_close(handle); return -1; } @@ -84,7 +87,7 @@ int scan(const struct scan *data) pcap_freecode(&fp); - // send packets + send_packets(data, sockfd); // TODO test with another cnt value if (pcap_dispatch(handle, 10, dispatch_callback, (u_char *)data)) { diff --git a/src/thread.c b/src/thread.c index cea0414..15fe328 100644 --- a/src/thread.c +++ b/src/thread.c @@ -21,6 +21,8 @@ void *routine(void *p_data) scan_data.response = &thread_data->responses[thread_data->port_start - port]; scan(&scan_data); + printf("state of port %d: %d\n", port, + scan_data.response->state); } return p_data;