高分求RAW SOCKET直接向目的地址发数据的代码??
高分求RAW SOCKET直接向目的地址发数据的代码??

解决方案 »

  1.   

    http://www.codeguru.com/Cpp/I-N/network/winsocksolutions/article.php/c2449
      

  2.   

    WIN XP SP2下无法发送RAW...#include <stdio.h>  #include <winsock2.h>
    #pragma comment(lib,"ws2_32.lib")   #include <ws2tcpip.h>  #define SOURCE_PORT 7234   
    #define MAX_RECEIVEBYTE 255   typedef struct ip_hdr   //定义IP首部   
    {   
    unsigned char h_verlen;   //4位首部长度,4位IP版本号   
    unsigned char tos;   //8位服务类型TOS   
    unsigned short total_len;   //16位总长度(字节)   
    unsigned short ident;   //16位标识   
    unsigned short frag_and_flags;   //3位标志位   
    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地址   
    }IPHEADER;   typedef struct tsd_hdr   //定义TCP伪首部   
    {   
    unsigned long saddr;   //源地址   
    unsigned long daddr;   //目的地址   
    char mbz;   
    char ptcl;   //协议类型   
    unsigned short tcpl;   //TCP长度   
    }PSDHEADER;   typedef struct tcp_hdr   //定义TCP首部   
    {   
    USHORT th_sport;   //16位源端口   
    USHORT th_dport;   //16位目的端口   
    unsigned int th_seq;   //32位序列号   
    unsigned int th_ack;   //32位确认号   
    unsigned char th_lenres;   //4位首部长度/6位保留字   
    unsigned char th_flag;   //6位标志位   
    USHORT th_win;   //16位窗口大小   
    USHORT th_sum;   //16位校验和   
    USHORT th_urp;   //16位紧急数据偏移量   
    }TCPHEADER;   //计算校验和的子函数   
    USHORT checksum(USHORT *buffer,int size)   
    {   
    unsigned long cksum=0;   
    while(size>1)   
    {   
    cksum+=*buffer++;   
    size-=sizeof(USHORT);   
    }   
    if(size)   
    {   
    cksum +=*(UCHAR*)buffer;   
    }   

    cksum=(cksum >>16)+(cksum & 0xffff);   
    cksum+=(cksum >>16);   
    return  (USHORT)(~cksum);   
    }   void useage()
    {   
    printf("***********************************************\n");
    printf("Useage:   TCPPing.exe   Target_ip   Target_port\n");
    printf("***********************************************\n");
    }int main(int argc,char* argv[])   
    {   
    WSADATA WSAData;   
    SOCKET sock;   
    SOCKADDR_IN addr_in;   
    IPHEADER ipHeader;   
    TCPHEADER tcpHeader;   
    PSDHEADER psdHeader;   

    char szSendBuf[60]={0};   
    BOOL flag;   
    int rect,nTimeOver;   

    useage();   

    if(argc!=3)   
    {   
    return false;   
    }   

    if(WSAStartup(MAKEWORD(2,2),&WSAData)!=0)   
    {   
    printf("WSAStartup Error!\n");   
    return false;   
    }   

    if((sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)   
    {   
    printf("Socket Setup Error!\n");   
    return false;   
    }   
    flag=true;   
    if (setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char*)&flag,sizeof(flag))==SOCKET_ERROR)   
    {   
    printf("setsockopt IP_HDRINCL error!\n");   
    return false;   
    }   

    nTimeOver=1000;   
    if(setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(char*)&nTimeOver,sizeof(nTimeOver))==SOCKET_ERROR)   
    {   
    printf("setsockopt SO_SNDTIMEO error!\n");   
    return false;   
    }    addr_in.sin_family=AF_INET;   
    addr_in.sin_port=htons(atoi(argv[2]));   
    addr_in.sin_addr.S_un.S_addr=inet_addr(argv[1]);   
     
    //填充IP首部   
    ipHeader.h_verlen=(4<<4 | sizeof(ipHeader)/sizeof(unsigned   long));   
    ipHeader.tos=0;   
    ipHeader.total_len=htons(sizeof(ipHeader)+sizeof(tcpHeader));   
    ipHeader.ident=1;   
    ipHeader.frag_and_flags=0;   
    ipHeader.ttl=128;   
    ipHeader.proto=IPPROTO_TCP;   
    ipHeader.checksum=0;   
    ipHeader.sourceIP=inet_addr("127.0.0.1");   
    ipHeader.destIP=inet_addr(argv[1]);   

    //填充TCP首部   
    tcpHeader.th_dport=htons(atoi(argv[2]));   
    tcpHeader.th_sport=htons(SOURCE_PORT);   //源端口号   
    tcpHeader.th_seq=htonl(0x12345678);   
    tcpHeader.th_ack=0;   
    tcpHeader.th_lenres=(sizeof(tcpHeader)/4<<4|0);   
    tcpHeader.th_flag=2;   //修改这里来实现不同的标志位探测,2是SYN,1是FIN,16是ACK探测   等等   
    tcpHeader.th_win=htons(512);   
    tcpHeader.th_urp=0;   
    tcpHeader.th_sum=0;   

    psdHeader.saddr=ipHeader.sourceIP;   
    psdHeader.daddr=ipHeader.destIP;   
    psdHeader.mbz=0;   
    psdHeader.ptcl=IPPROTO_TCP;   
    psdHeader.tcpl=htons(sizeof(tcpHeader));   

    //计算校验和   
    memcpy(szSendBuf, &psdHeader, sizeof(psdHeader));   
    memcpy(szSendBuf+sizeof(psdHeader), &tcpHeader,sizeof(tcpHeader));   
    tcpHeader.th_sum=checksum((USHORT *)szSendBuf,sizeof(psdHeader)+sizeof(tcpHeader));   

    memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));   
    memcpy(szSendBuf+sizeof(ipHeader),&tcpHeader,sizeof(tcpHeader));   
    memset(szSendBuf+sizeof(ipHeader)+sizeof(tcpHeader),0,4);   
    ipHeader.checksum=checksum((USHORT *)szSendBuf,sizeof(ipHeader)+sizeof(tcpHeader));   

    memcpy(szSendBuf,&ipHeader,sizeof(ipHeader));   

    rect=sendto(sock,szSendBuf,sizeof(ipHeader)+sizeof(tcpHeader),0,(struct sockaddr*)&addr_in,sizeof(addr_in));   
    if (rect==SOCKET_ERROR)   
    {   
    printf("send error!:%d\n",WSAGetLastError());   
    return false;   
    }   
    else   
    printf("send ok!\n");   

    closesocket(sock); WSACleanup();

    return   0;   
    }   
      

  3.   

    发送 ICMP 就是一个raw socket。ping 程序就是个好例子:
    //
    // Ping.h
    //#pragma pack(1)#define ICMP_ECHOREPLY 0
    #define ICMP_ECHOREQ 8// IP Header -- RFC 791
    typedef struct tagIPHDR
    {
    u_char  VIHL; // Version and IHL
    u_char TOS; // Type Of Service
    short TotLen; // Total Length
    short ID; // Identification
    short FlagOff; // Flags and Fragment Offset
    u_char TTL; // Time To Live
    u_char Protocol; // Protocol
    u_short Checksum; // Checksum
    struct in_addr iaSrc; // Internet Address - Source
    struct in_addr iaDst; // Internet Address - Destination
    }IPHDR, *PIPHDR;
    // ICMP Header - RFC 792
    typedef struct tagICMPHDR
    {
    u_char Type; // Type
    u_char Code; // Code
    u_short Checksum; // Checksum
    u_short ID; // Identification
    u_short Seq; // Sequence
    char Data; // Data
    }ICMPHDR, *PICMPHDR;
    #define REQ_DATASIZE 32 // Echo Request Data size// ICMP Echo Request
    typedef struct tagECHOREQUEST
    {
    ICMPHDR icmpHdr;
    DWORD dwTime;
    char cData[REQ_DATASIZE];
    }ECHOREQUEST, *PECHOREQUEST;
    // ICMP Echo Reply
    typedef struct tagECHOREPLY
    {
    IPHDR ipHdr;
    ECHOREQUEST echoRequest;
    char    cFiller[256];
    }ECHOREPLY, *PECHOREPLY;
    #pragma pack()//
    // PING.C -- Ping program using ICMP and RAW Sockets
    //#include <stdio.h>
    #include <stdlib.h>
    #include <winsock.h>#include "ping.h"// Internal Functions
    void Ping(LPCSTR pstrHost);
    void ReportError(LPCSTR pstrFrom);
    int  WaitForEchoReply(SOCKET s);
    u_short in_cksum(u_short *addr, int len);// ICMP Echo Request/Reply functions
    int SendEchoRequest(SOCKET, LPSOCKADDR_IN);
    DWORD RecvEchoReply(SOCKET, LPSOCKADDR_IN, u_char *);
    // main()
    void main(int argc, char **argv)
    {
        WSADATA wsaData;
        WORD wVersionRequested = MAKEWORD(1,1);
        int nRet; // Check arguments
        if (argc != 2)
        {
    fprintf(stderr,"\nUsage: ping hostname\n");
    return;
        } // Init WinSock
        nRet = WSAStartup(wVersionRequested, &wsaData);
        if (nRet)
        {
    fprintf(stderr,"\nError initializing WinSock\n");
    return;
        } // Check version
    if (wsaData.wVersion != wVersionRequested)
    {
    fprintf(stderr,"\nWinSock version not supported\n");
    return;
    } // Go do the ping
    Ping(argv[1]); // Free WinSock
        WSACleanup();
    }
    // Ping()
    // Calls SendEchoRequest() and
    // RecvEchoReply() and prints results
    void Ping(LPCSTR pstrHost)
    {
    SOCKET   rawSocket;
    LPHOSTENT lpHost;
    struct    sockaddr_in saDest;
    struct    sockaddr_in saSrc;
    DWORD   dwTimeSent;
    DWORD   dwElapsed;
    u_char    cTTL;
    int       nLoop;
    int       nRet; // Create a Raw socket
    rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    if (rawSocket == SOCKET_ERROR) 
    {
    ReportError("socket()");
    return;
    }

    // Lookup host
    lpHost = gethostbyname(pstrHost);
    if (lpHost == NULL)
    {
    fprintf(stderr,"\nHost not found: %s\n", pstrHost);
    return;
    }

    // Setup destination socket address
    //saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));
    saDest.sin_addr.s_addr =inet_addr("127.0.0.1");
    saDest.sin_family = AF_INET;
    saDest.sin_port = 0; // Tell the user what we're doing
    printf("\nPinging %s [%s] with %d bytes of data:\n",
    pstrHost,
    inet_ntoa(saDest.sin_addr),
    REQ_DATASIZE); // Ping multiple times
    for (nLoop = 0; nLoop < 4; nLoop++)
    {
    // Send ICMP echo request
    SendEchoRequest(rawSocket, &saDest); // Use select() to wait for data to be received
    nRet = WaitForEchoReply(rawSocket);
    if (nRet == SOCKET_ERROR)
    {
    ReportError("select()");
    break;
    }
    if (!nRet)
    {
    printf("\nTimeOut");
    break;
    } // Receive reply
    dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL); // Calculate elapsed time
    dwElapsed = GetTickCount() - dwTimeSent;
    printf("\nReply from: %s: bytes=%d time=%ldms TTL=%d", 
                   inet_ntoa(saSrc.sin_addr), 
       REQ_DATASIZE,
                   dwElapsed,
                   cTTL);
    }
    printf("\n");
    nRet = closesocket(rawSocket);
    if (nRet == SOCKET_ERROR)
    ReportError("closesocket()");
    }
    // SendEchoRequest()
    // Fill in echo request header
    // and send to destination
    int SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr) 
    {
    static ECHOREQUEST echoReq;
    static nId = 1;
    static nSeq = 1;
    int nRet; // Fill in echo request
    echoReq.icmpHdr.Type = ICMP_ECHOREQ;
    echoReq.icmpHdr.Code = 0;
    echoReq.icmpHdr.Checksum = 0;
    echoReq.icmpHdr.ID = nId++;
    echoReq.icmpHdr.Seq = nSeq++; // Fill in some data to send
    for (nRet = 0; nRet < REQ_DATASIZE; nRet++)
    echoReq.cData[nRet] = ' '+nRet; // Save tick count when sent
    echoReq.dwTime = GetTickCount(); // Put data in packet and compute checksum
    echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST)); // Send the echo request     
    nRet = sendto(s, /* socket */
     (LPSTR)&echoReq, /* buffer */
     sizeof(ECHOREQUEST),
     0, /* flags */
     (LPSOCKADDR)lpstToAddr, /* destination */
     sizeof(SOCKADDR_IN));   /* address length */ if (nRet == SOCKET_ERROR) 
    ReportError("sendto()");
    return (nRet);
    }
    // RecvEchoReply()
    // Receive incoming data
    // and parse out fields
    DWORD RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL) 
    {
    ECHOREPLY echoReply;
    int nRet;
    int nAddrLen = sizeof(struct sockaddr_in); // Receive the echo reply
    nRet = recvfrom(s, // socket
    (LPSTR)&echoReply, // buffer
    sizeof(ECHOREPLY), // size of buffer
    0, // flags
    (LPSOCKADDR)lpsaFrom, // From address
    &nAddrLen); // pointer to address len // Check return value
    if (nRet == SOCKET_ERROR) 
    ReportError("recvfrom()"); // return time sent and IP TTL
    *pTTL = echoReply.ipHdr.TTL;
    return(echoReply.echoRequest.dwTime);   
    }// What happened?
    void ReportError(LPCSTR pWhere)
    {
    fprintf(stderr,"\n%s error: %d\n",
    WSAGetLastError());
    }
    // WaitForEchoReply()
    // Use select() to determine when
    // data is waiting to be read
    int WaitForEchoReply(SOCKET s)
    {
    struct timeval Timeout;
    fd_set readfds; readfds.fd_count = 1;
    readfds.fd_array[0] = s;
    Timeout.tv_sec = 5;
        Timeout.tv_usec = 0; return(select(1, &readfds, NULL, NULL, &Timeout));
    }
    //
    // Mike Muuss' in_cksum() function
    // and his comments from the original
    // ping program
    //
    // * Author -
    // * Mike Muuss
    // * U. S. Army Ballistic Research Laboratory
    // * December, 1983/*
     * I N _ C K S U M
     *
     * Checksum routine for Internet Protocol family headers (C Version)
     *
     */
    u_short in_cksum(u_short *addr, int len)
    {
    register int nleft = len;
    register u_short *w = addr;
    register u_short answer;
    register int sum = 0; /*
     *  Our algorithm is simple, using a 32 bit accumulator (sum),
     *  we add sequential 16 bit words to it, and at the end, fold
     *  back all the carry bits from the top 16 bits into the lower
     *  16 bits.
     */
    while( nleft > 1 )  {
    sum += *w++;
    nleft -= 2;
    } /* mop up an odd byte, if necessary */
    if( nleft == 1 ) {
    u_short u = 0; *(u_char *)(&u) = *(u_char *)w ;
    sum += u;
    } /*
     * add back carry outs from top 16 bits to low 16 bits
     */
    sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
    sum += (sum >> 16); /* add carry */
    answer = ~sum; /* truncate to 16 bits */
    return (answer);
    }