how to reverse analyze the firmware of western digital hard disk (2)

Posted by millikan at 2020-04-01

In fact, there are many small parts in this article. For the convenience of reading, I have integrated them into two parts (the first part). Some of them are difficult to translate (foreigners have a lot of rubbish). I hope you will be merciful.

It seems that the startup code is only distributed in different memory addresses, but there is no easy way to export them all, so I decided to export the block from 0 × 00000000 in memory and then all of them reference the external address of the block (to build a basic code map).

Although hard disk models do have different addresses, my layout can give you a good idea.


After looking around for a while, I found that it would read code from some places into memory, so I guess this is flash memory.

Flash memory starts from a table spanning 0 to 0 × 120 (the first block at the beginning), each table item has 32 bytes and uses the same format (reference image). Each block has an ID from 1 to N, and the first block has an exception value of 0x5a.

The block at 0x5a is the boot program, which reads and decompresses the code from the remaining flash memory. I'm not sure, but it proves a problem. I want to disconnect the bootloader at the entry point, which sounds easy, but not so.

1. My hardware breakpoints did not take effect at some points of the boot process. It is possible that the processor rewrites the registers or disables them; however, I still did not find the problem. This means that I can't make a breakpoint (0 × 19000) at the entry point of the bootstrapper.

2. The complex code to load and execute the boot program is in ROM, so I have no way to set the software breakpoint.

3. The observation point doesn't seem to work. I can't make the code segment in any memory even before the breakpoint stops working.

4. Most of the code not in ROM uses paging technology. When they need it, they will read the code in specific area in memory, and then replace it when they don't have it to prevent using software breakpoints.

In a word, the situation is more difficult than I thought, so I decided to buy an extended EEPROM chip driver to replace the reconstruction in MCU. In this way, I can use EEPROM program to write software breakpoints into flash memory chip.

The hardware and firmware make this disk quite unified, except that the firmware is now stored in a 256K SPI flash memory chip to replace the existing MCU memory. The first thing I did was to use a multimeter to see if there was a place at the top of the PCB to connect to the flash memory chip (so we took the PCB off the disk).

WP ා and hold ා both exist in VCC, so this is not a problem. The rest of the required pin points need to be put forward to the test points around E11. I tried to connect the SPI interface of my tumpa to the test point and use the communication software, but I couldn't detect the chip. I'm not sure if my tumpa doesn't have the ability to program circuits, or if there are other fillings on the data line.

If other methods are not effective, I will try to find a SOIC chip, a good EEPROM programmer and soldering station. At the same time, I will try to find out what causes my breakpoint to stop working and fix it.

Try to find something new

This weekend I had a big breakthrough, which made me negate most of my previous research. I know that "don't build wheels again" is not always the best choice, especially when it comes to trusting other people's research conclusions.

One of the main goals is to find a fast and simple way to reprogram the hard disk when it can be accessed physically. On the spritemods blog, he took the flash chip off the PCB and attached it to some of the verobooards, so he was able to exchange data between the hard disk and the flash programmer. Obviously, this is not particularly useful for me, because I have to disconnect and reconnect the flash memory chips all the time, which is especially impractical for fast infecting disks.

I have known before that it is possible to copy the WD hard disk firmware from the operating system with an administrator or root account. The hard disk must be running in order to receive the SATA command and must be restarted to load the new firmware. If the new firmware has an error, the disk will not start, so the firmware cannot be repaired (usually the hard disk will become brick). In fact, I want to crack the firmware, so I can only copy it in other ways.

On line circuit programming

When the circuit is always connected, the in circuit programming (ICP) method can be programmed in flash memory chips and other components. In the last article, I was able to find the test port connected to the flash memory chip, but there was no way to program it. However, I was able to use ICP after doing some experiments over the weekend.


The biggest problem of ICP is that you need to turn on its power in order to write flash memory chip, but because it is connected with other circuits, it will eventually power other chips, which will send data on different buses to interfere with your communication attempts with flash memory.  

To prevent interference on the SPI bus, it is usually only necessary to press and hold the reset button or ground the reset signal, which will cause the system to be reset and unable to start (allowing you to have uninterrupted access to the flash bus).

Here are my attempts:

1. Directly use 3.3V power supply

2. When pressing and holding the system reset button, directly use 3.3V power supply

3. Directly supply power to the whole system by inserting HD interface

4. When pressing and holding the system reset button, insert the HD interface to directly supply power to the whole system

I almost gave up because everything didn't work (my SPI programmer couldn't even detect a flash chip), but when I decided to make my last attempt on Saturday, it worked (in a way).

