Re-programming the 2Wire NAND flash IC

Californian hacker RyanC suggested another method for unlocking the 2Wires:  re-purposing a SmartMedia or xD-Picture card reader to program the NAND flash memory. [1]

The SmartMedia format uses the standard ONFI command set for reading and programming the NAND flash. The xD-Picture specs are slightly more involved, being a superset of ONFI.

Simple, so far?

2Wire, however, has its own flash translation layer (FTL) to hold the logical-to-physical block mapping.  This mapping data is stored in the out-of-band (OOB) area of the NAND page.  Unfortunately, the average flash card reader cannot program arbitrary data to the OOB area, so can’t be used to reprogram a 2Wire flash.  All is not lost though..

Aside the professional NAND programmers costing $2000 or more, there is one consumer-grade NAND controller IC which offers raw read and write access to all areas of the flash device. The IC, codenamed the Alauda, is something of a mystery. No one is even sure who developed it, but it was probably on behalf of Fuji and/or Olympus.

The Alauda IC has a USB peripheral controller to interface very simply with the PC. This allows easy transfer of control messages and page data to the raw NAND device.  And it doesn’t matter if the NAND chip is embedded in a camera card, or in a TSOP48 surface mount package, as in the case of the 2Wire.

It was perhaps BrendanU who first publicly documented the capabilities of Alauda-based card readers. [2] An open source kernel driver was then developed for the Alauda by legendary Linux hacker Daniel Drake.[3]   Cory1492, a well-known XBox and PSP hacker, ported Daniel’s code, and built it against the userspace USB library, libusb. [4]   Cory’s efforts have made the tool available for most Unix platforms and even for Microsoft Windows.

Alauda NAND flash controller harnessed to TSOP48 cradle
256Mbit NAND from 2Wire board loose beneath
(click to enlarge)

The Alauda NAND controller IC
(click to enlarge)

The plan to exploit this hack and hardware was described earlier.  Briefly:

  • Gently lift the NAND flash IC off the PCB with a hot-air gun;
  • Dump contents with a NAND reader. For reasons above, the Alauda IC is ideal;
  • Rewrite “initd” XML table to re-enable secure shell daemon. See: http://pastebin.com/ss8sqMdu
  • Rewrite “user” XML table with new root password. See: http://pastebin.com/gucCEM3H
  • Update ECC in OOB areas of all modified pages. See: http://hack..error-correcting-code-ecc/
  • Re-program the modified NAND pages;
  • Re-install NAND IC on the 2Wire PCB;
  • Fingers crossed and boot!

Userspace tool for Alauda NAND reader by Cory1492

UPDATE:

This method was just trialled several times. While the NAND reading and writing works fine, the 2Wire board still won’t boot with our modified firmware image. The device just hangs with a solid red LED.

The search for that elusive 2Wire hack continues!

As for the NAND hack in general, it could be very useful in a range of other applications. Whether for unlocking routers, digital TV set-top boxes, or for reflashing PC BIOS chips, etc.

EDIT:

There are some more notes in the comments below. In the dueness of time, it can be properly documented and referenced.  The beauty of this NAND reader is that it costs scarcely $10 to make.

[1] https://plus.google.com/102161594653790479451/posts
[2] http://www.uchobby.com/index.php/2007/05/05/read-embedded-flash-chips/
[3] http://www.reactivated.net/weblog/
[4] http://www.xboxhacker.org/index.php?action=profile;u=15891 DEAD LINK
Mirrored at http://docs.google.com/folder/d/0B6wW18mYskvBOWE2OGQ5NzAtZjc4ZS00MjNkLWE5ODAtMjZkMjYwZTZkMmVj/edit

Suitable Mini Edge Card Socket?

Earlier, we had great difficulty finding a connector to fit the JTAG/I2C port on the 2Wire PCBs. In the end, something usable was fashioned out of a Sullins PCIe edge card socket. However, the connector below could be a better, low-cost solution.

