APS Logo APS_TUNING [ ABOUT ] [ BLOG ]
[ VISSZA A LOGOKHOZ ]

Hogyan flasheltem tuned kalibrációt egy BMW DDE6-ra WinKFP-vel? Sehogy. 😂

TIMESTAMP: 2026.05.31 | TARGET: BOSCH DDE626 (DDE6) - BMW | AUTHOR: APS TUNING | v2

Volt egy egyszerűnek tűnő ötletem: fogom a módosított .0da cal-fájlt, feltolom WinKFP-vel, és kész. Hát, nem így lett. Egy kis nyomozás, négy zsákutca, és egy meglepő végkifejlet után most már pontosan tudom, miért nem megy ez WinKFP-vel, és hogy kell megoldani saját flasherrel.

Ez a poszt a sztoriról szól. Ha valaki maga akar flash toolt írni, a végén ott a recept és a logika, amiből össze tudja rakni. Fontos pontosítás: a flash-authhoz továbbra is kell az RSA512-es auth-kulcs, illetve hozzáférési ág; itt nem ezt kerülöm meg. A poén az, hogy a másik, cal-data RSA-aláírási ág érvényes privát kulcsa nem kell, mert nem ezen az úton viszem be az ECU-t.

A felállás

A DDE626 flash 256 KB-os cal-zónája (0xC0000..0xFFFFF) tele van olyan mezőkkel, amik első ránézésre nem árulják el, melyik mit csinál. Van benne pár terminator, egy pointer-tábla, a tényleges cal-adat (mapek, paraméterek), és pár fingerprint-szerű érték a végén. A klasszikus tuner-tudás szerint a recept egyszerű: módosítod a mapeket, újraszámolod a Bosch sum-checksumot (a cal-data BE 32-bit word-jeinek összege egy fix konstansra kell kijöjjön), és kész.

Csak hát ez itt nem volt elég.

A nyomozás

Első tipp: hiányzik egy marker (AF FE 08 15) a 0xC0290 területen. Összehasonlítottam egy .0da fájlt egy ECU-ról mentett kalibrációval, és hiányzott ez a marker. Na de beleírom a fájlba, és minden okés lesz.

AF FE 08 15 marker a 0xC0290 területen

Az AF FE 08 15 marker a 0xC0290 területen, egy ECU-ról mentett kalibrációban.

Beleírtam. WinKFP szépen leflashelte. Az ECU programozási státusza maradt 0x06, ami a Bosch nyelvén nagyjából annyit tesz: "data-sign verify nem ment át". Tehát nem ez volt a kulcs.

WinKFP flash fail

WinKFP flash, a folyamat lefut, de a programozási státusz a verify miatt nem áll normálba.

Második tipp: a cal végén lévő CVN érték (egy fingerprint a 0xFD774-en) eltér a gyáritól, biztos azt ellenőrzi.

Pcap-analízis. Kiderült: a WinKFP magából a fájlból olvassa ezt az értéket, és az ECU futás közben rá se néz. Nem ez a probléma.

Harmadik tipp: van egy iflash mirror a cal-régióról, az nem konzisztens a frissen flashelt területtel.

Tisztázódott: ugyanazon az ECU-n flasheltem vissza, a mirror konzisztens volt. Megint mellé.

Negyedik tipp: van egy 64 byte-os RSA-aláírás a 0xC0100 körül.

Diff a két fájl között: ott mindkettőben csak FF. Ilyen sig nem létezik DDE626-on. A régebbi generációs Ghidra-tudás itt félrevezetett, generációs változás történt.

A felfedezés

Végül a diff a gyári kalibrációk között, azonos szoftvereken, egy konkrét helyen mutatott eltérést: egy 128 byte-os blob a 0xC0314-en. Ez minden egyes cal-on más. És itt jött a meglepetés: sikeres gyári flash után az ECU magától beírta az AFFE0815 markert a 0xC0290-re.

Ez fordította meg az egész képet:

Tehát az első tippem fejjel lefelé volt: én okozatot próbáltam bemásolni ok helyett.

Mi történik az ECU-ban?

A $31 09 04 routine indítja a data-sign verify-t. Nagyvonalakban:

Itt a lényeg, hogy a privát kulcs az ECU-ban nincs benne (helyesen, csak a publikus van), tehát új, érvényes aláírást előállítani a tuned cal-hoz a klasszikus úton nem lehet. Ezért bukik 0x06 státuszban minden tuned cal, amit a fő verify-ágon küldenek be.

0x06 programozási státusz

A 0x06 programozási státusz: a data-sign verify nem ment át a fő ágon.

Mit jelentenek pontosan a programozási státuszok?

A BMW NCS Dummyban van egy tábla a 09DDE604.prg fájlhoz, ami megadja az összes lehetséges állapotot. Pár fontos kódolás:

PROGRAMMIERSTATUS tábla a 09DDE604.prg fájlból

