zhang1990214
繁华落尽梦一场-
采纳率0%
2015-04-19 09:38

用winpcap发送syn数据包后收不到ack回复

用wincap发送syn,这样的帖子网上搜一下一大片,但在我做的过程中发现几个问题:
1、tcp报头校验时应该是 伪报头+tcp包头+数据的校验,很多人只是tcp包头+数据的校验,我不知道这些人到底有没有真正写给程序。
2、用winpcap发送数据包时需要添加以太网包头,其中包含源/目标主机的mac地址,有些人这儿全写1,有些写的各自的mac地址,但是假如我真的要和远端服务器建立连接时我只能知道它的ip地址,不可能知道mac地址,所以这个地方应该怎么写。
3、我用winpcap发送syn后收不到ack回应,忘大神指导。一下是代码
#include
#include
#include
#include
#include
using namespace std;

#pragma comment(lib, "lib/Packet.lib")
#pragma comment(lib, "lib/wpcap.lib")
#pragma comment(lib, "ws2_32.lib")

/* IP报文格式
0 8 16 32
+------------+------------+-------------------------+
| ver + hlen | 服务类型 | 总长度 |
+------------+------------+----+--------------------+
| 标识位 |flag| 分片偏移(13位) |
+------------+------------+----+--------------------+
| 生存时间 | 高层协议号 | 首部校验和 |
+------------+------------+-------------------------+
| 源 IP 地址 |
+---------------------------------------------------+
| 目的 IP 地址 |
+---------------------------------------------------+

*/

struct IP_HEADER
{
byte versionAndHeader;
byte serviceType;
byte totalLen[2];
byte seqNumber[2];
byte flagAndFragPart[2];
byte ttl;
byte hiProtovolType;
byte headerCheckSum[2];
byte srcIpAddr[4];
byte dstIpAddr[4];
};

/*
TCP 报文
0 16 32
+------------------------+-------------------------+
| 源端口地址 | 目的端口地址 |
+------------------------+-------------------------+
| 序列号 |
+--------------------------------------------------+
| 确认号 |
+------+--------+--------+-------------------------+
|HLEN/4| 保留位 |控制位/6| 窗口尺寸 |
+------+--------+--------+-------------------------+
| 校验和 | 应急指针 |
+------------------------+-------------------------+
*/

struct TCP_HEADER
{
byte srcPort[2];
byte dstPort[2];
byte seqNumber[4];
byte ackNumber[4];
byte headLen;
byte contrl;
byte wndSize[2];
byte checkSum[2];
byte uragentPtr[2];
};

struct PSDTCP_HEADER
{
byte srcIpAddr[4]; //Source IP address; 32 bits
byte dstIpAddr[4]; //Destination IP address; 32 bits
byte padding; //padding
byte protocol; //Protocol; 8 bits
byte tcpLen[2]; //TCP length; 16 bits

} ;

struct ETHERNET_HEADER
{

byte dstMacAddr[6];
byte srcMacAddr[6];
byte ethernetType[2];
};

struct DEVS_INFO
{
char szDevName[512];
char szDevsDescription[512];
};

int GetAllDevs( DEVS_INFO devsList[] )
{
int nDevsNum = 0;
pcap_if_t *alldevs;
char errbuf[PCAP_ERRBUF_SIZE];
if ( pcap_findalldevs(&alldevs,errbuf) == -1 )
{
return -1;
printf("error in pcap_findalldevs_ex: %s\n",errbuf);
}
for ( pcap_if_t *d = alldevs; d != NULL; d = d->next )
{
strcpy( devsList[nDevsNum].szDevName, d->name );
strcpy( devsList[nDevsNum].szDevsDescription, d->description );
nDevsNum++;
}
pcap_freealldevs(alldevs);

return nDevsNum;

}

char *FormatMacAddr( unsigned char *ucMacAddr, char *szStr )
{
szStr[0] = '\0';
char str[8];
for ( int i = 0; i < 6; ++i)
{
sprintf( str, "0x%02x-", ucMacAddr[i]);
if ( str[2] >= 'a' && str[2] <= 'z' )
{
str[2] = 'A' + str[2] - 'a';
}
if ( str[3] >= 'a' && str[3] <= 'z' )
{
str[3] = 'A' + str[3] - 'a';
}
strcat( szStr, str );
}
szStr[strlen(szStr) - 1] = '\0';

return szStr;

}

char *FormatIpAddr( unsigned uIpAddr, char szIp[] )
{
IN_ADDR addr;
addr.S_un.S_addr = uIpAddr;

strcpy( szIp, inet_ntoa( addr ) );
return szIp;

}

