Pular para o conteúdo
Fux da Sec
← voltar

Formato de firmware IMAGEWTY: estrutura e análise

·8 min·por Fux

Exploração técnica do formato de firmware IMAGEWTY, da sua estrutura e dos componentes que o formam.

O formato IMAGEWTY é usado pelas ferramentas LiveSuit, PhoenixSuit, PhoenixUSB e PhoenixCard, todas de código fechado, assim como seus protocolos e padrões.


Ferramentas de extração e repack

  • imgRePacker (Windows) Só funcionou no Windows, apesar de existir versão para Linux. Não conseguiu processar imagens com header 0x403.

  • imagewty-tool (Linux) Funcional e ainda em desenvolvimento. Testado com sucesso em imagens com headers 0x300 e 0x403.

  • AWUtils (Linux) Desatualizada, e a extração não funcionou como esperado (bugs).


Estrutura básica

O layout básico de uma imagem no formato IMAGEWTY pode ser representado assim:

Esta estrutura permite criar uma imagem válida mesmo sem os dados aleatórios (garbage) presentes nas imagens tradicionais. Numa visualização hexadecimal dá para observar dados adicionais de propósito desconhecido.

PLAINTEXT
+------------------------------+
| Global Header (96 bytes)     |
+------------------------------+
| Garbage / Unused (928 bytes) |
+------------------------------+
| File Header #1 (1024 bytes)  |
+------------------------------+
| File Header #2 (1024 bytes)  |
+------------------------------+
| File Header #3 (1024 bytes)  |
+------------------------------+
| ...                          |
+------------------------------+
| File Header #48 (1024 bytes) |
+------------------------------+
|                              |
|   File Data #1               |
|   (size varies)              |
|                              |
+------------------------------+
|                              |
|   File Data #2               |
|   (size varies)              |
|                              |
+------------------------------+
| ...                          |
+------------------------------+
|                              |
|   File Data #48              |
|   (size varies)              |
|                              |
+------------------------------+

A imagem é composta por um header global, seguido dos headers individuais de cada arquivo e, por fim, dos arquivos em si.

No exemplo, a ilustração contém 48 arquivos, cada um com seu respectivo header.


Header global

Embora o header tenha 96 bytes, apenas 68 bytes são de fato usados. A estrutura é esta:

PLAINTEXT
+---------+-----------+----------------------------------------+
| Offset  | Size       | Field / Description                   |
+---------+-----------+----------------------------------------+
| 0x00    | 8 bytes    | Magic / Signature ("IMAGEWTY")        |
| 0x08    | 4 bytes    | Header Version                        |
| 0x0C    | 4 bytes    | Header Size                           |
| 0x10    | 4 bytes    | Base RAM                              |
| 0x14    | 4 bytes    | Format Version                        |
| 0x18    | 4 bytes    | Total Image Size (compressed)         |
| 0x1C    | 4 bytes    | Header Size Including Alignment       |
| 0x20    | 4 bytes    | File Header Length                    |
| 0x24    | 4 bytes    | USB Product ID                        |
| 0x28    | 4 bytes    | USB Vendor ID                         |
| 0x2C    | 4 bytes    | Hardware ID                           |
| 0x30    | 4 bytes    | Firmware ID                           |
| 0x34    | 4 bytes    | Unknown Field #1                      |
| 0x38    | 4 bytes    | Unknown Field #2                      |
| 0x3C    | 4 bytes    | Number of Files in Archive            |
| 0x40    | 4 bytes    | Unknown Field #3                      |
| 0x44…   | padding    | Zeros to align to Header Size (96 B)  |
+---------+-----------+----------------------------------------+

O header começa com a assinatura de 8 bytes “IMAGEWTY”. Os campos restantes são armazenados em blocos de 4 bytes, totalizando 68 bytes de dados reais. Os 28 bytes extras e a área de garbage de 928 bytes podem ser preenchidos com zeros.

96 bytes

Offset: de 0x000 a 0x3FF — inclui os 96 bytes de header e os 928 bytes de garbage, totalizando 1024 bytes. Depois disso, os headers dos arquivos começam no offset 0x400.


Valores esperados

Valores presentes no header global da imagem de exemplo:

PLAINTEXT
Magic / Signature    = "IMAGEWTY"
Header Version       = 0x300      (v3)
Header Size          = 0x60       (96 Bytes)
Base RAM             = 0x4D00000
Format Version       = 0x100234
Total Size           = 0xA34B3800 (2,612.70 MB)
Header + Alignment   = 0x0        (0)
File Header Length   = 0x400      (1024 Bytes)
USB Product ID       = 0x1234
USB Vendor ID        = 0x8743
Hardware ID          = 0x100
Firmware ID          = 0x100
Unknown Field #1     = 0x1        (1)
Unknown Field #2     = 0x400      (1024)
Number of Files      = 0x30       (48)
Unknown Field #3     = 0x400      (1024)

