Artykuły na każdy temat
[PHP] Pseudo zdalny pulpit aka remote access
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="./favicon.ico">
<title>Remote access</title>
<link href="./css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="./css/style.css" type="text/css" rel="stylesheet">
<!--[if lt IE 9]>
<script src="./js/html5shiv.min.js"></script>
<script src="./js/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="jumbotron">
<h1>Remote access</h1>
<?php
/**
* @package Remote access
* @subpackage Panel
* @version: 1.00rc-1
* @author CapaciousCore
* @copyright Copyright (C) 2018 CapaciousCore
* @link http://www.capaciouscore.pl/
* @license Beerware
*/
define('BLOCK_INCLUDE', true);
// Load the necessary things
require './remote_access.class.php';
// Create remote access object
$remote_access = new remote_access();
if($remote_access -> is_authorized() === true)
{
?>
<div class="panel-group">
<div class="btn-group">
<a href="status" class="btn btn-default">Status</a>
</div>
<div class="btn-group">
<a href="take-screenshot" class="btn btn-success" role="button"><span class="glyphicon glyphicon-arrow-down"></span> Take screenshot</a>
<a href="view-screenshot" class="btn btn-primary" role="button"><span class="glyphicon glyphicon-picture"></span> View screenshot</a>
<a href="remove-screenshot" class="btn btn-danger" role="button"><span class="glyphicon glyphicon-remove"></span> Remove screenshot</a>
</div>
<div class="btn-group">
<a href="shutdown" class="btn btn-warning" role="button"><span class="glyphicon glyphicon-off"></span> Shutdown</a>
<a href="force-shutdown" class="btn btn-danger" role="button"><span class="glyphicon glyphicon-off"></span> Force shutdown</a>
</div>
</div>
<?php
switch($_GET['arg'])
{
case 'status':
if($remote_access -> send_request('ping') === true)
{
$statement = 'Machine is online';
$alert_type = 'success';
}
else
{
$statement = 'Machine is offline';
}
break;
case 'take-screenshot':
if($remote_access -> send_request('screenshot') === true)
{
$statement = 'Screenshot has been taken';
$alert_type = 'success';
}
else
{
$statement = 'Screenshot has not been taken';
}
break;
case 'view-screenshot':
if(file_exists('./screenshot') === true)
{
$screenshot = base64_encode(file_get_contents('./screenshot'));
$file_info = new finfo();
$mime_type = $file_info -> file('./screenshot', FILEINFO_MIME_TYPE);
}
else
{
$statement = 'Screenshot does not exist';
}
break;
case 'remove-screenshot':
if(file_exists('./screenshot') === true)
{
if(unlink('./screenshot') === true)
{
$statement = 'Screenshot has been removed';
$alert_type = 'success';
}
else
{
$statement = 'Screenshot has not been removed';
}
}
else
{
$statement = 'Screenshot does not exist';
}
break;
case 'shutdown':
if($remote_access -> send_request('shutdown') === true)
{
$statement = 'Shutdown in progress';
$alert_type = 'success';
}
else
{
$statement = 'Shutdown failed';
}
break;
case 'force-shutdown':
if($remote_access -> send_request('force shutdown') === true)
{
$statement = 'Forced shutdown in progress';
$alert_type = 'success';
}
else
{
$statement = 'Force shutdown failed';
}
break;
}
}
else
{
$statement = 'No authorization';
}
if($statement !== null)
{
if($alert_type === null)
{
$alert_type = 'danger';
}
// str_repeat() just for fun
echo str_repeat(' ', 4).'<div class="alert alert-'.$alert_type.'" role="alert"><p class="text-center">'.$statement.'</p></div>'.PHP_EOL;
}
else if($screenshot !== null)
{
echo str_repeat(' ', 4).'<img src="data:'.$mime_type.';base64,'.$screenshot.'" class="img-responsive img-thumbnail" alt="Screenshot">'.PHP_EOL;
}
?>
</div>
</div>
<script src="./js/jquery.min.js"></script>
<script src="./js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="./js/ie10-viewport-bug-workaround.js"></script>
</body>
</html>
Plik .htaccess:
Options +FollowSymLinks -Indexes -MultiViews
RewriteEngine On
# Jump to non www address
# RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
# RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
# Main address handling
RewriteRule ^([^.]*)$ index.php?arg=$1 [L]
<FilesMatch "^screenshot|ip$">
Order Allow,Deny
Deny from all
</FilesMatch
Plik config.php:
<?php
/**
* @package Remote access
* @subpackage Configuration file
* @version: 1.00rc-1
* @author CapaciousCore
* @copyright Copyright (C) 2018 CapaciousCore
* @link http://www.capaciouscore.pl/
* @license Beerware
*/
if(defined('BLOCK_INCLUDE') === false)
{
die('Restricted access');
}
$config['local']['protocol'] = 'tcp';
$config['local']['ip'] = '0.0.0.0';
$config['local']['port'] = 666;
$config['local']['allowed_ip'] = '127.0.0.1';
$config['remote']['protocol'] = 'tcp';
// $config['remote']['ip'] = '127.0.0.1';
$config['remote']['port'] = 666;
$config['system']['is_debugging_mode'] = true;
$config['system']['secret_cookie'] = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
$config['system']['remote_address'] = 'http://127.0.0.1/remote-access/';
$config['system']['api_key'] = 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz';
?>
Plik server.php (CLI):
<?php
/**
* @package Remote access
* @subpackage CLI server
* @version: 1.00rc-1
* @author CapaciousCore
* @copyright Copyright (C) 2018 CapaciousCore
* @link http://www.capaciouscore.pl/
* @license Beerware
*/
if(php_sapi_name() === 'cli')
{
define('BLOCK_INCLUDE', true);
// Load the necessary things
chdir(__DIR__);
require './remote_access.class.php';
// Create remote access object
$remote_access = new remote_access();
// Run server
$remote_access -> run();
}
?>
Plik client.php (CLI):
<?php
/**
* @package Remote access
* @subpackage CLI client
* @version: 1.00rc-1
* @author CapaciousCore
* @copyright Copyright (C) 2018 CapaciousCore
* @link http://www.capaciouscore.pl/
* @license Beerware
*/
if(php_sapi_name() === 'cli')
{
if($argc === 2)
{
define('BLOCK_INCLUDE', true);
// Load the necessary things
chdir(__DIR__);
require './remote_access.class.php';
// Create remote access object
$remote_access = new remote_access();
// Send request
$remote_access -> send_request($argv[1]);
}
else
{
echo 'Incorrect number of arguments '.PHP_EOL;
}
}
?>
Plik remote_access.class.php:
<?php
/**
* @package Remote access
* @subpackage Core
* @version: 1.00rc-1
* @author CapaciousCore
* @copyright Copyright (C) 2018 CapaciousCore
* @link http://www.capaciouscore.pl/
* @license Beerware
*/
if(defined('BLOCK_INCLUDE') === false)
{
die('Restricted access');
}
class remote_access
{
private $config;
private $crypt;
public function __construct()
{
// Load config file and crypt class
require './config.php';
require './crypt.class.php';
// Place configuration and crypt in class property
$this -> config = $config;
$this -> crypt = new crypt();
}
public function run()
{
if(php_sapi_name() === 'cli')
{
set_time_limit(0);
$this -> config['system']['mode'] = 'server';
$address = $this -> config['local']['protocol'].'://'.$this -> config['local']['ip'].':'.$this -> config['local']['port'];
$socket = stream_socket_server($address, $socket_error_id, $socket_error_message);
if($socket !== false)
{
$this -> log('Server socket established on specified address '.$address);
stream_set_timeout($socket, 5);
$this -> register_server_ip();
$this -> log('Server sent IP address');
while($client = stream_socket_accept($socket, -1, $peer))
{
if($this -> is_valid_address($peer) === true)
{
$this -> log('Connection accepted from '.$peer);
$command = $this -> crypt -> decode(fread($client, 0xFF)); // or 0x400 if you like
$this -> log('Received command: '.$command);
switch($command)
{
case 'ping':
$response = 'pong';
$message = 'Pong sent';
break;
case 'screenshot':
$response = $this -> screenshot();
$message = 'Screenshot sent';
break;
case 'shutdown':
$this -> shutdown();
$response = 'shutdown executed';
$message = 'Shutdown in progress';
break;
case 'force shutdown':
$this -> shutdown(true);
$response = 'forced shutdown executed';
$message = 'Forced shutdown in progress';
break;
default:
$response = $message = 'Unknown command';
break;
}
fputs($client, $this -> crypt -> encode($response));
$this -> log($message);
}
else
{
// Log unauthorized packets?
}
fclose($client);
$this -> log('Client disconnected');
}
fclose($socket);
// stream_socket_shutdown($socket, STREAM_SHUT_RDWR);
$this -> log('Server socket closed');
}
else
{
$this -> log($socket_error_message.' ('.$socket_error_id.')');
}
}
}
public function send_request($command)
{
$this -> config['system']['mode'] = 'client';
$remote_ip = long2ip(file_get_contents('./ip'));
$address = $this -> config['remote']['protocol'].'://'.$remote_ip.':'.$this -> config['remote']['port'];
$socket = stream_socket_client($address, $socket_error_id, $socket_error_message);
if($socket !== false)
{
$this -> log('Established connection with server on specified address '.$address);
fwrite($socket, $this -> crypt -> encode($command));
$this -> log('Command sent: '.$command);
while(feof($socket) !== true)
{
$data .= fgets($socket, 1024);
}
$data = $this -> crypt -> decode($data);
// $this -> log('Received data: '.$data);
fclose($socket);
if(strlen($data) > 0)
{
switch($command)
{
case 'ping':
if($data === 'pong')
{
$status = 'online';
$message = 'Pong received';
$return = true;
}
else
{
$status = 'offline';
$message = 'Pong not received';
}
break;
case 'screenshot':
file_put_contents('./screenshot', $data, LOCK_EX);
$response = 'screenshot received';
$message = 'Screenshot received';
$return = true;
break;
case 'shutdown':
if($data === 'shutdown executed')
{
$response = 'shutdown executed';
$message = 'Shutdown in progress';
$return = true;
}
else
{
$response = 'shutdown failed';
$message = 'Shutdown failed';
}
break;
case 'force shutdown':
if($data === 'forced shutdown executed')
{
$response = 'forced shutdown executed';
$message = 'Forced shutdown in progress';
$return = true;
}
else
{
$response = 'forced shutdown failed';
$message = 'Forced shutdown failed';
}
break;
default:
$message = 'Unknown command';
break;
}
}
else
{
$message = 'No data was received';
}
$this -> log($message);
$this -> log('Server connection closed'); // This should be after fclose($socket)
}
else
{
// Failed to establish a connection
$this -> log($socket_error_message.' ('.$socket_error_id.')');
}
if(php_sapi_name() === 'apache2handler')
{
return $return;
}
}
public function is_authorized()
{
// Other ways omitted
return $this -> config['system']['secret_cookie'] === $_COOKIE['auth'];
}
private function register_server_ip()
{
$ch = curl_init($this -> config['system']['remote_address'].'register_server.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['api_key' => $this -> config['system']['api_key']]));
$data = curl_exec($ch);
$info = curl_getinfo($ch);
if($info['http_code'] === 200)
{
if($data === 'saved')
{
return true;
}
}
curl_close($ch);
return false;
}
private function screenshot()
{
// Pathetic solution
ob_start();
imagepng(imagegrabscreen(), null, 9);
$screenshot = ob_get_contents();
ob_end_clean();
return $screenshot;
}
private function shutdown($is_forced = false)
{
if($this -> config['system']['is_debugging_mode'] === false)
{
if($is_forced === true)
{
$command = 'shutdown /s /d p /c "Executed shutdown via remote access"';
}
else
{
$command = 'shutdown /s /f /t 30 /d p /c "Executed forced shutdown via remote access"';
}
exec($command);
}
}
private function is_valid_address($address)
{
$ip = parse_url($address, PHP_URL_HOST);
if(is_array($this -> config['local']['allowed_ip']) === true)
{
return in_array($ip, $this -> config['local']['allowed_ip']);
}
else
{
return $this -> config['local']['allowed_ip'] === $ip;
}
}
private function log($message)
{
if(php_sapi_name() === 'cli')
{
echo $message.PHP_EOL;
}
file_put_contents('./logs/'.$this -> config['system']['mode'].'_'.date('d-m-Y').'.log', date('[H:i:s]').' '.$message.PHP_EOL, FILE_APPEND | LOCK_EX);
}
}
?>
Plik crypt.class.php (wrapper):
<?php
/**
* @package Remote access
* @subpackage Crypt module
* @version: 1.00rc-1
* @author CapaciousCore
* @copyright Copyright (C) 2018 CapaciousCore
* @link http://www.capaciouscore.pl/
* @license Beerware
*/
class crypt extends remote_access
{
private $key;
public function __construct()
{
}
public function encode($data)
{
// Do it yourself
return $data;
}
public function decode($data)
{
// Do it yourself
return $data;
}
private function encrypt($plain)
{
// Do it yourself
return $cipher;
}
private function decrypt($cipher)
{
// Do it yourself
return $plain;
}
}
?>
Plik register_server.php:
<?php
/**
* @package Remote access
* @subpackage Register server IP address
* @version: 1.00rc-1
* @author CapaciousCore
* @copyright Copyright (C) 2018 CapaciousCore
* @link http://www.capaciouscore.pl/
* @license Beerware
*/
if(php_sapi_name() === 'apache2handler')
{
define('BLOCK_INCLUDE', true);
// Load the necessary things
require './config.php';
if($config['system']['api_key'] === $_POST['api_key'])
{
echo (file_put_contents('./ip', ip2long($_SERVER['REMOTE_ADDR'])) > 0 ? 'saved' : 'not_saved');
}
}
?>
Plik set_admin_cookie.php czyli ustawienie pseudo autoryzacji:
<?php
/**
* @package Remote access
* @subpackage Set admin "cookie"
* @version: 1.00rc-1
* @author CapaciousCore
* @copyright Copyright (C) 2018 CapaciousCore
* @link http://www.capaciouscore.pl/
* @license Beerware
*/
if($_SERVER['REMOTE_ADDR'] === '127.0.0.1')
{
define('BLOCK_INCLUDE', true);
// Load the necessary things
require './config.php';
// Execute necessary things
echo (setcookie('auth', $config['system']['secret_cookie'], time() + 31536000, '/') ? 'ok' : 'fail'); // Expire in 1 year
}
?>
Komentarze
Dodaj komentarz