基于Passthru框架修改发送端IP不成功 本帖最后由 fo1_sky 于 2014-01-04 19:58:35 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 字数太多了,换IP的代码ChangeSendIP函数在这里给出VOID ChangeSendIP( PUCHAR buffer, int total_length ){ // 找到ip头所在位置 //PUCHAR ipheaderStart = buffer + 22; ////////////////////////////////////////////////////////////////////////// // IP头结构 // 4位版本号|4位首部长度|8位服务类型|16位总长度| // 16位标识 | 3位标志 | 13位片偏移 // 8位生存时间| 8位协议 | 16位首部检验各 // 32位源IP地址 // 32位目的IP地址 // 选项(如果有) // 数据 // 前面的不用管,只要找到第十二位的源IP,进行修改,然后计算校验各 // USHORT ipTotalLen = 0; PUCHAR ipHeaderStart = buffer + 14; PUCHAR tcpHeadStart = 0; USHORT tcpSourcePort = 0; USHORT tcpDstPort = 0; UINT sourceIP = 0; UINT targetIP = 0; UINT seriNUM = 0; // 找到IP首部长度 UCHAR ipHeadLen = *((PUCHAR)ipHeaderStart); ipHeadLen = ( ipHeadLen & 0X0F ) * 4; // TCP结构 // 16位源端口 | 16位目的端口 // 32位序号 // 32位确认序号 // 4位首部 | 保留6位 | URG|ACK|PSH|RST|SYN|FIN | 16位窗口大小 // 16位校验和 | 16位紧急指针 // 选项 // 数据 // 找到TCP的目的端口,如果目的端口不是80,则直接返回,暂时把所有的请求都进行 // 替换 tcpHeadStart = ipHeaderStart + ipHeadLen; tcpDstPort = NTOHS( *((PUSHORT)(tcpHeadStart + 2))); tcpSourcePort = NTOHS( *((PUSHORT)(tcpHeadStart))); // 用于测试的判断 if ( tcpDstPort != 6000 && tcpSourcePort != 6000 && tcpDstPort != 80 && tcpSourcePort != 80 ) { return; } // 找到总的长度位置,然后转换成本机字节序 *((PUCHAR)ipHeaderStart + 10) = 0; ipTotalLen = NTOHS ( *((PUSHORT) ( ipHeaderStart + 2 ) ) ); sourceIP = *((UINT*)(ipHeaderStart + 12)); sourceIP = NTOHL( sourceIP ); sourceIP = GeneratorIP( sourceIP, tcpSourcePort ); sourceIP = HTONL( sourceIP ); *((UINT*)(ipHeaderStart + 12)) = sourceIP; // 先把校验和清空,然后再重新计算 { { *((PUSHORT)(ipHeaderStart + 10 )) = 0; *((PUSHORT)(ipHeaderStart + 10 )) = cal_chksum( (PUSHORT)ipHeaderStart, (int) ipHeadLen ); } }} 计算校验和,不光有IP包的校验和要计算,还要重新计算Tcp数据包的校验和:typedef struct IP_HEADER{ UCHAR VIHL; // Version and IHL UCHAR TOS; // Type Of Service USHORT TotLen; // Total Length USHORT ID; // Identification USHORT FlagOff; // Flags and Fragment Offset UCHAR TTL; // Time To Live UCHAR Protocol; // Protocol USHORT Checksum; // Checksum ULONG iaSrc; // Internet Address - Source ULONG iaDst; // Internet Address - Destination}IP_HEADER, *PIP_HEADER;typedef struct PSD_HEADER{ ULONG srcip; //源IP地址 ULONG dstip; //目的IP地址 UCHAR mbz; //置空(0) UCHAR Protocol; //协议类型 USHORT plen; //TCP/UDP数据包的长度(即从TCP/UDP报头算起到数据包结束的长度 单位:字节) }PSD_HEADER, *PPSD_HEADER;// 求校验和函数USHORT CheckSum(ULONG addedCksum, USHORT *buffer, int size){ unsigned long cksum = addedCksum; while (size > 1) { cksum += *buffer++; size -= sizeof(USHORT); } if (size) { cksum += *(UCHAR*)buffer; } // 对每个16bit进行二进制反码求和 cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum);}// 求校验和函数ULONG CheckSumOnlyAdd(USHORT *buffer, int size){ unsigned long cksum=0; while (size > 1) { cksum += *buffer++; size -= sizeof(USHORT); } return cksum;}//求TCP或者UDP的校验和USHORT ReCalcCheckSum(PUCHAR pPacketContent){ USHORT checkSum; PSD_HEADER psdHeader; PIP_HEADER pIPHeader = (PIP_HEADER)(pPacketContent + IP_OFFSET); UINT ipHeaderLen = (pIPHeader->VIHL & 0x0F) * 4; PUSHORT pData = (PUSHORT)(pPacketContent + IP_OFFSET + ipHeaderLen); USHORT pLen = HTONS(pIPHeader->TotLen) - ipHeaderLen; psdHeader.dstip = pIPHeader->iaDst.S_un.S_addr; psdHeader.srcip = pIPHeader->iaSrc.S_un.S_addr; psdHeader.mbz = 0; psdHeader.Protocol = pIPHeader->Protocol; psdHeader.plen = HTONS(pLen); checkSum = CheckSum(CheckSumOnlyAdd((PUSHORT)&psdHeader, sizeof(PSD_HEADER)), pData, pLen); return checkSum;} 谢谢你这么细心看完我的代码.我还想确定,如果没有修改TCP数据段的内容,那么也需要重新校验?这个检验应该不包括IP头啊?还有PSDHeader,我在协议说明里面没找到在哪里定义的,能再说明一下吗? 我还想确定,如果没有修改TCP数据段的内容,那么也需要重新校验?因为你改了IP,而Tcp数据包是要较验IP地址的。这个检验应该不包括IP头啊?这个校验不包括IP头,要校验伪头部 + TCP数据包头 + TCP数据包数据,结果放在TCP数据包头的Checksum字段里。还有PSDHeader,我在协议说明里面没找到在哪里定义的,能再说明一下吗?PSDHeader就是伪头部,TCP/UDP数据包较验都要用到,结构上面有定义。dstip、srcip:目标IP地址、源IP地址,mbz设成0就行。Protocol设成IP数据包里的协议字段值就行,plen设成TCP/UDP数据包的长度(包头+数据)记得调用函数之前,先把TCP/UDP数据包头的Checksum字段设成0 我也记单词 vc++ 编译的exe程序,不知为什么会产生lib exp文件 请问在MFC AppWizard(dll)格式的dll中应该怎么声明一个全局变量? '&'的显示问题 关于CEditView中如何编辑字符 LNK1103的问题,大伙帮帮忙 需要 GDI+ 文档,中英文均可,但是要能离线看 请高手帮忙 新手求助:VC数据采集 VC如何和WEB服务器的ACCESS相连? 求大神们帮忙 如何从一段含有非时间信息的字符串中取出时间
{
// 找到ip头所在位置
//PUCHAR ipheaderStart = buffer + 22;
//////////////////////////////////////////////////////////////////////////
// IP头结构
// 4位版本号|4位首部长度|8位服务类型|16位总长度|
// 16位标识 | 3位标志 | 13位片偏移
// 8位生存时间| 8位协议 | 16位首部检验各
// 32位源IP地址
// 32位目的IP地址
// 选项(如果有)
// 数据
// 前面的不用管,只要找到第十二位的源IP,进行修改,然后计算校验各
// USHORT ipTotalLen = 0;
PUCHAR ipHeaderStart = buffer + 14; PUCHAR tcpHeadStart = 0;
USHORT tcpSourcePort = 0;
USHORT tcpDstPort = 0;
UINT sourceIP = 0;
UINT targetIP = 0; UINT seriNUM = 0; // 找到IP首部长度
UCHAR ipHeadLen = *((PUCHAR)ipHeaderStart);
ipHeadLen = ( ipHeadLen & 0X0F ) * 4;
// TCP结构
// 16位源端口 | 16位目的端口
// 32位序号
// 32位确认序号
// 4位首部 | 保留6位 | URG|ACK|PSH|RST|SYN|FIN | 16位窗口大小
// 16位校验和 | 16位紧急指针
// 选项
// 数据
// 找到TCP的目的端口,如果目的端口不是80,则直接返回,暂时把所有的请求都进行
// 替换
tcpHeadStart = ipHeaderStart + ipHeadLen;
tcpDstPort = NTOHS( *((PUSHORT)(tcpHeadStart + 2)));
tcpSourcePort = NTOHS( *((PUSHORT)(tcpHeadStart)));
// 用于测试的判断
if ( tcpDstPort != 6000 && tcpSourcePort != 6000 && tcpDstPort != 80 && tcpSourcePort != 80 )
{
return;
} // 找到总的长度位置,然后转换成本机字节序
*((PUCHAR)ipHeaderStart + 10) = 0;
ipTotalLen = NTOHS ( *((PUSHORT) ( ipHeaderStart + 2 ) ) ); sourceIP = *((UINT*)(ipHeaderStart + 12));
sourceIP = NTOHL( sourceIP );
sourceIP = GeneratorIP( sourceIP, tcpSourcePort );
sourceIP = HTONL( sourceIP );
*((UINT*)(ipHeaderStart + 12)) = sourceIP; // 先把校验和清空,然后再重新计算
{ {
*((PUSHORT)(ipHeaderStart + 10 )) = 0;
*((PUSHORT)(ipHeaderStart + 10 )) = cal_chksum( (PUSHORT)ipHeaderStart, (int) ipHeadLen );
} }
}
{
UCHAR VIHL; // Version and IHL
UCHAR TOS; // Type Of Service
USHORT TotLen; // Total Length
USHORT ID; // Identification
USHORT FlagOff; // Flags and Fragment Offset
UCHAR TTL; // Time To Live
UCHAR Protocol; // Protocol
USHORT Checksum; // Checksum
ULONG iaSrc; // Internet Address - Source
ULONG iaDst; // Internet Address - Destination
}IP_HEADER, *PIP_HEADER;typedef struct PSD_HEADER
{
ULONG srcip; //源IP地址
ULONG dstip; //目的IP地址
UCHAR mbz; //置空(0)
UCHAR Protocol; //协议类型
USHORT plen; //TCP/UDP数据包的长度(即从TCP/UDP报头算起到数据包结束的长度 单位:字节)
}PSD_HEADER, *PPSD_HEADER;
// 求校验和函数
USHORT CheckSum(ULONG addedCksum, USHORT *buffer, int size)
{
unsigned long cksum = addedCksum;
while (size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size)
{
cksum += *(UCHAR*)buffer;
}
// 对每个16bit进行二进制反码求和
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}// 求校验和函数
ULONG CheckSumOnlyAdd(USHORT *buffer, int size)
{
unsigned long cksum=0;
while (size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
return cksum;
}//求TCP或者UDP的校验和
USHORT ReCalcCheckSum(PUCHAR pPacketContent)
{
USHORT checkSum;
PSD_HEADER psdHeader; PIP_HEADER pIPHeader = (PIP_HEADER)(pPacketContent + IP_OFFSET);
UINT ipHeaderLen = (pIPHeader->VIHL & 0x0F) * 4;
PUSHORT pData = (PUSHORT)(pPacketContent + IP_OFFSET + ipHeaderLen);
USHORT pLen = HTONS(pIPHeader->TotLen) - ipHeaderLen; psdHeader.dstip = pIPHeader->iaDst.S_un.S_addr;
psdHeader.srcip = pIPHeader->iaSrc.S_un.S_addr;
psdHeader.mbz = 0;
psdHeader.Protocol = pIPHeader->Protocol;
psdHeader.plen = HTONS(pLen); checkSum = CheckSum(CheckSumOnlyAdd((PUSHORT)&psdHeader, sizeof(PSD_HEADER)),
pData, pLen); return checkSum;
}
我还想确定,如果没有修改TCP数据段的内容,那么也需要重新校验?这个检验应该不包括IP头啊?
还有PSDHeader,我在协议说明里面没找到在哪里定义的,能再说明一下吗?
因为你改了IP,而Tcp数据包是要较验IP地址的。这个检验应该不包括IP头啊?
这个校验不包括IP头,要校验伪头部 + TCP数据包头 + TCP数据包数据,结果放在TCP数据包头的Checksum字段里。还有PSDHeader,我在协议说明里面没找到在哪里定义的,能再说明一下吗?
PSDHeader就是伪头部,TCP/UDP数据包较验都要用到,结构上面有定义。
dstip、srcip:目标IP地址、源IP地址,mbz设成0就行。
Protocol设成IP数据包里的协议字段值就行,plen设成TCP/UDP数据包的长度(包头+数据)记得调用函数之前,先把TCP/UDP数据包头的Checksum字段设成0