Como o arquivo é little-endian, os dados podem aparecer de outra forma quando vistos em hexadecimal.

  • Header Size → tamanho do header global
  • File Header Length → tamanho de cada header de arquivo
  • Number of Files → total de arquivos na imagem

Headers dos arquivos

O primeiro header de arquivo começa no offset fixo 0x400, logo depois dos 1024 bytes do header global com o garbage.

Todos os arquivos seguem a mesma estrutura de header, com a maioria dos valores mudando muito pouco:

PLAINTEXT
+------------+--------+----------------------+
| Offset     | Size   | Field                |
+------------+--------+----------------------+
| 0x400      | 4 B    | Filename Length      |
| 0x404      | 4 B    | Header Size          |
| 0x408      | 8 B    | Maintype             |
| 0x410      | 16 B   | Subtype              |
| 0x420      | 4 B    | Unknown0             |
| 0x424      | 256 B  | Filename             |
| 0x524      | 4 B    | Stored Length        |
| 0x528      | 4 B    | Pad #1               |
| 0x52C      | 4 B    | Original Length      |
| 0x530      | 4 B    | Pad #2               |
| 0x534      | 4 B    | File Offset          |
| 0x538-0x7FF| 456 B  | Garbage / Padding    |
+------------+--------+----------------------+
  • Filename Length → tamanho do nome do arquivo
  • Header Size → tamanho deste header de arquivo (normalmente 1024 bytes)
  • Maintype → tipo principal (ex.: "COMMON")
  • Subtype → subtipo (ex.: "BOARD_CONFIG_BIN")
  • Filename → nome do arquivo, preenchido com nulos (ex.: boot.fex)
  • Stored Length → tamanho armazenado do arquivo (com padding)
  • Original Length → tamanho real do arquivo (sem padding)
  • File Offset → posição inicial dos dados do arquivo

Valores esperados (exemplo: sys_config.fex)

PLAINTEXT
Filename Length     = 0x100 (256)
File Header Size    = 0x400 (1024)
Maintype            = "COMMON  "
Subtype             = "SYS_CONFIG100000"
Unknown             = 0x0 (0)
Filename            = "sys_config.fex"
Stored Length       = 0x800 (2048)
Pad #1              = 0x0 (0)
File Length         = 0x7BF (1983)
Pad #2              = 0x0 (0)
File Offset         = 0xD800 (55296)
  • Stored Length → tamanho do arquivo incluindo o padding
  • File Length → tamanho real do arquivo, sem padding
  • File Offset → posição inicial do arquivo dentro da imagem

Header de arquivo preenchido com garbage


Visão geral

Nos testes que fiz, imagens geradas com o imagewty-tool e gravadas com o PhoenixSuit não apresentaram nenhum erro.

PLAINTEXT
+------------------------------+
| Global Header (96 bytes)     |
+------------------------------+
| Garbage / Unused (928 bytes) |
+------------------------------+
| File Header #1 (1024 bytes)  |  <- starts at offset 0x400
+------------------------------+
| File Header #2 (1024 bytes)  |
+------------------------------+
| File Header #3 (1024 bytes)  |
+------------------------------+
| ...                          |
+------------------------------+
| File Header #48 (1024 bytes) |
+------------------------------+
|                              |
|   File Data #1               |
|   (size varies)              |
|                              |
+------------------------------+
|                              |
|   File Data #2               |
|   (size varies)              |
|                              |
+------------------------------+
| ...                          |
+------------------------------+
|                              |
|   File Data #48              |
|   (size varies)              |
|                              |
+------------------------------+

Por enquanto, recomendo a leitura de:

Também pode ser útil:


Próximo post

No próximo post vou tratar dos arquivos extraídos da imagem e de como modificá-los, como o boot.fex e o super.fex.

PLAINTEXT
$ lsarisc.fex          dlinfo.fex         sys_config.fex     Vboot-resource.fex
aultls32.fex       dtbo.fex           sys_partition.fex  Vdtbo.fex
aultools.fex       env.fex            toc0.fex           vendor_boot.fex
board.fex          fes1.fex           toc1.fex           Venv.fex
boot0_nand.fex     misc.fex           u-boot-crash.fex   Vmisc.fex
boot0_sdcard.fex   Reserve0.fex       u-boot.fex         vmlinux.fex
boot.fex           split_xxxx.fex     usbtool_crash.fex  VReserve0.fex
boot_package.fex   sunxi.fex          usbtool.fex        Vsuper.fex
boot-resource.fex  sunxi_gpt.fex      vbmeta.fex         Vvbmeta.fex
cardscript.fex     sunxi_mbr.fex      vbmeta_system.fex  Vvbmeta_system.fex
cardtool.fex       sunxi_version.fex  vbmeta_vendor.fex  Vvbmeta_vendor.fex
config.fex         super.fex          Vboot.fex          Vvendor_boot.fex