2012-10-17 141 views
0

我试图修改ip包到我的电脑。我使用iptables排队数据包和libnetfilter_queue库来修改数据包,实际上是一些http-header内容。即使我更改单个字符,数据包也会被拒绝,这很可能是由于tcp校验和的更改。所以,我正在尝试重新计算修改的数据包的tcp校验和。最初,为了测试校验和功能,我不修改数据包,只是重新计算校验和。但是计算出来的校验和与原来的不匹配。下面是校验功能:`计算的tcp校验和与原始的tcp校验和不匹配

unsigned short tcp_sum_calc(unsigned short len_tcp, unsigned short src_addr[],unsigned short dest_addr[], unsigned short buff[]) 
{ 
unsigned char prot_tcp=6; 
unsigned long sum; 
int nleft; 
unsigned short *w; 

sum = 0; 
nleft = len_tcp; 

w=buff; 

/* calculate the checksum for the tcp header and payload */ 
while(nleft > 1) 
{ 
sum = sum + ntohs(*w); 
w++; 
nleft = nleft - 2; 
} 

/* if nleft is 1 there ist still on byte left. We add a padding byte (0xFF) to build a 16bit word */ 
if(nleft>0) 
{ 
    cout<<"check out"; 
// sum += *w&0xFF; 
sum += ntohs(*w&0xFF00);   // is this the correct way of doing 
} 

/* add the pseudo header */ 
sum += ntohs(src_addr[0]); 
sum += ntohs(src_addr[1]); 
sum += ntohs(dest_addr[0]); 
sum += ntohs(dest_addr[1]); 
sum += len_tcp; 
sum += prot_tcp; 

// keep only the last 16 bits of the 32 bit calculated sum and add the carries 
sum = (sum >> 16) + (sum & 0xFFFF); 
sum += (sum >> 16); 

// Take the one's complement of sum 
sum = ~sum; 

return ((unsigned short) sum); 
} 

这里是libnetfilter_queue模块的回调函数:

static int analyzeResponse(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,struct nfq_data *nfa, void *data) 
{ 
int len=0,id=0; 
struct iphdr *ip; 
struct tcphdr *tcp; 
    char *pktData; 
string tempPkt; 
unsigned short chksum=0,ip_hdr_len,tcp_len; 
unsigned int src_ip, des_ip; 
struct nfqnl_msg_packet_hdr *pktHeader; 
pktHeader = nfq_get_msg_packet_hdr(nfa); 

if (pktHeader) 
{ 
    id = ntohl(pktHeader->packet_id); 
} 
len = nfq_get_payload ((struct nfq_data *) nfa, (char**)&ip); 

if(len) 
{ 
    pktData=(char*)ip; 
    ip_hdr_len=(unsigned short)(pktData[0]&0x7); 
    src_ip=ip->saddr; 
    des_ip=ip->daddr; 
    int pos; 
    tempPkt.assign(pktData,len); 
    pos=tempPkt.find("teststring",0); 
     tempPkt.replace("teststring"); 
    pktData=(char*)tempPkt.c_str(); 
      tcp = (struct tcphdr*) (pktData + (4*ip_hdr_len)); 

    cout<<"*********************************************************************************"; 
    cout<<ip_hdr_len; 
    cout<<"\ntcp checksum: "<<tcp->check; 
    cout<<"\nip packet length: "<<ip->tot_len; 
    cout<<"\nip packet length_calc: "<<len; 
    cout<<"\nip source address: "<<src_ip; 
    cout<<"\nip destination address: "<<des_ip; 
    cout<<"*********************************************************************************"; 
    tcp->check=0; 
tcp_len=len - (4*ip_hdr_len); 
    chksum = tcp_sum_calc(tcp_len, (unsigned short *) &src_ip, (unsigned short *) &des_ip, (unsigned short *) &tcp); 
    tcp->check=chksum; 
    cout<<"\nnew checkksum: "<<chksum; 
return nfq_set_verdict(qh, id, NF_ACCEPT, len, (unsigned char*)pktData); 

} 
return nfq_set_verdict(qh, id, NF_ACCEPT, len, (unsigned char*)pktData); 
} 

这里是输出:

5 
tcp checksum: 11687 
ip packet length: 54017 
ip packet length_calc: 467 
ip source address: 1719453657 
ip destination address: 2569775296 
new checkksum: 36507 

`

回答

2

它看起来像你没有纠正数据的尾数或伪头。原始数据是big-endian,但英特尔架构是小端。因此,在进行直接添加之前,您需要交换单词的字节 - 您可以使用ntohs()

看到这个example

+0

我做了必要的修正,但它仍然不起作用 –

+0

@adnankamili它仍然无效......但行为是否改变了? –

+0

是的行为改变了,也许我搞砸了。任何人都可以发布更正后的代码。 –