SPI programmers can detect flash memory chips, but most of the data they read is wrong. After checking, I found that the VCC (power supply) cable was loose from the test point and hung on the table. So if the VCC cable is not connected and the system is not connected, how can the flash memory chip be read?

Through more experiments, I found that the circuit is set in such a way that some voltage (about 1.2V) sent to miso pin is fed back to VCC track in some way and then the chip is started. I am not a circuit expert, which makes me very confused, but it tells me that it is feasible to read chips in the circuit, I just want to learn some tricks.


After a lot of experiments and some failures, I found that pressing the reset button of the system (the solution to most ICP problems) was the only problem. I've got JTAG connected to the system so that the reset pin will be pulled down (hold reset), so I don't need to manually hold the reset myself. After disconnecting the srst pin of JTAG, as long as the disk is not inserted, everything works well, then I directly power on the flash memory chip. It seems that this system is specially designed for ICP. Do not reset it all the time, or there will be some problems.

This is a modified version of the diagram from the previous article

If you have a USB device that supports SPI programming and it's supported by flash ROM, as I did. You can connect it to a computer and use flash ROM to read, write and modify flash memory. Tumpa is a good board because it has two channels, so you don't need to disconnect JTAG to use SPI.

Don't rebuild the wheel

Before I decided to crack it, I decided to look at other people's research for inspiration. It's smart, isn't it? However, it turns out that most of the research I found is wrong or not suitable for my hard disk.

When I connect to JTAG and the "reset halt" command appears, I remember clearly that before the code runs, the system stops temporarily. When the boot program starts and executes from flash memory, I can track the boot program step by step.

After struggling to write my code in flash memory, I realized that it had been read to memory and executed for a long time before the system stopped. In fact, the code at 0xffff0000 is just the debugging console, which will jump to this only when the stop command is issued, or when the code reading or execution from flash memory fails. At this point, JTAG has been able to connect and the command line appears. The entire kernel has been loaded and initialized. That's why I can't get any breakpoints on the boot program.

I can write the breakpoint to flash memory to generate an exception to make the system fail to load, then delete the breakpoint and manually jump to the boot program, but I don't know why the system didn't boot properly for the second time. This is not a big problem, because I can debug the boot program until a certain point (as long as the code I write is executed in the early stage of boot, I can debug it), but later I find out why the second failure occurred, and I find that there is a time window in the later stage of boot and the early stage of kernel initialization (I can't debug).

My main goal is to insert code into the firmware by executing programs and physically accessing the hard disk drive on the target computer, which I have achieved. Now let's see what I can do.

If you realize that the original attacker is so easy to infect your hard drive firmware, here are two quick ways you can do it.

1. Send firmware update command from the host through the SATA interface (requires root or administrator permission)

2. Create a portable SPI programmer that can erase the firmware by pressing the test point at the bottom of the hard disk. (only 5 seconds)

Just five minutes later, I found the last bit of confusion: the second CPU core. When I realized that it had a single hard coded definition tap (test access port), I went to browse the openocd configuration, and I decided to comment it out and let openocd try to discover the tap automatically.

Autodetect found that the same ID has two taps, so I assume there are two different cores, so I need to modify my configuration.

Here are the configuration settings for both cores to work:


After a few minor tweaks, all that's left is to run openocd and see what's the secret in the new kernel.

When I connect to JTAG through IDA, everything is clear. I can see that the second core stops at the breakpoint I wrote to the flash memory chip, which is the core responsible for loading and executing the boot program. The core I saw before is just waiting in a loop. Obviously, the boot code must be different from core 2, because the other boot program just loops a little bit later.


So as you can see, with very little experience, I can JTAG a WD hard disk, export firmware, and even find out how to read and write flash memory chips using ICP. I will definitely spend more time studying firmware to see how it works, but these are beyond the scope of this article. In order to avoid boring everyone, this is the last article in this series. If I find anything interesting, I will publish my findings to the white paper and upload some demo videos.

I want to continue to publish hardware and software articles (as well as some tutorials). If you have any suggestions, please email me at [email protected]

Now it's clear that core 1 boot is just debugging / managing code, while core 2 has a completely separate code area mapped to the same address. Core 2 not only loads the boot code from flash memory, but also is responsible for most interesting operations, such as operating the SATA request and writing the cache descriptor.

*Reference source:, white hat translation next to FB editor Wang, reprint please indicate that it comes from freebuf hacker and geek (freebuf. Com)