Connector specialist, Samtec, stocks the MEC-1 series socket and it looks very promising for hacking the 2Wire. [1] [2]    Infact, it may be the very connector that 2Wire / Pace uses to re-flash and unbrick these devices.

Samtec MEC1-108-02-F-D-A

The 1.0mm pitch dual row card edge connector

[1] http://www.samtec.com/documents/webfiles/pdf/MEC1.PDF
[2] http://hackingbtbusinesshub.files.wordpress.com/2012/10/320918.pdf

PCB photo of 2Wire 2701HGV-E

Below is a nice clear photograph of the PCB in a 2Wire 2701HGV-E.

The photo is attributed to ‘seya‘, a contributor to a discussion thread on right.com.cn, a Chinese language web forum. [1]:

We can see that the 2701HGV-E is driven by a 2Wire Ares, a TriMedia five-issue slot VLIW CPU.   On the DSL side, the 2701HGV-E has a SiLabs SI3112-ZM1  ADSL2+ AFE and Line Driver.    It also has a USB peripheral port which isn’t present on the BT-issue 2701HGV-C.

Pace plc (new owner of 2Wire Inc)  has published an incomplete list of 2Wire models in the Home Gateway family. [2]

PCB of the 2Wire 2701HGV-E (click to enlarge)

[1] http://www.right.com.cn/forum/thread-40668-1-1.html
[2] http://www.pace.com/universal/gateways/2wire/gateway-platforms/models-and-specs/

Very Long Instruction Word Architectures, the ELI-512, and the success of VLIW today

If John Hennessy is the grandfather of the RISC architecture, then Joseph Fisher must the grandfather of VLIW.

Joseph Fisher, grandfather of VLIW

Linked below is Fisher’s seminal paper on VLIW from 1983, “Very Long Instruction Word Architectures and the ELI-512“.  [1]

ABSTRACT By compiling ordinary scientific applications programs with a radical technique called trace scheduling, we are generating code for a parallel machine that will run these programs faster than an equivalent sequential machine-we expect 10 to 30 times faster.

Wind forward a quarter century to Spring 2009, and Fisher and colleagues Paolo Faraboschi and Cliff Young authored the article “VLIW Processors: From Blue Sky to Best Buy” for IEEE magazine Solid State Circuits: [2]

ABSTRACT Very long instruction word (VLIW) is an architectural style that one of the authors—Josh Fisher—proposed about 30 years ago to speed up computers and otherwise enhance their performance. Those listening to Fisher’s first public “blue-sky” expositions of this technology in the early 1980s did not generally expect it to succeed. Indeed, they would have been stunned to hear of the success these processors are enjoying today, especially as embedded processors, designed to perform special-purpose functions, usually in real time, in some kind of hardware.

[1] http://inst.cs.berkeley.edu/~n252/paper/p263-fisher.pdf

[2] http://sites.google.com/site/paolofaraboschi/vliwbluesky2.pdf

2701HGV-C RSA-1024 private key

