# Cílená statická analýza protokolu CFL-605RT

## Výsledek

Statická analýza uzavřela geometrii, souřadnice, výběr nástroje, profilové hodnoty a epilog omezené první řezací úlohy. Neuzavřela životní cyklus systémového spojení RAW TCP ani bajty před prvním datovým zápisem. První bezpečný POC proto ještě vyžaduje jedinou cílenou síťovou sondu pro každou z těchto dvou mezer.

Analýza nespustila žádnou binárku Windows, neinstalovala ovladač, nekontaktovala plotr a neprovedla USB ani ethernetový záznam. Ghidra 12.1.2 načetla pouze `MMKPLT.dll` a `mpmserv_1.dll` do dočasného projektu mimo Git.

## Analyzované moduly

| Modul | SHA-256 | Relevantní sekce |
| --- | --- | --- |
| `payload/Printer_amd64/MMKPLT.dll` | `611da823f97b5f83afa94c28e8b705c61b7cce44d72ab14478a077e0c1029712` | `.text` VA `0x6a901000`, velikost `0x28f3d`; `.data` VA `0x6a92a000`; `.pdata` VA `0x6a931000` |
| `payload/PortMonitor_amd64/mpmserv_1.dll` | `3dde1e24123f4803ae66a6315f87fa9ec447a23dcbb0e2432d2b9b5d9038ad1d` | `.text` VA `0x180001000`, velikost `0x3f37`; `.data` VA `0x180005000`, velikost `0x200` |
| `payload/Printer_amd64/CFLJJ.PCD` | `15e8fe9037d518f09dee5f12e928def5f3deb04da662731e58cb905ccd723d51` | textová konfigurace: `MODEL=11`, `CUTTING=1`, `PENNOMAX=6`, `PAGEINIT=IN;`, `COMMAND MGL-IIc=1` |

## Q01 — životní cyklus TCP spojení

**Modul a místo:** `mpmserv_1.dll`, SHA-256 `3dde1e24123f4803ae66a6315f87fa9ec447a23dcbb0e2432d2b9b5d9038ad1d`, export `InitializePrintMonitor2` na `0x180001698` v `.text` a tabulka `MONITOR2` na `0x180005140` v `.data`.

**Pozorované bajty a tok:** Tabulka začíná bajty `b0 00 00 00 00 00 00 00 20 23 00 80 01 00 00 00 14 17 00 80 01 00 00 00 00 00 00 00 00 00 00 00`. Hodnota `cbSize=0xb0` a pořadí struktury `MONITOR2` mapují tyto callbacky:

| Posun tabulky | Callback | Adresa |
| ---: | --- | ---: |
| `+0x08` | `EnumPorts` | `0x180002320` |
| `+0x10` | `OpenPort` | `0x180001714` |
| `+0x18` | `OpenPortEx` | `NULL` |
| `+0x20` | `StartDocPort` | `0x180001794` |
| `+0x28` | `WritePort` | `0x180001bf8` |
| `+0x30` | `ReadPort` | `0x180002468` |
| `+0x38` | `EndDocPort` | `0x180001e04` |
| `+0x40` | `ClosePort` | `0x180001f94` |

`StartDocPort` začíná bajty `48 89 5c 24 10 48 89 6c 24 18 48 89 74 24 20 57 41 54 41 55 41 56 41 57 48 83 ec 60`. Rozlišuje vlastní cesty `MIMAKI FILE2`, `MIMAKI1394` a lokální zařízení, jejich cestu otevře přes `CreateFileW`. `WritePort` na `0x180001bf8` předává přijatý buffer beze změny do `WriteFile`. `EndDocPort` na `0x180001e04` dopíše pouze vlastní 1394 buffer, volá `FlushFileBuffers` a `CloseHandle` a žádný protokolový bajt nepřidává. `ClosePort` tvoří bajty `b8 01 00 00 00 c3` a nic dalšího nedělá.

**Závěr:** Vlastní port-monitorová cesta `MPMSERV_1.dll` nemá handshake, transformaci proudu ani vlastní síťový transport. `OpenPortEx=NULL` zároveň nedokládá delegaci do systémového monitoru. Ručně zvolenou konfiguraci S02 obsluhuje systémový Standard TCP/IP Port Monitor, jehož počet spojení, hranici jedné úlohy a okamžik zavření archivované moduly neobsahují.

