Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
inbox:d-link:dwr-921_image_cracking [2018/01/31 20:43] – Add info about 0x30 address. chkdsktoh:d-link:dwr-921_image_cracking [2018/06/01 10:41] (current) tmomas
Line 1: Line 1:
 +====== DWR-921 Stock Image Cracking ======
 +~~NOTOC~~
 +
 +{{page>meta:infobox:construction&noheader&nofooter&noeditbtn}}
 +
 +===== FW Image into the flash device =====
 +The layout into the flash device is the following:
 +
 +  0x000000000000-0x000000010000 : "Bootloader"
 +  0x000000010000-0x000000150000 : "Kernel"
 +  0x000000180000-0x000000f10000 : "RootFS"
 +
 +The Kernel partition is formatted by two block:
 +  - Image Header
 +  - Linux lzma image
 +
 +The Image Header provides some informations to the jboot (stock) bootloader to execute the bootstrap of the linux lzma image.
 +
 +The Image Header located in the flash is 0x38 byte long. The Image size is variable and its value is reported in one field of the Image Header.
 +I'm currently able to decode only some field present in the Image Header, but not all.
 +
 +With reference to the oem fw available from dlink DWR-921_RevC_Firmware3.01b07.bin, the Image Header is formatted as described below:
 +
 +  00000000: 04 04 24 2b magic
 +  00000004: 74 77 bd 08 Timestamp : (UTC_TIME-0x35016f00)/4
 +  00000008: 3c de 13 00 size(kernel.bin)+0x28
 +  0000000c: 38 b8         ~jboot_checksum(start value: 0, start address: 0x00000010, length: size(kernel.bin)+0x28) -> jboot_checksum description below
 +  0000000e: 1d ba         ~jboot_checksum(start value: 0, start address: 0x00000000, length: 0x0c) -> jboot_checksum description below
 +  00000010: 24 21 03 02 magic ?
 +  00000014: 00 00 00 80 kernel ram load address
 +  00000018: 14 de 13 00 size(kernel.bin)
 +  0000001c: 7c 61 6e 69 crc32(kernel.bin)
 +  00000020: 00 00 00 80 start ram address 
 +  00000024: 00 00 18 bc root.squashfs flash load address
 +  00000028: 00 a0 75 00 size(root.squashfs)
 +  0000002c: 10 5a e6 1a crc32(root.squashfs)
 +  00000030: fb 8d 6b e6 crc32 (area 0x20 -> 0x37, 0x30->0x33 replaced with zero)* -> see below
 +  00000034: 28 00 00 00 magic 
 +  00000038: 5d 00 00 00 <- 0x38 kernel (in lzma format) start
 +  0000003c: 02 64 27 3a
 +
 +The understanding of the word generation at offset 0x0c and 0x30 shall be enough to generate a firmware image accepted by jboot during the boot process.
 +
 +(*) To calculate crc32 from 0x30 You must set 0x30-0x33 to zero. Example:
 +
 +  00000020: 00 00 00 80  
 +  00000024: 00 00 18 bc 
 +  00000028: 00 a0 75 00 
 +  0000002c: 10 5a e6 1a
 +  00000030: 00 00 00 00
 +  00000034: 28 00 00 00
 +
 +What is jboot_checksum? It make sum of 16-bit data. If counter is above 0xFFFF,  is added extra "1" See c code:
 +
 +<code c>uint16_t checksum(uint16_t start_val, uint16_t *data, int size)
 +{
 +  uint32_t counter;
 +  uint16_t  *ptr;
 +
 +  counter = start_val;
 +  ptr = data;
 +  while ( size > 1 )
 +  {
 +    counter += *ptr;
 +    ++ptr;
 +    while ( counter >> 16 )
 +      counter = (uint16_t) counter + (counter >> 16);
 +    size -= 2;
 +  }
 +  if ( size > 0 )
 +    counter += *(uint8_t *)ptr;
 +  while ( counter >> 16 )
 +    counter = (uint16_t) counter + (counter >> 16);
 +  return counter;
 +}</code>
 +
 +
 +The squashfs rootfs is stored at the (absolute) location provided in the word at offset 0x24:
 +
 +  bc180000: 68 73 71 73 6a 05 00 00 d1 4c f7 57 00 00 02 00  hsqsj....L.W....    <- squashfs signature
 +  bc180010: 41 00 00 00 01 00 11 00 c0 00 01 00 04 00 00 00  A...............
 +  [ ... ]
 +
 +At power on reset the jboot should perform the foolowing operations:
 +  - verify the crc of the kernel and rootfs image
 +  - decompress the lzma image at the location reported in the field at 0x14 or 0x20 in the image
 +  - bootstrap the kernel with cmd line: console=ttyS1,57600n8 root=/dev/mtdblock3
 +
 +  This is the early log from the bootstrap:
 +  
 +  ...................
 +  Starting kernel @80000000...
 +  
 +  LINUX started...
 +  
 +  THIS IS ASIC
 +  Linux version 2.6.36 (tja@localhost.localdomain) (gcc version 4.3.5 (Buildroot 2011.05) ) #19 Thu Jul 7 15:20:08 CST 2016
 +  CMD_LINE:console=ttyS1,57600n8 root=/dev/mtdblock3
 +
 +
 +===== FW Replacement using jboot =====
 +The jboot can be used to replace the fw image. To activate this function it is enough to send a character over the console during the firs seconds of the bootstrap. In this way the standard bootstrap process is interrupted and a web page appears at address 192.168.1.243.
 +This web page can load a "fw update file" and flash the new image accordingly.
 +
 +The "fw update file" have a specific format and can be generated using the dlink binboy tool.
 +
 +The "fw update file" is the concatenation of the following blocks:
 +  - specific file headers (0x50 bytes long)
 +  - kernel headers (almost identical to the one stored in the kernel flash partition) (0x38 bytes long)
 +  - kernel image in lzma format (variable size)
 +  - squashfs rootfs headers (0x50 bytes long)
 +  - squashfs rootfs image (variable size)
 +
 +The file headers should be used to verify the file integrity and authenticity. Indeed jboot refuses the file if it is not properly formatted.
 +
 +Currently the "specific file headers" is completely undecoded.
 +
 +The kernel headers embedded in the "fw update file" is identical to the Kernel Image Header described in the previous section. The only differences is on the first byte: 0xff into the file, 0x04 into the flash.
 +
 +With reference to the oem fw available from dlink DWR-921_RevC_Firmware3.01b07.bin:
 +
 +  [flash kernel partition]      [fw update file] 
 +  00000000: 04 04 24 2b         00000050: ff 04 24 2b
 +  00000004: 74 77 bd 08         00000054: 74 77 bd 08 
 +  00000008: 3c de 13 00         00000058: 3c de 13 00 
 +
 +
 +===== Image Generation flow =====
 +Using the binboy tool found in the [[https://dlink-gpl.s3.amazonaws.com/GPL1500246/DWR-921C1_GPL_V3.00b07_20150724.tar.bz2|GPL Source Code]] is it possible to generate the "fw update file" accepted by the standard jboot bootloader.
 +
 +With reference to the lede distribution, the "fw update file" can be generated in this way:
 +
 +  cp <LEDE_DIR>/build_dir/target-mipsel_24kc_musl/linux-ramips_mt7620/dwr-921-kernel.bin .
 +  mv dwr-921-kernel.bin zImage.lzma
 +
 +  cp <LEDE_DIR>/build_dir/target-mipsel_24kc_musl/linux-ramips_mt7620/root.squashfs .
 +  mv root.squashfs squashfs.o
 +
 +  ./binboy-static @linux
 +  ./binboy-static @rootfs
 +  ./binboy-static @mydlink
 +  ./binboy-static @all
 +  
 +The File generatedconcatenate the kernel lzma compressed, the rootfs and FIXME
 +
 +{{ :media:dlink:dwr-921:dlink_binboy_flow.png?600 |}}
 +
  
  • Last modified: 2018/06/01 10:41
  • by tmomas