syn패킷보낼때 tcp 체크섬 계산
글쓴이: suner / 작성시간: 금, 2008/08/22 - 6:46오후
window 2000에서 rawsocket을 구현해 보았는데요
현재 syn 패킷이 발송됬다고 이더렐로 잡힙니다.
그러나 체크섬을 계산하지 못해서 syn + ack가 넘어오지 않습니다.
아래는 인터넷에서 찾은 소스인데 ip는 체크섬이 제대로 되는데
tcp가 체크섬이 안되네요, 가상 해더 역시 인터넷에 있는 소스를 구해서 적용해 보았습니다.
뭐가 틀렸는지 알려 주시면 감사하겠습니다.
//raw tcp packet crafter
#include "stdio.h"
#include "winsock2.h"
#include "ws2tcpip.h" //IP_HDRINCL is here
#include "conio.h"
#pragma comment(lib,"ws2_32.lib") //winsock 2.2 library
typedef struct ip_hdr
{
unsigned char ip_header_len:4; // 4-bit header length (in 32-bit words) normally=5 (Means 20 Bytes may be 24 also)
unsigned char ip_version :4; // 4-bit IPv4 version
unsigned char ip_tos; // IP type of service
unsigned short ip_total_length; // Total length
unsigned short ip_id; // Unique identifier
unsigned char ip_frag_offset :5; // Fragment offset field
unsigned char ip_more_fragment :1;
unsigned char ip_dont_fragment :1;
unsigned char ip_reserved_zero :1;
unsigned char ip_frag_offset1; //fragment offset
unsigned char ip_ttl; // Time to live
unsigned char ip_protocol; // Protocol(TCP,UDP etc)
unsigned short ip_checksum; // IP checksum
unsigned int ip_srcaddr; // Source address
unsigned int ip_destaddr; // Source address
} IPV4_HDR, *PIPV4_HDR, FAR * LPIPV4_HDR;
// TCP header
typedef struct tcp_header
{
unsigned short source_port; // source port
unsigned short dest_port; // destination port
unsigned int sequence; // sequence number - 32 bits
unsigned int acknowledge; // acknowledgement number - 32 bits
unsigned char ns :1; //Nonce Sum Flag Added in RFC 3540.
unsigned char reserved_part1:3; //according to rfc
unsigned char data_offset:4; /*The number of 32-bit words in the TCP header.
This indicates where the data begins.
The length of the TCP header is always a multiple
of 32 bits.*/
unsigned char fin :1; //Finish Flag
unsigned char syn :1; //Synchronise Flag
unsigned char rst :1; //Reset Flag
unsigned char psh :1; //Push Flag
unsigned char ack :1; //Acknowledgement Flag
unsigned char urg :1; //Urgent Flag
unsigned char ecn :1; //ECN-Echo Flag
unsigned char cwr :1; //Congestion Window Reduced Flag
////////////////////////////////
unsigned short window; // window
unsigned short checksum; // checksum
unsigned short urgent_pointer; // urgent pointer
} TCP_HDR , *PTCP_HDR , FAR * LPTCP_HDR , TCPHeader , TCP_HEADER;
#define u_int16_t unsigned short
#define u_int32_t unsigned int
#define u_int8_t unsigned char
#define n_short u_short
struct pseudohdr {
u_int32_t saddr;
u_int32_t daddr;
u_int8_t useless;
u_int8_t protocol;
u_int16_t tcplength;
};
unsigned short in_chksum(unsigned short *addr, int len)
{
int sum = 0;
int nleft = len;
u_short *w=addr;
u_short answer = 0;
while(nleft >1)
{
sum +=*w++;
nleft -= 2;
}
if(nleft == 1)
{
*(u_char *)(&answer) = *(u_char *)w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}
int main()
{
char host[100],buf[512],*data=NULL,source_ip[20]; //buf is the complete packet
SOCKET s;
int k=1;
struct pseudohdr *pseudo_header;
IPV4_HDR *v4hdr=NULL;
TCP_HDR *tcphdr=NULL;
int payload=400 , optval;
SOCKADDR_IN dest;
hostent *server;
struct sockaddr_in target_addr;
struct sockaddr_in your_addr;
//Initialise Winsock
WSADATA wsock;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsock) != 0)
{
fprintf(stderr,"WSAStartup() failed");
exit(EXIT_FAILURE);
}
printf("Initialised successfully.");
////////////////////////////////////////////////
//Create Raw TCP Packet
printf("\nCreating Raw TCP Socket...");
if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))==SOCKET_ERROR)
{
printf("Creation of raw socket failed.");
return 0;
}
printf("Raw TCP Socket Created successfully.");
////////////////////////////////////////////////
//Put Socket in RAW Mode.
printf("\nSetting the socket in RAW mode...");
if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof(optval))==SOCKET_ERROR)
{
printf("failed to set socket in raw mode.");
return 0;
}
printf("Successful.");
////////////////////////////////////////////////
//Target Hostname
printf("\nEnter hostname : ");
//gets(host);
printf("\nResolving Hostname...");
/*
if((server=gethostbyname(host))==0)
{
printf("to resolve.");
return 0;
}
*/
/*
dest.sin_family = AF_INET;
dest.sin_port = htons(50000); //your destination port
memcpy(&dest.sin_addr.s_addr,server->h_addr,server->h_length);
printf("Resolved.");
*/
/////////////////////////////////////////////////
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr("192.168.10.102");
dest.sin_port = htons(25);
printf("\nEnter Source IP : ");
//gets(source_ip);
target_addr.sin_family = AF_INET;
target_addr.sin_addr.s_addr = inet_addr("192.168.10.102");
target_addr.sin_port = htons(25);
your_addr.sin_addr.s_addr = inet_addr("192.168.10.101");
your_addr.sin_port = htons(30045);
v4hdr = (IPV4_HDR *)buf; //lets point to the ip header portion
memset((char *)v4hdr, 0, sizeof(v4hdr));
tcphdr = (TCP_HDR *)&buf[sizeof(IPV4_HDR)]; //get the pointer to the tcp header in the packet
//tcphdr = (TCP_HDR *)(buf + 20); //get the pointer to the tcp header in the packet
memset((char *)tcphdr, 0, sizeof(tcphdr));
tcphdr->source_port = htons(30045);
tcphdr->dest_port = htons(25);
tcphdr->cwr=0;
tcphdr->ecn=0;
tcphdr->urg=0;
tcphdr->ack=0;
tcphdr->psh=0;
tcphdr->rst=0;
tcphdr->syn=1;
tcphdr->fin=0;
tcphdr->ns=1;
tcphdr->acknowledge = htonl(0);
tcphdr->urgent_pointer = 0;
tcphdr->sequence = GetCurrentProcessId();
tcphdr->window = htons( 512 );
//pseudo_header = (struct pseudohdr *)&buf[sizeof(struct tcp_header)];
pseudo_header = (struct pseudohdr *)((char *)tcphdr - sizeof(struct pseudohdr));
pseudo_header->saddr = inet_addr("192.168.10.101");
pseudo_header->daddr = inet_addr("192.168.10.102");
pseudo_header->protocol = IPPROTO_TCP;
pseudo_header->tcplength = htons(sizeof(struct tcp_header));
tcphdr->checksum = in_chksum((u_short *)pseudo_header,(sizeof(struct pseudohdr)+sizeof(struct tcp_header)));
v4hdr->ip_version=4;
v4hdr->ip_header_len=5;
v4hdr->ip_tos = 0;
v4hdr->ip_total_length = htons ( sizeof(IPV4_HDR) + sizeof(TCP_HDR) + payload );
v4hdr->ip_id = htons(0);
v4hdr->ip_frag_offset = 0;
v4hdr->ip_frag_offset1 = 0;
v4hdr->ip_reserved_zero = 0;
v4hdr->ip_dont_fragment = 1;
v4hdr->ip_more_fragment = 0;
v4hdr->ip_ttl = 8;
v4hdr->ip_protocol = IPPROTO_TCP;
v4hdr->ip_srcaddr = inet_addr("192.168.10.101");
v4hdr->ip_destaddr = inet_addr("192.168.10.102");
v4hdr->ip_checksum = in_chksum((u_short *)&v4hdr, sizeof(ip_hdr));
// Initialize the TCP payload to some rubbish
//data = &buf[sizeof(IPV4_HDR) + sizeof(TCP_HDR)];
//memset(data, '^', payload);
printf("\nSending packet...\n");
printf(" %d packets send\n",k++);
if((sendto(s , buf , sizeof(IPV4_HDR)+sizeof(TCP_HDR) + payload, 0, (SOCKADDR *)&dest, sizeof(dest)))==SOCKET_ERROR)
{
printf("Error sending Packet : %d",WSAGetLastError());
}
printf("success");
return 0;
}Forums:


tcp체크섬 계산에 데이터 부분이 빠진것 같네요..
tcp header뒤에 오는 데이터 부분에 대한 checksum계산이 안되는듯 보입니다.
그러나 이제 때는 왔다
댓글 달기