Skip to content

TryExceptElseFinally/WITRN_binary

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 

Repository files navigation

WITRN Binary

Reverse Engineering for WITRN products binary firmware

Intro

For WITRNUP.exe, WITRN uses commercial grade ".NET Reactor" for obfuscation. We may never know correct symbol names nor be able to debug. All results are based on static analysis.

This repository contains only the analysis of binary file headers, as all WITRN products use a custom 2nd bootloader rather than a generic format for any microcontroller, binwalk helps nothing and so am I :(

Decrypt

WITRN uses a fixed mapping table to encrypt the firmware binary file.

MAPPING_TABLE = [26, 182, 183, 241, 123, 140, 213, 60, 124, 144, 210, 244, 53, 242, 27, 233, 219, 18, 119, 91, 61, 127, 63, 189, 45, 71, 42, 80, 220, 195, 255, 87, 130, 131, 96, 252, 155, 78, 136, 208, 0, 95, 46, 89, 43, 249, 198, 56, 240, 200, 142, 128, 68, 253, 115, 126, 11, 41, 25, 175, 216, 150, 113, 179, 98, 230, 229, 17, 145, 156, 70, 21, 196, 194, 165, 82, 185, 102, 172, 178, 34, 83, 238, 84, 170, 180, 116, 207, 176, 108, 114, 167, 146, 90, 86, 231, 133, 236, 193, 159, 206, 110, 174, 59, 120, 143, 93, 75, 226, 100, 12, 76, 19, 99, 192, 65, 79, 186, 228, 16, 4, 166, 62, 49, 225, 184, 72, 103, 5, 211, 152, 105, 191, 54, 101, 190, 6, 81, 92, 199, 139, 9, 55, 197, 169, 168, 112, 212, 135, 29, 218, 13, 243, 118, 48, 173, 23, 148, 224, 177, 20, 237, 14, 8, 66, 154, 51, 181, 85, 217, 69, 57, 227, 125, 77, 1, 203, 39, 239, 37, 106, 58, 122, 121, 109, 22, 64, 97, 164, 2, 171, 134, 15, 52, 111, 235, 107, 247, 40, 222, 163, 204, 117, 44, 202, 94, 129, 10, 250, 104, 248, 7, 3, 36, 205, 31, 162, 47, 50, 67, 157, 245, 215, 188, 158, 187, 73, 74, 214, 138, 132, 161, 33, 223, 151, 254, 32, 209, 30, 147, 28, 141, 251, 38, 24, 149, 246, 201, 221, 234, 153, 35, 232, 160, 88, 137]

data_array = bytearray(data)
data_length = len(data_array)
decrypted_array = bytearray(data_length)

for i in range(data_length):
	decrypted_array[i] = MAPPING_TABLE[data_array[i]]

Header

[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct Header
{
	[FixedBuffer(typeof(byte), 7)]
	public Header.MagicFixedBuffer magic;

	public ushort year;

	public byte month;

	public byte day;

	[FixedBuffer(typeof(byte), 9)]
	public Header.ReversedFixedBuffer reversed;

	public UUID uuid;

	public uint size;

	public uint xor_checksum;

	public uint add_checksum;
    
	[CompilerGenerated]
	[UnsafeValueType]
	[StructLayout(LayoutKind.Sequential, Size = 7)]
	internal struct MagicFixedBuffer
	{
		public byte FixedElementField;
	}

	[UnsafeValueType]
	[CompilerGenerated]
	[StructLayout(LayoutKind.Sequential, Size = 9)]
	internal struct ReversedFixedBuffer
	{
		public byte FixedElementField;
	}
}

Field

  1. magic

    Length: 7 bytes

    Value:

    • Hex: 67 7A 75 74 61 70 70
    • ASCII: gzutapp

    Note: "GZUT", "Guangzhou Youshuo Microelectronics Technology Co., Ltd.", "广州市优硕微电子科技有限公司", has close ties with WITRN, and GZUT holds partial of the “WITRN” trademark.

  2. year

    Length: 2 bytes

    Value: The year of the date when this firmware was built (or packaged). Example:

    • Hex: E9 07
    • ASCII: 2025
  3. month

    Length: 1 byte

    Value: The month of the date when this firmware was built (or packaged). Example:

    • Hex: 08
    • ASCII: 08
  4. day

    Length: 1 byte

    Value: The day of the date when this firmware was built (or packaged). Example:

    • Hex: 15
    • ASCII: 15
  5. reversed

    Length: 9 bytes

    Value: Filled with 7F

  6. uuid

    Length: 16 bytes

    Value: Struct. Contains a UUID, where each UUID refers to a WITRN product. See below.

  7. size

    Length: 2 bytes

    Value: Size of the firmware body (excluding header size (48 bytes))

  8. xor_checksum

    Length: 2 bytes

    Value: Firmware body (excluding header) XOR checksum

  9. add_checksum

    Length: 2 bytes

    Value: Firmware body (excluding header) ADD checksum

UUID

[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct UUID
{
	public uint uuid_1;

	public ushort uuid_2;

	public ushort uuid_3;

	[FixedBuffer(typeof(byte), 8)]
	public UUID.uuid_4FixedBuffer uuid_4;

	[UnsafeValueType]
	[CompilerGenerated]
	[StructLayout(LayoutKind.Sequential, Size = 8)]
	internal struct uuid_4FixedBuffer
	{
		public byte FixedElementField;
	}
}

UUID is a mapping list. Each UUID corresponds to a WITRN product. For example

KNOWN_MODELS = {
    "A3DC1BC1-8FD1-4374-85B9-FC9A2650FDDA": "WITRN W96D",
    "B793053A-236B-4F99-A6E1-5A48A08B86D1": "WITRN U3"
}

Can find UUID in MeterUP.exe. There's no chaos there :D

Version

WITRN does not define Version in header, but some place within the firmware.

VERSION_OFFSET = 48 + 2048

The upper 4 bits of this byte (8 bit) value is major version, lower 4 bits is minor version.

Demo

Of course there's a Python demo :D (demo.py)

About

Reverse Engineering for WITRN products binary firmware

Resources

Stars

Watchers

Forks

Languages