Share
## https://sploitus.com/exploit?id=24FDC459-E0B3-5930-B2F8-E3ECD2C919F7
# CZeView / Meari Camera โ€” Root & Firmware Research

Reverse engineering and root shell exploit research for **CZeView** (Meari/CloudEdge platform) battery IP cameras. Includes fully reversed SD card OTA firmware format (STRN), XOR encryption, flash partition map, and custom firmware builder.

**Status: Work in progress** โ€” SD card OTA flashing confirmed working, squashfs rebuild blocked by vendor-modified XZ compression.

## Device Info

| Field | Value |
|-------|-------|
| **Brand** | CZeView (CloudEdge/Meari platform) |
| **SoC** | Ingenic T23 (MIPS XBurst) |
| **Board** | SNB24T_T22_V10_MIS5 |
| **Flash** | 8 MB SPI NOR |
| **WiFi** | ESP32 SDIO module |
| **Power** | Battery (sleeps when idle) |
| **Kernel** | Linux 3.10.14-Archon (LZ4 compressed uImage) |
| **Firmware** | 6.1.3.20250530 (firmware-B411B-m_general) |
| **UART** | 115200 baud, ttyS1, 3.3V |
| **Platform** | Meari/CloudEdge (com.cloudedge.smarteye) |
| **P2P** | PPPP protocol |
| **Main binary** | ppsapp (1.75 MB, MIPS LE ELF) |

## What's Been Done

### SD Card OTA Format โ€” Fully Reversed

The STRN firmware format was completely reverse-engineered from MIPS disassembly of `ppsapp_czeview`. We can build valid SD card OTA packages that the camera accepts and flashes.

**Confirmed working**: First flash attempt succeeded โ€” no errors, marker file consumed, camera rebooted with new app partition.

See [CZEVIEW_FIRMWARE_REFERENCE.md](CZEVIEW_FIRMWARE_REFERENCE.md) for full format documentation.

### Key Discoveries

- **No firmware signing** โ€” only byte-sum checksums, no RSA/EC signatures
- **XOR "encryption"** โ€” trivially reversible, 16-byte key embedded in binary
- **SD card upgrade** โ€” any firmware with valid STRN format is accepted
- **No SSL pinning** โ€” DNS spoof attacks viable for OTA hijacking
- **Command injection** โ€” properties 54, 9999, 107 accept unsanitized input
- **Backdoor hook exists** โ€” `initrun.sh` already checks for `/app/init/initrun_custom.sh`

### What's Blocking Root

The app partition uses **SquashFS 4.0 with vendor-modified XZ compression**. The LZMA2 data inside is standard, but the XZ container format is modified โ€” standard tools (`unsquashfs`, `sasquatch`) fail on ~15% of data blocks with "xz uncompress failed with error code 9".

We can extract 34 of 39 files. The 5 that fail include critical libraries (`libstdc++.so`, `libaudioProcess.so`). Without these, the camera won't boot. This prevents rebuilding the squashfs with backdoor files added.

**Possible paths forward:**
1. Custom firmware (Thingino/OpenIPC) โ€” bypass vendor squashfs entirely
2. UART root shell โ€” most reliable, needs physical access to test pads
3. Binary-patch the squashfs โ€” modify compressed blocks in-place (complex)
4. `mksquashfs -append` โ€” add files without touching existing blocks

## SPI Flash Layout

```
Offset      Size     MTD  Name     Format
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
0x000000    256K     0    uboot    U-Boot bootloader
0x040000    352K     1    tag      Device tags/info
0x098000     32K     2    enc      Encryption keys
0x0A0000    2.5M     3    kernel   uImage (LZ4)
0x320000   1.375M    4    rootfs   Compressed (magic 0xFBE31200)
0x480000      3M     5    app      SquashFS 4.0 (XZ)
0x780000    448K     6    cfg      jffs2 (/home/cfg)
0x7F0000     64K     7    setup    Config
```

## STRN OTA Format (Summary)