void DecodeTcpPacket( const byte *packet )
{
TCP_HEADER *pTcpHeader = (TCP_HEADER *)packet;
//printf("%d\n", pTcpHeader->contrl);
//printf("%d\n", (0x01 << 4) | (0x1 << 1) );

if ( pTcpHeader->contrl == 18 )// (0x01 << 4) | (0x1 << 1) )
{
    printf("收到ack回应");
}

}

void DecodeIpPacket( const unsigned char *ucPacket )
{
IP_HEADER *pIpHeader = ( IP_HEADER *)ucPacket;
unsigned srcIp = *( unsigned *) pIpHeader->srcIpAddr;
unsigned dstIp = *( unsigned *) pIpHeader->dstIpAddr;

memcpy(&srcIp, pIpHeader->srcIpAddr, 4);
memcpy(&dstIp, pIpHeader->dstIpAddr, 4);


char szSrcIp[32], szDstIp[32];
FormatIpAddr( srcIp, szSrcIp );
FormatIpAddr( dstIp, szDstIp );
if ( 0 != strcmp("10.126.72.37", szDstIp ) || 0 != strcmp("10.126.72.37", szSrcIp) ) return;

if ( pIpHeader->hiProtovolType != 0x06 ) return;

DecodeTcpPacket( (byte *)(ucPacket + sizeof(IP_HEADER)) );
//printf("Ip: %s\t%s\n", szSrcIp,szDstIp );

}

void HandlePacketCallBack(unsigned char param,const struct pcap_pkthdr packet_header, const unsigned char *ucCaptureContent)
{
ETHERNET_HEADER *pEthHeader = ( ETHERNET_HEADER *)ucCaptureContent;
if ( *((unsigned short *)(pEthHeader->ethernetType)) == htons(0x0800) )
{
ETHERNET_HEADER *pEthHeader = ( ETHERNET_HEADER *)ucCaptureContent;
unsigned char srcMac[6], dstMac[6];
memcpy(srcMac, pEthHeader->srcMacAddr, 6);
memcpy(dstMac, pEthHeader->dstMacAddr, 6);

    char szSrcMac[32], szDstMac[32];
    FormatMacAddr(srcMac, szSrcMac);
    FormatMacAddr(dstMac, szDstMac);
    //printf("MAC: %s\t%s\n", szSrcMac,szDstMac );

    DecodeIpPacket( ucCaptureContent + sizeof (ETHERNET_HEADER) );
}
return;

}

unsigned short CheckSum(unsigned short packet[], int size )
{
unsigned long cksum = 0;
while (size > 1)
{
cksum += packet++;
size -= sizeof(USHORT);
}
if (size)
{
cksum += *(UCHAR
)packet;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);

return (USHORT)(~cksum);

}