Another XML config table has been extracted from the firmware image of a 2Wire 2701HGV-C. This is the root RSA private key, broken down into its components.

    <?xml version="1.0" encoding="UTF-8"?>
    <CM VERS="1">
      <TABLE NAME="keys" B="6.3.9.41" B0="6" B1="3" B2="9" B3="41">
        <ROW ID="0">
          <P N="type" T="S">root_rsa</P>
          <P N="key_len" T="U">0x00000262</P>
          <P N="key_data" T="VB">
            02623082025e02010002818100ee6fe39369ab015ea885a9f91dc032f5a0b425
            aac3ce42b384108f1d6a84e29b5f7d8ef3c16899bc65a6a3c8cf55cc26e6b1f9
            569d431709e683f22cefa730429c405794d99c681619857909c4879ed8d57e39
            701ef41760a3b5837acbcf8a29118ecefdd6c378cff3e69ba284b96da238dfa1
            dc93ac0e0c8654680eda269a9d020301000102818018b3248b0fc634351f1601
            9e99d360340bbabdb02bea810461a8e97a6d9f686e19fd42c2c385576fa9c412
            7169f1045dff45ee8367751cbcdcd14c54155b67673be2452417af5231c3455f
            a48e50799f23a71f5285a22860520b62bb04d2b2edbfce29d3093813003fd0a7
            d2fafef0f51344b42298f309ab13454ac79c525cad024100f892f234d33420b5
            72a2f146f5378140426e42d8c9454c343ff49aa9118f187a405bd524b20b32f6
            ecc418df2ef6bfe83143cad9bfd8a4716285c28c9b968b83024100f58f6aca98
            3573f1ffb84cf06685664622617d2f431ad3ad6928299fc7fcf4bd3b5019bde0
            fdf2f408a58f5562958b3922940e8b2d352a8dcb244794e7f2c75f0241008435
            5bff7eaa060f9be650600642bc4b1a4a1ce1c2c349d1ac8683d01297c2541b70
            fc7fa4f6d1e7856c9331f97fa1f87463733bb78f197f79005dc67d6667d30241
            0082f80d1324ff4d69c2e3ff5530b8f185728ce081b69eb64b850c80b6d1a95e
            b716cd700d4fd4e221ba02e361bd04d98e8d9cbded091d9426b03417619a1c68
            ad024100b124ef836c3b3e881e89ae688bb29ab551e523036dd704c7de25d9aa
            f2a3f4c4cdf68440970787265064097f00a913c9280052a43df21c8e3246d726
            1faf87fc
          </P>
        </ROW>
      </TABLE>
    </CM>

The hexdump of the private key can be broken down into its components: [1]

RSA 1024-bit private key:

key length:
0262

header:
3082025e  (0x3082 == ASN.1 Sequence)

separator:
0201 (0x02 == integer and 0x01 == 1 byte long)

algorithm version:
00  (0x00 == algorithm version zero)

separator:
028181 (0x02 == integer and 0x81 == 129 bytes long)

modulus:  (129 byte modulus, starts with a null (0x00) - remove this)
00  
ee6fe39369ab015ea885a9f91dc032f5
a0b425aac3ce42b384108f1d6a84e29b
5f7d8ef3c16899bc65a6a3c8cf55cc26
e6b1f9569d431709e683f22cefa73042
9c405794d99c681619857909c4879ed8
d57e39701ef41760a3b5837acbcf8a29
118ecefdd6c378cff3e69ba284b96da2
38dfa1dc93ac0e0c8654680eda269a9d

separator:
0203  (0x02 == integer and 0x03 == 3 bytes long)

public exponent:  (3 bytes)
010001  (integer value 65537, Fermat Number F4)

separator:
028180  (0x02 == integer and 0x80 == 128 bytes long)

private exponent: (128 byte)
18b3248b0fc634351f16019e99d36034
0bbabdb02bea810461a8e97a6d9f686e
19fd42c2c385576fa9c4127169f1045d
ff45ee8367751cbcdcd14c54155b6767
3be2452417af5231c3455fa48e50799f
23a71f5285a22860520b62bb04d2b2ed
bfce29d3093813003fd0a7d2fafef0f5
1344b42298f309ab13454ac79c525cad

separator:
0241 (0x02 == integer and 0x41 == 65 bytes long)

prime1:  (65 bytes - starts with a null - remove this)
00
f892f234d33420b572a2f146f5378140
426e42d8c9454c343ff49aa9118f187a
405bd524b20b32f6ecc418df2ef6bfe8
3143cad9bfd8a4716285c28c9b968b83

separator:
0241  (0x02 == integer and 0x41 == 65 bytes long) 

prime2: (65 bytes - starts with a null - remove this)
00
f58f6aca983573f1ffb84cf066856646
22617d2f431ad3ad6928299fc7fcf4bd
3b5019bde0fdf2f408a58f5562958b39
22940e8b2d352a8dcb244794e7f2c75f

