2012-10-17 187 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

是的行爲改變了,也許我搞砸了。任何人都可以發佈更正後的代碼。 –