#include #include #include #include #include #include #include #include unsigned short ip_cksum(unsigned char * buff, int len) { unsigned long sum = 0; if (len > 3) { __asm__("clc\n" "1:\t" "lodsl\n\t" "adcl %%eax, %%ebx\n\t" "loop 1b\n\t" "adcl $0, %%ebx\n\t" "movl %%ebx, %%eax\n\t" "shrl $16, %%eax\n\t" "addw %%ax, %%bx\n\t" "adcw $0, %%bx" : "=b" (sum) , "=S" (buff) : "0" (sum), "c" (len >> 2) ,"1" (buff) : "ax", "cx", "si", "bx" ); } if (len & 2) { __asm__("lodsw\n\t" "addw %%ax, %%bx\n\t" "adcw $0, %%bx" : "=b" (sum), "=S" (buff) : "0" (sum), "1" (buff) : "bx", "ax", "si"); } if (len & 1) { __asm__("lodsb\n\t" "movb $0, %%ah\n\t" "addw %%ax, %%bx\n\t" "adcw $0, %%bx" : "=b" (sum), "=S" (buff) : "0" (sum), "1" (buff) : "bx", "ax", "si"); } sum =~sum; return(sum & 0xffff); } unsigned short tcp_check(struct tcphdr *th, int len, unsigned long saddr, unsigned long daddr) { unsigned long sum; __asm__(" addl %%ecx, %%ebx adcl %%edx, %%ebx adcl $0, %%ebx " : "=b"(sum) : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_TCP*256) : "bx", "cx", "dx" ); __asm__(" movl %%ecx, %%edx cld cmpl $32, %%ecx jb 2f shrl $5, %%ecx clc 1: lodsl adcl %%eax, %%ebx lodsl adcl %%eax, %%ebx lodsl adcl %%eax, %%ebx lodsl adcl %%eax, %%ebx lodsl adcl %%eax, %%ebx lodsl adcl %%eax, %%ebx lodsl adcl %%eax, %%ebx lodsl adcl %%eax, %%ebx loop 1b adcl $0, %%ebx movl %%edx, %%ecx 2: andl $28, %%ecx je 4f shrl $2, %%ecx clc 3: lodsl adcl %%eax, %%ebx loop 3b adcl $0, %%ebx 4: movl $0, %%eax testw $2, %%dx je 5f lodsw addl %%eax, %%ebx adcl $0, %%ebx movw $0, %%ax 5: test $1, %%edx je 6f lodsb addl %%eax, %%ebx adcl $0, %%ebx 6: movl %%ebx, %%eax shrl $16, %%eax addw %%ax, %%bx adcw $0, %%bx " : "=b"(sum) : "0"(sum), "c"(len), "S"(th) : "ax", "bx", "cx", "dx", "si" ); /* We only want the bottom 16 bits, but we never cleared the top 16. */ return((~sum) & 0xffff); } void resolve_address(struct sockaddr *addr, char *hostname, u_short port) { struct sockaddr_in *address; struct hostent *host; address = (struct sockaddr_in *)addr; (void) bzero((char *)address, sizeof(struct sockaddr_in)); address->sin_family = AF_INET; address->sin_port = htons(port); address->sin_addr.s_addr = inet_addr(hostname); if ((int)address->sin_addr.s_addr == -1) { host = gethostbyname(hostname); if (host) { bcopy( host->h_addr, (char *)&address->sin_addr, host->h_length); } else { puts("Couldn't resolve address!!!"); exit(-1); } } } char *create_ip(u_long source, u_long dest, u_char protocol, u_char ttl, u_short id, char *data, int data_len) { char *ip_datagram; struct iphdr *ip_header; ip_datagram = malloc(sizeof(struct iphdr) + data_len); ip_header = ip_datagram; ip_header->version = 4; ip_header->tos = 0; ip_header->frag_off = 0; ip_header->check = 0; ip_header->saddr = source; ip_header->daddr = dest; ip_header->protocol = protocol; ip_header->ttl = ttl; ip_header->id = htons(id); ip_header->ihl = 5; ip_header->tot_len = htons(sizeof(struct iphdr) + data_len); ip_header->check = htons(ip_cksum(ip_datagram,sizeof(struct iphdr))); bcopy(data,ip_datagram+sizeof(struct iphdr),data_len); return ip_datagram; } char *create_tcp(u_long source, u_long dest, u_short sport, u_short dport, u_long seqnum, u_long acknum, u_char flags, char *data, int datalen) { char *wewt; struct tcphdr *tcp_header; wewt = malloc(sizeof(struct tcphdr) + datalen); tcp_header = wewt; tcp_header->th_sport = sport; tcp_header->th_dport = dport; tcp_header->th_seq = seqnum; tcp_header->th_ack = acknum; tcp_header->th_flags = flags; tcp_header->th_sum = 0; tcp_header->th_sum = htons(tcp_check(tcp_header, sizeof(struct tcphdr), source, dest)); bcopy(data,wewt+sizeof(struct tcphdr),datalen); return wewt; } void sendpack(char *fromhost, int fromport, char *tohost, int toport) { char *packet; char *tcppacket; char *sendme; static struct sockaddr_in local, remote; static int sock = 0; if (!sock) { resolve_address((struct sockaddr *)&local, fromhost, fromport); resolve_address((struct sockaddr *)&remote, tohost, toport); sock = socket(AF_INET, SOCK_RAW, 255); if (sock == -1) { perror("Getting raw socket"); exit(-1); } } tcppacket = create_tcp(&local.sin_addr, &remote.sin_addr, local.sin_port, remote.sin_port, 795930600, 0, TH_SYN, NULL, 0); packet = create_ip(&local.sin_addr, &remote.sin_addr, 6, 24, 4, NULL, 0); sendme = (struct iphdr *)packet; bcopy(tcppacket, sendme+sizeof(struct iphdr), sizeof(tcppacket)); printf("the ip header is %d bytes long.\n", sizeof(struct iphdr)); printf("the tcp header is %d bytes long.\n", sizeof(struct tcphdr)); printf("the ip packet is %d bytes long.\n", sizeof(packet)); printf("the tcp packet is %d bytes long.\n", sizeof(tcppacket)); printf("the final packet is %d bytes long.\n", sizeof(sendme)); { int result; result = sendto(sock, packet, sizeof(packet), 0, (struct sockaddr *)&remote, sizeof(remote)); if (result != sizeof(packet)) { perror("sending packet"); } } } main(int argc, char **argv) { if (argc!=5) { printf("usage: %s \n", argv[0]); exit(-1); } printf("forging packet from %s.%d to %s.%d\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4])); sendpack(argv[1], atoi(argv[2]), argv[3], atoi(argv[4])); }