separator:
0241  (0x02 == integer and 0x41 == 65 bytes long) 

exponent1: (65 bytes - starts with a null - remove this)
00
84355bff7eaa060f9be650600642bc4b
1a4a1ce1c2c349d1ac8683d01297c254
1b70fc7fa4f6d1e7856c9331f97fa1f8
7463733bb78f197f79005dc67d6667d3

separator:
0241  (0x02 == integer and 0x41 == 65 bytes long) 

exponent2: (65 bytes - starts with a null - remove this)
00
82f80d1324ff4d69c2e3ff5530b8f185
728ce081b69eb64b850c80b6d1a95eb7
16cd700d4fd4e221ba02e361bd04d98e
8d9cbded091d9426b03417619a1c68ad

separator:
0241  (0x02 == integer and 0x41 == 65 bytes long) 

coefficient: (65 bytes - starts with a null - remove this)
00
b124ef836c3b3e881e89ae688bb29ab5
51e523036dd704c7de25d9aaf2a3f4c4
cdf68440970787265064097f00a913c9
280052a43df21c8e3246d7261faf87fc

[1] http://etherhack.co.uk/asymmetric/docs/rsa_1024.html

2Wire’s NAND Flash Error Correcting Code (ECC)

Earlier we developed TriMedia code to dump the contents of the NAND flash device on the 2Wire boards. [1]

The diagram below illustrates the organisation of a NAND flash memory array. In addition to a main data page area (usually 512 bytes), NAND devices also have a small ‘Spare Area’ of extra bytes per flash page. In small NAND arrays, this ‘Spare Area’ typically holds 16 bytes.

NAND Memory Array Organisation

This is what that NAND flash Spare Area looks like in a 2Wire 2701HGV:

$ xxd -g4 2701HGV-C_6.3.9.41_nand_full_oob_dump_2.img | cut -c10-44 | ./parsehex
[...]
0199200: c0cf 3c55 24ff 69a5 00ff ff96 0600 ff99  ..<U$.i.........
0199400: 003f fcc0 24ff cc30 00ff ff96 0600 ff99  .?..$..0........
0199600: c3cc 0c3f 24ff c0c0 00ff ff96 0600 ff99  ...?$...........
0199800: a699 693f 24ff cf3c 00ff ff96 0600 ff99  ..i?$..<........
0199a00: 0030 0cfc 24ff c33c 00ff ff96 0600 ff99  .0..$..<........
[...]

The NAND Spare Area is also known as the redundancy area or the out-of-band (OOB) area of the flash page. Manufacturers use the area to store bad block information, to hold mapping data for the flash translation layer, and to store Error Correction Code (ECC)

The NAND spare area of the 2Wire 2701HGV router was found to include the check bits of ECC.

The ECC scheme used by 2Wire is based on a Hamming Code algorithm.

In a Hamming Code algorithm, the NAND page (aka the data block) is divided into various partitions – halves, quarters, eighths, even and odd rows and columns, and so on. Parity bits are calculated for each partition of the data block. These become the ECC bits.

The Hamming scheme allows an individual bit in error to be identified and corrected. The scheme can also detect (but not correct) a second errored bit in the same data block.

In 2Wire‘s modified Hamming Code algorithm, a data block of 256 bytes is used. This is half the size of a small NAND flash page (512 bytes).   22-bits are used for calculating the various row and column ECC parities for each 256 byte block. However, in 2Wire’s modified scheme, an additional check bit is used for the column parity ECC byte for each of those blocks. This means that for every 256 byte data block, the scheme uses 23 bits to hold all of the ECC parity bits. Three bytes are needed to store those 23 bits, leaving, it seems, one bit of those three bytes unused.

The 2Wire configuration of ECC requires in total six bytes from the out-of-band area for every 512 byte NAND page.

