Python Forum
converting Perl to Python
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
converting Perl to Python
#1
how hard would it be to convert this Perl thing to Python?
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#2
I never tried it and it seems unmaintained, but maybe PyPerl is an option?

How big is this API? If it really this useful then why don't you rewrite it in python. Writing an automatic converter will probably take longer then rewriting the API.

And even if you manage to automatically rewrite it, the resulting code probably won't be very pythonic anyway.
Reply
#3
It looks fairly clean. I don't understand all of it, but there are comments explaining what each of the broad strokes are. I'd guess how difficult it would be to translate relies fairly heavily on how much of the networking libs are available in python, and I don't know a lot about our socket module.

If you were ok with non-standard library modules, scapy could probably do something similar fairly easily: https://scapy.net/

http://killcx.sourceforge.net/killcx.txt
#!/usr/bin/perl
######################################################################
# killcx :
#
# Close a TCP connection under Linux.
#
# (c) Jerome Bruandet - <[email protected]>
#
# version 1.0.3 - 18-May-2011
#
# doc : http://killcx.sourceforge.net/
#
######################################################################
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
######################################################################

use strict;
use Socket;
use Net::RawIP;
use Net::Pcap;
use NetPacket::Ethernet qw(:strip);
use NetPacket::IP qw(:strip);
use NetPacket::TCP;
use POSIX qw(setsid);

my $appname = 'killcx';
my $version = 'v1.0.3';
my $copyright = '(c)2009-2011 Jerome Bruandet - http://killcx.sourceforge.net/';

print "$appname $version - $copyright\n\n";
if ( $> ) {
   print "\t[ERROR] : you must be root\n\n";
   exit 1;
} elsif ( $^O ne 'linux' ){
   print "\t[ERROR] : that script is for Linux only, not $^O\n\n";
   exit 1;
}
$SIG{USR1} = \&check_res;

my ( $dest_ip, $dest_port ) =
   $ARGV[0] =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d+)$/;
my $interface = $ARGV[1];

if ( ( ! $dest_ip ) || ( ! $dest_port ) ) {
print "- syntax   : $appname <destip:destport> <interface>

  destip               : remote IP
  destport             : remote port
  interface (optional) : network interface (eth0, lo etc). Note that
                         in many cases, using 'lo' (loopback) will give
                         better results, specially when a connection
                         is not yet or no longer in the ESTABLISHED state
                         (SYN_RECV, TIME_WAIT etc).

- example  : $appname 10.11.12.13:1234
             $appname 10.11.12.13:1234 eth0

- doc      :  http://killcx.sourceforge.net/

";
   exit 1;
}

my $pid = $$;

my %TCP_STATES = (
'01' => 'ESTABLISHED', '02' => 'SYN_SENT',  '03' => 'SYN_RECV',
'04' => 'FIN_WAIT1',   '05' => 'FIN_WAIT2', '06' => 'TIME_WAIT',
'07' => 'CLOSE',       '08' => 'CLOSE_WAIT','09' => 'LAST_ACK',
'0A' => 'LISTEN',      '0B' => 'CLOSING'
);

# convert to network byte order :
$dest_ip =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
my $dest_hex = sprintf "%.2X%.2X%.2X%.2X:%.4X",$4,$3,$2,$1,$dest_port;
# check in /proc/net/tcp :
print "[PARENT] checking connection with [$dest_ip:$dest_port]\n";
my ( $local_ip, $local_port, $state) = &check_tcp( $dest_hex );
if ( ! $state ) {
   print "[PARENT] error : unable to find a connection with ".
      "[$dest_ip:$dest_port]\n\n";
   exit 1;
}

print "[PARENT] found connection with [$local_ip:$local_port] ".
   "($TCP_STATES{$state})\n";

# fork our child which will hook the server response to our spoofed
# packet and extract the correct acknum (and seqnum) needed to close
# the connection :
print "[PARENT] forking child\n";
use POSIX 'WNOHANG';
$SIG{CHLD} = sub { while( waitpid( -1,WNOHANG ) > 0 ) {} };
defined ( my $child_pid = fork ) or
   die "[PARENT] error : cannot fork : $!\n";
if ( $child_pid == 0 ) {
   setsid or die "[CHILD]  error : cannot setid : $!";
   my ($err, $filter, $netmask, $address, $pcap);

   # no interface given, let's try to find one :
   if ( ! $interface ) {
      $interface = Net::Pcap::lookupdev( \$err );
      print "[CHILD]  ";
      if ( $interface ) {
         print "interface not defined, will use [$interface]\n";
      } else {
         # switch to loopback if we can't find any interface :
         print "no interface found, switching to loopback\n";
         $interface = 'lo';
      }
   }
   # let's sniff :
   print "[CHILD]  setting up filter to sniff ACK on [$interface]".
      " for 5 seconds\n";
   my $pcap = Net::Pcap::open_live( $interface, 100, 1, 5000, \$err) ||
      die "[CHILD]  error : open_live failed : $err\n";
   # setup filter :
   Net::Pcap::compile( $pcap, \$filter,
      "(dst port $dest_port) && (src port $local_port)",
      0, $netmask) &&
      die "[CHILD]  error : compile failed : $!\n";
   Net::Pcap::setfilter($pcap, $filter) &&
      die "[CHILD]  error : setfilter failed : $!\n";
   # only want to hook 1 packet :
   Net::Pcap::loop($pcap, 1 , \&process_packet, '');
   Net::Pcap::close($pcap);
   # all done, let's inform our parent :
   print "[CHILD]  all done, sending USR1 signal to parent [$pid] ".
      "and exiting\n";
   `kill -s USR1 $pid`;
   exit 0;
}

