💾 Archived View for aphrack.org › issues › phrack65 › 11.gmi captured on 2022-03-01 at 15:54:51. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2021-12-03)

-=-=-=-=-=-=-

                             ==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.