5

How to use PowerShell to restart router?

My computer is connected to the router using a network cable, the router acts as a modem, it connects to the ISP through PPPoE, my computer is behind NAT.

The model of my router: Huawei HS8545M, LAN address: 192.168.1.1, webpage administrator login: CMCCAdmin, webpage administrator password: aDm8H%MdA.

I have to do the following to restart the router (7 clicks in total, the browser remembers the login and password):

enter image description here

enter image description here

Way too many steps.

I have tried to use this method:

$ie = New-Object -ComObject 'internetExplorer.Application'
$ie.Navigate "https://192.168.1.1"

But after a short while the connection is lost, .Document is empty, trying to refresh results in this error:

OperationStopped: The RPC server is unavailable. (0x800706BA)

I am using Windows 10 20H2 and I have disabled Remote Desktop, Remote Assistance, Remote Registry, Windows Remote Management and many other things, I disabled remote stuff because they pose threats to security, I think they are relevant to this; By the way, RPC service is running.

Can anyone help me?


Source code of first page: page1.html

Source code of second page: page2.html

This should be simple to do, login in 192.168.1.1, create a cookie, and use the cookie to get into 192.168.1.1/index.asp, submit Restart_button, job done, however I am not very familiar with commands that deal with networks...


I am currently looking for the Python way, I am using Python 3.9.1 amd64, I have put it in PATH long ago, I have installed Selenium and Twill via pip. and downloaded and extracted GeckoDriver.exe to Python installation folder;

I know selenium, twill, urllib, urllib2, cookielib and webbot, all are capable of doing this, I am currently trying to figure out how to do it in the best way.


I have managed to login to the router in Python via twill, however I don't know what to do next:

from twill.commands import *
go('http://192.168.1.1')
showforms()
fv("1","txt_Username","CMCCAdmin")
fv("1","txt_Password","aDm8H%MdA")
showforms()
submit('btnSubmit')
go("http://192.168.1.1/index.asp")

enter image description here

The button:

<input type="button" name="Restart_button" id="Restart_button" class="submit" style="width:98px" onclick="Reboot()" value="重启">

It is located at:

html.body.#container.#center.#content.table.tbody.tr.td.#frameContent.html.body.div.#Restart_button