We examined ECC algorithms from NetBSD/Atmel, Numonyx/Micron and from Frans Meulenbroeks of Philips NV. However, no algorithm worked ‘out of the box’. Because of that extra bit for overall column parity, the ECC scheme used by 2Wire is slightly different to anything we could find published.  Instead, the existing ECC algorithms for calculation, detection and correction were slightly tweaked.

It was Meulenbroeks‘ code which we selected for tweaking, because of its simplicity and its elegance.[2]  Meulenbroeks uses this code as his foundation for discussing the speed optimisations of ECC algorithms. However, we chose to use his unoptimised algorithm because it is so easy to follow. And on a quad core AMD64 it’s not that slow either. The code takes a fraction of a second to calculate the ECCs for all the sectors in a 32MByte NAND image.

//  Modified from Linux kernel docs..  asbokid 2012
//  GPL v.3
//  Author: Frans Meulenbroeks
//  Copyright (C) 2008 Koninklijke Philips Electronics NV.

const char parity[256] = {
    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0
};

void meul_ecc1_2wire(const unsigned char *buf, unsigned char *code)
{
    int i;
    const unsigned char *bp = buf;
    unsigned char cur, par;
    unsigned char rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
    unsigned char rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15;

    par = 0; rp0 = 0; rp1 = 0; rp2 = 0; rp3 = 0;
    rp4 = 0; rp5 = 0; rp6 = 0; rp7 = 0;
    rp8 = 0; rp9 = 0; rp10 = 0; rp11 = 0;
    rp12 = 0; rp13 = 0; rp14 = 0; rp15 = 0;

    for (i = 0; i < 256; i++) {
        cur = *bp++;
        par ^= cur;
        if (i & 0x01) rp1 ^= cur; else rp0 ^= cur;
        if (i & 0x02) rp3 ^= cur; else rp2 ^= cur;
        if (i & 0x04) rp5 ^= cur; else rp4 ^= cur;
        if (i & 0x08) rp7 ^= cur; else rp6 ^= cur;
        if (i & 0x10) rp9 ^= cur; else rp8 ^= cur;
        if (i & 0x20) rp11 ^= cur; else rp10 ^= cur;
        if (i & 0x40) rp13 ^= cur; else rp12 ^= cur;
        if (i & 0x80) rp15 ^= cur; else rp14 ^= cur;
    }
    code[0] =
        (parity[rp7] << 7) |
        (parity[rp6] << 6) |
        (parity[rp5] << 5) |
        (parity[rp4] << 4) |
        (parity[rp3] << 3) |
        (parity[rp2] << 2) |
        (parity[rp1] << 1) |
        (parity[rp0]);
    code[1] =
        (parity[rp15] << 7) |
        (parity[rp14] << 6) |
        (parity[rp13] << 5) |
        (parity[rp12] << 4) |
        (parity[rp11] << 3) |
        (parity[rp10] << 2) |
        (parity[rp9]  << 1) |
        (parity[rp8]);
    code[2] =
        (parity[par & 0xf0] << 7) |
        (parity[par & 0x0f] << 6) |
        (parity[par & 0xcc] << 5) |
        (parity[par & 0x33] << 4) |
        (parity[par & 0xaa] << 3) |
        (parity[par & 0x55] << 2) |
        (parity[par & 0x00] << 1) |
        (parity[par & 0xff]);       // asbokid added for 2wire

/*  code[0] = ~code[0];
    code[1] = ~code[1];             // asbokid removed for 2wire
    code[2] = ~code[2];  */
}

In tests the algorithm works fine on the 2Wire NAND contents. It correctly calculates the ECC for each data block and checks it against the stored ECC code in the out-of-band area of the NAND:

$ gcc -o nanddumpparse nanddumpparse.c 2wire_ecc.c

$ ./nanddumpparse
Usage: ./nanddumpparse nandimage.bin  nandimage.oob

