V
Visla Hardware
Portal R&D
πŸ”¬ R&D Visla β€” reverse engineering firmware Β· lug 2026

G11L Β«VISLA NOMADΒ» β€” Analisi firmware

Firmware custom Seeworld per il G11L-SE v2 Β· Unisoc + A7670 Cat-1 Β· GT06/Seeworld
πŸ“‚ Folder GitHub β†’
βœ… Config Visla bakeata πŸ”“ customer_app decompresso (LZMA) 🧩 616 comandi πŸ“… build 02 lug 2026

Cos'Γ¨

VISLA NOMAD Γ¨ il firmware custom che Seeworld compila per Visla sul tracker G11L-SE (piattaforma Unisoc/Spreadtrum arom-tiny + modem A7670 Cat-1, protocollo GT06/Seeworld). Questa scheda documenta il reverse engineering del pacchetto customer_app.bin: dov'Γ¨ la config, cosa Γ¨ giΓ  puntato sui server Visla, e cosa si riesce a vedere/modificare.

Risultato chiave: il fornitore ha davvero preconfigurato server GPS e APN Visla (erano invisibili solo perchΓ© l'app Γ¨ compressa LZMA). L'unico parametro ancora Β«cineseΒ» Γ¨ il server OTA β€” motivo per cui abbiamo tirato su ota.vislagps.com.

πŸ”§ Firmware & piattaforma
Versione
VISLA_NOMAD_EUSA_016_V01
Build
2026-07-02
SDK
A131B01V09A7670M6C_ CUS_CZJ_260413
Piattaforma
Unisoc arom-tiny
Modem
A7670 (LTE Cat-1)
App
customer_app.bin
Compressione
LZMA (hdr 8B)
Size
145 KB β†’ 339 KB
Codice
ARM Thumb-2
Base addr
~0x7e1b0000

Parametri di default (bakeati nel firmware)

Blocco config trovato a ~0x4bf00 nel customer_app decompresso.

βœ…
Server GPS gps.vislagps.com:5010

Nostro server (5010 = listener decoder attivo). Il device 186 arriva davvero al decoder.

βœ…
APN iot.1nce.net

APN 1NCE bakeato come default esplicito (NON Γ¨ nella tabella auto-APN generica da 415 operatori).

⚠️
Server OTA / FOTA fota.iotlink.net + http://183.57.42.234:888/…/visla_nomad/70e_lasa/01/track.bin

Ancora il server cinese del fornitore (aika168 / iotlink). Unico parametro non-Visla.

πŸ”Ή
Protocollo GT06 / Seeworld

Comandi in stile `CMD,param#`, ACK a frame binari. Parser con 616 token `#`.

Dump completo del blocco config @ ~0x4bf00

Tutti i default decodificati con certezza (stringhe + porte + mode adiacenti). I campi numerici comportamentali sono uno struct separato a 0x4c070+ non ancora mappato (vedi sotto).

Offset Campo Valore di default
0x4bf14 Server GPS β€” mode 1 (dominio) πŸ”Ή
0x4bf20 Server GPS β€” host gps.vislagps.com βœ…
0x4bf1c Server GPS β€” porta 5010 (0x1392) βœ…
0x4bfac Server OTA β€” mode 1 (dominio) πŸ”Ή
0x4bfb4 Server OTA β€” host fota.iotlink.net ⚠️
0x4bfb0 Server OTA β€” porta 8915 (0x22d3) ⚠️
0x4bffa APN iot.1nce.net βœ…
β€” APN user / pwd (vuoti) βœ…
0x4c1b8 Tag protocollo/FOTA V3_OPEN_JT808 πŸ”Ή
0x4c1ac Codice default 70444 πŸ”Ή
0x4bea2 Default "000000" 000000 (pwd/id?) πŸ”Ή
0x4c231 OTA download URL http://183.57.42.234:888/uploadfile/visla_nomad/70e_lasa/01/track.bin ⚠️
0x4c281 FOTA bin URL http://www.aika168.com/uploadfile/visla_nomad/70e_lasa/01/fota.bin ⚠️
βœ… Visla Β· ⚠️ fornitore (da ripuntare) Β· πŸ”Ή neutro
πŸ“‹ Default comportamentali

Struct numerico @0x4c070+ non ancora mappato. Questi sono i valori documentati nella tabella comandi V2.1 β€” da confermare a bench con PARAM#.

TIMER Intervallo upload (movimento)
10 s
HBT Heartbeat
3 min
DEFENSE Ritardo armamento auto
3 min
GMT Fuso orario
E,8,0
UTC Sync orario
ON
πŸ” Hexdump grezzo del blocco (righe non-zero)
04bea2  30 30 30 30 30 30                                 000000
04bf00  05 00 00 00 00 00 00 00 b4 00 00 00 b4 00 00 00  ................
04bf10  00 00 00 00 01 00 27 61 1e 81 00 00 92 13 00 00  ......'a........
04bf20  67 70 73 2e 76 69 73 6c 61 67 70 73 2e 63 6f 6d  gps.vislagps.com
04bfac              01 01 2f 38 d0 b6 00 00 d3 22 00 00      ../8....."..
04bfb4  66 6f 74 61 2e 69 6f 74 6c 69 6e 6b 2e 6e 65 74  fota.iotlink.net
04bffa  69 6f 74 2e 31 6e 63 65 2e 6e 65 74              iot.1nce.net
04c1b8  56 33 5f 4f 50 45 4e 5f 4a 54 38 30 38           V3_OPEN_JT808
04c231  http://183.57.42.234:888/…/visla_nomad/70e_lasa/01/track.bin
04c281  http://www.aika168.com/…/visla_nomad/70e_lasa/01/fota.bin

πŸ”¬ Reverse engineering (radare2)

Disassembly del customer_app (ARM Thumb-2). La RE mappa la struttura del config; i valori di default stanno in RAM (init al boot) β†’ si leggono col PARAM# a bench e si validano con questi offset.

πŸ“ Ancore RE
Base address
0x7e1b0000
derivato da 16/20 puntatori-stringa
Builder PARAM#
track_read_param_info @ 0x7e1bf354
assembla la risposta PARAM# campo per campo
Config struct
RAM global @ 0x7e20bc58
size > 0x236 B; popolato al boot da NV/default
Codice
ARM Thumb-2
r5 = puntatore base allo struct config
πŸ—ΊοΈ Mappa campi config (verificata)
+0x88 u32 HBT β€” heartbeat
+0x95 u8 Server β€” mode (1=dominio)
+0x9c u32 Server β€” campo porta/flag
+0xe1 u8 Server2 β€” enable
+0x178 u8 APN β€” Auto (0/1)
+0x1f6 i16 UTC β€” sync on/off
+0x1f8 u8 TimeZone β€” segno E/W
+0x1f9 u8 TimeZone β€” valore
+0x236 u16 Defense time β€” ritardo arm
Offset relativi a 0x7e20bc58. Estratti da track_read_param_info.

Cosa si riesce a vedere

Dopo la decompressione LZMA del customer_app.

🟒

Config di default

Completo

Blocco parametri in chiaro: server GPS + porta, APN, server OTA, mode dominio/IP. Leggibili byte-per-byte dopo la decompressione LZMA.

🟒

Tabella comandi

Completo

616 token comando terminati da `#` β€” l'intero parser Seeworld, inclusi comandi interni/non documentati (es. allfactory#, backup#, config,din#) oltre a quelli della tabella ufficiale V2.1.

🟒

Logica allarmi/eventi

Leggibile

Stringhe di stato che rivelano la logica: jamming, collision, acceleration/deceleration, angle, door open/close, fire, SOS, low battery, geofence (Into of fence). Si capisce QUALE evento e COME viene etichettato.

🟑

Formati protocollo

Parziale

Format string (%s,%d) e template dei pacchetti danno la struttura dei frame in uscita, ma i valori numerici (bit di stato, offset campo) vanno dedotti dal codice.

🟠

Algoritmi / soglie

Solo via disasm

La logica vera (soglie IMU, timer, macchine a stati) Γ¨ codice ARM Thumb-2, non stringhe. Serve Ghidra con base ~0x7e1b0000 per leggerla.

Cosa si riesce a modificare

Dal piΓΉ facile (config) al piΓΉ difficile (logica). Nota: il reflash NON Γ¨ l'unica via β€” c'Γ¨ l'override a runtime.

🟒

Runtime β€” nessun reflash

Immediato

Tutto ciò che è già un comando (~62 sul G11L-SE): il valore corrente si cambia via SMS/TCP e resta in NV (cus_data), sopravvive a FACTORY#. È il provisioning standard.

  • β€’Server GPS + porta (SERVER) Β· dual-IP (SERVER2 / DOUBLEIP)
  • β€’APN (APN) Β· server OTA (FOTASVR)
  • β€’Soglie allarmi: ECOLLI, EACCELE, EDECELE, EANGLE, SENLEVEL, JAMALM, POWERALM
  • β€’Comportamento: TIMER, HBT, GMT, DEFENSE, ACCVIRT/DELAYACC, SOS/center
🟑

Patch binario β€” default di fabbrica

Facile β†’ Medio

I VALORI di default nel blocco config (~0x4bf00): patch in-place β†’ ricomprimi LZMA β†’ riscrivi header 8 byte β†’ flash partizione customer_app.

  • β€’Stringhe pari lunghezza (server, APN, OTA URL) β†’ facile, nessun pointer da toccare
  • β€’Numeri (porta, soglie, timer iniziali) β†’ medio, spesso costanti nel codice
  • β€’Testi / label / risposte dei comandi
🟠

Reverse (Ghidra) β€” logica

Difficile

Codice ARM Thumb-2 (base ~0x7e1b0000): leggibile, ma per cambiarlo serve disasm + patch istruzioni + re-checksum. Fattibile ma fragile e non manutenibile.

  • β€’Calcolo allarmi, macchine a stati, timer interni non esposti
  • β€’Logica sleep / risparmio energetico
  • β€’Aggiungere comandi nuovi o cambiare il formato dei pacchetti
πŸ”΄

Off-limits β€” serve Seeworld

No

Fuori portata con una patch: layer chiuso/firmato o senza sorgente. Va chiesto a Seeworld, che ha l'SDK sorgente.

  • β€’Modem / baseband: cp.bin, dsp.bin, rf.bin (firmato)
  • β€’Bootloader / SDK di sistema in modo strutturale
  • β€’Ricompilare pulito da sorgente: non abbiamo l'SDK
  • β€’Feature nuove complesse (MQTT nativo, nuovo protocollo)

πŸ”“ Ricetta: decomprimere customer_app.bin

L'app Γ¨ un header di 8 byte (ca380200 + crc) seguito da uno stream LZMA-alone (props 0x5d, dict 8 MB).

import lzma
raw = open('customer_app.bin','rb').read()
app = lzma.decompress(raw[8:], format=lzma.FORMAT_ALONE)
# 145.618 β†’ 338.936 byte, raw ARM Thumb-2
# Ghidra: ARM Cortex little-endian Thumb, base ~0x7e1b0000
# config block @ ~0x4bf00: server / porta / APN / OTA

πŸ“‘ Flusso OTA Visla

  1. FOTASVR,1,ota.vislagps.com,80# β€” punta il server OTA su Visla (override del default cinese), oppure
  2. FOTASTART,http://ota.vislagps.com/visla_nomad/track.bin# β€” trigger con URL completo esplicito
  3. otastart# β€” download + flash dal server configurato
  4. FACTORY# β€” reset finale (NON tocca IP+APN)

Server OTA Visla: nginx su GKE (ns firmware-ota) dietro Cloudflare Tunnel. File servito: /visla_nomad/track.bin.

🧩 Contenuto del pacchetto (line-flash)

customer_app
app + config (LZMA)
firmware.bin / system.img
SDK + modem stack
cp.bin / dsp.bin / rf.bin
modem / DSP / RF
nvm / cus_data
config runtime (persistente)
fota_param.bin
stato OTA

Flash via Unisoc ResearchDownload (Windows) β†’ download.json. nvm/cus_data NON sono nel pacchetto β†’ sopravvivono a reflash e FACTORY#.

πŸ“Œ Note

  • Patch diretta dei default = solo con re-LZMA + re-header; per modifiche di prodotto conviene farle bakeare a Seeworld (hanno l'SDK sorgente).
  • La tabella auto-APN generica (415 operatori) NON contiene 1NCE β†’ serviva il default esplicito, che c'Γ¨.
  • Changelog build 20260702: modifica alla logica allarme vibrazione (unico update dichiarato rispetto a 20260603).
  • Unico gap verso Visla: il server OTA. Richiesta mirata a Seeworld = ripuntare solo l'OTA URL su ota.vislagps.com.