Also, the inputfields of the first page(http://192.168.1.1):

PS C:\Windows\System32> $html.inputfields

outerHTML : <input name="txt_Username" type="text" id="txt_Username" style="float:left;padding:0;width:218px;height:38px;line-height:38px;text-indent:0.5em;border:0 solid green;background-color:transparent;" maxlength="31"/>
tagName   : INPUT
name      : txt_Username
type      : text
id        : txt_Username
style     : float:left;padding:0;width:218px;height:38px;line-height:38px;text-indent:0.5em;border:0 solid green;background-color:transparent;
maxlength : 31

outerHTML : <input name="txt_Password" type="password" id="txt_Password" maxlength="127" style="float:left;padding:0;width:218px;height:38px;line-height:38px;text-indent:0.5em;border:0 solid green;background-color:transparent;"
            maxlength="31"/>
tagName   : INPUT
name      : txt_Password
type      : password
id        : txt_Password
maxlength : 31
style     : float:left;padding:0;width:218px;height:38px;line-height:38px;text-indent:0.5em;border:0 solid green;background-color:transparent;

outerHTML : <input type="button" id="btnSubmit" name="btnSubmit" value="确定" onclick="SubmitForm();" class="button_css"/>
tagName   : INPUT
type      : button
id        : btnSubmit
name      : btnSubmit
value     : 确定
onclick   : SubmitForm();
class     : button_css

outerHTML : <input type="reset" name="Submit2" value="取消" onclick="canceltext();" class="button_css"/>
tagName   : INPUT
type      : reset
name      : Submit2
value     : 取消
onclick   : canceltext();
class     : button_css

I have got the source code of the reset page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Pragma" content="no-cache" />
<link rel="stylesheet"  href='../../../../Cuscss/frame.css?2020070716413845-1425773353' type='text/css'>
<script language="JavaScript" src="../../../resource/common/util.js?2020070716413845-1425773353"></script>
<script language="JavaScript" type="text/javascript">

function LoadFrame()
{
}


function Reboot()
{
if(ConfirmEx("确定要重启设备吗?"))
{
setDisable('Restart_button',   1);
setDisable('Restore_button',    1);
setDisable('btnRestoreDftCfg', 1);
var Form = new webSubmitForm();

Form.setAction('set.cgi?x=' + 'InternetGatewayDevice.X_HW_DEBUG.SMP.DM.ResetBoard'
 + '&RequestFile=html/ssmp/devmanage/cmccdevicereset.asp');
Form.addParameter('x.X_HW_Token', getValue('onttoken'));
Form.submit();
}
}

</script>
</head>
<body class="mainbody" onLoad="LoadFrame();">

<div class="func_spread"></div>
<div class="title_with_desc">
<label id="Title_reboot_lable">设备重启</label>
</div>
<div class="title_01" style="padding-left:10px;" width="100%">
<label id="Title_reboot_tips_lable">点击如下按钮重启路由器。</label>
</div>
<div class="button_spread"></div>
<div align="right">
<input type="hidden" name="onttoken" id="hwonttoken" value="de0f5f98c4d4a77239ccb981cd5c4bf3">
<input type='button' name="Restart_button" id="Restart_button" class="submit" style="width:98px" onClick='Reboot()' value="重启">
</div>
</body>
</html>

It is located at address:

http://192.168.1.1/html/ssmp/devmanage/cmccdevicereset.asp

Also I don't really know if Submit('btnSubmit') logged me in or not, I am not totally sure...

And although this works, Firefox initializes very slowly.


I have finally figured out how to do it the telnet way:

telnet 192.168.1.1
root
adminHW
reset

How can I make it a script that automatically inputs commands?

8
  • Is curl able to return content? My first thought would be to sniff the requests made by your browser and then mirror them with curl.
    – Richard
    Jan 26, 2021 at 8:11
  • 1
    You could use your browser’s developer tools to try and reverse engineer how the login works and then what the reboot button does.
    – Daniel B
    Jan 26, 2021 at 9:04
  • 1
    Are you really sure that URL is “https://192.168.1.1” (i.e. httpS instead of http)?
    – Sasha
    Jan 26, 2021 at 10:23
  • Yep, it uses http protocol, I just had some brain lapses... Jan 26, 2021 at 10:37
  • The commands really don't exist... Jan 26, 2021 at 11:40

4 Answers 4

2

The SSH way

If your router supports SSH access (you probably need to enable it in the router settings), you can try issuing a command via SSH to restart it.

It could be something like ssh USERNAME@ROUTER_ADDRESS reboot or ssh USERNAME@ROUTER_ADDRESS "sudo reboot".

  1. First, you need to enable SSH access. Ensure that it works by typing smth like ssh USERNAME@ROUTER_ADDRESS (if it does, you will be asked for password and, after entering correct password, get into the router's command prompt).
  2. Then determine which command you need to type into the router's command prompt to restart it. It could be just reboot. But you may also need to specify exact path like /sbin/reboot, /usr/sbin/reboot or etc. And/or you may also need to elevate the privileges like sudo COMMAND or su -c 'COMMAND' root.
  3. I the previous two steps are passed, you can combine logging in into SSH (ssh USERNAME@ROUTER_ADDRESS) and issuing a reboot command (e.g. sudo reboot) into a single command (like ssh USERNAME@ROUTER_ADDRESS "sudo reboot"). You will still be asked for password every time, but it can be avoided (please ping me in comments if you reached this step and want to avoid typing passwords).

The HTTP way

Open Network Monitor in your browser (e.g. in Firefox that's Shift+Ctrl+E) and try to determine which exactly web request is issued when you confirm restart (e.g. in Firefox you can see the whole data of the request).

8
  • 1
    Nope, accessing the router using ssh gives the same result as accessing the router using telnet, same console, same login and password, and I have tried all your commands and they aren't working... Jan 26, 2021 at 9:01
  • @XeнεiΞэnвϵς, could it happen that more commands exist, but they are not in $PATH?
    – Sasha
    Jan 26, 2021 at 10:20
  • Nope, probably the commands were removed by the ISP, to prevent people from hacking their routers, Chinese telecommunication companies are all controlled by CCP, they wouldn't dare to let their customers to have the chance to bypass the GFW, however I have the many ways to bypass the GFW, but they all only effect the computer, none of them is LAN-wide... Jan 26, 2021 at 10:26
  • @XeнεiΞэnвϵς, why wouldn't they just disable telnet/ssh then?
    – Sasha
    Jan 26, 2021 at 10:28
  • In fact telnet and ssh are disabled by default, I hacked the router and enabled telnet and ssh, however the shell is incomplete, so I can't really use it... Jan 26, 2021 at 10:31
1

According to user Ligeti here, for a similar model: https://jalalsela.com/accessing-hg8245q-shell/

  • SSH/Telnet to the device
  • Log in as root
  • You can list available commands with /?

From here you can try and find a command like reboot to restart, or shell to give access to more bash commands, maybe shutdown -r or help/? from there. If it says you don't have permission for something, he includes steps to super-admin yourself, but I don't think it would be necessary.

1
  • I got the command by typing ?(without hitting Enter), it automatically displays all available commands once question mark is inputted, and that's how I have found the command. Thanks. Jan 28, 2021 at 9:43
1

Finally I have done it, and I found it to be very easy.

I used Python 3.9.1, Internet Explorer , Selenium and IEDriverServer.exe (32-bit).

The code:

    import selenium
    from selenium import webdriver
    ie = webdriver.Ie()
    ie.get('http://192.168.1.1')
    ie.find_element_by_id('txt_Username').send_keys("CMCCAdmin")
    ie.find_element_by_id('txt_Password').send_keys("aDm8H%MdA")
    ie.find_element_by_id('btnSubmit').click()
    ie.get('http://192.168.1.1/html/ssmp/devmanage/cmccdevicereset.asp')
    ie.find_element_by_id('Restart_button').click()
    ie.switch_to.alert.accept()

I saved it as RebootModem.py, it works well, just it doesn't close the Window automatically after the router rebooted, and the code execution just hangs at ie.switch_to.alert.accept() and won't quit, requiring me to manually close the IE window...

I tried the code in console, and I have found that the console won't accept commands until the router has finished rebooting...

I am currently trying to find the webbot, urllib(2), cookielib and twill way to do this, I don't think relying on a browser is very efficient.


I have made it automatically close the IE window and script by:

    start-process -filepath python -argumentlist $PSScriptRoot\RebootModem.py
    start-sleep -seconds 15
    get-process -name iexplore | stop-process
    get-process -name IEDriverServer| stop-process

Save as RebootModem.ps1, at the same directory as RebootModem.py, run RebootModem.ps1 to start execution of RebootModem.py and it will automatically close the IE window and Python.exe (its name is changed to IEDriverServer.exe) after 15 seconds...


To generalize the code, just replace the elementids with the elementids of your router's webpage, you can get them by Ctrl+Shift+I, and replace the addresses with the addresses you found (though you probably don't need to change 192.168.1.1), I got the address of the page used to reboot modem by "View Frame Source".


P.S. the full code I used to reset all network settings:

devcon disable *dev_8168*
devcon enable *dev_8168*
start-sleep -seconds 3
netsh winsock reset
netsh winhttp reset proxy
netsh http flush log buffer
net start dot3svc
netsh lan reconnect
net stop dot3svc
start-sleep -seconds 3
netsh int ip reset
netsh int ipv4 reset
netsh int ipv6 reset
netsh int httpstunnel reset
netsh int portproxy reset
netsh int tcp reset
start-sleep -seconds 3
ipconfig /release
ipconfig /all
ipconfig /flushdns
ipconfig /registerdns
ipconfig /renew

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 
RunDll32.exe InetCpl.cpl,ResetIEtoDefaults
Start-Sleep -Seconds 1
[System.Windows.Forms.SendKeys]::SendWait("{Tab}")
[System.Windows.Forms.SendKeys]::SendWait(" ")
[System.Windows.Forms.SendKeys]::SendWait("R")
Start-Sleep -Seconds 2
[System.Windows.Forms.SendKeys]::SendWait("C")

start-process -filepath python -argumentlist $PSScriptRoot\RebootModem.py
start-sleep -seconds 15
get-process -name iexplore | stop-process
get-process -name IEDriverServer| stop-process

Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name "ProxyEnable" -Type DWord -Value 1
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name "ProxyOverride" -Type String -Value "login.live.com;account.live.com;clientconfig.passport.net;wustat.windows.com;*.windowsupdate.com;*.wns.windows.com;*.hotmail.com;*.outlook.com;*.microsoft.com;*.msftncsi.com;<local>"
1
  • I know the PowerShell code I used to time the script is dirty, however I currently don't know the Python way to stop a command that prevents console from accepting new commands, I am still learning and researching... Jan 27, 2021 at 8:09
0

I have done it...again!

The PowerShell + VBScript + Telnet way to do this:

set router = CreateObject ("WScript.Shell")
router.run("Telnet")
WScript.Sleep 750
router.sendkeys("Open 192.168.1.1")
router.sendkeys("{Enter}")
WScript.Sleep 750
router.sendkeys("root")
router.sendkeys("{Enter}")
WScript.Sleep 750
router.sendkeys("adminHW")
router.sendkeys("{Enter}")
WScript.Sleep 750
router.sendkeys("reset")
router.sendkeys("{Enter}")

Save as RebootModem.vbs

Start-Process -Filepath cscript.exe -Argumentlist $PSScriptRoot\RebootModem.vbs
Start-Sleep -Seconds 6
Get-Process -Name Telnet | Stop-Process

Save as RebootModem.ps1

Run RebootModem.ps1 to restart the modem via Telnet and automatically close Telnet.exe after 6 seconds.


Pure PowerShell method:

    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    Start-Process -Filepath Telnet.exe -Argumentlist 192.168.1.1
    Start-Sleep -Seconds 1
    [System.Windows.Forms.SendKeys]::SendWait("root")
    [System.Windows.Forms.SendKeys]::SendWait("{Enter}")
    [System.Windows.Forms.SendKeys]::SendWait("adminHW")
    [System.Windows.Forms.SendKeys]::SendWait("{Enter}")
    [System.Windows.Forms.SendKeys]::SendWait("reset")
    [System.Windows.Forms.SendKeys]::SendWait("{Enter}")
    Get-Process -Name Telnet | Stop-Process

It gets the job done in less than 3 seconds. I have determined that this is indeed the most efficient way to do this.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .