980 lines
46 KiB
Plaintext
980 lines
46 KiB
Plaintext
==Phrack Inc.==
|
|
|
|
Volume 0x0c, Issue 0x41, Phile #0x0b of 0x0f
|
|
|
|
|=-------------------=[ Hacking the $49 Wifi Finder ]=-------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=-------------------------=[ by openschemes ]=--------------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
--[ Contents
|
|
|
|
1.0 - Introduction
|
|
2.0 - Device Overview
|
|
3.0 - Opening the Device
|
|
4.0 - Internals and Investigation
|
|
5.0 - Accessing the ISP Loader
|
|
6.0 - ISP Loader Capabilities
|
|
7.0 - Software Bootloader Capabilities
|
|
8.0 - Inserting Your Own Code
|
|
9.0 - Conclusion
|
|
A.0 - References
|
|
|
|
|
|
|
|
--[ 1.0 - Introduction
|
|
|
|
Christmas has passed, and in the cold weeks since we have already become
|
|
bored with the shiny new toys Santa left us under the tree. Our only
|
|
choice is to hack them! This article describes our successful attack on a
|
|
popular wifi finder, and will provide you with the ability to use the
|
|
device in new and interesting ways. You are limited only by your own
|
|
creativity!
|
|
|
|
Any successful hack must begin by setting a clear goal. Through
|
|
determination and creative thinking, you will then see the steps necessary
|
|
to achieve that goal. Simply saying "I would like to hack this device" is
|
|
meaningless without context, and setting unachievable goals will cause you
|
|
to be bogged down by the intermediate steps and probably abandon the
|
|
project. So we urge you to begin each hack by taking small steps, and upon
|
|
the completion of each of these steps you will open new doors and new
|
|
pathways for further investigation and development.
|
|
|
|
In the case of the wifi finder, our penultimate goal was to execute our
|
|
own code on it's internal microcontroller. We have achieved that goal and
|
|
will describe the steps we took to achieve it. It is easy to see that upon
|
|
reaching this goal, we have opened many new pathways to extending the
|
|
capabilities of the device. Some are easy, such as allowing the device to
|
|
seach hidden SSIDs and browse wifi channels not allowed in the US. Others
|
|
are lofty, such as the development of a portable "aircracking" device.
|
|
Some of these topics will be covered in the future, but we urge you to sit
|
|
down with the device and your knowledge of it, and plan your own path.
|
|
|
|
We apologize if you feel this text is a long, rambling description of our
|
|
attack but we believe the PROCESS, and not the result is the true hack.
|
|
Give a man a hack, and he can program his wifi-finder. Teach a man to
|
|
hack, and he can program anything...
|
|
|
|
|
|
The tools used in this attack are:
|
|
- On the hardware side, we used a modified USB to RS232 converter to
|
|
communicate with the serial port on the wifi finder. An alternative to
|
|
this is to build your own 3.3v RS232 converter using the MAX3232 IC.
|
|
Schematics for this are detailed below.
|
|
|
|
- On the software side, we used a combination of IDA disassembler [1] and
|
|
Keil A51 assembler [2]. This assembler can be used from the command line,
|
|
or from within the Keil uVision IDE.
|
|
|
|
The main steps in this project are
|
|
A) Open and identify the devices and their capabilities
|
|
B) Research to find a back-door into the device
|
|
C) Construction and operation of interface to communicate with the device
|
|
D) Investigation into the device's internal operation
|
|
E) Extension and modification of the device's operation
|
|
|
|
That is just a brief overview of the top-level scheme, and as you will
|
|
soon discover, it requires quite a bit of low-level hacking in order to
|
|
achieve each of these steps in turn. We hope that you will find this
|
|
text informative and enlightening as we chronicle our attack on this
|
|
interesting little device.
|
|
|
|
|
|
|
|
--[ 2.0 - Device Overview
|
|
|
|
There are a few levels of wifi-finder on the market today. Some cheap
|
|
devices simply detect microwave radiation. They will detect 802.11, but
|
|
also some cordless phones, baby monitors, or the nondescript mom
|
|
microwaving some soup down the street. These are garbage, consisting only
|
|
of an amplifier and bandpass filter. The next level can detect access
|
|
points, but give no feedback other than a few lights to tell you whether it
|
|
is near or far. Also garbage.
|
|
|
|
The highest tier of wifi-finder today costs between $40 and $100 USD, and
|
|
consists of a standalone USB wifi card mated to a host microcontroller and
|
|
LCD screen for display of the SSID, channel, and signal strength. It
|
|
contains a small lithium-ion battery for portable use, and charges itself
|
|
anytime it is connected to a USB port. You can easily identify this
|
|
device, as it is the only wifi finder with an LCD screen! This market has
|
|
been cornered by one developer selling their design to many companies, so
|
|
as of now there is only one true product which has been re-branded to many
|
|
models. In our investigations, we feel that all these devices are
|
|
basically identical in hacking potential, and they are all suceptible to
|
|
our attacks. Here is a list of what we've found so far, all are available
|
|
at your local store or online retailers such as Amazon.com.
|
|
|
|
Manufacturer Model Reference
|
|
------------ --------- ---------
|
|
Allnet ALL-0298 [3]
|
|
ZyXel AG-225H [4]
|
|
ConnecTec AG-225H None
|
|
TrendNet TEW-429UB [5]
|
|
Linksys WUSBF54G [6]
|
|
|
|
All the devices share a common form factor: USB stick with an On-Off
|
|
switch and two buttons for portable use: "Seek" and "Next".
|
|
|
|
|
|
Seek Next
|
|
______________==_____==______
|
|
| ___________ |___
|
|
| | | _ |
|
|
| HackMe | LCD | _ | USB
|
|
| |___________| ___|
|
|
|_____________________________|
|
|
\_/
|
|
On-Off Switch
|
|
|
|
|
|
Powering on the device when it is disconnected from a PC will start the
|
|
finder routine. Additionally, pressing Seek at most times will restart the
|
|
finder routine. Once some hotspots have been found, pressing Next will
|
|
cycle through them, displaying the SSID, Channel, Encryption Type, and
|
|
signal Strength.
|
|
|
|
By holding Seek upon power-up, the device enters a simple self-test
|
|
routine used to check the LCD screen and internal timing. By holding Next
|
|
upon power-up, the device enters a Firmware Upgrade Mode used to upload new
|
|
firmware via USB. Always a wonderful feature! But don't think that we
|
|
simply patch some boring vendor code and call it a hack: For most of the
|
|
devices we have found, this firmware upgrade mode has been obsoleted and is
|
|
no longer able to upload to the host microcontroller. We must find a new
|
|
way into the micro, and they have not made it easy.
|
|
|
|
|
|
|
|
--[ 3.0 - Opening the Device
|
|
|
|
The easiest device to open is the ZyXel/Allnet, followed by the Linksys
|
|
and then the TrendNet. By successively "cheapening" the manufacturing
|
|
these vendors have inadvertantly made it a pain to get into the box without
|
|
damaging it. But we don't mind a little damage, and even a TrendNet with
|
|
it's little tabs broken off can be closed back up and returned to the store
|
|
without trouble. Not that you would ever do that, of course.. Just an
|
|
example.
|
|
|
|
To open the device, you will need to remove the BACK panel (not the panel
|
|
holding the LCD). Start by pressing hard at the rear sides of the device,
|
|
where the rear is the side WITHOUT the usb connector. By pressing near
|
|
either of the back corners, you can get the ZyXel to pop open easily. A
|
|
little prying with the cap can also work wonders and leave no marks. The
|
|
TrendNet device is secured with 6 very cheap plastic tabs which will
|
|
easily break when you try to open it. But the Trend it is the most
|
|
inexpensive device on the market so this is the one you will most likely
|
|
try to attack.
|
|
|
|
Of course, you could always pry it open with a screwdriver if you don't
|
|
care about getting it back together again.
|
|
|
|
Once you get the device open, you will see that it consists of two
|
|
circuit boards mated together by a 10-pin header. The top board is secured
|
|
by one small screw near the back of the device. Feel free to throw the
|
|
screw away, or eat it, or something. It's not needed. The USB/wifi board
|
|
contains a ZD1211 802.11 chip and the RF subsystem. It is basically the
|
|
same as a generic USB 802.11 adapter you would buy in the same form factor.
|
|
After the screw is removed, you can grab the USB connector and wiggle this
|
|
board up, freeing it from the 10-pin header that connects it to the bottom
|
|
board. The bottom board contains the focus of our attack, the mysterious
|
|
WHFX30 microcontroller that seems to be the "brains" of the operation.
|
|
|
|
|
|
Here is a side view of how the boards fit together. When viewed from
|
|
above during disassembly, you will note that the wifi board has the
|
|
components on the bottom, and the microcontroller board has the components
|
|
on the top. It is necessary to unconnect the boards to actually see any
|
|
interesting components.
|
|
|
|
Side View of the Wifi Finder Boards
|
|
|
|
|
|
RF (shielded) ZD1211 USB
|
|
Top Board _____________________________________ _ __________
|
|
|______________| \________/ |_| |_____|
|
|
____________ _____ | |
|
|
Bottom |____________|--____/ \________|_|_
|
|
Board Battery WHFX30 10-Pin Header
|
|
|
|
|
|
|
|
--[ 4.0 - Internals and Investigation
|
|
|
|
As was previously mentioned, the entire top board can be used as a
|
|
generic, standalone USB wifi card for your PC. This architecture using the
|
|
ZD1211 chipset is widely used, and to us: boring. For knowledge on this
|
|
board and the ZD1211 device, I refer you to the excellent work of the Linux
|
|
community whose drivers and source code are freely available at [7].
|
|
There you can browse the source to discover the USB endpoints, register
|
|
setup of the ZD1211, promiscuous mode, channels, and other fine
|
|
information.
|
|
|
|
But nowhere is there information on the "WHFX30" device... It is a
|
|
ghost, a semi-custom IC that holds the brains of the finder. Since the
|
|
vendor firmware updater is so limited, we must find a way to break into
|
|
this mystery chip and get our own code onto it.
|
|
|
|
By researching the device online, we see some excellent starting points
|
|
of our attack at J. Maushammer's investigation of the device [8].
|
|
Mr. Maushammer was the first one to attempt to hack the device, and the
|
|
owner of a great deal of initial information. He hypothesizes that the
|
|
WHFX30 contains an 805x microcontroller, and by disassembling one of the
|
|
firmware updates this seems very likely. He has also outlined some of the
|
|
data blocks in the WHFX30 firmware, showing us the font table and power-on
|
|
graphics but he goes no further. Perhaps his goals were too lofty, or he
|
|
became bogged down in the intermediate steps. We are resolved to keep our
|
|
goal clear: Get into the WHFX30.
|
|
|
|
By investigating the firmware updater file, we can see that only the 16k
|
|
block of residing at 0x4000 is 8051 code. However, it contains no jump
|
|
vectors (that would reside at 0x0000) nor any interrupt service routines so
|
|
it is probably NOT the entire 8051 program. Additionally, the text strings
|
|
for the self-test and firmware update routines are missing. This brings us
|
|
to the conclusion that the firmware updater is only allowed to touch a
|
|
small portion of the device code: Specifically the finder routine. It also
|
|
tells us that the WHFX30 device probably contains more that 16k of code
|
|
memory, which is a good thing for extending the capabilities.
|
|
|
|
We will take this opportunity to borrow Maushammer's pinout of the 10-pin
|
|
header. We can make up our own names, but it will be better to begin
|
|
forming a standard on how we refer to the device. Note that we are viewing
|
|
the header socket on the bottom (WHFX30) board.
|
|
|
|
|
|
On-Off Switch
|
|
-----/ \----------------
|
|
----- |
|
|
1 | o o | 2 |
|
|
3 | o o | 4 |
|
|
5 | o o | 6 |
|
|
7 | o o | 8 |
|
|
9 | o o | 10 |
|
|
----- |
|
|
---\_/-----------------
|
|
"Next"
|
|
|
|
Pinout
|
|
------
|
|
J1) Unknown (for now)
|
|
J2) Scanning
|
|
J3) Start of Scan
|
|
J4) GND
|
|
J5) GND
|
|
J6) USB Data (obsolete?)
|
|
J7) Serial data (ZD1211 TxD, WHFX30 RxD)
|
|
J8) USB Data (obsolete?)
|
|
J9) Serial Data (ZD1211 RxD, WHFX30 TxD)
|
|
J10) USB Power to charger (when connected to PC)
|
|
|
|
|
|
|
|
When faced with a chip that you are not familiar with, it is best to
|
|
collect as much information as possible and begin sifting down until you
|
|
have a positive identification. I feel that basically all devices will fit
|
|
into one of three categories.
|
|
|
|
A) A production chip
|
|
- Information on these devices will be freely, or easily available.
|
|
|
|
B) A semi-custom chip based on a production chip.
|
|
- Information MAY be available, depending on the secrecy of the
|
|
application. For example, ATM machines often use generic, secure
|
|
8051 CPU's but noone will ever admit this to you.
|
|
|
|
C) A full-custom chip.
|
|
- Only feasable for huge volume runs, like special graphics chips for
|
|
the new playstation. Unless you work at Sony or Nvidia the
|
|
likelihood of getting any information on these chips is near 0.
|
|
|
|
|
|
Our device is not an A, and this cheap USB toy does not warrant a C so we
|
|
must be stuck in B: Probably an off-the-shelf (but re-marked) chip, or at
|
|
least based on one.
|
|
|
|
An example of a B-type is a neat CPU I've seen in Japanese slot machines.
|
|
Way too many pins to be a normal CPU, but the surrounding circuitry is too
|
|
crude to be anything else. What did that one turn out to be? Well it's a
|
|
generic 8032 microcontroller with a generic EEPROM chip in the same
|
|
package. It's only made for that manufacturer of Pachislo machines, but
|
|
internally it's all off-the-shelf stuff. I guess the theory is that by not
|
|
knowing what it is, users and competitors won't be able to access it?
|
|
WRONG! Obscurity does not create security. That device can be read and
|
|
written with a standard EEPROM burner once the pinout is known.
|
|
|
|
But back to our little wifi-finder. We can trace the locations of VDD
|
|
(the power supply) and GND pins, and we know it has an RS232 port on a few
|
|
other pins. A few pin locations is often good enough to discover the
|
|
identity of an "easy B" - a standard device that is simply marked as
|
|
something else. For this guy, that's no good. There are too many 805x
|
|
derivatives with too many pinouts for us to make a positive identification.
|
|
|
|
We need some additional information. You could try social engineering,
|
|
but it seems the vendors are also unaware of the internals of the WHFX30
|
|
and the original design house is under confidentiality to the vendors so
|
|
you are probably out of luck here.
|
|
|
|
It's at this point that one of our members resorted to a bit of a dirty
|
|
trick in the investigation of the WHFX30. It's called "Decap", and it is
|
|
basically when a hole is etched into the top of the plastic IC package
|
|
using strong acid so you can look at the chip inside. We do not recommend
|
|
you try this yourself, as it is obvously dangerous and is likely to damage
|
|
the board if you are not careful! But for a small fee of $50-$100, there
|
|
are companies that can decap your IC even when it is attached to a PCB.
|
|
You can find one of these companies by searching some terms such as "SEM"
|
|
(scanning electron microscope), "FIB" (focused ion beam), "Decap", "IC
|
|
Failure Analysis". They will be happy to decap your IC for a nominal fee,
|
|
and usually laugh and joke with you if you bring in an ipod or some other
|
|
high value item. I find that they are not laughing because you want to
|
|
decap some of Apple's proprietary chips, but that they have already done it
|
|
so many times they would rather just tell you what's inside. Cheeky
|
|
bastards!
|
|
|
|
After the WHFX30 was decapped, it was examined with a microscope to find
|
|
the logo of the manufacturer: Macronix. The manufacturer will almost
|
|
always put a logo and trademark on the IC, unless it is a matter of great
|
|
security or so damn cheap (like a blinkey toy) that the logo is omitted.
|
|
With the manufacturer's name, it was an easy job to research Macronix's
|
|
products until we found one that matched the pinout and capabilities of the
|
|
WHFX30: MX10E8050A. You can download the datasheet of this device from
|
|
Keil, who makes a nice compiler/debugger suite called microvision (uVision)
|
|
that you will probably use later. The MX108050A datasheet is available
|
|
at [9].
|
|
|
|
|
|
The MX10E8050A is a low-level 8051 clone that offers a few GPIO ports, a
|
|
UART, 2k of internal RAM, and a nice big 64k EEPROM (broken into 4x 16k
|
|
blocks) for code storage. Just this little bit of knowledge helps us
|
|
decipher what the funny 0x4000 offset in the firmware upgrader is for: You
|
|
can only erase this EEPROM in 16k blocks, and can not (should not?) erase a
|
|
block that you are executing code from. So in order to have a "Firmware
|
|
Upgrade Mode", the designers must have put those routines along with the
|
|
jump vectors and interrupt service routines down in the first block of
|
|
EEPROM, from 0x0000-0x3FFF. Next comes the hotspot finder routines in
|
|
0x4000-0x7FFF, and the upper two blocks are unused. NOTE: Actually they
|
|
are scratchpad memory for writing the new firmware to before flashing it to
|
|
0x4000, but let's not get into it.
|
|
|
|
|
|
|
|
--[ 5.0 - Accessing the ISP Loader
|
|
|
|
At this point, things are unraveling fast. We have completed our
|
|
intermediate goals of investigating and identifying our target, and a
|
|
little browsing of the MX10 datasheet tells us that there is a deeper
|
|
bootloader hardwired into ROM in each device. That is usually the case in
|
|
8051 clones, and large smiles came to our faces as we learned how to bring
|
|
it to life.
|
|
|
|
We are close to our main goal now, and should soon have the ability to
|
|
dump and overwrite the entire 64k of EEPROM with a little help from the ISP
|
|
Loader. But we need a way to talk to the device, as well as a way to
|
|
exceute a special startup sequence required to activate this factory ROM
|
|
loader. Let's start with the power-up sequence. The datasheet tells us
|
|
that if we hold the !PSEN pin low, ALE pin and !EN pin high while leaving
|
|
reset we will enter the ISP loader.
|
|
|
|
EA is held high by the board, and ALE will default to high when !PSEN is
|
|
forced low so really we only need to hold !PSEN low. We started by
|
|
stabbing it with a grounded needle, which works but risks damaging the
|
|
I/O circuitry in the abused pin. A little tracing of the PCB showed us
|
|
that J1 on the 10-pin header is used as a !PSEN pulldown during a small
|
|
power-on delay. So it's simple! We just ground J1 by connecting it to J4,
|
|
and power-up the device. Boom! We've hit the loader!
|
|
|
|
When the loader is active, the RS232 port on the WHFX30 is used to
|
|
transfer commands and EEPROM data. However, it is a 3.0v, 0v logic signal
|
|
instead of the -12v, 12v signals used by the RS232 port in your PC. DO NOT
|
|
connect your PC to the finder without a suitable interface or you will blow
|
|
the WHFX30. Since the WHFX30 required 3v logic levels, you can use the 3v
|
|
version of the popular MAX232 chip, the MAX3232. Get the datasheet from
|
|
Maxim [A].
|
|
|
|
|
|
You will need the '3232 IC, five 0.1uf capacitors and either a chopped-off
|
|
RS232 cable or an RS232 connector. I will describe the circuit here, as
|
|
ASCII schematics always leave something to be desired. In this circuit
|
|
description, some common names are used that are explained here. VCC or
|
|
VDD is the supply voltage for the device, here 3.0v or 3.3v. GND is the
|
|
ground of the device. RxD is the recieving input, and TxD is the
|
|
transmitting output. Both the PC and the finder have TxD and RxD lines,
|
|
so this interface IC is used to connect the PC's TxD to the finder's
|
|
RxD and vice versa. That should help you keep it clear when wiring the
|
|
chip.
|
|
|
|
Wiring steps:
|
|
A) Connect your 3v power supply to pin 16.
|
|
NOTE: Connect a cap (C5)from VCC to GND to filter noise.
|
|
B) Connect your power supply GND to pin 15.
|
|
NOTE: Connect this GND to WHFX30 GND on J4 of the 10-pin header.
|
|
C) Pump capacitor C1 connects from pin 1 to pin 3.
|
|
D) Pump capacitor C2 connects from pin 4 to pin 5.
|
|
E) Reservoir cap C3 connects from pin 2 to GND
|
|
F) Reservoir cap C4 connects from pin 6 to GND.
|
|
NOTE: Cap C4 has negative polarity, so the + side connects to GND.
|
|
G) RS232 RxD (Pin 2 on a 9-pin RS232 connector) connects to pin 14
|
|
H) RS232 TxD (pin 3 on a 9-pin RS232 connector) connects to pin 13
|
|
I) WHFX30 RxD (Pin J7 on the 10-pin header) connects to pin 12
|
|
J) WHFX30 TxD (Pin J9 on the 10-pin header) connects to pin 11
|
|
|
|
|
|
MAX3232 Interface
|
|
|
|
___ ___
|
|
+-----)|--- C1+ -|1 U 16|- Vcc ---|(---GND
|
|
| GND--)|-- V+ -|2 15|- GND --------GND
|
|
+---------- C1- -|3 14|- T1out ---> RS232 RxD (RS232 p2)
|
|
+---)|---- C2+ -|4 13|- R1in <--- RS232 TxD (RS232 p3)
|
|
+--------- C2- -|5 12|- R1out ---> WHFX30 RxD (Header J7)
|
|
GND--|(-- V- -|6 11|- T1in <--- WHFX30 TxD (Header J9)
|
|
T2out -|7 10|- T2in
|
|
R2in -|8 9|- R2out
|
|
|_______|
|
|
|
|
|
|
As an alternate route, you can buy a cheap USB-RS232 converter and just
|
|
tap into the 3v RxD, TxD pins, saving yourself the trouble of building the
|
|
MAX3232 circuit.
|
|
|
|
|
|
|
|
--[ 6.0 - ISP Loader Capabilities
|
|
|
|
OK, you have built and tested your interface board, and connected it to
|
|
the wifi finder. You have jumpered J1 and J4 to enable the bootloader, and
|
|
you have powered up the wifi finder while hyperterminal runs on your PC.
|
|
What now?
|
|
|
|
At first, the device will send nothing or a garbage character. It's
|
|
waiting for the uppercase "U" in order to detect and configure the baud
|
|
rate. After sending a few "U"'s to the device, it will begin echoing
|
|
characters back. You are now talking to the ISP loader.
|
|
|
|
It is at this point that we note a discrepancy in the datasheet. Maybe
|
|
our device is not exactly a MX10E8050A, or maybe they screwed up. The
|
|
datasheet says that either ASCII or binary records can be sent. We find
|
|
that it only responds to binary records (so hyperterminal is somewhat
|
|
limited). But the commands listed in the datasheet are accurate, you just
|
|
need to send them in binary form, not ASCII. Go get a comms program from
|
|
the openschemes site listed at the end of the article.
|
|
|
|
The records you will send are based on the Intel Hex Record format that
|
|
you may have seen in those .HEX files from your compiler. But this device
|
|
uses an extended set to include commands. The format is the same, though.
|
|
Details of the hex record format are available at reference [B] below.
|
|
|
|
Generic hex record format
|
|
: nn aa aa rr dd ... dd cc <crlf>
|
|
|
|
Number Data Description
|
|
------ ---- ------------
|
|
1) 0x3A (The ":" character) starts a record.
|
|
2) 0xnn The number of data bytes in the command.
|
|
3-4) 0xaa, 0xaa Address of the location to access, or 00,00 otherwise
|
|
otherwise
|
|
5) 0xrr The record type (or command type)
|
|
6-n) 0xdd..... Data Packet, of length described in byte #2.
|
|
n+1) 0xcc 2's complement checksum. Sum, (exept :), mod FF,
|
|
invert-1
|
|
|
|
So upon receipt of a complete command, the device will either respond
|
|
with a "." to indicate good checksum, or an "X" to indicate bad checksum.
|
|
The only other response would be an "R", if you attempted to write data but
|
|
it was not successfully written. We've never recieved one unless we
|
|
attempted to write before the EEPROM was erased.
|
|
|
|
|
|
Some nice commands are offered in the datasheet, and we've come up with
|
|
some others. We will print them as hex strings, because the ASCII looks
|
|
like garbage! A typical set of commands may be the sequence that follows.
|
|
|
|
---------------------------------------------------------------------------
|
|
1) Dump EEPROM.
|
|
0x3A, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xF9
|
|
|
|
Description: Read EEPROM (0x04) from location 0x0000 to 0xFFFF, checksum
|
|
0xF9.
|
|
|
|
This beauty dumps the entire contents of the WHFX30 code memory to
|
|
the serial port. This is the first command you will want to use, in order
|
|
to get a clean copy of the 64k EEPROM in case you screw it up later.
|
|
|
|
---------------------------------------------------------------------------
|
|
2) Full Chip Erase
|
|
0x3A, 0x01, 0x00, 0x00, 0x03, 0x07, 0xF5
|
|
|
|
Description: Erase all EEPROM blocks (0x03) + Status byte and Boot vector,
|
|
checksum:0xF5.
|
|
|
|
You can also do block-wise erase, but this command will clear everything
|
|
in the chip, which is our preferred method. Please note that you will
|
|
need to re-write the boot vector after erasing, otherwise the chip will
|
|
be stuck in the ISP loader.
|
|
|
|
---------------------------------------------------------------------------
|
|
3) Blank Check Device
|
|
0x3A, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0xF8
|
|
|
|
Description: Blank check (0x01) the device from 0x0000 to 0xFFFF
|
|
|
|
You can't successfully program EEPROM with data in it, so you will want
|
|
to blank check it. This takes several seconds if it's going to pass, but
|
|
if you fail it will fail as soon as the chip finds any data. Cool!
|
|
|
|
---------------------------------------------------------------------------
|
|
4) Program Data
|
|
0x3A, 0x10, 0x00, 0xhh, 0xll, 0x00, 16 Data bytes, Checksum
|
|
|
|
Description: Program EEPROM (0x00) at location 0xhhll with the following
|
|
bytes. First byte is the data length. Here we use 0x10 for 16 bytes but
|
|
that can be changed. Please note you will need to calculate the checksum
|
|
on the fly, and the checksum summation does NOT include the first byte,
|
|
0x3A.
|
|
|
|
If you don't know how to make intel checksums, here you go:
|
|
|
|
a) Sum bytes mod 256 (or sum in a byte-wide variable and let it roll over)
|
|
b) Convert to 2's complement. A cheat for this if you don't want to look
|
|
it up is to subtract your sum from 256 (0x100), or leave as 0 if the
|
|
sum turned out to be 0x00.
|
|
|
|
For those of you unfamiliar with 2's complement, it is the number required
|
|
to make the entire sum equal 0x100. So for a summation total of 0x7E, our
|
|
checksum would be 0x82. Since we are doing byte-wide checksum, a sum
|
|
total of 0x17E or 0x217E would also use a checksum of 0x82, since it is
|
|
only the last byte that counts. If the sum total is some multiple of
|
|
0x100, then the checksum would be 0x00.
|
|
|
|
|
|
---------------------------------------------------------------------------
|
|
5) Erase Boot Vector and Status Byte
|
|
0x02, 0x00, 0x00, 0x03, 0x04, 0x00, 0xf7
|
|
|
|
Description: Erase (0x03) the BV/Status byte (0x04) after programming is
|
|
completed in preparation for restoring default values.
|
|
|
|
|
|
After programming, the device will have status and BV set to continue
|
|
booting into the ISP loader. In order to return the chip to normal mode
|
|
(booting into EEPROM), we need to clear and rewrite the BV manually.
|
|
Please note that after clearing these bytes, it is very important that you
|
|
successfully re-write the BV to it's default value or you will effectively
|
|
DISABLE the ISP loader and will never get back into it. If you are having
|
|
problems writing the BV, simply do a full-chip erase to get out of this
|
|
dangerous condition. But NEVER power down if you are stuck at step 5.
|
|
|
|
---------------------------------------------------------------------------
|
|
6) Write Boot Vector
|
|
0x03, 0x00, 0x00, 0x03, 0x06, 0x01, 0xFC, 0xF7
|
|
|
|
Description: Write (0x03) boot vector (0x01) to value 0xFC (for 0xFC00),
|
|
checksum: 0xF7.
|
|
|
|
This resets the boot vector to the default value of 0xFC00. Do not
|
|
power down the device between steps 5 & 6, or the boot vector will be
|
|
stuck at 0x0000, running the programmed EEPROM always and disabling
|
|
your ability to hit the ISP loader ever again.
|
|
|
|
---------------------------------------------------------------------------
|
|
|
|
We will assume at this point that you have dumped out the entire 64k of
|
|
EEPROM that exists in the device. A measly 16k will match the data you can
|
|
find in the vendor's firmware upgrade file, which leaves us with MOST of
|
|
the data still an unknown. Fear not, intrepid hacker - we will now frame
|
|
out the location and function of this code EEPROM for you.
|
|
|
|
The 64k EEPROM is divided into four logical blocks of 16k each. This
|
|
partitioning is provided by the manufacturer to allow the chip to erase and
|
|
reprogram itself in a limited manner. In all the firmwares investigated,
|
|
the partitioning follows the scheme here
|
|
|
|
Partition Logical Address Function
|
|
--------- --------------- --------
|
|
1 0000h-3FFFh Bootloader and Self-Test Routines
|
|
2 4000h-7FFFh Hotspot Finder Routines
|
|
3 8000h-BFFFh Scratchpad 1 - Wifi Data?? Still unsure..
|
|
4 C000h-FFFFh Scratchpad 2 - Updater Scratchpad
|
|
|
|
As is the case with most 8051 microcontrollers, typical execution from
|
|
power-on or reset begins at 0000h in partition 1. Here the micro will
|
|
first clear RAM and check for corrupted memory before checking the state
|
|
of the buttons. If either self-test mode or bootloader buttons are
|
|
depressed, the micro will operate exclusively in partition 1. In the
|
|
"Firmware Upgrade Mode" located in this partition, the micro can erase
|
|
and re-write the other blocks. For example, when a new finder routine is
|
|
uploaded in firmware upgrade mode, the micro first erases the C000 block
|
|
and writes the downloaded data here. If the checksum is good, the 4000
|
|
block will be erased and the new finder routine written there.
|
|
|
|
The second partition is the hotspot finder routine, which is what you
|
|
see executing whenever the device is actively looking for hotspots. If
|
|
no buttons are held down upon power-up, we will jump over the bootloader
|
|
and continue in the finder routine in this block.
|
|
|
|
The third partition is used as scratchpad, but it's function is not
|
|
100% determined. We suspect that it is used to write wifi data but our
|
|
notes on this are not verified.
|
|
|
|
The fourth partition is used as scratchpad during firmware upgrade mode
|
|
to write the new finder firmware temporarily. Upon entrance into the
|
|
firmware upgrade mode, the C000 block is erased. As new firmware is sent
|
|
to the device, it is written here first. After a successful transfer,
|
|
this data is checksummed for validity. If valid, the 4000 block is then
|
|
erased and this data copied there for permanent use as the new finder
|
|
routine. This simplified upgrade is a bit safer since it is downloaded
|
|
and checksummed before any upgrade is performed, so this will be the
|
|
focus of our next section.
|
|
|
|
|
|
--[ 7.0 - Software Bootloader Capabilities
|
|
|
|
For those who are wary of erasing and fooling with the EEPROM at it's
|
|
lowest levels, we can also communicate with the software bootloader, also
|
|
known as "Firmware Upgrade Mode". It is limited to working on the 16k
|
|
block of EEPROM residing at 0x4000 (the finder routines), but this is still
|
|
useful in some cases. It's a good alternative for those who don't want to
|
|
risk corrupting the device memory or boot vector. I consider it very safe,
|
|
because the software bootloader itself resides in the 0x0000 block,
|
|
separated from the writing and erasing being done at 0x4000 and above. So
|
|
in no case could you lose the ability to go back to the original EEPROM.
|
|
|
|
When we power up the device (with no J1-J4 jumper) with the "Next" button
|
|
held down, the software bootloader runs as previously discussed. The
|
|
serial port is automatically configured to 115.2k, 8n1 and the device will
|
|
begin outputting characters. It intends to speak to the ZD1211, but we can
|
|
simply attach our RS232 interface and communicate with it directly.
|
|
|
|
I will not go into all the details here, but we had to disassemble the
|
|
bootloader itself to find the commands and communication sequence. You can
|
|
do the same, if you like. Or, a small program to read and write the device
|
|
using firmware upgrade mode is available online. A quick overview of a
|
|
partial disassembly shows some details we used in development of our
|
|
program.
|
|
|
|
Upon entrance into firmware upgrade mode, the device sends 8 0x00 bytes
|
|
to the serial port to show it is alive, and then 8 0xA6 bytes to flag that
|
|
it is about to erase the 0xC000 block. After erasing the scratchpad block
|
|
the device sends 8 0xA7 bytes. Finally, it sends 8 0x11 bytes as the
|
|
equivalent of a "command prompt". A good command will be executed, and a
|
|
bad command will be ignored and will get us to another 8 0x11 bytes.
|
|
|
|
Although all instructions are not shown, you can see the operation of each
|
|
of these sections by our comments here.
|
|
|
|
Snippet 1: Send the 0xA6's, erase the 0xC000 block and send the 0xA7's.
|
|
NOTE: All 8 transmissions of 0xA6 and 0xA7 are not shown, but you get
|
|
the picture.
|
|
|
|
053A 7F A6 mov R7, #0xA6 ; Load 0xA6
|
|
053C 12 28 A0 lcall SerialOut0 ; Send it to the serial port
|
|
053F 7F A6 mov R7, #0xA6 ; Load 0xA6
|
|
0541 12 28 A0 lcall SerialOut0 ; Send it to the serial port
|
|
0544 7F C0 mov R7, #0xC0 ; Load 0xC0 for erasing 0xC000 block
|
|
0546 12 29 3C lcall Do_IAP_ERASE ; Do the IAP Rom call to erase 0xC000
|
|
0549 7F A7 mov R7, #0xA7 ; Send 8x 0xA7 to signify erasure done
|
|
054B 12 28 A0 lcall SerialOut0
|
|
054E 7F A7 mov R7, #0xA7
|
|
0550 12 28 A0 lcall SerialOut0
|
|
0553 7F A7 mov R7, #0xA7
|
|
0555 12 28 A0 lcall SerialOut0
|
|
... And so on ...
|
|
|
|
|
|
Snippet 2: Sending last few 0x11 bytes of the command prompt, and the
|
|
inspection of the "password" and command.
|
|
|
|
058F 7F 11 mov R7, #0x11 ; Load 0x11
|
|
0591 12 28 A0 lcall SerialOut0 ; Send it to the serial port
|
|
0594 7F 11 mov R7, #0x11 ; Load 0x11
|
|
0596 12 28 A0 lcall SerialOut0 ; Send it to the serial port
|
|
0599 12 29 A2 lcall SerIn_OneByte ; Get one byte from serial port
|
|
059C BF AA D2 cjne R7, #0xAA, L_571 ; If byte is not 0xAA, bail out
|
|
059F 12 29 A2 lcall SerIn_OneByte ; Get one byte from serial port
|
|
05A2 BF 77 CC cjne R7, #0x77, L_571 ; If byte is not 0x77, bail out
|
|
05A5 12 29 A2 lcall SerIn_OneByte ; Get one byte from serial port
|
|
05A8 8F 28 mov RAM_28, R7 ; Store it in location 28
|
|
05AA E5 28 mov A, RAM_28 ; Store it in A as well
|
|
05AC 64 A5 xrl A, #0xA5 ; XOR it with 0xA5
|
|
05AE 70 2B jnz L_5DB ; If NOT 0xA5, continue to "Erasing"
|
|
05B0 7F A5 mov R7, #0xA5 ; Otherwise echo 0xA5's as ack
|
|
05B2 12 28 A0 lcall SerialOut0
|
|
05B5 7F A5 mov R7, #0xA5
|
|
05B7 12 28 A0 lcall SerialOut0
|
|
|
|
We can see that the bootloader requires a "password" of 0xAA, 0x77 in
|
|
order to get to the beginnings of the command interpreter. Afterward, it
|
|
is looking for the 0xA5 byte to start an upload. Once it gets an 0xA5,
|
|
it will echo 8 0xA5's back to the host and continue on to the "Recieving"
|
|
routine.
|
|
|
|
You will note that these function names are our own, and are obviously
|
|
not embedded in the firmware. Feel free to make up your own names and
|
|
comments if you decide to disassemble the code yourself. Furthermore,
|
|
you will note that in order to erase the 0xC000 block, we must use the
|
|
device's internal ROM calls. This is an interesting feature supplied
|
|
by the IC vendor to make EEPROM programming easier. The details of the
|
|
IAP rom calls are listed in the datasheet, and we will show a short
|
|
snippet of the Do_IAP_ERASE call here, just for clarity.
|
|
|
|
293C Do_IAP_ERASE:
|
|
293C 8F 2F mov RAM_2F, R7 ; Get the address to erase
|
|
293E 75 F8 5A mov SFR_F8, #0x5A ; Write ROM Security code
|
|
2941 43 A2 20 orl FIE, #0x20 ; Set ENBOOT to enable IAP ROM
|
|
2944 79 01 mov R1, #1 ; Function 0x01 (ERASE EEPROM)
|
|
2946 8F 83 mov DPH, R7 ; High byte of address into DPH
|
|
2948 75 82 00 mov DPL, #0 ; Low byte of address into DPL
|
|
294B 12 FF F0 lcall L_FFF0 ; Execute the IAP ROM Call
|
|
294E FF mov R7, A ; Store the result in R7
|
|
294F 53 A2 DF anl FIE, #0xDF ; Clear the ENBOOT flag
|
|
2952 53 F8 00 anl SFR_F8, #0 ; Clear the ROM security code
|
|
2955 22 ret
|
|
2955 ; End of function Do_IAP_ERASE
|
|
|
|
It's interesting because there is no actual code at location FFF0, but
|
|
rather this location has been remapped to an internal function supplied
|
|
by the manufacturer of the IC. We enable this remap by writing a password
|
|
and setting the ENBOOT bit. As was mentioned, the details are in the
|
|
datasheet, but this is the general procedure to call the IAP functions with
|
|
your desired command in register R1.
|
|
|
|
|
|
Had enough assembly for now? Let's get back to the descriptions!
|
|
|
|
|
|
When using the firmware upgrade mode, the 16k file must pass an internal
|
|
checksum where the bytes at 0x0E and 0x0F (0x400E, 0x400F) are set so the
|
|
16-bit sum of the entire 16k block is 0x0000. It's an easy calculation,
|
|
and our program to talk to upgrade mode will check and correct it on the
|
|
fly if needed. When writing your own, please take this into account: If
|
|
the entire file is uploaded but the checksum fails, the device will display
|
|
BED CS: ???? on the LCD, with the checksum displayed in the ?? values.
|
|
The EEPROM will not be updated in the case of a failed checksum. If the
|
|
checksum is good, the device will display "Erasing", "Upgrading" for a few
|
|
moments and then show the new firmware version before restarting at your
|
|
command.
|
|
|
|
Please note is that the 0xC000 block and maybe the 0x8000 blocks are
|
|
used as scratchpad memory when a new 16k BIN file is being uploaded. So
|
|
if you have located your own code there when you enter firmware upgrade
|
|
mode, be warned that these blocks will be erased automatically on entry
|
|
into upgrade mode.
|
|
|
|
|
|
|
|
--[ 8.0 - Inserting Your Own Code
|
|
|
|
We assume you have a compiler, and the necessary knowledge to write 8051
|
|
code. The next step is to insert some of our own code for execution.
|
|
There are essentially two ways to do this: by patching the finder routines
|
|
in the case of using the firmware upgrade mode; Or by patching the
|
|
bootloader in the case that you are overwriting all the memory using the
|
|
ISP Loader.
|
|
|
|
Either one is fine, but space is very limited in the finder routine,
|
|
basically consisting of about 1400 bytes up at 0x7A80. Nonetheless, we
|
|
will demonstrate it here.
|
|
|
|
The entry point to the finder routines is at 0x4020, jumped to after the
|
|
check for the bootloader. Here we clear some memory and then jump to the
|
|
main finder routine at 0x71FE. By inserting a jump or call right after
|
|
we clear the internal RAM, we can divert execution to our own code, which
|
|
we assume resides at 0x7A80. After our code is done, we can continue on
|
|
with the normal finder routine by jumping then to 0x71FE. Or, you can
|
|
insert a call down after the RAM clear, and simply return to it.
|
|
|
|
Original code for finder entry point
|
|
|
|
org 0x4020
|
|
;-------------------------------------------
|
|
Finder_Entry:
|
|
|
|
mov R0, #0x7F ; Load the address of top of RAM
|
|
clr A ; Clear the ACC
|
|
|
|
Memclear_Loop: ; seg000_4023
|
|
mov @R0, A ; Store a 0 at the address in R0
|
|
djnz R0, Memclear_Loop ; Decrement R0, loop if not done yet
|
|
mov SP, #0xA1 ; Set the stack pointer to 0xA1
|
|
ljmp Finder_Start ; Continue to 0x71FE
|
|
|
|
|
|
We would insert our jump or call right before the ljmp to Startup.
|
|
After this ljmp, there is blank space up to 0x4070 so it's no
|
|
problem to insert a few instructions here. For example..
|
|
|
|
Modified code for finder entry point
|
|
|
|
org 0x4020
|
|
;-------------------------------------------
|
|
Finder_Entry:
|
|
|
|
mov R0, #0x7F ; Load the address of top of RAM
|
|
clr A ; Clear the ACC
|
|
|
|
Memclear_Loop: ; seg000_4023
|
|
mov @R0, A ; Store a 0 at the address in R0
|
|
djnz R0, Memclear_Loop ; Decrement R0, loop if not done yet
|
|
mov SP, #0xA1 ; Set the stack pointer to 0xA1
|
|
ljmp MyRoutine ; Change this jump to our code
|
|
|
|
|
|
org 0x7A80
|
|
;-------------------------------------------
|
|
MyRoutine:
|
|
do our instructions here
|
|
...
|
|
...
|
|
ljmp Finder_Start ; Continue to 0x71FE
|
|
|
|
|
|
|
|
Now we have not shown the fact that a lot of data exists between
|
|
these two points. It is best to compile your program and then convert
|
|
the .HEX file to .BIN file (using HEX2BIN.exe-search it or download from
|
|
reference [C]). Finally you can insert your new code using copy/paste
|
|
from a hex editor into the proper locations in the original .BIN file
|
|
before upload to the device.
|
|
|
|
|
|
For the daring folks, it is much better to update the entire EEPROM
|
|
using the ISP Loader. Then, we can basically take over the entire 16k
|
|
block at 0x8000. This one is only erased by command when we're in the
|
|
firmware upgrade mode so it is relatively safe. If you use the EEPROM
|
|
block at 0xC000, you must not enter firmware upgrade mode or it will
|
|
immediately be erased and you will have to reprogram it to get your code
|
|
back into the device.
|
|
|
|
Upon startup, the device begins executing at 0x0000, where we can only fit
|
|
one instruction: The reset jump vector. You can always patch this location
|
|
to jump to your code, and later continue with it's original value by
|
|
jumping to location 0x0100. More desireable is to patch at 0x0109, after
|
|
the device has cleared it's internal RAM and set the stack pointer.
|
|
|
|
This code at 0x0100 is almost identical to the start of the finder routine
|
|
we looked at before. Our strategy is identical, and in this example we
|
|
will take over at 0x0109 and jump to our code at 0x8000. Once our code is
|
|
done we can continue on by jumping to the next stage of the original
|
|
startup routines (checking the next/seek buttons) with a jump to 0x26D2.
|
|
|
|
|
|
Original code for power-on startup. Jumped to by 0x0000 jump vector.
|
|
|
|
org 0x0100
|
|
;-------------------------------------------
|
|
Power-ON:
|
|
|
|
mov R0, #0x7F ; Load the address of top of RAM
|
|
clr A ; Clear the ACC
|
|
|
|
Memclear_Loop0: ; seg000_0103
|
|
mov @R0, A ; Store a 0 at the address in R0
|
|
djnz R0, Memclear_Loop0 ; Decrement R0, loop if not done yet
|
|
mov SP, #0xA1 ; Set the stack pointer to 0xA1
|
|
ljmp Boot_Check ; Continue to 0x26D2
|
|
|
|
|
|
Modified code for power-on startup
|
|
|
|
|
|
org 0x0100
|
|
;-------------------------------------------
|
|
Power-ON:
|
|
|
|
mov R0, #0x7F ; Load the address of top of RAM
|
|
clr A ; Clear the ACC
|
|
|
|
Memclear_Loop0: ; seg000_0103
|
|
mov @R0, A ; Store a 0 at the address in R0
|
|
djnz R0, Memclear_Loop0 ; Decrement R0, loop if not done yet
|
|
mov SP, #0xA1 ; Set the stack pointer to 0xA1
|
|
ljmp MyRoutine ; Continue to 0x8000 for our code
|
|
|
|
|
|
org 0x8000
|
|
;--------------------------------------------
|
|
MyRoutine:
|
|
do our instructions here
|
|
...
|
|
...
|
|
ljmp Boot_Check ; Continue to 0x26D2
|
|
|
|
|
|
|
|
This approach is a little bit easier to hex edit because it's just a few
|
|
bytes' change down at 0x0109. Then we can ignorantly paste up to 16k of
|
|
code up at 0x8000.
|
|
|
|
Obviously, the best hacks do not use hex editing, but will create a full
|
|
.ASM recreation of the rest of the EEPROM. Either ourselves or another
|
|
group will eventually release this .ASM file - we are still negotiating -
|
|
but it will take some time as we are all still studying the disassembly.
|
|
|
|
|
|
|
|
--[ 9.0 - Conclusion
|
|
|
|
We have just scratched the surface here in this article, to give you the
|
|
tools and a starting point for your own development. More advanced
|
|
techniques such as inserting two RS232 interfaces between the two boards
|
|
can allow us to monitor all the communications back and forth during the
|
|
finder routine or firmware upgrade mode. With this method we can easily
|
|
see the command sequences passed back and forth between the two chips.
|
|
Additionally, USB snooping is a great tool to watch high-level
|
|
communication between the PC and the finder at any time. Also, these
|
|
commands can be seen in a complete disassembly and analysis of the firmware
|
|
files, which was not included here. Using your own imagination and
|
|
creativity will lead to many other advances we have not even considered!
|
|
|
|
|
|
In conclusion, this article is focused on the hardware hack, so some of
|
|
our musings on the software and discussion of our custom software tools
|
|
were omitted. For a more in-depth analysis and details, as well as access
|
|
to the software tools described in the article, please visit our web page,
|
|
generously hosted by the Openschemes project at [D].
|
|
|
|
Good luck, and happy hacking!
|
|
|
|
|
|
|
|
--[ A.0 - References
|
|
|
|
[1] - IDA Disassembler by DataRescue Corporation
|
|
http://www.datarescue.com/
|
|
|
|
[2] - Keil uVision IDE
|
|
http://www.keil.com/uvision/
|
|
|
|
[3] - Allnet Allspot ALL0298
|
|
http://www.allnet-usa.com/html/shop.php?kat=WiFi+54Mbit
|
|
|
|
[4] - ZyXel AG-225H
|
|
http://www.zyxel.com (Direct link too long to include)
|
|
|
|
[5] - TrendNet TEW-429UB
|
|
http://trendnet.com/products/proddetail.asp?prod=155_TEW-429UB
|
|
|
|
[6] - Linksys WUSBF54G
|
|
http://www.linksys.com (Direct link too long to include)
|
|
|
|
[7] - ZD1211 Linux Driver Development
|
|
http://zd1211.wiki.sourceforge.net
|
|
|
|
[8] - ZyXEL AG-225H WiFi Finder Reverse Engineering
|
|
http://www.maushammer.com/systems/wififinder/index.html
|
|
|
|
[9] - Macronix MX108050A Datasheet
|
|
http://www.keil.com/dd/docs/datashts/mxic/mx10e8050i.pdf
|
|
|
|
[A] - Maxim MAX3232 Datasheet
|
|
http://datasheets.maxim-ic.com/en/ds/MAX3222-MAX3241.pdf
|
|
|
|
[B] - Intel Hex Record Format at Keil
|
|
http://keil.com/support/docs/1584.htm
|
|
|
|
[C] - HEX2BIN Download
|
|
http://www.tech-tools.com/d_hx2bin.htm
|
|
|
|
[D] - Wifi Finder Reverse Engineering at Openschemes
|
|
http://wifi.openschemes.com.
|
|
|
|
|
|
|