int main()
{
DEVS_INFO devsList[64];
int nDevsNum = GetAllDevs( devsList );
if ( nDevsNum < 1 )
{
printf("Get adapter infomation failed!");
exit(0);
}
int selIndex = 5;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *handle = pcap_open_live(devsList[selIndex-1].szDevName, 65536, 1, 1000, errbuf );
if ( NULL == handle ) return 0;

const char *lpszSrcIp = "192.168.5.101";
const char *lpszDstIp = "119.75.218.70";


TCP_HEADER tcpHeader;
memset(&tcpHeader, 0, sizeof tcpHeader );
*(unsigned short *)tcpHeader.srcPort = htons(9999);
*(unsigned short *)tcpHeader.dstPort = htons(80);
*(unsigned int *)tcpHeader.seqNumber = htonl(0xFF);
*(unsigned int *)tcpHeader.ackNumber = htonl(0x00);
tcpHeader.headLen = 5 << 4; 
tcpHeader.contrl = 1 << 1;
*(unsigned short *)tcpHeader.wndSize = htons(0xFF);

PSDTCP_HEADER psdHeader;
memset(&psdHeader, 0, sizeof psdHeader);
*(unsigned int *)psdHeader.dstIpAddr = inet_addr( lpszDstIp );
*(unsigned int *)psdHeader.srcIpAddr = inet_addr( lpszSrcIp );
psdHeader.protocol = 0x06;
*(unsigned short *)psdHeader.tcpLen = htons(sizeof(TCP_HEADER));

char data[] = "Hello world";

byte psdPacket[1024];
memset( psdPacket, 0, sizeof psdPacket);
memcpy( psdPacket, &psdHeader, sizeof psdHeader );
memcpy( psdPacket + sizeof psdHeader, &tcpHeader, sizeof tcpHeader );
//memcpy( psdPacket + sizeof psdHeader + sizeof tcpHeader, data, sizeof data );

*(unsigned short *)tcpHeader.checkSum = (CheckSum( (unsigned short*) psdPacket, sizeof psdHeader + sizeof tcpHeader ) );


IP_HEADER ipHeader;
memset( &ipHeader, 0, sizeof ipHeader );
unsigned char versionAndLen = 0x04;
versionAndLen <<= 4;
versionAndLen |= sizeof ipHeader / 4; //版本 + 头长度

ipHeader.versionAndHeader = versionAndLen;
*(unsigned short *)ipHeader.totalLen = htons( sizeof(IP_HEADER) + sizeof(TCP_HEADER) ); 

ipHeader.ttl = 0xFF;
ipHeader.hiProtovolType = 0x06;

*(unsigned int *)(ipHeader.srcIpAddr) = inet_addr( lpszSrcIp );
*(unsigned int *)(ipHeader.dstIpAddr) = inet_addr( lpszDstIp );
*(unsigned short *)(ipHeader.headerCheckSum) = CheckSum( (unsigned short *)&ipHeader, sizeof ipHeader );

byte srcMac[] = {0x64, 0x27, 0x37, 0x7D, 0xF7, 0x74};
byte dstMac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
//byte mac[] = {0x90, 0x2B, 0x34, 0x9A, 0xC2, 0xBB};

ETHERNET_HEADER ethHeader;
memset(&ethHeader, 0, sizeof ethHeader);
//memcpy(ethHeader.dstMacAddr, dstMac, 6);
memcpy(ethHeader.srcMacAddr, srcMac, 6); //这个地方的源/目标主机mac地址怎么写
*(unsigned short *)ethHeader.ethernetType = htons(0x0800);

byte packet[1024];
memset(packet, 0, sizeof packet);

memcpy(packet, &ethHeader, sizeof ethHeader);
memcpy(packet + sizeof ethHeader, &ipHeader, sizeof ipHeader);
memcpy(packet + sizeof ethHeader + sizeof ipHeader, &tcpHeader, sizeof tcpHeader);
//memcpy(packet + sizeof ethHeader + sizeof ipHeader + sizeof tcpHeader, data, sizeof data );


unsigned int syn = *(unsigned int *)tcpHeader.seqNumber;
unsigned char ctl = *(unsigned char*)&tcpHeader.contrl;
printf("%d\n%d\n", ntohl(syn), ctl);

int size = sizeof ethHeader + sizeof ipHeader + sizeof tcpHeader;// + sizeof data;
//while ( 1 )
{
    system("pause");
    pcap_sendpacket(handle, packet, size );
}

if ( NULL == handle )
{
    printf("\nUnable to open the adapter. %s is not supported by WinPcap\n");
    return 0;
}
pcap_close(handle); 
return 0;

}


  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

5条回答

  • hwhaocool Yellow_Tail 6年前

    发syn包时,不是对服务器发的,而是对你的网关发的,你发给网关后,后续的工作由它完成,也就是说你发syn包,
    根本不用考虑服务器的MAC,只需要知道你网关的MAC和服务器IP即可。
    所以说你的第二个问题有点多余,

    当然如果没有网关,也可以在syn之前ping一下,winpcap截获数据包,提取MAC

    点赞 1 评论 复制链接分享
  • zzkjliu zzkjliu 6年前

    关于你的第二个问题:

    1、TCP/IP是网络层的概念,MAC地址是链路层的概念。
    2、在链路层,含有MAC地址的以太网包只能在局域网或虚拟局域网中的同一网段(子网)传输,目标主机的mac是通过ARP获得的。
    3、如果目的IP位于其他子网、或广域网(互联网),只要传输给本子网的网关或路由器即可,这称为一跳,接下去第2跳由网关或路由器完成,然后会一跳一跳的继续下去,最后到达目的IP。IP协议中有个TTL字段,这个就是设置该IP包最多可经过多少跳的,每经过一跳该字段减1,到0时如果还到不了目的地,该IP包就会被抛弃。traceroute就是用于观察到目的地需要经过哪些路由器和总共需要多少跳得。

    这样简单的说,对于没有链路层概念的人未必能明白,建议看看Richard Steven的《TCP/IP详解》这本书。

    点赞 1 评论 复制链接分享
  • yxlorange yxlorange 5年前

    你不需要知道mac地址,mac地址是在数据链路层填充的,你软件里不需要设置。

    点赞 评论 复制链接分享
  • zhang1990214 繁华落尽梦一场- 6年前

    这篇帖子没解决我的第二个问题,第一次连接的时候我不可能知道对方的mac地址,不然直接用mac,不用ip了

    点赞 评论 复制链接分享
  • devmiao devmiao 6年前
    点赞 评论 复制链接分享