**Jistota:** vysoká pro vlastní callbacky `MPMSERV_1.dll`; nízká pro životní cyklus ručně zvoleného systémového RAW TCP portu. Q01 zůstává otevřená.

## Q02 — handshake a první síťový bajt

**Modul a místo:** `mpmserv_1.dll`, SHA-256 `3dde1e24123f4803ae66a6315f87fa9ec447a23dcbb0e2432d2b9b5d9038ad1d`, `ReadPort` na `0x180002468` v `.text`; `MMKPLT.dll`, SHA-256 `611da823f97b5f83afa94c28e8b705c61b7cce44d72ab14478a077e0c1029712`; `CFLJJ.PCD`, SHA-256 `15e8fe9037d518f09dee5f12e928def5f3deb04da662731e58cb905ccd723d51`, s `PAGEINIT=IN;`.

**Pozorované bajty a tok:** Celý vlastní `ReadPort` tvoří `41 83 21 00 b8 01 00 00 00 c3`. Funkce zapíše do `*pcbRead` nulu a vrátí `TRUE`. `StartDocPort` vlastní cesty nečte před prvním zápisem a `WritePort` data nemění. Modelová konfigurace vkládá do spoolovacího proudu `IN;`.

**Závěr:** Vlastní cesta `MPMSERV_1.dll` před daty nečte a nepřidává handshake. Tento závěr nelze přenést na ručně zvolený systémový Standard TCP/IP Port Monitor. Statická analýza proto nepotvrzuje, zda je prvním síťovým bajtem `I` z `IN;`, ani zda systémová cesta před prvním zápisem očekává odpověď.

**Jistota:** vysoká pro vlastní cestu `MPMSERV_1.dll`; nízká pro první bajt systémové RAW TCP cesty. Q02 zůstává otevřená.

## Q03 — epilog omezené první úlohy

**Modul a místo:** `MMKPLT.dll`, SHA-256 `611da823f97b5f83afa94c28e8b705c61b7cce44d72ab14478a077e0c1029712`, tabulka `DRVFN` na `0x6a92fe50` v `.data`, `DrvEnableDriver` na `0x6a902b88`, `DrvSendPage` na `0x6a909a9c`, `DrvEndDoc` na `0x6a909a38` a zapisovací funkce `0x6a905294` a `0x6a90533c` v `.text`.

**Pozorované bajty a tok:** `DrvEnableDriver` vrací verzi `0x20000`, 25 položek a ukazatel na tabulku. Položky `iFunc=0x20`, `0x21`, `0x22` a `0x23` ukazují postupně na `0x6a909a9c`, `0x6a9092ec`, `0x6a909a38` a `0x6a907ab8`. Ve veřejné struktuře `winddi.h` odpovídají funkcím `DrvSendPage`, `DrvStartPage`, `DrvEndDoc` a `DrvStartDoc`.

`DrvSendPage` začíná bajty `48 8b c4 48 89 58 10 48 89 68 18 48 89 70 20 57 48 83 ec 40`. Pro `MODEL=11`, `COMMAND MGL-IIc` a vypnuté rozšířené přesuny stránky vede obyčejná větev na řetězec `PUSP0;` na `0x6a901908`, délku 6 a následné volání `0x6a90533c(..., 9)`. Větev modelu 11 přeskočí kandidát `;JE;` na `0x6a90193c`. `DrvEndDoc` běžné větvi žádné další bajty nepřidá.

**Závěr:** Omezená první úloha končí přesně bajty `PUSP0;`, tedy zdvihem nástroje a volbou `SP0`, a následným flush spoolovacího bufferu. Závěr platí pouze pro `MODEL=11`, jeden běžný list a bez rozšířeného posunu nebo podávání stránky.

**Jistota:** vysoká. Q03 je pro takto omezený POC uzavřená.

## Q04 — pohyb bez řezu a s řezem

**Modul a místo:** `MMKPLT.dll`, SHA-256 `611da823f97b5f83afa94c28e8b705c61b7cce44d72ab14478a077e0c1029712`, dispečery `0x6a913324`, `0x6a913488` a `0x6a913544`, modelová funkce `0x6a911f38` a řetězce na `0x6a901c44` až `0x6a901c54` v `.text`.

**Pozorované bajty a tok:** Dispečer začátku kontury `0x6a913324` začíná `48 83 ec 38 48 8b 81 70 0a 00 00 83 b9 18 09 00 00 01`. Dispečer řezného bodu `0x6a913488` začíná `48 83 ec 38 48 8b 81 70 0a 00 00 41 b9 01 00 00 00`. Oba pro modelovou hodnotu `0x0b` pokračují přes větev `<0x15` do `0x6a911f38`.

Funkce `0x6a911f38` používá řetězce `PU` na `0x6a901c44`, `PD` na `0x6a901c4c`, `PA` na `0x6a901c50` a `PR` na `0x6a901c54`. Start nebo přesun bez řezu emituje `PU`, absolutní režim `PA` a dvojici podepsaných desítkových souřadnic. Řezný bod emituje `PD`, `PA` a stejnou dvojici. Relativní větev emituje `PD`, `PR` a rozdíly souřadnic. Bajty `45 50` na `0x6a901c48` jsou `EP`, nikoli `PD`.

**Závěr:** Minimální absolutní geometrie používá `PU` + `PAx,y` pro pohyb bez řezu a `PD` + `PAx,y` pro pohyb s řezem. Souřadnice jsou podepsaná desítková celá čísla oddělená čárkou. Ovladač mezi těmito mnemoniky nevkládá středník.

**Jistota:** vysoká. Q04 je uzavřená.

## Q05 — jednotky, počátek a osy

**Modul a místo:** `MMKPLT.dll`, SHA-256 `611da823f97b5f83afa94c28e8b705c61b7cce44d72ab14478a077e0c1029712`, `0x6a911f38` v `.text`; veřejný zdroj S01 pro `GDP UNIT` a plochu 610 × 510 mm; S02 pro počátek vlevo dole.

**Pozorované bajty a tok:** Při `context+0xdb8 == 0` funkce ukládá `x_cmd=x_gdi` a `y_cmd=page_height-y_gdi`. Varianty rotace 1 až 3 osy prohazují nebo invertují. Funkce `0x6a9051e0` serializuje výsledné hodnoty jako podepsaná desítková celá čísla. Ovladač dostává už kvantované souřadnice GDI; neprovádí převod z milimetrů.

S01 povoluje pouze jednotky 0,025 mm a 0,010 mm. S01 uvádí efektivní plochu 610 × 510 mm. S02 vyžaduje počátek vlevo dole.

**Závěr:** První POC musí zakázat rotaci, vyžadovat počátek vlevo dole a mít explicitní profil `gdp_unit_mm` s hodnotou `0.025` nebo `0.010`. Přímý encoder z milimetrů použije `x_cmd=x_mm/gdp_unit_mm` a `y_cmd=y_mm/gdp_unit_mm` v soustavě vlevo dole. Host musí před serializací použít a zdokumentovat vlastní pravidlo kvantování; ovladač jeho volbu nedokládá.

Z fyzické plochy a jednotky vycházejí tyto odvozené meze: při 0,025 mm `x=0…24400`, `y=0…20400`; při 0,010 mm `x=0…61000`, `y=0…51000`. Nejde o publikované protokolové maximum.

**Jistota:** vysoká pro orientaci a povolené jednotky; střední pro odvozené číselné meze. Q05 je uzavřená.

## Q06 — `SP` a fyzický nástroj

**Modul a místo:** `MMKPLT.dll`, SHA-256 `611da823f97b5f83afa94c28e8b705c61b7cce44d72ab14478a077e0c1029712`, profilová funkce `0x6a9143b4`, řetězec `SP` na `0x6a901d50` v `.text`; S01, `PEN ASSIGN`.

**Pozorovaný tok:** Pro model `0x0b` funkce `0x6a9143b4` načte z 28bajtového profilového záznamu logické číslo v druhém 32bitovém poli a emituje `SP` následované desítkovým číslem. PCD omezuje počet logických per na šest.

S01 definuje uživatelsky měnitelné `PEN ASSIGN` 1 až 6. Tovární mapa je: 1 = B/REC.CUTTER1, 2 = B/ROLLER1, 3 = B/θCUTTER, 4 = B/ROLLER2, 5 = A/SWIVEL, 6 = A/PEN.

**Závěr:** `SPn` vybírá logický slot `n` v rozsahu 1 až 6, nikoli neměnný fyzický nástroj. Profil POC musí uvést `pen_slot` a obsluha musí před ostrým řezem potvrdit aktuální panelové přiřazení. Tovární mapa je vodítko pro kontrolu, ne implementační výchozí hodnota.

**Jistota:** vysoká. Q06 je uzavřená explicitním slotem a kontrolou panelu.

## Q07 — rychlost, tlak a offset

**Modul a místo:** `MMKPLT.dll`, SHA-256 `611da823f97b5f83afa94c28e8b705c61b7cce44d72ab14478a077e0c1029712`, `0x6a9143b4` a formátovač `0x6a914264` v `.text`; řetězce `VS`, `ZF`, `FS`, `ZO` a `AS` na `0x6a901d54` až `0x6a901d64`.

**Pozorované bajty a tok:** Pro model 11 čte `0x6a9143b4` z 28bajtového záznamu:

- bajt na posunu `0x0c`; pokud není nula, emituje `VS` a celé desítkové číslo;
- 16bitovou hodnotu na posunu `0x0e`; pokud není nula, emituje `FS` nebo `ZF` a celé desítkové číslo podle příkazového režimu PCD;
- `float` na posunu `0x14`; při kladné hodnotě emituje `ZO` a výsledek formátovače `0x6a914264`.

Formátovač `0x6a914264` začíná bajty `48 8b c4 48 89 58 08 48 89 68 18 66 89 50 10 56 57 41 54 48 83 ec 30`. Volá `_fcvt(value, 2, …)` a vždy tvoří dvě desetinná místa. Modelová větev 11 zde neemituje `AS` ani `ZA`. Nulová rychlost, tlak nebo offset příkaz zcela vynechá; neemituje hodnotu nula.

S01 uvádí fyzickou rychlost 0,2 až 30 cm/s a offset 0,00 až 2,50 mm v kroku 0,05 mm. Tlak závisí na nástroji: například swivel 30 až 1000 g, tangenciální nůž a roller 500 až 1500 g. Ovladač serializuje rychlost jako celé číslo, takže omezený POC smí použít pouze celočíselnou rychlost 1 až 30 cm/s. Kódování desetinné rychlosti zůstává neověřené a první POC je nepotřebuje.

**Závěr:** Profil používá `SPn`, volitelně `VSv`, `FSf` nebo `ZFf` a `ZOo.oo`. Příkazy se řetězí bez vloženého středníku, například `SP1VS10FS100ZO0.30`. Chybějící hodnota ponechá prioritu panelu. Profil nesmí mít obecný výchozí tlak; musí validovat rozsah vybraného nástroje. `ZA` zůstane pro první POC panelovým nastavením.

**Jistota:** vysoká pro bajtovou serializaci a vynechání nul; vysoká pro veřejné fyzické rozsahy; nízká pro desetinnou rychlost, kterou omezený POC zakazuje. Q07 je uzavřená pro tento POC.

## Otázky třídy D

Q08 (více průchodů a pořadí), Q09 (odpovědi a stavové čtení) a Q10 (hostitelské spuštění registračních značek) neblokují první samostatný jednosměrný řez. Tato etapa je pouze klasifikuje a dál je nerozebírá. U Q09 je doloženo jen to, že vlastní `ReadPort` modulu `mpmserv_1.dll` vrací nula bajtů; chování systémové RAW TCP cesty zůstává neověřené.

## Hloubkové doplnění po odložení capture

Protože síťový capture je odložen o několik dní, byla statická analýza dotažena na maximum. Následující byte-chainy uzavírají dřívější mezery obsahu proudu.

### FS vs. ZF řídí PCD klíč `CUTTING`, ne `COMMAND` (E38 → `potvrzeno`)

Příznak `[pdev+0xa70]+0x104` je plněn parserem PCD. Keyword tabulka na `0x6a92a6b0` váže `CUTTING` na handler `0x6a926e80`, který dělá `add rcx,0x104` a tail-calluje generický atoi setter `0x6a9264b8`. Default recordu je nula (`0x6a925f82: mov [rbx+0x104], r13d` s `r13d=0`). Handler `COMMAND` (`0x6a926e98`) cílí jiné pole `+0x118`. V `CFLJJ.PCD` je `CUTTING=1` → `+0x104=1`. Emisní větev `0x6a914617`: přednabije `ZF` (`0x6a901d58`), `cmp [rax+0x104],0`, `jne` → `+0x104=1≠0` ponechá **`ZF`**; `FS` (`0x6a901d5c`) by padlo jen při `CUTTING=0`. Tentýž `+0x104` gatuje i druhou emisní kopii `0x6a914b9b` a barevnou/řezovou větev `0x6a91468f`.

### Souřadnice se nezaokrouhlují (E39 → `potvrzeno`)

Geometrie `0x6a911f38` počítá jen celočíselně (`sub edi,r8d`; `sub esi,edx`) a předává serializeru `0x6a9051e0`, který volá `msvcrt!_ltoa` s bází 10 (IAT `0x6a901488`). Jediné `MulDiv` (`0x6a91ac8a`) je na dráze rozlišení/DPI, ne per-vertex. Driver tedy dostává už kvantované celé číslo; pravidlo zaokrouhlení mm→jednotka je plně na hostovi.

### Zápisová cesta je jednosměrná (E29 → `potvrzeno`)

`MMKPLT` importuje `WritePrinter`/`WriteFile`, ne `ReadPrinter`; `ReadFile` je jen se souborovým mapováním konfigurace. V kódu nejsou status-opkódy (`OH`/`OS`/`OA`/`OI`/`!`). Vlastní `ReadPort` `MPMSERV_1.dll` vrací nula bajtů. Status jde jen out-of-band (SNMP / Event Mail).

### Softwarové stropy rychlosti a tlaku (E20/E22 → `potvrzeno`)

`MMKPLT` při serializaci neclampuje (jen `!=0` a delta-suprese). Stropy vynucuje `MMK_UI` přes `UDM_SETRANGE`: model 11 rychlost 0–50 (`0x6a912fe1: mov eax,0x32`) vs. ostatní 0–40 (`0x6a912fb9: 0x28`); tlak 0–5000 (`0x6a912ff5: mov r15d,0x1388`). Dřívější „10000 g" byla chyba; skutečný strop je 5000.

### Delegace legacy monitoru vyloučena (E36 → `potvrzeno`)

Parse importů `mpmserv_1.dll`: 58 funkcí z šesti systémových DLL, žádný Winsock, žádný `LoadLibrary`/`GetProcAddress`. Všech 194 nepřímých volání míří do vlastní IAT `0x180001000`–`0x1800011e0`. `DeviceIoControl` cílí lokální `\\?\1394#mimaki&printer_status`, ne TCP/AFD. `OpenPortEx=NULL` tedy není skrytá delegace — RAW cesta na 11110 běží výhradně přes systémový `tcpmon.dll`, který v podkladech není.

### Registrační značky (E32)

`MMKPLT` neemituje žádný mnemonik čtení značek; detekci provádí senzor stroje, host jen nastaví režim přes UI dialog 608 (`[RegMark] 0/1`).

## Hranice závěru

- `PUSP0;` platí pro omezenou běžnou větev `MODEL=11`; rozšířené posuny a podávání stránky jsou zakázané.
- Převod milimetrů na celé jednotky je odpovědnost budoucího hosta. Ovladač nepředepisuje jeho zaokrouhlení.
- Tovární `PEN ASSIGN` se může na panelu změnit.
- Absence čtení v `MPMSERV_1.dll` není důkazem chování systémového Standard TCP/IP Port Monitoru.
- Aktuální DeviceIO 5.12.3 používá oddělené app-vrstvové cesty `CDeviceEtherData` a `CDeviceIDCut`. Jejich porty a rámce nejsou důkazem legacy RAW TCP/11110.
- Podobnost názvu MGL s HP-GL nebyla použita jako důkaz žádného příkazu.
