All pastes #575519 Raw Edit

Something

public text v1 · immutable
·published 2007-06-19 02:30 UTC
rendered paste body
# proxy.pl
# honeyclient proxy engine
# Copyright (c) 2004-2005 Kathy Wang <knwang@synacklabs.net>

# proxy.pl opens two sockets, one of which is listening for IE requests,
# and the other is receiving traffic from the remote webserver. proxy.pl
# does not do anything beyond parse out URLs from the remote server and
# save those URLs as external and internal URLs in hash tables.
# proxy.pl and driver.pl communicate with each other through files, namely
# domainfile. 

#!/usr/bin/perl 
use strict;
use Socket;
use IO::Select;
use IO::Socket;
use Net::hostent;
use HTML::LinkExtor;
use Carp;

my $intfile = "intfile";
my $extfile = "extfile";
my $domainfile = "domainfile";
my $donefile = "donefile";
my $proxydonefile = "proxydone";
my $timeout = 10;

my @intlinks = ();
my @extlinks = ();

# my $remote_addr = shift || 'localhost';
my $remote_port = shift || 6768;

my $local_port = 6768;
my $proto = getprotobyname('tcp');
my $local_iaddr = INADDR_ANY;
my $local_paddr = sockaddr_in($local_port, $local_iaddr);
my $remote_paddr;
my $baseurl;

my $done = 0;

# print "Heading into loooooooooop\n";

while(!$done) {

# If domainfile is populated with URL, then open listening and remote sockets.
# Listening socket listens for traffic from IE, and remote socket listens for
# traffic from remote webserver.

    if (-f $domainfile) {
	open DOMAIN, "$domainfile" or die "Could not open $domainfile: $!\n";
	
	my $remote = <DOMAIN>;
	chomp $remote;
	close(DOMAIN);
	unlink $domainfile;
	my $remote_iaddr = inet_aton($remote);
	if($remote_iaddr) {
	    $remote_paddr = sockaddr_in($remote_port, $remote_iaddr);
	    
	    my $server = IO::Socket::INET->new( Proto     => 'tcp',
						LocalPort => $local_port,
						Listen    => SOMAXCONN,
						Reuse     => 1);
	    
	    
	    $baseurl = $remote;
	    my $local_socket = $server->accept();
	    proxyrun($local_socket);
	    close($local_socket);
	} else {
	    print "Proxy did not detect address for $remote\n";
	    open INTFILE, ">$intfile" or die "Cannot open $intfile: $!\n";
	    print INTFILE "\n";
	    close INTFILE;
	    open EXTFILE, ">$extfile" or die "Cannot open $extfile: $!\n";
	    print EXTFILE "\n";
	    close EXTFILE;
	    open PROXYDONE, ">$proxydonefile" or die "Cannot open $proxydonefile: $!\n";
	    print PROXYDONE "Done!\n";
	    close PROXYDONE;
	}
    }
    if(-f $donefile) {
	$done = 1;
    }

# Process sleeps for one second before checking whether domainfile is
# populated. If not, then sleep for another second, then check again, etc

    sleep(1);
}

# This subroutine writes all internal URLs to intfile, and all external
# links to extfile when proxy times out, which is currently set to 5 secs.

sub proxycomplete {
    my $self = shift;
#   print "Completing!\n";
    open INTFILE, ">$intfile" or die "Cannot open $intfile: $!\n";
    foreach my $value (@intlinks) {
	print INTFILE "$value\n";
#	print "INTFILE $value\n";
    }
    print INTFILE "\n";
    close INTFILE;
    open EXTFILE, ">$extfile" or die "Cannot open $extfile: $!\n";
    foreach my $value (@extlinks) {
	print EXTFILE "$value\n";
#	print "EXTFILE $value\n";
    }
    print EXTFILE "\n";
    close EXTFILE;
    open PROXYDONE, ">$proxydonefile" or die "Cannot open $proxydonefile: $!\n";
    print PROXYDONE "Done!\n";
    close PROXYDONE;
    return;
}

# This subroutine extracts URL information and puts the key (tag) and
# value (tag values) into a hash table. Also, the URL is parsed to determine
# whether it is an internal or external link. For example, if the URL starts 
# with 'http://' vs if the URL is internal (e.g. '/project/foo')

sub linkextract {
    my($tag, %attr) = @_;
    return if $tag ne 'a';  # we only look closer at <a href=> tags
#   print "LINKEXTRACT CALLED!\n";
#   print "LINKS: $tag type\n";
#   print values %attr;
    
    foreach my $attribute (values %attr) {
	if ($attribute =~/$baseurl/i) {
	    push(@intlinks, $attribute);
	} elsif ($attribute =~ /http:\/\//i) {
	    push @extlinks, $attribute;
	} elsif ($attribute =~/^\//) {
	    push(@intlinks, $attribute);
	} elsif ($attribute =~/^[a-zA-Z0-9]/) {
	    my $newatt = "/" . $attribute;
	    push(@intlinks, $newatt);
	}
    }
}

sub proxyrun {
    my $local_socket = shift;

    my $done = 0;
    my $readmask = "";
    my $readready = "";
    my @ready_handles = [];
    my $localdone = 0;
    my $remotedone = 0;
    my $readbuf;
    my $readpos = 0;
    my $blksize = 4096;
    my $lasttraffic = time();

    vec($readmask, fileno(Local_Sock), 1) = 1;

    socket(Remote_Sock, PF_INET, SOCK_STREAM, $proto) or die "socket: $!";
    connect(Remote_Sock, $remote_paddr)               or die "connect: $!";
    my $select = IO::Select->new();
    my $linkextor = HTML::LinkExtor->new(\&linkextract);
#	$linkextor->end = \&proxycomplete;
    $select->add(\*Remote_Sock);
    $select->add($local_socket);
    while(!$done) {
	@ready_handles = $select->can_read(1);
	foreach my $handle(@ready_handles) {
	    if ($handle == \*Remote_Sock) {
		$lasttraffic = time();
		my $len = sysread(Remote_Sock, $readbuf, $blksize);
		if($len == 0) {
		    $remotedone = 1;
		} else {
#                   print "Back: ". $readbuf;
		    $linkextor->parse($readbuf);
		    syswrite($local_socket, $readbuf, $blksize);
		    if($readbuf =~ /<\/html>/i) {
#			print "Got the end\n";
			$done = 1;
		    }
		}
	    } elsif ($handle == $local_socket) {
		$lasttraffic = time();
		my $len = sysread($local_socket, $readbuf, $blksize);
		if($len == 0) {
		    $localdone = 1;
		} else {
		    #          print "Out: " . $readbuf;
		    syswrite(Remote_Sock, $readbuf, $blksize);
		}
	    } else {
		die "Unknown handle returned by select\n";
	    }
	}
	if($localdone && $remotedone) {
#	    print "Local and Remote Done";
	    $done = 1;
	}
	my $currenttime = time();
	my $differential = $currenttime - $lasttraffic;
	if($differential > $timeout) {
#	    print "Timed out: $lasttraffic $currenttime $differential\n";
	    $done = 1;
	} else {

	}
    }
    $linkextor->eof();
    proxycomplete();
}