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