$ ./nanddumpparse 2701HGV-C_6.3.9.41_nand_full_dump_2.img 2701HGV-C_6.3.9.41_nand_full_oob_dump_2.img

Read 33554432 bytes of NAND data from 2701HGV-C_6.3.9.41_nand_full_dump_2.img
Read 1048576 bytes of NAND OOB from 2701HGV-C_6.3.9.41_nand_full_oob_dump_2.img

[...]
Offset 0030000 - [bytes 000-255] : ECC1(stored) = c3:30:0c; ECC1(calc) = c3:30:0c;    ECC okay
Offset 0030100 - [bytes 256-511] : ECC2(stored) = 95:56:65; ECC2(calc) = 95:56:65;    ECC okay
Offset 0030200 - [bytes 000-255] : ECC1(stored) = fc:fc:f0; ECC1(calc) = fc:fc:f0;    ECC okay
Offset 0030300 - [bytes 256-511] : ECC2(stored) = a6:59:95; ECC2(calc) = a6:59:95;    ECC okay
Offset 0030400 - [bytes 000-255] : ECC1(stored) = 30:f0:3c; ECC1(calc) = 30:f0:3c;    ECC okay
Offset 0030500 - [bytes 256-511] : ECC2(stored) = fc:0f:00; ECC2(calc) = fc:0f:00;    ECC okay
Offset 0030600 - [bytes 000-255] : ECC1(stored) = 96:a9:55; ECC1(calc) = 96:a9:55;    ECC okay
Offset 0030700 - [bytes 256-511] : ECC2(stored) = a5:a6:65; ECC2(calc) = a5:a6:65;    ECC okay
Offset 0030800 - [bytes 000-255] : ECC1(stored) = 66:56:69; ECC1(calc) = 66:56:69;    ECC okay
Offset 0030900 - [bytes 256-511] : ECC2(stored) = f0:0f:fc; ECC2(calc) = f0:0f:fc;    ECC okay
Offset 0030a00 - [bytes 000-255] : ECC1(stored) = 99:56:69; ECC1(calc) = 99:56:69;    ECC okay
Offset 0030b00 - [bytes 256-511] : ECC2(stored) = 5a:56:59; ECC2(calc) = 5a:56:59;    ECC okay
Offset 0030c00 - [bytes 000-255] : ECC1(stored) = 3c:3f:00; ECC1(calc) = 3c:3f:00;    ECC okay
Offset 0030d00 - [bytes 256-511] : ECC2(stored) = 95:56:65; ECC2(calc) = 95:56:65;    ECC okay
Offset 0030e00 - [bytes 000-255] : ECC1(stored) = 65:69:95; ECC1(calc) = 65:69:95;    ECC okay
[...]
Offset 1ffbd00 - [bytes 256-511] : ECC2(stored) = 30:f0:30; ECC2(calc) = 30:f0:30;    ECC okay
Offset 1ffbe00 - [bytes 000-255] : ECC1(stored) = 6a:66:65; ECC1(calc) = 6a:66:65;    ECC okay
Offset 1ffbf00 - [bytes 256-511] : ECC2(stored) = 9a:66:95; ECC2(calc) = 9a:66:95;    ECC okay

ECC Errors: CORRECTABLE 0; UNCORRECTABLE 0
Page Utilisation: USED 30199; FREED 2979, ERASED 32347; TOTAL 65536
$

The ECC code patched for 2Wire flash contents can be downloaded from [3].

The 16-byte Spare Area is also safeguarded against corruption. This is achieved through a simple modulo-256 checksum which is performed on bytes [8:14] of the Spare Area.

Using the Spare Area excerpt below, the mod-256 checksum is (0×00+0xff+0xff+0×96+0×06+0×00+0xff) % 0×100 = 0×99, which is then stored in byte 15 of the Spare Area.