A teljes PROGRAMMIERSTATUS tábla a Tool32-ből, kiolvasva a 09DDE604.prg fájlból. Itt látszik a Bosch tervezett állapotgépe a két különálló sign-verify ággal (PAF, DAF) és a köztes hibakezelési állapotokkal.

A két kulcs amivel itt találkozni, a 0x05 PAF és a 0x06 DAF. Ezek a két különálló sign-verify ág kimenete. Ha csak kalibrációs adatot módosítasz, akkor 0x06-on bukik az ECU. Ha kód is módosul, akkor lehet 0x05 is, vagy 0x06, attól függően melyik ág bukik először a verify sequence-ben.

A 0x06 szó szerint azt jelenti, hogy a Datensignaturprüfung nem futott le (nicht durchgeführt), nem azt hogy lefutott és elbukott. Ez a finomság a Bosch szövegezésben pontos: az ECU nem tud bizonyítani sikeres verify-t, ezért a marker nem íródik be, ezért a fallback ág is bukik (ha a marker eleve hiányzik), ezért az állapotgép ezen ragad.

A kiskapu: egy szándékos fallback

A nyomozás közben viszont előkerült egy második kódág. Amikor a programozási státuszt kérdezed le, az ECU nem mindig fut bele a teljes RSA-verify-be. Van egy gyorsabb, fallback útvonal:

Ez nem bug. Ez egy szándékos service-mode útvonal szerintem, dealer vagy factory-reset szcenárióra, ahol még nincs friss aláírás, de a marker megléte elég bizonyíték. A Bosch threat-modellje itt vállalhatóan pragmatikus: "a casual tunert kizárjuk a fő verify-jal, a master-szintű RE-támadót meg úgyis nehéz." Tudatos kompromisszum, nem hiba.

Miért nem megy ez WinKFP-vel?

Itt a csavar a WinKFP-ben van. A pcap szerint a gyári flash-folyamat a $34/$36/$37 write-keretekkel soha nem ír a 0xC0290 területre. Akkor sem, ha beleírod a .0da fájlba. Az erase ugyan letörli ezt a területet flash közben, de visszaírni csak az ECU írja vissza, sikeres $31 09 04 után.

Vagyis WinKFP-vel tuned cal esetén:

Ez tiszta separation-of-concerns a Bosch részéről: a tool szállítja a payloadot, az ECU dönt a verify-ról és a marker beírásáról. Logikus, csak épp nem hagy kiskaput a tunernek.

Hogyan oldja meg a saját flasherem?

A teljes flash-területet maga kontrollálja, beleértve a 0xC0290-et. Tehát:

Nincs szükség a cal-data RSA privát kulcsára, és firmware-patchre sem. Az RSA512-es flash-auth ettől még megmarad belépési feltételnek a programozáshoz; a trükk csak az, hogy a másik, fő data-sign verify ág tuned cal-on nem fut le érdemben, és helyette a szándékos service-fallback dönt.

A két flow egymás mellett: gyári vs tuned

A legtisztább bizonyíték a két flash-log $31 09 04 finalize lépése. Ugyanaz a tool, ugyanaz az ECU, csak a cal tartalma más. Először a gyári, érvényes aláírású cal (egy visszaolvasott WinKFP-frissítés):

$31 09 04 finalize, gyári cal
[4b] CVN Finalize ($31 $09 $04)...
  $31 $09 $04 OK (5.0s, 2 retries): 71 09 01
    r[2]=0x01, FRESH CVN VERIFY PERFORMED (correct path)
  $31 $09 $04 #2 OK: 71 09 01
    #2 r[2]=0x01 (fresh verify confirmed)

Itt az r[2]=0x01 azt jelenti, hogy a fő RSA-verify ténylegesen lefutott és átment. Ezután az ECU maga írja be az AFFE markert, és a státusz 0x01. Ez a "rendes" út, pont mint WinKFP-nél.

DDE Flasher, gyári cal CVN finalize, r[2]=0x01

A DDE Flasher gyári cal flashelése közben: a CVN finalize 71 09 01, r[2]=0x01, fresh verify lefutott (correct path).

Most ugyanaz a finalize lépés, de tuned cal-lal (a 0xC0290-en már bent van a kézzel beírt marker):

$31 09 04 finalize, tuned cal
[4b] CVN Finalize ($31 $09 $04)...
  $31 $09 $04 OK (5.0s, 2 retries): 71 09 00
    r[2]=0x00, ECU already in app mode, NO fresh verify ran
    Boot-time sig check may reject the flash.
  $31 $09 $04 #2 OK: 71 09 00

A tool itt figyelmeztet, hogy nem futott fresh verify, és hogy a boot-time sig check elvileg elutasíthatná a flasht. De a reset utáni identify-ban:

DDE Flasher, tuned cal CVN finalize, r[2]=0x00

Ugyanaz a tool tuned cal-lal: a CVN finalize 71 09 00, r[2]=0x00, a piros keret a "NO fresh verify ran" figyelmeztetést emeli ki. A flash mégis sikeres, és az ECU 0x01-be áll a fallback-ág miatt.

Reset utáni identify, tuned cal
[IDENTIFY] $31 0A OK, Status: 0x01 Normal operation

A státusz 0x01, normál működés, annak ellenére, hogy a fő verify nem futott le (r[2]=0x00). Ez a fallback memcmp-ág a gyakorlatban: az ECU nem talált friss aláírást, viszont a 0xC0290-en megvan az AFFE marker, és ennyi elég neki. Pontosan ezt az ágat írtuk le fentebb, csak most élő logon is látszik.

A lényeg dióhéjban: gyári cal-on r[2]=0x01 (fresh verify lefut, átmegy), tuned cal-on r[2]=0x00 (fresh verify nem fut), de a végeredmény mindkét esetben 0x01 Normal operation, mert a marker megléte a fallback-ágon elég.

A kód-oldali sztori ugyanaz

A sztori nem áll meg a .0da-nál. Az ext-flash-ben négy AFFE0815 marker-blokk van, két RSA-1024 aláírással, a másik két blokk pedig benne van a 0pa fájlban is, így az nem releváns.

Ugyanaz az architektúra: 64 byte marker (AF FE 08 15 plusz 60 byte zero), majd a tábla folytatása, majd a típuscímke (00 00 00 20), majd a 128 byte RSA-1024 aláírás. Két különálló védelmi ág, ugyanazzal a Bosch receptúrával.

A WinKFP a .0pa (Programm-Anwendung) fájlt is ugyanúgy kezeli mint a .0da-t. A $34/$36/$37 write-keretek soha nem írnak a 0x010290 területre sem. Ha módosítod a kódot, a Programm-sign-verify ugyanúgy elbukik mint a Daten-sign-verify, és az ECU 0x06 (vagy 0x05) státuszba ragad. Ugyanaz a fallback ág van itt is, csak más címen.

Ha csak a cal-t módosítod (kód érintetlen), a kód-AFFE-t a gyári dump-ból úgyis tudod átemelni, egy bytewise copy a működő ECU 0x010290 területéről. Az ECU magától nem írja vissza ezt a területet flash közben (a separation-of-concerns ott is érvényes), de a fájlban benne kell legyen.

Variációk a témára, a 6HP TCU

Mellékág, ami közben felbukkant: a ZF 6HP TCU .0da fájlokban is megtaláltam ugyanezt a mintázatot. Egy RSA-1024-es aláírási blokk után egy second-tier marker-mező, a pozíció a 0x50084 környéke, közvetlenül az aláírás után.

Egy fontos különbség viszont: a 6HP-nél a Bosch fordított konvenciót használ. A .0da fájl üres területeit nem FF-fel tölti, hanem 0x00-val, beleértve a marker-mezőt is. Tehát ami DDE6-on FF FF plusz az AFFE0815 marker, az 6HP-n 00 00 plusz FF FF marker. Egy 0x01-státuszú TCU-ból kiolvasva a 0x50084 területen FF FF van, a .0da csere fájlban 00 00. Ugyanaz a koncepció (csere-fájlban inert állapot, ECU írja a fallback markert sikeres verify után), csak az erased state és a marker pattern fordított.

6HP TCU RSA-1024 aláírás és marker-mező

Egy 6HP TCU flash-fájl hexdumpja, a 0x50004 környéki 128 byte RSA-1024 aláírás után közvetlenül a marker-mező. A jelölt területeken jól látszik a fordított Bosch konvenció.

Flashelést itt még nem futtattam, csak a fájlstruktúra-azonosítás van meg. De a logika strukturálisan azonos. Ha a tool a flash közben biztosítja, hogy a 0x50084 területen FF FF legyen, a fallback ág valószínűleg ugyanúgy átengedi a verify-t, mint a DDE6 esetében.

Architektúrálisan egyértelmű: ugyanaz a Bosch design-nyelv, csak más byte-mintával és fordított erased-state konvencióval.

A recept (ha magad akarsz toolt írni)

Egy gyári, működő cal-dumpból kiindulva így állítható elő egy 0x01-státuszú, tuned flash:

A cal-aláírás privát kulcsa sehol nem kell. Az RSA512-es auth-kulcs, illetve hozzáférés viszont kell a flashelési session megnyitásához, csak a második RSA, vagyis a cal-data signature privát kulcsa nem szükséges. A "védelem" itt a tuned oldalon nem új aláírás gyártásával dől el, hanem azon, hogy tudni kell, melyik ellenőrzési ágon megy be az ECU.

A "ne fuss bele, mint én" rész

Pár buktató, amibe én belefutottam, hogy te ne kelljen:

Tanulság

Nem kellett firmware-t patchelni. Az egész azon múlt, hogy megértsem: az ECU-ban két különböző ellenőrző-ág van, és a WinKFP meg a saját toolom különböző ágakon viszi be az ECU-t. Az AFFE0815 markerről pedig kiderült, hogy nem a belépőjegy, hanem a pecsét, amit az ECU üt rá, ha bejutottál, és van egy oldalsó ajtó, ahol a régi pecsét felmutatása is elég.

< VISSZA A LOGOKHOZ