Being able to run IDA scripts from the command line is very useful, but can be a bit kludgy. Fortunately, idascript was written to simplify this process. Unfortunately (for me), it was written for Windows.
Since I work primarily in a Linux environment, I re-wrote the idascript utility in Python. I also added a few features to the idascript Python module, for convenience:
- Script arguments are accessible via the normal sys.argv
- The script can be terminated via the normal sys.exit function
- The directory to your collection of IDA scripts (specified during install) is added to sys.path
Installation is straightforward:
eve@eve:~/idascript$ sudo ./install.py
Absolute path to your IDA install directory: /opt/ida/bin
Absolute path to the directory where you usually keep all your IDA scripts: /opt/ida/scripts
IDA_INSTALL_PATH = /opt/ida/bin
IDA_SCRIPT_PATH = /opt/ida/scripts
IDA_OUT_FILE = /tmp/idaout.txt
Using existing IDAPython scripts with idascript is as easy as importing the idascript module:
print "Cross references to strcpy:"
for xref in XrefsTo(LocByName("strcpy")):
print "0x%.8X %s" % (xref.frm, GetDisasm(xref.frm))
And usage of idascript itself is the same as the original idascript utility:
eve@eve:~$ idascript ./target.idb ./strcpy.py
Cross references to strcpy:
0x00407F68 jalr $t9 ; strcpy
0x0040B9B8 jalr $t9 ; strcpy
0x0040E5BC jr $t9 ; strcpy
0x0041D448 jalr $t9 ; strcpy
0x00422C04 jalr $t9 ; strcpy
0x00422D04 jalr $t9 ; strcpy
0x00424C4C jalr $t9 ; strcpy
0x00425400 jalr $t9 ; strcpy
0x00430358 jalr $t9 ; strcpy
0x0043045C jalr $t9 ; strcpy
0x00434118 jalr $t9 ; strcpy
0x00436A30 jalr $t9 ; strcpy
0x0043CE48 jalr $t9 ; strcpy
0x00407F58 la $t9, strcpy
0x0040B9AC la $t9, strcpy
0x0040E598 la $t9, strcpy
0x0041D440 la $t9, strcpy
0x00422BF8 la $t9, strcpy
0x00422CF8 la $t9, strcpy
0x00422D74 la $t9, strcpy
0x00424C44 la $t9, strcpy
0x004253F0 la $t9, strcpy
0x004302D8 la $t9, strcpy
0x00430454 la $t9, strcpy
0x00434110 la $t9, strcpy
0x00436A28 la $t9, strcpy
0x0043CE40 la $t9, strcpy
0x00498ECC .word strcpy
Today we’ll be jailbreaking the Netgear NTV300 set top box…with a TV remote.
The Netgear NeoTV 300
Negear’s NeoTV set top boxes are designed to compete with the popular Roku, and can stream video from all the usual sources (Netflix, HuluPlus, Youtube, etc). The NTV300 is one of the least expensive NeoTV models, and while a GPL release is available, it contains only copies of the various standard open source utilities used by the NTV300. All the interesting bits – such as Netflix streaming, or the ability to build a custom firmware image – are not included.
Inside the NTV300 we find a Mediatek ARM SoC, a 128MB NAND flash chip and 256MB of RAM:
Inside the NTV300
Although D-Link’s CAPTCHA login feature has a history of implementation flaws and has been proven to not protect against the threat it was intended to thwart, they continue to keep this feature in their products. Today we’ll be looking at the CAPTCHA implementation in the D-Link DIR-605L, which is a big-endian MIPS system running Linux 2.4.
A pre-authentication vulnerability exists in the DIR-605L’s processing of the user-supplied CAPTCHA data from the Web-based login page. The formLogin function in the Boa Web server is responsible for handling the login data, and obtains the value of the FILECODE POST variable using the websGetVar function. The FILECODE value contains a unique string identifying the CAPTCHA image displayed on the login page, and is saved to the $s1 register:
$s1 = FILECODE
If the CAPTCHA feature is enabled, this value is later passed as the second argument to the getAuthCode function:
FILECODE value being passed to getAuthCode
The getAuthCode function saves the FILECODE value back to the $s1 register:
$s1 = $a1
Which in turn is passed as the third argument to sprintf, (note the ‘%s’ in the sprintf format string):
sprintf’s are bad, mmmk?
The result of the sprintf is saved to the address contained in $s0, which is the address of the stack variable var_80:
$a0 = var_80
This is a classic stack based buffer overflow, and overflowing var_80 allows us to control all of the register values saved onto the stack by getAuthCode’s function prologue, including the saved return address and the saved values of the $s0 – $s3 registers:
getAuthCode stack layout
I have an old DTV converter sitting around gathering dust, so I thought it would be interesting to take a look inside:
Inside the DTV Converter
As you can see, there’s not much there: a Thomson TV tuner, an IR receiver, 32MB of RAM and a 2MB flash chip (on the underside of the board). What really makes this interesting though is the LGDT1111 SoC; this is a DTV chip manufactured by LG, so it’s a little different than the Broadcom/Atheros/Ralink/etc SoCs found in a lot of other consumer devices. It is very popular with many DTV converters though, so determining its CPU architecture and reversing the underlying firmware could be interesting.
Digging around on the Internet turned up a nice block diagram of the LGDT1111 (courtesy of MVPtek):
LGDT1111 Block Diagram
The MVPtek web site states that the SoC uses an “AMR926EJ-STM” controller…could they mean an ARM926EJ-STM? Hmmm…
Today we’re going to take a look at an interesting little device, the Linksys WMB54G wireless music bridge.
This is a pretty specialized device, so it’s likely a fairly minimalistic system. Even the administrative interface is small and simple:
WMB54G Administrative Interface
The Linksys support page doesn’t have any firmware updates available, so let’s take a peek at the hardware.
Opening the case reveals an expectedly limited system, with just 2MB of flash, 8MB of RAM and a small processor covered up by a heat sink:
There are two connectors on the right hand side of the board, labelled J5 and J9. J5 appears to be a JTAG connector, while J9 shows promise of being a serial port:
J5 and J9 Connectors
Being able to emulate embedded applications in Qemu is incredibly useful, but not without pitfalls. Probably the most common issue that I’ve run into are binaries that try to read configuration data from NVRAM; since the binary is running in Qemu and not on the target device, there is obviously no NVRAM to read from.
Embedded applications typically interface with NVRAM through a shared library. The library in turn interfaces with the MTD partition that contains the device’s current configuration settings. Many programs will fail to run properly without the NVRAM configuration data, requiring us to intercept the NVRAM library calls and return valid data in order to properly execute the application in Qemu.
Here’s a Web server extracted from a firmware update image that refuses to start under Qemu:
It looks like httpd can’t start because it doesn’t know what IP address to bind to. The IP can’t be set via a command line argument, so it must be getting this data from somewhere else. Let’s fire up IDA and get cracking!
Qemu usually does a great job emulating embedded Linux applications, but as with anything you will occasionally run into bugs. While attempting to debug an embedded application in Qemu the other day, I ran into the following error:
eve@eve:~/firmware$ sudo chroot . ./qemu-mips bin/ls
bin/ls: Invalid ELF image for this architecture
This error is usually indicative of using the wrong endian emulator, but I knew that the target binary was big endian MIPS. The file utility began to shed some light on the issue:
eve@eve:~/firmware$ file bin/busybox
bin/busybox: ELF 32-bit MSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked (uses shared libs), corrupted section header size
Hmmm, a corrupted section header? Let’s take a closer look at the binary.
So far in this series we’ve found that we can log in to our target TEW-654TR router by either retrieving the plain text administrator credentials via TFTP, or through SQL injection in the login page. But the administrative web interface is just too limited – we want a root shell!
We’ll be doing a lot of disassembly and debugging, so having IDA Pro Advanced is recommended. But for those of you who don’t have access to IDA, I’ve included lots of screenshots and an HTML disassembly listing courtesy of IDAnchor.
In part 2 of this series we found a SQL injection vulnerability using static analysis. However, it is often advantageous to debug a target application, a capability that we’ll need when working with more complex exploits later on.
In this segment we won’t be discovering any new vulnerabilities, but instead we will focus on configuring and using our debugging environment. For this we will be using Qemu and the IDA Pro debugger. If you don’t have IDA you can use insight/ddd/gdb instead, but in my experience IDA is far superior when it comes to embedded debugging.
In part 1 we used the TEW-654TR’s TFTP service to retrieve the administrative credentials to our target system.
But what if we didn’t have access to the TFTP service? Many embedded devices don’t have a TFTP service, or there may be a firewall between us and the target that blocks traffic to UDP port 69. In this case, we’ll have to take a closer look at the web application running on the target.