$ xxd -g4 2701HGV-C_6.3.9.41_nand_full_oob_dump_2.img | cut -c10-44 | ./parsehex
[...]
0199200: c0cf 3c55 24ff 69a5 00ff ff96 0600 ff99  ..<U$.i.........
[...]

It was important to discover and document the ECC scheme used by 2Wire. When the flash contents are modified, the ECC check bits must be re-calculated for every modified flash page. We can move on now to examine the other elements in the Out-of-Band flash area.

For those interested, more general information on Hamming Code for ECC in NAND Flash can be found in [4] [5] [6] [7] [8]

[1] http://hackingbtbusinesshub.wordpress.com/2012/01/14/the-flash-header-of-an-ares-based-2wire-2701hgv-c/
[2] http://lxr.linux.no/#linux+v3.2.9/Documentation/mtd/nand_ecc.txt
[3] http://docs.google.com/leaf?id=0B6wW18mYskvBX2JOenVYMVBUWDJYSGlVQ000UTBCQQ
[4] http://www.cypress.com/?docID=19134
[5] http://www.latticesemi.com/dynamic/view_document.cfm?document_id=9622
[6] http://www.elenota.pl/datasheet_download/44776/AN1823
[7] http://www.micron.com/~/media/Documents/Products/Technical%20Note/NAND%20Flash/tn2908_NAND_hamming_ECC_code.ashx
[8] http://www.elnec.com/sw/samsung_ecc_algorithm_for_256b.pdf

2701HGV-C system services XML config file

While poking around in the flash dump images of the 2701HGV-C to discover the FTL mapping algorithm, a number of XML config files were unearthed.

One of those XML files is listed below. It contains the system services that are started at boot time. Some of those services are shown as “DISABLED”. One such service is sshd, the secure shell daemon. See element ROW ID=”15″ below.

sshd is presumably present for remote management. It would be great if it could be re-enabled to allow LAN-side shell access to the 2Wire.

Before that is possible, several things need doing:

  • the flash block(s) holding that XML file needs to be erased and re-written with the enabling config element.
  • the out-of-band ECC bytes need to be re-written to reflect the new content of the data block
  • a new ssh key pair must be generated for the sshd server
  • the flash block(s) holding those keys need identifying, erasing and re-writing.
