diff --git a/gitignore b/gitignore new file mode 100644 index 0000000..b99ad55 --- /dev/null +++ b/gitignore @@ -0,0 +1 @@ +./npcap \ No newline at end of file diff --git a/nethdr.h b/nethdr.h new file mode 100644 index 0000000..b7ca9eb --- /dev/null +++ b/nethdr.h @@ -0,0 +1,18 @@ +#ifndef NETHDR_H +#define NETHDR_H +#include + +struct arphdr_c { + uint16_t htype; + uint16_t ptype; + uint8_t hlen; + uint8_t plen; + uint16_t opcode; + uint8_t sender_mac[6]; + uint8_t sender_ip[4]; + uint8_t target_mac[6]; + uint8_t target_ip[4]; +} __attribute__((packed)); + + +#endif diff --git a/npcap.c b/npcap.c new file mode 100644 index 0000000..3710d3f --- /dev/null +++ b/npcap.c @@ -0,0 +1,124 @@ +// +// Created by ako on 8/22/25. +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "nethdr.h" +#include "npcap_handle.h" +#include +#include // if_nametoindex() + +void cleanup(int socket, unsigned char* buffer) { + close(socket); + free(buffer); +} + +int main() +{ + if (geteuid() != 0) + { + printf("Please run me as root.\n"); + return 1; + } + + int sock_raw = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (sock_raw < 0) + { + fprintf(stderr, "Unable to connect to network socket.\n"); + return -1; + } + + unsigned char *buffer = (unsigned char *) calloc(65536, sizeof(unsigned char)); + + if (buffer == NULL) { + fprintf(stderr, "Unable to connect to allocate memory.\n"); + cleanup(sock_raw, buffer); + return 1; + } + + struct sockaddr_ll sourceaddr; + socklen_t sourceaddr_len = sizeof(sourceaddr); + + int loopback_ifindex = if_nametoindex("lo"); + if (loopback_ifindex == 0) { + perror("if_nametoindex for lo"); + cleanup(sock_raw, buffer); + return 1; + } + + while (1) { + ssize_t buflen = recvfrom(sock_raw, buffer, 65536, 0, (struct sockaddr *)&sourceaddr, &sourceaddr_len); + + if (buflen == -1) { + perror("Couldn't read from socket"); + cleanup(sock_raw, buffer); + return 1; + } + + if (sourceaddr.sll_ifindex == loopback_ifindex) { + continue; + } + printf("\n===== Paquet reçu =====\n"); + printf("Paquet de %ld octets\n", buflen); + + // Debug + printf("Hexdump des 32 premiers octets:\n"); + for (int i = 0; i < 32 && i < buflen; i++) { + printf("%02x ", buffer[i]); + if ((i + 1) % 8 == 0) printf(" "); + } + printf("\n"); + + // + // COUCHE 2 + // + // Décodage entête Ethernet + struct ethhdr *eth = (struct ethhdr *)buffer; + handle_eth(eth); + + + // + // COUCHE 3 + // + switch (ntohs(eth->h_proto)) + { + // Décodage entête ARP + case ETH_P_ARP: + struct arphdr_c *arp = (struct arphdr_c *) (buffer + sizeof(struct ethhdr)); + handle_arp(arp); + break; + + case ETH_P_IP: + struct iphdr *ip = (struct iphdr *) (buffer + sizeof(struct ethhdr)); + handle_ip(ip); + + switch (ip->protocol) { + case 0x01: + handle_icmp(); + break; + case 0x06: + handle_tcp(); + break; + case 0x11: + handle_udp(); + break; + default: + break; + } + + break; + } + + // printf("\n=======================\n"); + } + cleanup(sock_raw, buffer); +} diff --git a/npcap_handle.c b/npcap_handle.c new file mode 100644 index 0000000..a5f0fc2 --- /dev/null +++ b/npcap_handle.c @@ -0,0 +1,69 @@ +#include "npcap_handle.h" + +int handle_eth(struct ethhdr* eth) { + printf("\nEthernet:\n"); + printf("\tSource : %02x:%02x:%02x:%02x:%02x:%02x\n", + eth->h_source[0], eth->h_source[1], eth->h_source[2], + eth->h_source[3], eth->h_source[4], eth->h_source[5]); + printf("\tDestination : %02x:%02x:%02x:%02x:%02x:%02x\n", + eth->h_dest[0], eth->h_dest[1], eth->h_dest[2], + eth->h_dest[3], eth->h_dest[4], eth->h_dest[5]); + printf("\tProtocole : 0x%04x\n", ntohs(eth->h_proto)); + return 0; +} + +int handle_arp(struct arphdr_c* arp) { + printf("\n\tARP:\n"); + printf("\t\tCode d'opération ARP : %d\n", arp->opcode); + printf("\t\tMAC Source : %02x:%02x:%02x:%02x:%02x:%02x\n", + arp->sender_mac[0], arp->sender_mac[1], arp->sender_mac[2], + arp->sender_mac[3], arp->sender_mac[4], arp->sender_mac[5]); + printf("\t\tIP Source : %d.%d.%d.%d\n", + arp->sender_ip[0], arp->sender_ip[1], arp->sender_ip[2], arp->sender_ip[3]); + printf("\t\tMAC Destination : %02x:%02x:%02x:%02x:%02x:%02x\n", + arp->target_mac[0], arp->target_mac[1], arp->target_mac[2], + arp->target_mac[3], arp->target_mac[4], arp->target_mac[5]); + printf("\t\tIP Destination : %d.%d.%d.%d\n", + arp->target_ip[0], arp->target_ip[1], arp->target_ip[2], arp->target_ip[3]); + return 0; + +} + +int handle_ip(struct iphdr* ip) { + + char srcip[INET_ADDRSTRLEN]; + char dstip[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &ip->saddr, srcip, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &ip->daddr, dstip, INET_ADDRSTRLEN); + char* protostr; + switch (ip->protocol) { + case 0x01: + protostr = "ICMP"; + break; + case 0x06: + protostr = "TCP"; + break; + case 0x11: + protostr = "UDP"; + break; + default: + protostr = "Unexpected"; + break; + } + + printf("\n\tIPv4:\n"); + printf("\t\tVersion : %d\n", ip->version); + printf("\t\tIHL : %d\n", ip->ihl); + printf("\t\tToS : %d\n", ip->tos); + printf("\t\tLongueur : %d\n", ip->tot_len); + printf("\t\tID : %d\n", ip->id); + // printf("\t\tFlags : %d%d%d\n"); + // printf("\t\tFragment offset:"); + printf("\t\tTTL : %d\n", ip->ttl); + printf("\t\tProtocole : 0x%02x (%s)\n", ip->protocol, protostr); + printf("\t\tHeader cksm: %d\n", ip->check); + printf("\t\tIP Source : %s\n", srcip); + printf("\t\tIP Dest. : %s\n", dstip); + return 0; + +} diff --git a/npcap_handle.h b/npcap_handle.h new file mode 100644 index 0000000..5120e2e --- /dev/null +++ b/npcap_handle.h @@ -0,0 +1,13 @@ +#ifndef NPCAP_HANDLE_H +#define NPCAP_HANDLE_H +#include +#include "nethdr.h" +#include +#include +#include + +int handle_eth(struct ethhdr* eth); +int handle_arp(struct arphdr_c* arp); +int handle_ip(struct iphdr* ip); + +#endif