<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>James Slater</title>
	<atom:link href="http://james.slaterspage.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://james.slaterspage.com</link>
	<description>If that&#039;s what you were looking for, you&#039;ve found it.</description>
	<lastBuildDate>Thu, 07 Feb 2013 17:16:37 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.2</generator>
		<item>
		<title>Hacking the AMX NXA-WAP250G Access Point (with a Raspberry Pi)</title>
		<link>http://james.slaterspage.com/hacking-the-amx-nxa-wap250g-access-point-with-a-raspberry-pi/</link>
		<comments>http://james.slaterspage.com/hacking-the-amx-nxa-wap250g-access-point-with-a-raspberry-pi/#comments</comments>
		<pubDate>Thu, 07 Feb 2013 11:47:18 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Reversing]]></category>

		<guid isPermaLink="false">http://james.slaterspage.com/?p=322</guid>
		<description><![CDATA[A post on the (aptly named) /dev/ttyS0 device hacking blog entitled &#34;<a href="http://www.devttys0.com/2012/11/reverse-engineering-serial-ports/">Reverse Engineering Serial Ports</a>&#34; reminded me that I had an <a href="http://www.amx.com/products/NXA-WAP250G.asp">AMX NXA-WAP250G Wireless Access Point</a> that I'd been meaning to investigate for some time. I thought I'd document the process I went through while reverse engineering it, in the hope that it's interesting or useful to someone.
<a href="http://james.slaterspage.com/wp-content/uploads/2013/02/amx_wap250g_external.jpg"><img src="http://james.slaterspage.com/wp-content/uploads/2013/02/amx_wap250g_external.jpg" alt="AMX WAP-250G" title="AMX WAP-250G" class="alignleft size-full wp-image-409" /></a>

<h3>The Firmware</h3>

Not having the device to hand, I started with what I could find out from a saved firmware update - a file named <tt>zz-img.bin</tt>, dated 2008-08-04 and 1,350,968 bytes in size. I went with what's usually my first instinct in situations like this, and tried the <em><a href="http://en.wikipedia.org/wiki/File_(command)">file</a></em> command:

<code>$ file zz-img.bin
zz-img.bin: ELF 32-bit MSB executable, MIPS, MIPS-II version 1 (SYSV), statically linked, stripped</code>

It seemed likely the firmware image was actually a <a href="http://en.wikipedia.org/wiki/MIPS_Technologies">MIPS</a>-architecture <a href="http://en.wikipedia.org/wiki/Executable_and_Linkable_Format">ELF</a>, in which <em><a href="http://en.wikipedia.org/wiki/Strings_(Unix)">strings</a></em> showed some strong indications that <a href="http://en.wikipedia.org/wiki/Zlib">zlib</a> compression was present:

<code>$ strings zz-img.bin
oversubscribed dynamic bit lengths tree
incomplete dynamic bit lengths tree
oversubscribed literal/length tree
incomplete literal/length tree</code>

I've omitted the other 14,000 lines of output!

As the only human-readable strings of characters in the output, they were quite obvious. They're likely to be immediately recognisable to anyone who has reverse engineered firmware before, but a simple Google[ref]Other search engines are available.[/ref] search for any of them would be enough to come to the same conclusion.

Hoping to find out what was hiding compressed inside the file, I tried running <em><a href="http://code.google.com/p/binwalk/">binwalk</a></em> over it; that told me nothing I didn't already know - that I was looking at a MIPS ELF. Slightly disheartened, I hacked together a trivial Python program to naively step through the firmware image, repeatedly calling <a href="http://docs.python.org/2/library/zlib.html#zlib.decompress">zlib.decompress</a> until it succeeded without error, or the end of the file was reached.

A moment later, starting 19,569 bytes from the beginning of the file, decompression was successful. I now had 3,303,265 bytes of output saved to a file imaginatively named <tt>zz-img.out</tt>; <em>file</em> didn't recognise it but <em>binwalk</em> claimed had 88 identifiable components:

<code>$ binwalk zz-img.out

DECIMAL   	HEX       	DESCRIPTION
-------------------------------------------------------------------------------------------------------
1062235   	0x10355B  	LZMA compressed data (sig 2), properties: 0x5D, dictionary size: 554696704 bytes, uncompressed size: 50372624 bytes
2339492   	0x23B2A4  	Zip archive data,  v0.0
2380548   	0x245304  	GIF image data, version 89a, 69 x 23
2381732   	0x2457A4  	GIF image data, version 89a, 1 x 1
2382466   	0x245A82  	TIFF image data, little-endian
2464692   	0x259BB4  	GIF image data, version 89a, 69 x 23
2465938   	0x25A092  	TIFF image data, little-endian
2466722   	0x25A3A2  	TIFF image data, little-endian
2467538   	0x25A6D2  	TIFF image data, big-endian
2534356   	0x26ABD4  	GIF image data, version 89a, 69 x 23
2535636   	0x26B0D4  	GIF image data, version 89a, 69 x 23
2536866   	0x26B5A2  	TIFF image data, little-endian
2542338   	0x26CB02  	TIFF image data, little-endian
2545572   	0x26D7A4  	GIF image data, version 89a, 69 x 23
2546740   	0x26DC34  	GIF image data, version 89a, 69 x 23
2809172   	0x2ADD54  	GIF image data, version 89a, 32 x 32
2898498   	0x2C3A42  	TIFF image data, little-endian
2988972   	0x2D9BAC  	LZMA compressed data (sig 2), properties: 0x5D, dictionary size: 687865856 bytes, uncompressed size: 10 bytes
2996232   	0x2DB808  	Linux Journalled Flash filesystem, little endian
3021080   	0x2E1918  	gzip compressed data, was "HACL.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:05 2004
3021992   	0x2E1CA8  	gzip compressed data, was "HCfg.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:05 2004
3022612   	0x2E1F14  	gzip compressed data, was "HQos.htm", from NTFS filesystem (NT), last modified: Tue Sep 14 09:39:59 2004
3023176   	0x2E2148  	gzip compressed data, was "HSecurity.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:05 2004
3023852   	0x2E23EC  	gzip compressed data, was "HServer.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:06 2004
3024468   	0x2E2654  	gzip compressed data, was "HSetup.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:06 2004
3025208   	0x2E2938  	gzip compressed data, was "HSetupAv.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:06 2004
3026100   	0x2E2CB4  	gzip compressed data, was "HWpa.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:06 2004
3026644   	0x2E2ED4  	gzip compressed data, was "Hfw.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:06 2004
3027024   	0x2E3050  	gzip compressed data, was "Hfwadv.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:06 2004
3027696   	0x2E32F0  	gzip compressed data, was "Hradio.htm", from NTFS filesystem (NT), last modified: Tue Sep 14 04:13:29 2004
3028572   	0x2E365C  	gzip compressed data, was "Hsetup2.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:07 2004
3029060   	0x2E3844  	gzip compressed data, was "about.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:07 2004
3029296   	0x2E3930  	gzip compressed data, was "ap_stats.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:07 2004
3030240   	0x2E3CE0  	gzip compressed data, was "cfgscr.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:07 2004
3031228   	0x2E40BC  	gzip compressed data, was "configs.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:07 2004
3032416   	0x2E4560  	gzip compressed data, was "index.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:12 2004
3033104   	0x2E4810  	gzip compressed data, was "lastupld.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:12 2004
3033376   	0x2E4920  	gzip compressed data, was "privacy.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:12 2004
3034432   	0x2E4D40  	gzip compressed data, was "privedit.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:12 2004
3036020   	0x2E5374  	gzip compressed data, was "privnew.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:12 2004
3037940   	0x2E5AF4  	gzip compressed data, was "qos.htm", from NTFS filesystem (NT), last modified: Tue Sep 14 08:43:01 2004
3039708   	0x2E61DC  	gzip compressed data, was "radio.htm", from NTFS filesystem (NT), last modified: Thu Sep 16 12:04:50 2004
3041244   	0x2E67DC  	gzip compressed data, was "reboot.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:13 2004
3041580   	0x2E692C  	gzip compressed data, was "rstcfg.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:13 2004
3041828   	0x2E6A24  	gzip compressed data, was "scanning.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:13 2004
3042136   	0x2E6B58  	gzip compressed data, was "security.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:14 2004
3044496   	0x2E7490  	gzip compressed data, was "server.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:14 2004
3045708   	0x2E794C  	gzip compressed data, was "setleft.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:15 2004
3046316   	0x2E7BAC  	gzip compressed data, was "setup.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:15 2004
3047624   	0x2E80C8  	gzip compressed data, was "setup2.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:15 2004
3049028   	0x2E8644  	gzip compressed data, was "setupadv.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:15 2004
3050884   	0x2E8D84  	gzip compressed data, was "setupfr3.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:15 2004
3051220   	0x2E8ED4  	gzip compressed data, was "stafr3.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:16 2004
3051592   	0x2E9048  	gzip compressed data, was "stafr3a.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:16 2004
3051968   	0x2E91C0  	gzip compressed data, was "stafr3b.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:16 2004
3052348   	0x2E933C  	gzip compressed data, was "staleft.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:16 2004
3053180   	0x2E967C  	gzip compressed data, was "stalist.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:17 2004
3053920   	0x2E9960  	gzip compressed data, was "stastats.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:17 2004
3055432   	0x2E9F48  	gzip compressed data, was "survey.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:17 2004
3056192   	0x2EA240  	gzip compressed data, was "upldadv.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:18 2004
3057888   	0x2EA8E0  	gzip compressed data, was "upldprog.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:18 2004
3058180   	0x2EAA04  	gzip compressed data, was "upldstat.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:18 2004
3059028   	0x2EAD54  	gzip compressed data, was "upload.htm", from NTFS filesystem (NT), last modified: Fri Aug 13 05:44:18 2004
3060464   	0x2EB2F0  	gzip compressed data, was "wpa.htm", from NTFS filesystem (NT), last modified: Fri Sep 10 04:32:37 2004
3061812   	0x2EB834  	GIF image data, version 89a, 1 x 1
3061856   	0x2EB860  	GIF image data, version 89a, 61 x 25
3062528   	0x2EBB00  	GIF image data, version 89a, 88 x 25
3063412   	0x2EBE74  	GIF image data, version 89a, 77 x 25
3067216   	0x2ECD50  	GIF image data, version 89a, 61 x 25
3067936   	0x2ED020  	GIF image data, version 89a, 364 x 390
3072756   	0x2EE2F4  	GIF image data, version 89a, 460 x 235
3120580   	0x2F9DC4  	GIF image data, version 89a, 39 x 15
3121012   	0x2F9F74  	GIF image data, version 89a, 77 x 25
3121820   	0x2FA29C  	GIF image data, version 89a, 1 x 1
3121864   	0x2FA2C8  	GIF image data, version 89a, 179 x 120
3127352   	0x2FB838  	GIF image data, version 89a, 54 x 40
3127656   	0x2FB968  	GIF image data, version 89a, 95 x 40
3128144   	0x2FBB50  	GIF image data, version 89a, 1 x 40
3128192   	0x2FBB80  	GIF image data, version 89a, 72 x 40
3128584   	0x2FBD08  	GIF image data, version 89a, 94 x 25
3129540   	0x2FC0C4  	GIF image data, version 89a, 77 x 25
3130348   	0x2FC3EC  	GIF image data, version 89a, 77 x 25
3131156   	0x2FC714  	GIF image data, version 89a, 1 x 1
3131200   	0x2FC740  	GIF image data, version 89a, 270 x 80
3132364   	0x2FCBCC  	GIF image data, version 89a, 61 x 25
3133136   	0x2FCED0  	GIF image data, version 89a, 61 x 25
3211978   	0x3102CA  	Linux Journalled Flash filesystem, little endian</code>

(I initially tried binwalk v0.4.3 which output over a hundred false positive "JFFS" and "LZMA" entries. The output shown is from v0.5.0 which is much more accurate, on this sample at least.)

Of those, the <a href="http://en.wikipedia.org/wiki/Gzip">gzipped</a> ones looked like they could be interesting, with plausible names and modification dates. Using the <em><a href="http://en.wikipedia.org/wiki/Dd_(Unix)">dd</a></em> and <em>gunzip</em> commands, I extracted one (though I understand the latest version of <em>binwalk</em> can do this itself) but the resulting HTML file turned out to be a fairly uninteresting part of the access point's web interface.

Moving on, I tried <em>strings</em> again on <tt>zz-img.out</tt>. This time, operating on uncompressed data, the output was much more useful.

There were many references to VxWorks:

<code>VxWorks5.4.2
Jul 11 2008, 15:37:45</code>

Boot parameters:

<code>j8tffs:(0,0):/fl/zz-img.bin f=0x00 e=192.168.1.240:0xffffff00 o=ae g=192.168.1.254 s=factory
AR531XPLUS
unknown boarddata rev!
Atheros AR5315 default</code>

There appeared to be a command line interface, complete with help:

<code>Type "help" for a list of valid commands.</code>

Some of which looked particularly interesting:

<code>Searching for BSS
find
connect to BSS X
connect
Copy file
Boot parameters
boot
Temporary factory admin
admin</code>

One of the other strings stood out too, “OWOWOWOWOWOWOWOW”. Amusingly, a Google search for that string led me straight back to another post on the /dev/ttyS0 blog about a <a href="http://www.devttys0.com/2011/06/mystery-file-system/">mystery VxWorks filesystem</a> (later identified as MemFS).

At this point, I considered it was fairly likely the device was running VxWorks, had a command line interface of some sort, and that if it came to it, modifying the existing firmware update was at least plausible. There's much more I could have investigated in the firmware - perhaps starting with that MemFS filesystem - but by this point I'd managed to find the actual device itself and was eager to open it up and see what it looked like inside.

<h3>The Hardware</h3>

As it turned out, I could have probably skipped the firmware analysis and jumped straight to powering the device up and taking it to pieces (not necessarily in that order).

<a href="http://james.slaterspage.com/wp-content/uploads/2013/02/amx_wap250g_internal.jpg"><img src="http://james.slaterspage.com/wp-content/uploads/2013/02/amx_wap250g_internal-300x225.jpg" alt="AMX WAP-250G Board" title="AMX WAP-250G Board" width="300" height="225" class="alignleft size-medium wp-image-412" /></a>

Any router hackers out there will no doubt find that board familiar; it looks just like a <a href="http://www.h-peters.com/fonap/inrouter.html">Fonera 2100</a>. The FON2100 router is based on the <a href="http://wiki.openwrt.org/doc/hardware/soc#atheros1">Atheros AR5315 SoC</a>, which matched up with what I'd seen in my firmware analysis. The part numbers of the Hynix HY57V281620ETP-H memory is also consistent, while the ST 25P32V6P flash chip is slightly different.

From some further research, I discovered that the Fonera 2100 is actually an Accton MR3201A in disguise. The Edge-Core WA3101, Philips SNR6500, SMC WEBT-G, Siemens Gigaset WLAN Repeater 108, and the Meraki Mini all appear to be slightly (if that) modified versions of the same design. This was great news, because it meant reverse engineering my esoteric router would be enormously simpler than I might have expected - there's plenty of information about those other routers about there, particularly concerning running Linux on them.

Delving into the information that the <a href="http://wiki.openwrt.org/toh/fon/fonera">OpenWRT</a> and <a href="http://www.dd-wrt.com/wiki/index.php/Fonera">DD-WRT</a> projects had about these routers, I found out that most, if not all, of them had an ST 25P64V6P - 8MB - flash, while the WAP250G has a 25P32V6P with only 4MB capacity. That was annoying, but among the many published hardware hacks is an SD card mod which would massively improve the amount of storage available.

Aside from some fanciful ideas about future hardware modifications, the most pertinent information I'd found out was that Fonera's serial port pinout is well known and published. To connect to it, I needed something that would talk <a href="http://en.wikipedia.org/wiki/Serial_port">serial</a> at TTL signal levels (3.3V) and not RS-232 (somewhere around 15V). Just as I was considering cutting up a <a href="http://jethomson.wordpress.com/2010/02/21/diy-usb-to-serial-cable-for-3usd/">USB phone cable</a>, I realised that I had a full-blown Linux system with a handily accessible serial port that runs at the correct voltage - my Raspberry Pi.

<h3>The Raspberry Pi</h3>

I cut up and soldered together some cables from an old PC case that would previously have connected the external buttons to the PC's motherboard - the ones that would have gone to the HDD LED and reset switch of the PC are quite obvious in the picture below. The GPIO pins of the Pi are <a href="http://elinux.org/RPi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29">well documented</a> and the OpenWRT page about the Fonera includes its serial pinout, which I confirmed with a multimeter, as described in the post that set me off with this whole project.
<a href="http://james.slaterspage.com/wp-content/uploads/2013/02/amx_wap250g_raspberrypi.jpg"><img src="http://james.slaterspage.com/wp-content/uploads/2013/02/amx_wap250g_raspberrypi.jpg" alt="" title="Raspberry Pi and AMX WAP-250G" width="1024" height="768" class="alignleft size-full wp-image-414" /></a>

With Raspbian Wheezy running on the Pi, using the serial port was quite straightforward. I had to edit <tt>cmdline.txt</tt> on the SD card to disable the serial console on <tt>/dev/ttyAMA0</tt>, otherwise the Pi would be outputting kernel messages over it as it booted up. Likewise I commented out the <em>getty</em> line from <tt>/etc/inittab</tt> on the system to prevent it from issuing a login prompt over the serial port.

With the Pi connected to the powered-up router as pictured above, I fired up <em>minicom</em>, told it to connect to <tt>ttyAMA0</tt> with the baud rate 9600 and 8N1 (rarely a bad guess) and gingerly tapped “enter”.

I was instantly greeted with a login prompt. Neat! I knew from the 250G's documentation what the web interface default credentials were, so I tried those - 'Admin' and '1988':

<code>AP login: Admin
Password: ****

ACCTON Access Point Rev v1.0.6.0
wlan[0,0] -> help
List of Access Point CLI commands:
wlan[0,0] -> </code>

As you can see, the serial connection works, the login was successful but the 'help' output I initially found while examining the firmware was absent. I tried on of the commands I'd seen in that help text:

<code>wlan[0,0] -> version
AP software v1.0.6.0</code>

That worked, so it seemed like the 'help' might be correct, so I wasn't sure why I couldn't see it. Looking back at that help text for some other commands to try, one in particular stood out - 'admin'. The line above it - presumably the description of the command - said "Temporary Factory admin" so I tried it:

<code>wlan[0,0] -> admin
Password: ****
Sorry
wlan[0,0] -> admin
Password: 
Ok</code>

It asked me for a password; I tried '1998' which was incorrect. Just as I was considering loading the firmware up in IDA or looking through it for more suspicious looking strings, I tried again and just hit enter - a blank password. That worked!

Interestingly, after using the 'admin' command, 'help' now works and outputs the full unabridged text I had extracted from the firmware earlier:

<code>wlan[0,0] -> help
List of Access Point CLI commands:
 ?                                  -- Display CLI Command List
 i                                  -- Display task information
 add remoteWbr                      -- Add a remote Wireless Bridge
 admin                              -- Temporary factory admin
 boot flash                         -- Boot from flash
 boot ethernet                      -- Boot from network
 cp                                 -- Copy file
 config wlan                        -- config wlanX
 config virtualap                   -- config virtual ap
 config bss                         -- config bss
 connect bss                        -- connect to bssX
 del acl                            -- Delete Access Control List
 del key                            -- Delete Encryption key
 del remoteWbr                      -- Delete a remote Wireless Bridge
 find bss                           -- Find BSS
 find bssPassive                    -- Find BSS with passive scans
 find channel                       -- Find Available Channel
 find all                           -- Find All BSS
 format                             -- Format flash filesytem
 MFT_Ant                            -- Setting Antenna Status
 MFT_Boot_Ver                       -- MFT Show boot code version .
 MFT_Led                            -- MFT Setting Led Traffic Rate .
 MFT_Show_Boot                      -- Show boot up message
 start_tr                           -- start traffic rate monitor 
 stop_tr                            -- stop traffic rate monitor 
 bootrom                            -- Update boot rom image
 ftp                                -- Software update via FTP
 get 11gonly                        -- Display 11g Only Allowed
 get 11goptimize                    -- Display 11g Optimization Level
 get 11goverlapbss                  -- Display Overlapping BSS Protection
 get abolt                          -- 
 get acl                            -- Display Access Control List
 get aging                          -- Display Aging Interval
 get antenna                        -- Display Antenna Diversity
 get arptable                       -- Display ARP Table
 get route                          -- Display Route Table
 get association                    -- Display Association Table
 get authentication                 -- Display Authentication Type
 get autochannelselect              -- Display Auto Channel Select
 get basic11b                       -- Display Basic 11b Rates
 get basic11g                       -- Display Basic 11g Rates
 get beaconinterval                 -- Display Beacon Interval
 get bootLine                       -- Display the bootLine
 get burstSeqThreshold              -- Display Max Number of frames in a Burst
 get burstTime                      -- Display Burst Time
 get cacheperf                      -- Display the cache performance counters
 get calibration                    -- Display Noise And Offset Calibration Mode
 get cckTrigHigh                    -- Display Higher Trigger Threshold for CCK Phy Errors for ANI Control
 get cckTrigLow                     -- Display Lower Trigger Threshold for CCK Phy Errors for ANI Control
 get cckWeakSigThr                  -- Display ANI Parameter for CCK Weak Signal Detection Threshold
 get channel                        -- Display Radio Channel
 get cipher                         -- Display Encryption cipher
 get compproc                       -- Display Compression scheme
 get compwinsize                    -- Display Compression Window Size
 get config                         -- Display Current AP Configuration
 get countrycode                    -- Display Country Code
 get cpu                            -- Display CPU Loading
 get radarnewchannel                -- Display radar new channel
 get csabeaconcount                 -- Display CSA Beacon Count
 get ctsmode                        -- Display CTS mode
 get ctsrate                        -- Display CTS rate
 get ctstype                        -- Display CTS type
 get domainsuffix                   -- Display Domain Name Server suffix
 get dtim                           -- Display Data Beacon Rate (DTIM)
 get enableANI                      -- Display Adaptive Noise Immunity Control On/Off
 get encryption                     -- Display Encryption Mode
 get extendedchanmode               -- Display Extended Channel Mode
 get firStepLvl                     -- Display ANI Parameter for FirStepLevel
 get fragmentthreshold              -- Display Fragment Threshold
 get frequency                      -- Display Radio Frequency (MHz)
 get gateway                        -- Display Gateway IP Address
 get gbeaconrate                    -- Display 11g Beacon Rate
 get gdraft5                        -- Display 11g Draft 5.0 compatibility
 get groupkeyupdate                 -- Display Group Key Update Interval (in Seconds)
 get hardware                       -- Display Hardware Revisions
 get hostipaddr                     -- Display Host IP Address
 get information                    -- Display Manufacture Information
 get interVF                        -- Display Inter Vap Forwarding State
 get intraVF                        -- Display Intra Vap Forwarding State
 get ipaddr                         -- Display IP Address
 get ipmask                         -- Display IP Subnet Mask
 get jsw                            -- Display Jumpstart Mode
 get jsP2PassPhrase                 -- Display JS-P2 passphrase
 get key                            -- Display Encryption Key
 get keyentrymethod                 -- Display Encyrption Key Entry Method
 get keysource                      -- Display Source Of Encryption Keys
 get login                          -- Display Login User Name
 get minimumrate                    -- Display Minimum Rate
 get nameaddr                       -- Display IP address of name server
 get nf                             -- Display Noise Floor
 get noiseImmunityLvl               -- Display ANI Parameter for Noise Immunity Level
 get ofdmTrigHigh                   -- Display Higher Trigger Threshold for OFDM Phy Errors for ANI Control
 get ofdmTrigLow                    -- Display Lower Trigger Threshold for OFDM Phy Errors for ANI Control
 get ofdmWeakSigDet                 -- Display ANI Parameter for OFDM Weak Signal Detection
 get overRidetxpower                -- Display Tx power override
 get operationMode                  -- Display Operation Mode
 get pktLogEnable                   -- Display Packet Logging Mode
 get power                          -- Display Transmit Power Setting
 get pppoe                          -- display the PPPoE setting
 get pppoeInfo                      -- display the PPPoE setting
 get pvid                           -- Display the VLAN Tag
 get quietAckCtsAllow               -- Display if Ack/Cts frames are allowed during quiet period
 get quietDuration                  -- Display Duration of quiet period
 get quietOffset                    -- Display Offset of quiet period into the beacon period
 get radiusname                     -- Display RADIUS server name or IP address
 get radiusport                     -- Display RADIUS port number
 get rate                           -- Display Data Rate
 get reg                            -- Display the register contents at the given offset
 get telecregstatus                 -- Display Telec 5GHz Regulatory Update status
 get remoteAp                       -- Display Remote Ap's Mac Address
 get reset                          -- Display # of resets
 get remoteWbr                      -- Display configured Remote Wireless bridges
 get hwtxretries                    -- Display HW Transmit Retry Limit
 get swtxretries                    -- Display SW Transmit Retry Limit
 get rogueAPDetect                  -- Display Rogue AP Detection Mode
 get bkScaninterval                 -- Display Background Scan Interval for Rogue AP detection
 get rtsthreshold                   -- Display RTS/CTS Threshold
 get shortpreamble                  -- Display Short Preamble Usage
 get shortslottime                  -- Display Short Slot Time Usage
 get snmp                           -- Display SNMP Community Name
 get sntpserver                     -- Display SNTP/NTP Server IP Address
 get softwareretry                  -- Display Software Retry
 get spurImmunityLvl                -- Display ANI Parameter for Spur Immunity Level
 get ssid                           -- Display Service Set ID
 get ssidsuppress                   -- Display SSID Suppress Mode
 get active                         -- Display Active (up) Mode
 get station                        -- Display Station Status
 get SuperG                         -- Display SuperG Feature Status
 get systemname                     -- Display Access Point System Name
 get telnet                         -- Display Telnet Mode
 get timeout                        -- Display Telnet Timeout
 get tzone                          -- Display Time Zone Setting
 get updateparam                    -- Display Vendor Default Firmware Update Params
 get upsd                           -- Display UPSD Mode
 get uptime                         -- Display UpTime
 get vaps                           -- Display Number of Virtual APs
 get vlan                           -- Display VLAN Operational State
 get qos                            -- Display QoS Mode
 get watchdog                       -- Display Watchdog Mode
 get wds                            -- Display WDS Mode
 get wep                            -- Display Encryption Mode
 get wirelessmode                   -- Display Wireless LAN Mode
 get wmm                            -- Display WMM Mode
 get wmmParamBss                    -- Display WMM parameters used by STA in this BSS
 get wmmParam                       -- Display WMM parameters used by this AP
 get usrp                           -- Display the User Priority
 get wlanstate                      -- Display wlan state
 get xrpoll                         -- Display XR poll
 get xrbss                          -- Display XR Bss Info
 get xrFragmentThreshold            -- Display XR fragment threshold
 get mtu                            -- Display ppp MTU
 help                               -- Display CLI Command List
 Lebradeb                           -- Disable reboot during radar detection
 ls                                 -- list directory
 mem                                -- system memory statistics
 mv                                 -- Move file
 netpool                            -- Display Netpool usage
 np                                 -- Network Performance
 ns                                 -- Network Performance Server
 ping                               -- Ping
 pktLog                             -- Packet Log
 radar!                             -- Simulate radar detection on current channel
 reboot                             -- Reboot Access Point
 rm                                 -- Remove file
 run                                -- Run command file
 quit                               -- Logoff
 set 11gonly                        -- Set 11g Only Allowed
 set 11goptimize                    -- Set 11g Optimization Level
 set 11goverlapbss                  -- Set Overlapping BSS Protection
 set abolt                          -- 
 set acl                            -- Set Access Control List
 set aging                          -- Set Aging Interval
 set antenna                        -- Set Antenna
 set authentication                 -- Set Authentication Type
 set autochannelselect              -- Set Auto Channel Selection
 set basic11b                       -- Set Use of Basic 11b Rates
 set basic11g                       -- Set Use of Basic 11g Rates
 set beaconinterval                 -- Modify Beacon Interval
 set bkScaninterval                 -- Modify Background Scan Interval for Rogue AP Detection
 set board                          -- Set the board data
 set bootLine                       -- Change the bootline
 set burstSeqThreshold              -- Set Max Number of frames in a Burst
 set burstTime                      -- Set Burst Time
 set cachePerf                      -- Begin cache performance monitoring
 set calibration                    -- Set Calibration Period
 set cckTrigHigh                    -- Set Higher Trigger Threshold for CCK Phy Errors For ANI Control
 set cckTrigLow                     -- Set Lower Trigger Threshold for CCK Phy Errors For ANI Control
 set cckWeakSigThr                  -- Set ANI Parameter for CCK Weak Signal Detection Threshold
 set channel                        -- Set Radio Channel
 set cipher                         -- Set Cipher
 set compproc                       -- Set Compression Scheme
 set compwinsize                    -- Set Compression Window Size
 set consolelog                     -- Set Console Log Enable Disable
 set countrycode                    -- Set Country Code
 set radarnewchannel                -- Set radar new channel
 set csabeaconcount                 -- Set CSA Beacon Count
 set ctsmode                        -- Set CTS Mode
 set ctsrate                        -- Set CTS Rate
 set ctstype                        -- Set CTS Type
 set domainsuffix                   -- Set Domain Name Server Suffix
 set dtim                           -- Set Data Beacon Rate (DTIM)
 set enableANI                      -- Turn Adaptive Noise Immunity Control On/Off
 set encryption                     -- Set Encryption Mode
 set extendedchanmode               -- Set Extended Channel Mode
 set factorydefault                 -- Restore to Default Factory Settings
 set firStepLvl                     -- Set ANI Parameter for FirStepLevel
 set fragmentthreshold              -- Set Fragment Threshold
 set frequency                      -- Set Radio Frequency (MHz)
 set gateway                        -- Set Gateway IP Address
 set gbeaconrate                    -- Set 11g Beacon Rate
 set groupkeyupdate                 -- Set Group Key Update Interval (in Seconds)
 set gdraft5                        -- Set 11g Draft 5.0 compatibility
 set getsnmp                        -- Modify Get SNMP Community Name
 set hostipaddr                     -- Set Host IP address
 set interVF                        -- Set Inter Vap Forwarding State
 set intraVF                        -- Set Intra Vap Forwarding State
 set ipaddr                         -- Set IP Address
 set ipmask                         -- Set IP Subnet Mask
 set jsw                            -- Set Jumpstart Mode
 set jsp2Passwd                     -- Set JS-P2 password
 set key                            -- Set Encryption Key
 set keyentrymethod                 -- Select Encryption Key Entry Method
 set keysource                      -- Select Source Of Encryption Keys
 set login                          -- Modify Login User Name
 set minimumrate                    -- Set Minimum Rate
 set minimumrate                    -- Set Minimum Rate
 set minimumrate                    -- Set Minimum Rate
 set minimumrate                    -- Set Minimum Rate
 set minimumrate                    -- Set Minimum Rate
 set nameaddress                    -- Set Name Server IP address
 set noiseImmunityLvl               -- Set ANI Parameter for Noise Immunity Level
 set ofdmTrigHigh                   -- Set Higher Trigger Threshold for OFDM Phy Errors for ANI Control
 set ofdmTrigLow                    -- Set Lower Trigger Threshold for OFDM Phy Errors for ANI Control
 set ofdmWeakSigDet                 -- Set ANI Parameter for OFDM Weak Signal Detection
 set overRidetxpower                -- Set Tx power override
 set operationMode                  -- Set operation Mode
 set password                       -- Modify Password
 set passphrase                     -- Modify Passphrase
 set pktLogEnable                   -- Enable Packet Logging
 set power                          -- Set Transmit Power
 set pppoe                          -- Enable the PPPoE
 set pppoePassword                  -- Set the PPPoE password
 set pppoeUsername                  -- Set the PPPoE username
 set pvid                           -- Set the VLAN Tag
 set quietAckCtsAllow               -- Allow Ack/Cts frames during quiet period
 set quietDuration                  -- Duration of quiet period
 set quietOffset                    -- Offset of quiet period into the beacon period
 set radiusname                     -- Set RADIUS name or IP address
 set radiusport                     -- Set RADIUS port number
 set radiussecret                   -- Set RADIUS shared secret
 set rate                           -- Set Data Rate
 set rate                           -- Set Data Rate
 set rate                           -- Set Data Rate
 set rate                           -- Set Data Rate
 set rate                           -- Set Data Rate
 set reg                            -- Set Register Value
 set telecregupdate                 -- Perform Telec Regulatory Update
 set telecregupdatereverse          -- Perform Reverse of Telec Regulatory Update
 set regcapbitswrite                -- Write Regulatory Domain Capability bits to EEPROM
 set regulatorydomain               -- Set Regulatory Domain
 set remoteAP                       -- Set Remote AP's Mac Address
 set hwtxretries                    -- Set HW Transmit Retry Limit
 set swtxretries                    -- Set SW Transmit Retry Limit
 set rogueAPDetect                  -- Set Rogue AP Detection Mode
 set rtsthreshold                   -- Set RTS/CTS Threshold
 set shortpreamble                  -- Set Short Preamble
 set shortslottime                  -- Set Short Slot Time
 set setsnmp                        -- Modify Set SNMP Community Name
 set sntpserver                     -- Set SNTP/NTP Server IP Address
 set softwareretry                  -- Set Software Retry
 set spurImmunityLvl                -- Set ANI Parameter for Spur Immunity Level
 set ssid                           -- Set Service Set ID
 set ssidsuppress                   -- Set SSID Suppress Mode
 set active                         -- Set Active (up) Mode
 set station                        -- Set Station Skype Authentication
 set SuperG                         -- Super G Features 
 set systemname                     -- Set Access Point System Name
 set telnet                         -- Set Telnet Mode
 set timeout                        -- Set Telnet Timeout
 set tzone                          -- Set Time Zone Setting
 set updateparam                    -- Set Vendor Default Firmware Update Params
 set vaps                           -- Set Number of Virtual APs
 set upsd                           -- Set UPSD Mode
 set vlan                           -- Set VLAN Operational State
 set qos                            -- Set QoS Mode
 set watchdog                       -- Set Watchdog Mode
 set wds                            -- Set WDS Mode
 set wep                            -- Set Encryption Mode
 set wlanstate                      -- Set wlan state
 set wirelessmode                   -- Set Wireless LAN Mode
 set usrp                           -- Set the User Priority
 set wmm                            -- Set WMM Mode
 set wmmParamBss                    -- Set WMM parameters used by STAs in this BSS
 set wmmParam                       -- Set WMM parameters used by this AP
 set xr                             -- Set XR
 set nat                            -- Set NAT/DHCP Server
 set mtu                            -- Display ppp MTU
 spy report                         -- Print spy report
 spy start                          -- Start spy
 spy stop                           -- Stop spy
 start wlan                         -- Start the current wlan
 stop wlan                          -- Stop the current wlan
 timeofday                          -- Display Current Time of Day
 version                            -- Software version
 nat_tcp                            -- nat_tcp_show
 nat_udp                            -- nat_udp_show</code>
 
I tried a few commands to get a feel for the device:

<code lines="-1">wlan[0,0] -> get information
Product SN  :  
AP Software : v1.0.6.0
MAC Address : 00-12-CF-80-46-2C
wlan[0,0] -> get updateparam
Vendor Default Update Parameters:
       Hostname:  
       Username:  
       Password:  
       Imagepath: 
       Imagename: 
       Flag:      0x0
wlan[0,0] -> ls
zz-img.bin  1350968
apcfg          6886
apcfg.bak      6885
2101248 bytes free
wlan[0,0] -> MFT_Boot_Ver
Boot code version is  1.1.0
wlan[0,0] -> bootrom
Not enough parameters!</code>

It looked like there was a filesystem on the flash, containing the <tt>zz-img.bin</tt> firmware I originally started with, and another file called <tt>apcfg</tt>. Using the 'ftp' command I'd seen in 'help' I uploaded both of these files to an FTP server running on the Pi. The <em>md5sum</em> of the new <tt>zz-img.bin</tt> matched the firmware image I started with, while the <tt>apcfg</tt> was, as the name implies, a configuration file. It begins:

<code># DO NOT EDIT -- This configuration file is automatically generated
magic Ar52xxAP
fwc: 8
login Admin
nameaddr 8.8.8.8
domainsuffix 
RADIUSaddr 
RADIUSport 1812
RADIUSsecret 
password 1988</code>

(At some point, someone - probably me - must have configured it with Google's Public DNS service running on the IP address 8.8.8.8)

As I belatedly found out, all of these commands work fine over the telnet interface that’s also running on the router. I should probably have tried that earlier, but I was particularly interested in gaining access to the bootloader on the router to see if I could persuade it to boot up a different firmware. Eager to see if that was possible, I typed 'reboot' and crossed my fingers:

<code lines="-1">wlan[0,0] -> reboot
0x80ed2750 (tCliTask): wlan0: vportBSSEndStop -- already stopped!
Rebooting AP...

ar531xPlus rev 0x00000086 firmware startup...


Accton boot code version 1.1.0


 4 3   00
auto-booting...

Attached TCP/IP interface to ae0.
Warning: no netmask specified.
Attaching network interface lo0... done.
Attaching to TFFS... Attaching to TFFS... done.
Loading /fl/zz-img.bin...Boot web up ...
1456176
Starting at 0x804846e0...

                                                    /fl/  - Volume is OK 
Reading Configuration File "/fl/apcfg".
Configuration file checksum: 85c2c is good
Attaching interface lo0...done
wireless access point starting...
Auto Channel Scan selected 2412 MHz, channel 1
wlan0 Ready
Ready</code>

Success! Hitting enter got me back to the login prompt, so that appeared to be the sum total of the bootup messages. Soft-rebooting the device like this (rather than powering it up with the Pi attached) was fortuitous as the router has the same bug as the Fonera; having something already connected to the serial interface when it’s powered on causes it to hang and produce no serial output.

Trying to interrupt the boot loader, after much trial and error I hit 'Esc' during what's evidently supposed to be a countdown that appears just before the "auto-booting" message. That dropped me into what looked like a command prompt, so I tried 'help' again:

<code lines="-1">4
oot]: help

 ?                     - print this list
 @                     - boot (load and go)
 p                     - print boot params
 c                     - change boot params
 L                     - ACCTON MFT Led Test
 e                     - print fatal exception
 v                     - print version
 B                     - change board data
 S                     - show board data
 n netif               - print network interface device address
 $dev(0,procnum)host:/file h=# e=# b=# g=# u=usr [pw=passwd] f=# 
                           tn=targetname s=script o=other 
 boot device: tffs=drive,removable     file name: /tffs0/vxWorks 
 Boot flags:           
   0x02  - load local system symbols 
   0x04  - don't autoboot 
   0x08  - quick autoboot (no countdown) 
   0x20  - disable login security 
   0x40  - use bootp to get boot parameters 
   0x80  - use tftp to get boot image 
   0x100 - use proxy arp 

available boot devices:Enhanced Network Devices
 ae0 tffs</code>

This is the standard VxWorks "BSP" bootloader, and the commands it lists works as advertised:

<code>[Boot]: p

boot device          : tffs:
unit number          : 0 
processor number     : 0 
file name            : /fl/zz-img.bin
inet on ethernet (e) : 192.168.1.240:0xffffff00
flags (f)            : 0x0 
other (o)            : ae

[Boot]: c

'.' = clear field;  '-' = go to previous field;  ^D = quit

boot device          : tffs:0 
processor number     : 0 
host name            : 
file name            : /fl/zz-img.bin 
inet on ethernet (e) : 192.168.1.240:0xffffff00 
inet on backplane (b): 
host inet (h)        : 
gateway inet (g)     : 
user (u)             : 
ftp password (pw) (blank = use rsh): 
flags (f)            : 0x0
target name (tn)     : 
startup script (s)   : 
other (o)            : ae 

[Boot]: S
name:     SAP2315A-FLF-38FT
magic:    35333131
cksum:    a943
rev:      5
major:    1
minor:    0
pciid:    0013
wlan0:    yes 00:12:cf:80:46:2d
wlan1:    no  ff:ff:ff:ff:ff:ff
enet0:    yes 00:12:cf:80:46:2c
enet1:    no  ff:ff:ff:ff:ff:ff
localbus: no  ff:ff:ff:ff:ff:ff
PCI:      no  ff:ff:ff:ff:ff:ff
uart0:    yes
sysled:   no, gpio 0
factory:  yes, gpio 6
serclk:   internal
cpufreq:  calculated 184000000 Hz
sysfreq:  calculated 92000000 Hz
memcap:   disabled
watchdg:  enabled
product sn:           
country code:        NA
hardware rev:   R01
product name:        SAP2315A-FLF-38FT
hardware id:         0
manufacturing date:  20080205
Wireless Bridge is not supported
Boot code version : 1.1.0
[Boot]: v
CPU: SAP2315A-FLF-38FT
BSP version: 1.1.0
Creation date: Aug 17 2006, 19:47:11</code>

I was pleased to see that loading a boot image over the network was supported. To try it, I used the 'c' command seen above to change the boot device to ae0, entered the IP address of the Pi, the path to its local copy of <tt>zz-img.bin</tt> and set the flags value to 0x80 ("use tftp to get boot image").

Without that flag, the BSP would try to use ordinary FTP (as opposed to TFTP) which I encountered some issues with ("Error loading file: errno = 0xDD"[ref]0xDD is 221 in decimal, which rather suspiciously is the "Service closing control connection" FTP status code.[/ref]). Being somewhat simpler, TFTP was easier to get working - I just installed acftpd on the Pi, verified from my laptop that I could download a file from it, then rebooted the router.

I was slightly surprised to see it work! Other than a slightly different "Loading" message, the router fetched its firmware from the Pi and booted up into it as normal. This told me two things, firstly that as long as I could still access the bootloader I had a potential way to recover the device from any meddling gone wrong, and secondly that BSP would fetch and execute an ELF image.

I'd noted earlier that all of the other routers in this family I could find reportedly ran Linux out of the box. It seemed that using the same RedBoot bootloader that they did would help get me towards my vague long-term goal for getting Linux going on this router too. It would also prove that I could run arbitrary code on the device.

<h3>RedBoot</h3>

Getting a copy of RedBoot for this router was an interesting learning experience - most people aren't interested in an ELF executable of it, they want a stripped down 'ROM' version to flash directly to their device. I certainly wanted to make sure it would work before I thought about going that far, and not finding any suitable pre-built images, I decided to build my own. That would also help with the issue of the 250G's flash memory size being different to that of the Fonera.

As the Fonera 2100 is so well known, there are plenty of logs out there of RedBoot booting on it. All of them contained the line "Board: ap51" which was very helpful in helping me narrow down what I was looking for. That led me to <a href="http://www.dd-wrt.com/wiki/index.php/Micro_Redboot">Micro Redboot</a>, which seemed to be almost exactly what I was looking for. Unfortunately I failed to get it to build - unfortunately the world, and particularly <a href="http://en.wikipedia.org/wiki/GNU_Compiler_Collection">gcc</a>, seems to have moved on in the years since most router RedBoot trees were last built, resulting in all sorts of incompatibilities and syntax errors when attempting to build them with a modern toolchain.

I wish I'd noticed this before spending the time I did on Micro Redboot, but knowing that the WAP250G was practically a clone of the <a href="http://www.fontastic.org/fon/google-invests-in-merakis-mesh-technology/">Meraki Mini</a> was very helpful, because they provide their source code, including the version of RedBoot they use. Building it turned out to be straightforward, as the file <a href="http://dl.meraki.net/linux/redboot-ap61.tar.gz">redboot-ap61.tar.gz</a> - despite the ‘61’ in the name - can also be used to build an ap51 RedBoot, and even contains the i386 Linux toolchain needed to do so.

After unpacking that archive under Linux and examining the Makefile, building a customized RedBoot was almost as simple as typing:

<code>$ make AP_TYPE=ap51 DRAM_MB=16 FLASH_MB=4 ENET_PHY=admtek ap51</code>

Knowing the values to use for the RAM and flash size was straightforward, being identifiable from the markings on the chips themselves. The Ethernet PHY was harder, if only because I couldn’t see it on the board. Various Fonera-hacking websites told me it was an "Altima AC101" (which is printed on a chip on the bottom of the board), but how that mapped to the choices I had ("admtek", "marvell", "realtek", "icplus" or "kendin") I had no idea. So I tried the first one.

Of course, when I said building it was "almost as simple" as the command above, I hadn't factored in the error that would appear partway through the build process:

<code>tail: cannot open `+2' for reading: No such file or directory</code>

That was caused by the use of some obsolete syntax ("tail +2" should be "tail -n2" since 2007 or so!) and could be corrected by setting the <em>_POSIX2_VERSION</em> variable in the environment before running <em>make</em>:

<code>$ _POSIX2_VERSION=199209 make TFTPPATH=~/tftpboot AP_TYPE=ap51 DRAM_MB=16 FLASH_MB=4 ENET_PHY=icplus ap51</code>

I set the <em>TFTPPATH</em> variable to somewhere under my home directory (rather than the default /tftpboot) so I'd have permission to write to it. After typing the above, and a few seconds of compilation, I now had two new files: <tt>ap51-4mb-16mb.ram</tt> and <tt>ap51-4mb-16mb.ram</tt>. The former is the ELF image I needed.

<code>$ ls -l ~/tftpboot/
total 752
-rwxr-xr-x 1 james james 601653 Nov 28 18:28 ap51-4mb-16mb.ram
-rwxr-xr-x 1 james james 158816 Nov 28 18:28 ap51-4mb-16mb.rom</code>

The (relatively) huge size of the ELF (almost 600KB!) surprised me for a moment, but as <em>file</em> noted, the file wasn't stripped of debugging symbols. The <em>mipsisa32-elf-strip</em> tool included in the toolchain made short work of those. I was left with a with a 152KB ELF, which I uploaded to the Pi and placed in the tftp directory. Switching back to <em>minicom</em>, I accessed the bootloader on the router and changed it to boot this new file, which was just a case of changing the filename as it was already set up to boot over TFTP. I then tried booting it up:

<code lines="-1">[Boot]: @
Attached TCP/IP interface to ae0.
Attaching network interface lo0... done.
Loading... 250448
Starting at 0x800410bc...

+**Warning** FLASH configuration checksum error or invalid key
Use 'fconfig -i' to [re]initialize database
Invalid PHY ID1 for enet0 port0.  Expected 0x0243, read 0x0022
... waiting for BOOTP information
Ethernet eth0: MAC address 00:12:cf:80:46:2c
Can't get BOOTP info for device!

RedBoot(tm) bootstrap and debug environment [RAM]
Non-certified release, version v1.3.0 - built 18:28:43, Nov 28 2012

Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.

Board: ap51 
RAM: 0x80000000-0x81000000, [0x8007e250-0x80fe1000] available
FLASH: 0xa8000000 - 0xa83f0000, 64 blocks of 0x00010000 bytes each.
RedBoot> </code>

Wow. RedBoot loaded fine - though the "Invalid PHY ID1" message told me that I'd guessed wrong when choosing the PHY earlier. The "Expected 0x0243, read 0x0022" detail was extremely useful though - buried in the RedBoot source, in a file called <tt>rtPhy.h</tt> I found this:

<code>#define RT_PHY_ID1_EXPECTATION  0x22</code>

which contained the comment:

<code lang="c">/*
 * rtPhy.h - definitions for the ethernet PHY.
 * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
 * and compatible PHYs, such as the Kendin KS8721B.
 * All definitions in this file are operating system independent!
 */</code>
 
That looked promising, so I tried rebuilding RedBoot with the <em>ENET_PHY</em> value set to 'realtek'. Unfortunately, an unsatisfied constraint - that on the AR531X platform the PHY could be any of the types I listed except 'realtek' (typical) - caused the build to fail. The helpful comment above led me to try 'kendin' instead, and that both built and booted fine:

<code>+**Warning** FLASH configuration checksum error or invalid key
Use 'fconfig -i' to [re]initialize database
PHY ID is 0022:5521
... waiting for BOOTP information
Ethernet eth0: MAC address 00:12:cf:80:46:2c
IP: 192.168.0.10/255.255.255.0, Gateway: 192.168.0.1
Default server: 192.168.0.1

RedBoot(tm) bootstrap and debug environment [RAM]
Non-certified release, version v1.3.0 - built 18:48:12, Nov 28 2012

Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.

Board: ap51 
RAM: 0x80000000-0x81000000, [0x8007d6f0-0x80fe1000] available
FLASH: 0xa8000000 - 0xa83f0000, 64 blocks of 0x00010000 bytes each.
RedBoot> bdshow
name:     SAP2315A-FLF-38FT
magic:    35333131
cksum:    a943
rev:      5
major:    1
minor:    0
pciid:    0013
wlan0:    yes 00:12:cf:80:46:2d
wlan1:    no  ff:ff:ff:ff:ff:ff
enet0:    yes 00:12:cf:80:46:2c
enet1:    no  ff:ff:ff:ff:ff:ff
uart0:    yes
sysled:   no, gpio 0
factory:  yes, gpio 6
serclk:   internal
cpufreq:  calculated 184000000 Hz
sysfreq:  calculated 92000000 Hz
memcap:   disabled
watchdg:  enabled
serialNo: <Not a string: 0xA83E007C>
Watchdog Gpio pin: 65535
secret number: <Not a string: 0xA83E008A></code>

It even set an IP address over BOOTP, so the network interface was clearly working.

RedBoot's 'help' output is well known, so I won't paste it here, but one of the reasons I wanted to run it in the first place was this command:

<code>Display (hex dump) a range of memory
   x -b <location> [-l <length>] [-s] [-1&#124;2&#124;4]</code>
   
The RedBoot startup banner lists RAM and FLASH memory locations and sizes, so I speculated that I could use that command to dump their contents over the serial interface. After making sure minicom was logging everything to disk (or rather the SD card on the Pi), I dumped the flash contents like so:

<code>RedBoot> dump -b 0xa8000000 -l 0x3f0000
A8000000: 10 00 01 4F 00 00 00 00 10 00 02 04 00 00 00 00 &#124;...O............&#124;
A8000010: 10 00 06 78 00 00 00 00 10 00 06 76 00 00 00 00 &#124;...x.......v....&#124;
A8000020: 10 00 06 74 00 00 00 00 10 00 06 72 00 00 00 00 &#124;...t.......r....&#124;
A8000030: 10 00 06 70 00 00 00 00 10 00 06 6E 00 00 00 00 &#124;...p.......n....&#124;
...</code>

(I've altered the spacing slightly to get it to fit neatly.)

The actual output was of course 258,048 (0x3F0000) lines long, and I wish I'd thought to increase the baud rate before typing the command, as it took several hours to complete over the 9600 baud connection!

A couple of lines of Python code was sufficient to turn the dumped output into a binary image of the flash contents, exactly 4MB in length. I was conscious that dumping 20MB (before conversion) of hex dump over a bodged-together serial connection with no handshaking might not be very reliable, but luckily there was another RedBoot command to help:

<code>Compute a 32bit checksum [POSIX algorithm] for a range of memory
   cksum -b <location> -l <length></code>
   
Handily, it accepts the same parameters as the ‘dump’ command, and I used it to calculate a checksum of the flash contents:

<code>RedBoot> cksum -b 0xa8000000 -l 0x3f0000
POSIX cksum = 3466121872 4128768 (0xce98d290 0x003f0000)</code>

I was momentarily dismayed though when the CRC32 of my dumped binary didn't match that value, but looking at the above again I started wondering what exactly the "POSIX algorithm" was referring to. As I had the source code to hand I could find out easily, and in the process of looking at <tt>posix_crc.c</tt> in the RedBoot source, found what’s probably the most useful source code comment I have ever read:

<code lang="c">// Compute a CRC, using the POSIX 1003 definition

// Same basic algorithm as CRC-16, but the bits are defined in the
// opposite order.  This computation matches the output of the
// Linux 'cksum' program.</code>

Well, that’s handy. Sure enough:

<code>$ cksum rom.bin 
3466121872 4128768 rom.bin</code>

At this point I was fairly sure that I had an accurate dump of the entire flash contents from the router. Even if I break the bootloader somehow, I can hopefully find a way to re-flash that image back to the chip, either via a JTAG cable or by physically de-soldering it from the board, if it came to that. Having said that, if it did come to that, I'd probably just put an 8MB chip in its place and flash it with the dump from a Fonera 2100 or a Meraki Mini.

From a reverse engineering perspective, the dumped data turns out to be reasonably interesting. Presumably for wear levelling purposes, slightly changed copies of the <tt>apcfg</tt> file are spread out fairly evenly over the flash, including details of all of the SSIDs this router has previously been configured with.

Next, I'll probably use RedBoot to flash itself directly to the device, using the 'fis' commands it provides. 'fis list' shows what looks like garbage at the moment:

<code>RedBoot> fis list
Name              FLASH addr  Mem addr    Length      Entry point
AP2315A-FLF-38FT  0x00FFFFFF  0x00323030  0x38303230  0x35000031
<Not a string: 0x80FF0000>                 0x2D464C46  0x2D333846  0x54006566  0x61756C74
</code>

I assume that's due to the flash block it would use to store that information being used by VxWorks for a different purpose. 'fis create' would probably fix that, but I’d like to be more sure before I try!

Once RedBoot is permanently on the device, I'll use it to boot Linux, either DD-WRT or OpenWRT most likely; first over the network and once I'm satisfied it works as expected, directly from flash. Longer term I'll probably perform the <a href="http://www.dd-wrt.com/wiki/index.php/LaFonera_Hardware_SD-Card#Fonera_sd-card_hack">Fonera SD card mod</a>, and I have a vague idea about using the router as an <a href="http://en.wikipedia.org/wiki/I%C2%B2C">I²C</a> or <a href="http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus">SPI</a> controller interfaced to some LED lighting strips.

<h3>Final Notes (TL;DR)</h3>

I now know that almost everything here could have been performed over the telnet connection without opening the device up at all; the 'boot ethernet' command can be used to instruct the bootloader to load an image over the network. The change persists between reboots, though holding down the reset button can be used to reset the unit to factory defaults and hence boot again from flash. That could be used to recover from failed attempts to network boot.

Likewise, RedBoot can be connected to over telnet once it has loaded, so in theory the whole process of re-flashing the device with a new bootloader and operating system could be done remotely. The procedure would take some refinement though.

During the research for this post, I found these instructions for <a href="http://wiki.openwrt.org/toh/d-link/dwl-2100ap#install.redboot.using.serial.console">flashing a D-Link DWL-2100AP</a> over its serial console. They look very similar to what I was planning on doing to flash RedBoot to the WAP250G, the 2100AP is based on the same architecture and has the same RAM and flash size (though it's not connected through SPI, so there are differences). If the 2100AP has a telnet accessible shell, and it has the 'boot ethernet' command, it should be possible to flash it to Linux without opening it up, too. According to that router's <a href="http://www.dlink-jp.com/display/sc/M/file/D/380/F/DWL-2100AP_EN_CLI_MAN_R2.50.pdf.html">official documentation</a> [PDF] though, that command is missing. I think I might have one in a box somewhere, if I find it I'll give it a try.

After dumping the flash contents, I did so for the RAM too. I booted VxWorks, then soft rebooted into RedBoot via the BSP bootloader in as few steps as I could. I didn't bother checksumming it due to its volatile nature, but I was pleased to see that easily identifiable chunks of VxWorks code remained visible in the resulting 16MB file. I've not read about anyone using RedBoot to dump the entire RAM or ROM contents of a device before, so I think this technique has a certain novelty to it. I now have a firmware image, its decompressed contents and a partial memory dump from running code to investigate should I wish to do so further.

I enjoyed finding out more about what makes this little router tick, and hope to find something useful to do with it soon!]]></description>
		<wfw:commentRss>http://james.slaterspage.com/hacking-the-amx-nxa-wap250g-access-point-with-a-raspberry-pi/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Scraping Google Related (with bonus PageRank)</title>
		<link>http://james.slaterspage.com/scraping-google-related-with-bonus-pagerank/</link>
		<comments>http://james.slaterspage.com/scraping-google-related-with-bonus-pagerank/#comments</comments>
		<pubDate>Wed, 24 Aug 2011 13:06:09 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Reversing]]></category>

		<guid isPermaLink="false">http://james.slaterspage.com/?p=266</guid>
		<description><![CDATA[While using <a href="https://chrome.google.com/webstore/detail/cikfgcnnhcibkipoldbjegmeojnkaled">Google Related</a> some JSON formatted data is requested from Google about each page you visit; that data comes from a URL similar to the one below:

<code>
https://toolbarqueries.google.com/tbr
     ?client=navclient-auto
     &#038;features=GR
     &#038;ch=8e991fe19
     &#038;q=info:http%3A%2F%2Fwww.bronco.co.uk%2F
     &#038;oe=UTF-8
     &#038;grv=0.6.9
</code>

(split over several lines for readability)

The response is much too wordy for me to paste here, but what jumped out at me was how similar that URL is to those used by Google Toolbar to request the PageRank of a particular URL. Indeed, the checksum (8e991fe19 in the above example) calculation is exactly the same, and in fact simply replacing the "GR" in the features line with the word "Rank" turns it into a valid request for PageRank, responding something like:

<code>
Rank_1:1:5
</code>

This example URL has a PageRank value of 5 (the '1' in between the colons indicates the length of the returned value, in this case just one character). It is even possible to combine the two, for example:

<code>
https://toolbarqueries.google.com/tbr
     ?client=navclient-auto
     &#038;features=Rank:GR
     &#038;ch=8e991fe19
     &#038;q=info:http%3A%2F%2Fwww.bronco.co.uk%2F
     &#038;oe=UTF-8
     &#038;grv=0.6.9
</code>

Responds with both PageRank and Google Related data, separated by newlines:

<code>
Rank_1:1:5
GR_1:24019:{"server_output_object_version":"","request_id": .....
</code>

(cut for brevity)

Calculating the correct checksum for a given URL is fairly straightforward - my Python code to do so is shown below.

[cc lang="python"]
GPR_HASH_SEED = "Mining PageRank is AGAINST GOOGLE'S TERMS OF SERVICE. Yes, I'm talking to you, scammer."

def google_hash(value):
    magic = 0x1020345
    for i in xrange(len(value)):
        magic ^= ord(GPR_HASH_SEED[i % len(GPR_HASH_SEED)]) ^ ord(value[i])
        magic = (magic >> 23 &#124; magic << 9) &#038; 0xFFFFFFFF
    return "8%08x" % (magic)
[/cc]


I am not currently aware of any combination of 'features' that result in a reply other than "GR" and "Rank".]]></description>
		<wfw:commentRss>http://james.slaterspage.com/scraping-google-related-with-bonus-pagerank/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Cyber Security Challenge Cipher Solution</title>
		<link>http://james.slaterspage.com/cyber-security-challenge-cipher-solution/</link>
		<comments>http://james.slaterspage.com/cyber-security-challenge-cipher-solution/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 08:20:17 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Reversing]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://james.slaterspage.com/?p=86</guid>
		<description><![CDATA[I was pointed to the <a href="https://cybersecuritychallenge.org.uk/">Cyber Security Challenge</a> earlier this week, and eventually stumbled upon the cipher they offer as an "immediate opportunity to test your skills". Despite not really understanding the point of the exercise or how it related to the other competitions mentioned, I was pleased to see that the "ciphertext" was right there on the site with no tedious registration procedure required. I decided to give it a go; this is the procedure I followed to work it out.

<h3>Stage 1</h3>

I quickly recognised the <a href="https://cybersecuritychallenge.org.uk/docs/cybersecuritychallenge.txt">starting text</a> as probably being <a href="http://en.wikipedia.org/wiki/Base64">Base64</a> encoded.[ref]There are a number of spaces present in the text file before the content begins. They don't appear to have a purpose, other than perhaps drawing attention to the space character (ASCII 0x20) that's relevant later.[/ref] If I hadn't recognised it, counting the number of unique symbols used would probably have led to the same conclusion. The GNU base64 program decoded it, and a quick look at the resulting file left me slightly surprised to see the familiar "JFIF" text indicating I now had a JPEG image.[ref]The image also has an Exif header which has been zeroed out, at a guess, either by hand or with a simple tool. Why not just remove it altogether?[/ref]

[caption id="attachment_118" align="aligncenter" width="300" caption="Decoded Comic"]<img src="http://james.slaterspage.com/wp-content/uploads/2010/07/xkcd.jpg" alt="Decoded comic" title="XKCD" width="350" height="175" class="size-medium wp-image-118" />[/caption]

Smiling at the usage of that particular comic, I thought "Oh, was that it?" ... then I noticed the strange looking border. Including the URL of the original comic was a nice touch for those who might not otherwise notice the alteration.

<h3>Stage 2</h3>

The border of the image looked very much like a sequence of bits to me, pixels set to black or white to indicate a 1 or 0. I noted that the lower pixel in the row was always the inverse of the top one, so really there's only one bit per column. The pixels - presumably due to the JPEG compression - aren't actually always pure black or white but they seemed close enough[ref]I picked an arbitrary value of "50" for or less in the red component to as meaning "black", with every intention of improving it - turns out what wasn't necessary.[/ref] for that to be the intention. I wasn't about to copy them down by hand, so I wrote a quick Python (and <abbr title="Python Imaging Library">PIL</abbr>) script to do so for me.
 
[cc lang="python"]
import Image

# Read the bits encoded as pixels around the border of an image.
# They are ordered in a clockwise fashion, in the order shown below:
#
#   1
#   --->
#   ^  &#124; 2
# 4 &#124;__&#124;
#     3
#
# Note that the order changes from left-to-right to right-to left from
# 2 to 3, effectively reading the outermost bits in a clockwise rotation.
# For this reason, the bit strings returned for 3 and 4 are reversed
# before decoding to ASCII.

def get_border_bits(filename):
	im = Image.open(filename)
	pels = im.load()
	(w, h) = im.size

	bits = ""
	bits += get_block_h(pels, 0,     0,     w)
	bits += get_block_v(pels, w - 1, 3,     h - 6)
	bits += get_block_h(pels, 0,     h - 1, w)[::-1]
	bits += get_block_v(pels, 0,     3,     h - 6)[::-1]

	out = bins_to_str(bits)
	print out
	print out.encode("rot13")

# Given a string of binary digits ("010111....") return a string of
# ASCII characters corresponding to each eight bits, little endian.
def bins_to_str(bits):
	bstr = ""

	blen = len(bits)
	for i in xrange(0, blen, 8):
		bin = bits[i:i + 8]
		val = int(bin, 2)

		#print "%-8s 0x%02X %c" % (bin, val, val)
		bstr += chr(val)

	return bstr

# get_block for a horizontal group of bits
def get_block_h(pels, x, y, count):
	return get_block(pels, x, y, count, True)

# get_block for a vertical group of bits
def get_block_v(pels, x, y, count):
	return get_block(pels, x, y, count, False)

# Get string of binary digits from the pixels in the given range
def get_block(pixels, x, y, count, horiz):
	bits = ""
	for i in xrange(0, count):
		if horiz:
			b = pixels[i + x, 0 + y]
		else:
			b = pixels[0 + x, i + y]

		bits += '1' if is_black(b) else '0'
	return bits

# Returns if the given pixel (tuple) is black (set)
def is_black(p):
	if p[0] < 50:
		return True
	return False
[/cc]

As the comment at the top of the code explains, I read the bits clockwise, reading the outermost set of them. Reading the top row of bits (01000011011110010111001001101110...) and treating them as 8-bit ASCII characters produced the following:

[cc]
Cyrnfr sbyybj guvf yvax:      uggcf://plore
[/cc]

After double checking the output to make sure it wasn't producing complete gibberish, I noticed that "uggcf://" looked suspiciously like a URL scheme. The obvious one the same length as "uggcf" is "https" and the two Ts matching up with the two Gs seemed like too much of a coincidence. I decided it was likely to be a simple substitution cipher, "uggcf://plore" was probably "https://cyber" (the start of the challenge's web address).

Something was ringing an embarrassingly faint bell at this point, but it wasn't until I'd noted that 'u' comes 13 characters after 'h' in the alphabet and that 'g' is 13 characters <em>before</em> 't' that I realised that it was Caesar cipher - more specifically <a href="http://en.wikipedia.org/wiki/ROT13">ROT13</a>. The alphabet is simply rotated by 13 characters, leaving non-letter characters untouched.

It's quite a common cipher, so it was easy to use an existing tool to rotate the alphabet back again:

[cc]
Please follow this link:      https://cyber
[/cc]

That certainly looked promising!

Earlier I mentioned that I read the outermost bits from the image in a clockwise fashion. That wasn't a decision I arrived at by chance, I'd like to think that it was a clever bit of puzzle design. After decoding that first row, I made an educated guess that the next few characters would continue the URL - "cybersecuritychallenge". That meant that I knew what bits to expect, and hence where to look on the image.

Between the four groups of bits in the image are white gaps. The fact that no inverse colour was present indicated that these were to be skipped rather than read as a 0.

As I worked my way around the borders of the image, the same property held. "Knowing" what bits were needed to continue the sequence helped when working out that the bits were arranged in a clockwise fashion. The following lines show the message (after rotating it) continuing round to the right hand side, along the bottom and then up towards the starting position in the top left.

[cc]
Please follow this link:      https://cybersecuritychallenge.org
Please follow this link:      https://cybersecuritychallenge.org.uk/834jtp.html https://cybersecuritychallen
Please follow this link:      https://cybersecuritychallenge.org.uk/834jtp.html https://cybersecuritychallenge.org.uk/834jtp.html
[/cc]

Of course, I followed the link...

<h3>Stage 3</h3>

The last stage starts with a long sequence of hexadecimal digits. I copied and pasted the lot through a tiny Python script (via binascii.unhexlify) to convert it into a binary file and examined the output with a hex editor. The only thing immediately apparent was that there appeared to be a pattern to the data - lots of 0xEC and 0xED and so on.

I'd be interested to know how other people solved this bit - perhaps by counting the frequencies of different characters - but I tried a very simple version of a "known plaintext" attack. I had a strong suspicion that "cybersecuritychallenge" would appear somewhere in the encoded content - either as part of a web address or email address.

I wrote another Python script to quickly iterate through the new file and look for a pattern that might correspond to that plain text. Essentially I looked for a pattern like this:

[cc]
cybersecuritychallenge
1  2  21     1  332  2
[/cc]

That is, read one character and if the character seven characters later is the same one, and the sixth after that is the same value, then we've probably found what 'c' corresponds to. Likewise for the 'e' and 'l' as shown above. When I tried it, that pattern matched once in the file. Success!

I now knew it was probably another substitution cipher, and could map every character in "cybersecuritychallenge" to their equivalents:

<table>
<tr><td>a</td><td>b</td><td>c</td><td>d</td><td>e</td><td>f</td><td>g</td><td>h</td><td>i</td><td>j</td><td>k</td><td>l</td><td>m</td></tr>
<tr><td>2C</td><td>4C</td><td>6C</td><td>__</td><td>AC</td><td>__</td><td>EC</td><td>0D</td><td>2D</td><td>__</td><td>__</td><td>8D</td><td>__</td></tr>
<tr><td>n</td><td>o</td><td>p</td><td>q</td><td>r</td><td>s</td><td>t</td><td>u</td><td>v</td><td>w</td><td>x</td><td>y</td><td>z</td></tr>
<tr><td>CD</td><td>__</td><td>__</td><td>__</td><td>4E</td><td>6E</td><td>8E</td><td>AE</td><td>__</td><td>__</td><td>__</td><td>2F</td><td>__</td></tr>
</table>

It was easy enough to fill in the missing values for the alphabet, but doing so for the rest of the character set would be tedious. It wasn't until I looked at the binary values for the characters I noticed the pattern:

[cc]
For 'a' (ascii 0x61, encoded as 0x2C):

0x2C 00101100
0x61    01100001

For 'b' (ascii 0x61, encoded as 0x4C):

0x4C 01001100
0x62    01100010
[/cc]

My ASCII-art diagram probably isn't very helpful - but the bits in each individual byte of the message have been rotated by three positions, wrapping back around to the left. I wrote a very quick and ugly Python script to complete the rest of the alphabet, resulting in the following message:

<blockquote>Congratulations ? you?ve found and completed the REAL challenge. Your win code is  <b>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</b>. 

Please email this code to our team at media@cybersecuritychallenge.org.uk. If you?re the first person to do so, and can prove you meet the eligibility criteria (British citizen currently resident in the UK) we will be in touch to advise how to claim your prize. Well done and good luck in the Cyber Security Challenge competitions taking place throughout the rest of the year.</blockquote>

In the decoded output, the question marks show where the decoded output wasn't a printable character. From the context I can guess what they're supposed to be, but I didn't (and still don't) see how they fit the pattern. Luckily they weren't necessary to decode the "win code" from the message, which I have omitted from the plaintext above - though I'm sure it's all over the web by now.

I'm going to write a separate post on my impressions of the challenge, as this one is already comfortably the longest I've ever written!]]></description>
		<wfw:commentRss>http://james.slaterspage.com/cyber-security-challenge-cipher-solution/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MacBook Pro vs. Ash Cloud</title>
		<link>http://james.slaterspage.com/macbook-pro-vs-ash-cloud/</link>
		<comments>http://james.slaterspage.com/macbook-pro-vs-ash-cloud/#comments</comments>
		<pubDate>Wed, 21 Apr 2010 11:59:08 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Hardware]]></category>

		<guid isPermaLink="false">http://james.slaterspage.com/?p=68</guid>
		<description><![CDATA[Or "Things you don't want to see when tracking the delivery of your shiny new toy"

<table>
<tbody>
<tr><th>Location</th><th>Date</th><th>Local Time</th><th>Description</th></tr>
<tr><td>KOELN (COLOGNE), DE</td><td>04/18/2010</td><td>3:20&#160;P.M.</td><td>PACKAGE DATA PROCESSED BY BROKERAGE. WAITING  FOR CLEARANCE / RELEASED BY CLEARING AGENCY. NOW IN-TRANSIT FOR  DELIVERY</td></tr>
<tr><td rowspan="2">SHANGHAI, CN</td><td>04/18/2010</td><td>5:55&#160;A.M.</td><td><strong>NATURAL DISASTER</strong></td></tr>
<tr><td>04/18/2010</td><td>5:21&#160;A.M.</td><td>DEPARTURE SCAN</td></tr>
<tr><td>KOELN (COLOGNE), DE</td><td>04/17/2010</td><td>2:45&#160;P.M.</td><td>PACKAGE DATA PROCESSED BY BROKERAGE. WAITING  FOR CLEARANCE</td></tr>
<tr><td>SHANGHAI, CN</td><td>04/17/2010</td><td>7:35&#160;P.M.</td><td>EXPORT SCAN</td></tr>
<tr><td>SHANGHAI, CN</td><td>04/16/2010</td><td>12:10&#160;P.M.</td><td>ORIGIN SCAN</td></tr>
<tr><td>CN</td><td>04/16/2010</td><td>5:45&#160;A.M.</td><td>BILLING INFORMATION RECEIVED</td></tr>
</tbody>
</table>

I was slightly taken aback when I saw "Natural Disaster" on there. Who would have thought that ash cloud would have a <a href="http://www.beckynaylor.co.uk/the-winners-and-losers-of-the-ash.html">noticeable effect</a> [on me]?]]></description>
		<wfw:commentRss>http://james.slaterspage.com/macbook-pro-vs-ash-cloud/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Twitter Exploit Still Not Fixed</title>
		<link>http://james.slaterspage.com/twitter-exploit-still-not-fixed/</link>
		<comments>http://james.slaterspage.com/twitter-exploit-still-not-fixed/#comments</comments>
		<pubDate>Wed, 26 Aug 2009 12:15:58 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Social Media]]></category>

		<guid isPermaLink="false">http://james.slaterspage.com/?p=33</guid>
		<description><![CDATA[Sigh.

I wrote another article on <a href="http://www.davidnaylor.co.uk/twitter-exploit-still-works.html">Dave Naylor's blog</a> about the XSS exploit I found yesterday. It seems they've made a pretty amateurish attempt to fix the issue, completely missing the massive problem staring them in the face. It seems to be picking up a bit more traction today - I've even been <a href="http://www.techcrunch.com/2009/08/26/massive-twitter-security-problem-not-resolved-just-yet/">quoted by TechCrunch</a>! It's a bit strange reading my own words back at me in the context of someone else's article. Neat.]]></description>
		<wfw:commentRss>http://james.slaterspage.com/twitter-exploit-still-not-fixed/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Taking down Twitter</title>
		<link>http://james.slaterspage.com/taking-down-twitter/</link>
		<comments>http://james.slaterspage.com/taking-down-twitter/#comments</comments>
		<pubDate>Tue, 25 Aug 2009 16:51:35 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Social Media]]></category>

		<guid isPermaLink="false">http://james.slaterspage.com/?p=25</guid>
		<description><![CDATA[I had the opportunity (probably) to take down Twitter today. Or at least stir up a whole lot of trouble. I really can't believe I'm the first person to think of it, but I'm pretty sure it would have worked!

Because I'm a nice guy - and not at all grudgingly, honest - we're holding off on publishing the details until someone from Twitter gets back to us. Maybe they can give me one of those neat "Verified Account" badges to say thankyou?

Edit: As you probably know if you're reading this, the details <a href="http://www.davidnaylor.co.uk/massive-twitter-cross-site-scripting-vulnerability.html">got published</a>.]]></description>
		<wfw:commentRss>http://james.slaterspage.com/taking-down-twitter/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Xbox 360 Battery Pack Disassembled</title>
		<link>http://james.slaterspage.com/xbox-360-battery-pack-disassembled/</link>
		<comments>http://james.slaterspage.com/xbox-360-battery-pack-disassembled/#comments</comments>
		<pubDate>Mon, 10 Aug 2009 13:51:21 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Hardware]]></category>

		<guid isPermaLink="false">http://james.slaterspage.com/?p=16</guid>
		<description><![CDATA[I've had an official Xbox 360 'Play &#038; Charge' kit for a year or so now, and the battery life has slowly but surely dropped to nothing over that time. I decided to take it to pieces to see if I could figure out what was up with it. As you can see from the image below, there's not a lot to it.

<img src="http://james.slaterspage.com/wp-content/uploads/2009/08/360_battery_pack.jpg" alt="Xbox 360 Battery Pack Disassembled" title="Xbox 360 Battery Pack Disassembled" width="500" height="370" class="aligncenter size-full wp-image-15" />

The two halves are just cemented together - you can see the "dashed" effect the cement has left in along the edges. If you want to open one up, you just have to force the two halves apart with enough force to break the bond between them. At least that's what I did!

There's (what I assume is) a thermistor that sits between the cells for monitoring their temperature. It's also fairly obvious the battery pack is just two standard 2100mAh NiMH AA cells. In my case, I assume that one or both of them has stopped working so I've ordered some new ones. Hopefully I can just drop them straight in there and all will be good once again. Stay tuned.]]></description>
		<wfw:commentRss>http://james.slaterspage.com/xbox-360-battery-pack-disassembled/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

 Served from: james.slaterspage.com @ 2013-05-23 18:00:24 by W3 Total Cache -->