<?xml version="1.0" encoding="UTF-8"?>
<CM VERS="1">
  <TABLE NAME="initd" B="6.3.9.41" B0="6" B1="3" B2="9" B3="41">
    <ROW ID="0">
      <P N="name" T="S">mifd</P>
      <P N="path" T="S">/usr/bin/mifd</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000004</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="1">
      <P N="name" T="S">pkgd</P>
      <P N="path" T="S">/usr/bin/pkgd</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000004</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="2">
      <P N="name" T="S">pkgc</P>
      <P N="path" T="S">/usr/bin/pkgc</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000002</P>
      <P N="runlevel" T="U">0x00000004</P>
      <P N="args" T="M">
        <E N="arg1">00032d5200</E>
        <E N="arg2">000773797374656d00</E>
        <E N="arg3">00032d5400</E>
        <E N="arg4">000433303000</E>
      </P>
    </ROW>
    <ROW ID="3">
      <P N="name" T="S">pkgc</P>
      <P N="path" T="S">/usr/bin/pkgc</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000002</P>
      <P N="runlevel" T="U">0x00000004</P>
      <P N="args" T="M">
        <E N="arg1">00032d5200</E>
        <E N="arg2">0007636f6e66696700</E>
        <E N="arg3">00032d5400</E>
        <E N="arg4">000433303000</E>
        <E N="arg5">00032d4d00</E>
      </P>
    </ROW>
    <ROW ID="4">
      <P N="name" T="S">login</P>
      <P N="path" T="S">/usr/bin/login</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000004</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="5">
      <P N="name" T="S">syslogd</P>
      <P N="path" T="S">/usr/bin/syslogd</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000004</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="6">
      <P N="name" T="S">lmd</P>
      <P N="path" T="S">/usr/bin/lmd</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000005</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="7">
      <P N="name" T="S">nodesd</P>
      <P N="path" T="S">/usr/bin/nodesd</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000006</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="8">
      <P N="name" T="S">dhcpd</P>
      <P N="path" T="S">/usr/bin/dhcpd</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000006</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="9">
      <P N="name" T="S">named</P>
      <P N="path" T="S">/usr/bin/named</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000006</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="10">
      <P N="name" T="S">rpcbind</P>
      <P N="path" T="S">/usr/bin/rpcbind</P>
      <P N="status" T="ENUM">DISABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000006</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="11">
      <P N="name" T="S">pkgc</P>
      <P N="path" T="S">/usr/bin/pkgc</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000002</P>
      <P N="runlevel" T="U">0x00000007</P>
      <P N="args" T="M">
        <E N="arg1">00032d5200</E>
        <E N="arg2">0004616c6c00</E>
        <E N="arg3">00032d5400</E>
        <E N="arg4">000433303000</E>
      </P>
    </ROW>
    <ROW ID="12">
      <P N="name" T="S">rfsd</P>
      <P N="path" T="S">/usr/bin/rfsd</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000007</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="13">
      <P N="name" T="S">httpd</P>
      <P N="path" T="S">/usr/bin/httpd</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000007</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="14">
      <P N="name" T="S">hostapd</P>
      <P N="path" T="S">/usr/bin/hostapd</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000007</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="15">
      <P N="name" T="S">sshd</P>
      <P N="path" T="S">/usr/bin/sshd</P>
      <P N="status" T="ENUM">DISABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000007</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="16">
      <P N="name" T="S">ssdpd</P>
      <P N="path" T="S">/usr/bin/ssdpd</P>
      <P N="status" T="ENUM">DISABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000007</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="17">
      <P N="name" T="S">puckd</P>
      <P N="path" T="S">/usr/bin/puckd</P>
      <P N="status" T="ENUM">DISABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000007</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="18">
      <P N="name" T="S">sntpcd</P>
      <P N="path" T="S">/usr/bin/sntpcd</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000008</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="19">
      <P N="name" T="S">iked</P>
      <P N="path" T="S">/usr/bin/iked</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000008</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="20">
      <P N="name" T="S">cwmd</P>
      <P N="path" T="S">/usr/bin/cwmd</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000001</P>
      <P N="runlevel" T="U">0x00000009</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="21">
      <P N="name" T="S">csd</P>
      <P N="path" T="S">/usr/bin/csd</P>
      <P N="status" T="ENUM">DISABLED</P>
      <P N="type" T="U">0x00000003</P>
      <P N="runlevel" T="U">0x00000009</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="22">
      <P N="name" T="S">fwmond</P>
      <P N="path" T="S">/usr/bin/fwmond</P>
      <P N="status" T="ENUM">DISABLED</P>
      <P N="type" T="U">0x00000003</P>
      <P N="runlevel" T="U">0x00000009</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="23">
      <P N="name" T="S">hotspotd</P>
      <P N="path" T="S">/usr/bin/hotspotd</P>
      <P N="status" T="ENUM">DISABLED</P>
      <P N="type" T="U">0x00000003</P>
      <P N="runlevel" T="U">0x00000009</P>
      <P N="args" T="M"></P>
    </ROW>
    <ROW ID="24">
      <P N="name" T="S">voiced</P>
      <P N="path" T="S">/usr/bin/voiced</P>
      <P N="status" T="ENUM">ENABLED</P>
      <P N="type" T="U">0x00000003</P>
      <P N="runlevel" T="U">0x00000007</P>
      <P N="args" T="M"></P>
    </ROW>
</TABLE>
</CM>

The hex-encoded parameters for /usr/bin/pkgc are:

/usr/bin/pkgc -R system -T 300
/usr/bin/pkgc -R config -T 300 -M
/usr/bin/pkgc -R all -T 300