```
Header (64 bytes, XOR-encrypted):
  [0:4]   magic         0x5354524E ("STRN")
  [4:8]   checksum      byte_sum(plaintext[12:meta_len])
  [8:12]  meta_len      num_entries * 128 + 64
  [12:16] num_entries
  [28]    pkg_version   >= 4 required; >= 5 enables data encryption
  [29-31] version       major.minor.revision
  [32:34] platform      87

Partition entries (128 bytes each, XOR-encrypted):
  [0x04]  name          null-terminated ASCII
  [0x64]  version       major.minor.revision (3 bytes)
  [0x68]  data_offset   absolute offset in file
  [0x6C]  data_size
  [0x70]  data_checksum byte_sum(plaintext_data)

Data (XOR-encrypted if pkg_version >= 5):
  Raw partition data, each encrypted from key index 0
```

**XOR key** (16 bytes from ppsapp at 0x54F6A0):
```
BA CD BC FE D6 CA DD D3 BA B9 A3 AB BF CB B5 BE
```

**XOR index**: `key_idx = (i + (i // 16)) % 16`

## Scripts

### `build_upgrade_firmware.py`

Builds `upgrade-for-factory.bin` from a modified flash image. Handles XOR encryption, checksums, and partition entries. Includes built-in verification.

```
python build_upgrade_firmware.py
# Output: upgrade-for-factory.bin
# Copy to SD card with empty G0K5G1TS marker file, power cycle camera
```

### `sqfs_extract_v2.py`

Custom squashfs parser and extractor. Handles the vendor-modified XZ by stripping the XZ container and decompressing raw LZMA2 streams. Extracts 34/39 files successfully.

```
python sqfs_extract_v2.py
# Output: sqfs_full_extract/ directory with extracted files
```

### PoC Scripts

| Script | Description |
|--------|-------------|
| `poc_attack_chain.py` | Combined 8-attack chain |
| `poc_dns_firmware_hijack.py` | DNS spoof + ARP + fake OTA server |
| `poc_pppp_p2p.py` | PPPP P2P client implementation |
| `poc_p2p_connect.py` | Full P2P connection with relay + wake + MQTT |
| `pppp_decode_initstring.py` | P2P initstring decoder (working) |
| `camera_control.py` | CLI tool: LED, sensitivity, detection config |

## Boot Flow

```
1. U-Boot loads kernel from MTD3
2. Kernel mounts rootfs (MTD4), then app squashfs (MTD5) at /app
3. /app/init/initrun.sh runs:
   a. Create /dev/esps0 for ESP32 WiFi
   b. Mount jffs2 cfg โ†’ /home/cfg
   c. Start ppsapp (main camera process)
   d. Symlink libraries from /app/lib โ†’ /lib
   e. Load pps_devlink.ko kernel module
   f. Run /app/init/initrun_custom.sh if it exists  โ† backdoor hook
```

## Hardware Notes

### UART

- **Baud**: 115200
- **Port**: ttyS1
- **Voltage**: 3.3V (DO NOT use 5V)
- Most reliable path to root shell

### SPI Programmer

- CH341A USB programmer + SOIC-8 clip
- Read first, verify twice before writing
- **Lesson learned**: Second flash attempt bricked the camera (app partition erased to 0xFF, write interrupted)

### P2P Protocol

- PPPP protocol with initstring containing relay server IPs
- Servers alive: 112.74.108.149, 54.84.37.235, 54.254.195.28
- AJCloud relays: 97.107.140.113:60722, 167.172.230.224:60722
- Camera sleeps (battery) โ€” `P2P_REQ` returns 0xFD when not registered

## Related Projects

- [jooan-ja-a52-root](https://github.com/rickdeboer1987/jooan-ja-a52-root) โ€” Root exploit for Jooan JA-A52 camera (same Ingenic T23 SoC family, different platform)

## Disclaimer

This research was performed on personally owned hardware for educational and security research purposes. Do not use these tools on devices you do not own.