# wait 0.5 second for our child to be ready :
select( undef, undef, undef, 0.5 );
print "[PARENT] sending spoofed SYN to [$local_ip:$local_port]".
   " with bogus SeqNum\n";

# send spoofed SYN packet :
my $packet = Net::RawIP->new({
      ip => {  frag_off => 0, tos => 0,
               saddr => $dest_ip, daddr => $local_ip
            },
      tcp =>{  dest => $local_port, source => $dest_port,
               seq => 10, syn => 1
            }
   });
   $packet->send;

# wait max 5 seconds :
select( undef, undef, undef, 5 );

# didn't receive any signal from our child, it has probably failed :
print "[PARENT] no response from child, operation may have failed\n";
if ( $interface ne 'lo' ) {
   print "[PARENT] => you may try using 'lo' as interface parameter\n";
}
print "[PARENT] killing child [$child_pid] and exiting program\n\n";
# kill it and exit :
kill 9, $child_pid;

exit 1;

######################################################################

sub check_res {

   # received signal from our child :
   print "[PARENT] received child signal, checking results...\n";
   # check whether the operation was successful or not :
   ( $local_ip, $local_port, $state) = &check_tcp( $dest_hex );
   if ( $state ) {
   print "         => error : connection hasn't been closed\n\n";
      exit 1;
   }
   print "         => success : connection has been closed !\n\n";
   exit 0;

}

######################################################################

sub process_packet {

   my( $user_data, $header, $packet ) = @_;
   my $ether_data = NetPacket::Ethernet::strip($packet);

   # decode TCP/IP packet (server response to our spoofed packet) :
   my $ip = NetPacket::IP->decode($ether_data);
   my $tcp = NetPacket::TCP->decode($ip->{'data'});

   print "[CHILD]  hooked ACK from [$local_ip:$local_port]\n";
   # look for the magic acknum :
   print "[CHILD]  ";
   if ( $tcp->{acknum} ) {
      print "found AckNum [$tcp->{acknum}] and SeqNum ".
         "[$tcp->{seqnum}]\n";
      print "[CHILD]  sending spoofed RST to [$local_ip:$local_port]".
         " with SeqNum [$tcp->{acknum}]\n";
      # we have it : spoof another packet (RST) with the correct seqnum
      # to close the connection :
      my $packet = Net::RawIP->new( {
         ip => {  frag_off => 0, tos => 0,
                  saddr => $dest_ip, daddr => $local_ip
               },
         tcp =>{  dest => $local_port, source => $dest_port,
                  seq => $tcp->{acknum}, rst => 1
               }
      } );
         $packet->send;

      # if the connection was in the ESTABLISHED state we close it
      # with the remote host as well, otherwise we don't care
      # (the server would reply with a RST packet anyway) :
      if ( $state == 1 ) {
         print "[CHILD]  sending RST ".
            "to remote host as well with SeqNum [$tcp->{seqnum}]\n";
         my $packet = Net::RawIP->new( {
         ip => {  frag_off => 0, tos => 0,
                  saddr => $local_ip, daddr => $dest_ip
               },
         tcp =>{  dest => $dest_port, source => $local_port,
                  seq => $tcp->{seqnum}, rst => 1
               }
         } );
         $packet->send;
      }
   } else {
      # very unlikely to happen (ACK packets always have acknum) :
      print "error : no AckNum found in packet\n";
      exit 1;
   }
}

######################################################################

sub check_tcp {

   my $hex_rem = shift;
   my ( $li, $lp, $st );
   open TCP, "</proc/net/tcp";
   while ( <TCP> ) {
      if ( /^\s*\d+:\s+(.{8}):(.{4})\s+$hex_rem\s+(.{2})\s/ ) {
         $st = $3;
         $lp = hex( $2 );
         ($li) = $1 =~ /(.{2})(.{2})(.{2})(.{2})/;
         $li = inet_ntoa( pack("N", hex( $4.$3.$2.$1 ) ) );
         last;
      }
   }
   close TCP;
   # if not found, check /proc/net/tcp6 :
   if ( ( ! $st ) && ( -e '/proc/net/tcp6' ) ) {
      open TCP, "</proc/net/tcp6";
      while ( <TCP> ) {
         if ( /^\s*\d+:\s+\d{16}FFFF0000(.{8}):(.{4})\s+
               \d{16}FFFF0000$hex_rem\s+(.{2})\s/x ) {
            $st = $3;
            $lp = hex( $2 );
            ($li) = $1 =~ /(.{2})(.{2})(.{2})(.{2})/;
            $li = inet_ntoa( pack("N", hex( $4.$3.$2.$1 ) ) );
            last;
         }
      }
      close TCP;
   }
   return ( $li, $lp, $st );

}

######################################################################
# EOF
Reply
#4
yeah, starting from scratch to code this is better than trying to understand rubbish.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Any Perl users here? millpond 2 5,897 Aug-03-2019, 12:26 AM
Last Post: millpond

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020