Ein kleines Reverse-Engineering-Projekt

Lässt sich der Jooki-Kin­der­laut­spre­cher mit eige­nen Figür­chen ver­wen­den? Ich wage ein Ex­peri­ment mit RFID-Chips.

Neulich habe ich den Jooki-Kinderlautsprecher vorgestellt. Er funktioniert wie ein normaler WLAN-Lautsprecher – nur mit der Besonderheit, dass das Programm über kleine Figürchen ausgewählt wird, die man auf das Gerät stellt.

Da ist eine Idee nahe liegend: Nämlich selbst Figürchen zu basteln, die mit Wiedergabelisten verbunden werden können. Klar, man kann auch mehr Figürchen kaufen. Aber eine interessante Herausforderung ist natürlich die Frage, ob man die auch selbst hinbekommt.

Das Geist-Figürchen gibt diesen Link zurück.

Dafür muss man als erstes herausfinden, wie die Figürchen mit dem Lautsprecher kommunizieren. Man tippt auf RFID und hält daher probehalber die EC-Karte an den Jooki. Und tatsächlich: Er reagiert darauf.

Der erste Schritt wäre herauszufinden, wie die Figürchen erkannt werden. Dazu benutze ich die App NfcActions, die es kostenlos fürs iPhone gibt. Da tippt man auf den Scnan-Knopf, hält ein Figürchen ans iPhone und voilà; entdeckt wird ein Link, der beim Antippen die Begrüssung «Hello 鬼 Ghost» zurückgibt.

Wenn man nur nach dem chinesischen Zeichen googelt, erscheint auf der Suchseite die Wikipedia-Seite zu Gespenst. Man liegt somit wahrscheinlich richtig, wenn man vermutet, dass dieses Zeichen ebenfalls etwas mit einem Gespenst zu tun hat.

Wie fabriziert man neue Figürchen?

… und der Server sagt Hallo zum Geist.

An der Stelle fragt man sich: Tut es irgendein RFID-Chip? Oder muss der eine spezifische Botschaft aussenden? Die einfachste Lösung wäre, ein vorhandenes Figürchen zu klonen. Dafür gibt es im Netz die passenden Anleitungen. Dann hat man allerdings zwei Figürchen für die gleiche Playlist: nicht sinnvoll.

Darum müsste man in einem nächsten Schritt einen programmierbaren RFID-Chip auftreiben oder sein Smartphone (eher Android als iPhone) dazu bringen, einen RFID-Chip zu imitieren.

Das ist dann der nächste Schritt. Falls ihr Ideen habt, wie man so eine Reverse-Engineering-Aktion am besten angeht, dann lasst es mich über die Kommentarfunktion wissen. Ich bin sicher, ich kann da viel von euch lernen!

Es besteht natürlich das Risiko, dass es gar nicht funktioniert. Denn es gibt auch einen Ndef payload, der einen länglichen alphanumerischen String enthält. Falls das eine kryptografische Absicherung ist, dann hat man Pech gehabt. Wäre schade – denn wer basteln will, sollte das tun dürfen, finde ich.

Auch die Box könnte man komplett selbst bauen

Übrigens: Wenn man gleich die ganze Box selbst bauen will, gibt es dafür mehrere Wege. Man findet die passenden Videos auf Youtube.

Und der grossartige Tipp eines Lesers ist Tonuino; eine Musikbox, in der ein Arduino steckt. Die Anleitung dafür findet sich hier.

Beitragsbild: Hello Ghost (Kellepics/Pixabay, Pexels-Lizenz)

28 Kommentare zu «Ein kleines Reverse-Engineering-Projekt»

  1. Der Webdienst scheint auch ungültige Tags zu akzeptieren, nur die Länge der „Codes“ muss stimmen. Ändert man das hinterste Segment, gibt es keine Änderung der Antwort. Ändert man den Parameter „s“, kommen andere Antworten. „s=0000“ ergibt „Hello unknown_4150“.

    Vermutung: das Token würde dann als „unknown_4150“ erkannt und ihm könnte eine Playlist zugewiesen werden.

    Testen können sollte man das mit einer App wie „NFC NDEF Tag Emulator“. Dort Payload Type URI wählen und den Link eintragen. Mit dem iPhone daneben kann man ja prüfen, ob die Antwort identisch ist mit dem vom richtigen Token.

    Mit etwas Glück funktioniert das schon. Ansonsten würde ich schauen, ob man irgendwie an die Firmware des Gerätes kommt (per Download von Update oder so). Evtl. ist das ein unverschlüsseltes Linux-Image.

  2. Würde auch gerne Tokens selbst basteln für den Jooki. Wenn ich mit der Andoid app „NFC Tools“ einen token auslese sehe ich das es ein NFC typ NTAG213 ist. Payload ist immer eine URL wie z.B.: https://s.jooki.rocks/s/?s=ruxow8lnn88uyeX (Ghost)
    Ich vermute die sind jeh nach Typ immer gleich. Nun müsste man entweder alle Tags die es gibt einmal auslesen und online stellen (so könnten andere, leere NFC tags beschreiben mit „Figuren“ die noch nicht im Besitz sind) oder raus finden wie dieser s parameter in der URL sich zusammen setzt. Jemand Ideen?

    1. Moin,

      mit einer „Magic/Changeable UID Ntag213“ Karte konnte ich erfolgreich eine Karte mit der Android App „Mifare++ Ultra“ Klonen.

      Könntest du auch mal deine Figuren mit der App einlesen und posten? Ich würde dies wenn ich zu Haus bin auch mal machen.

      Ich denke das ggf. die UID der Karte zur URL passen muss. So dass man entweder bekannte Figuren untereinander „tauschen“ kann oder den Algorithmus zur Bestimmung der URL Query Parameter bestimmen müsste. Bei der TonieBox werden mEn die Karten direkt online geprüft… weiß nicht ob es ggf. auch so ist.

      Der SSH Port ist offen beim Jooki aber nur mit Private Key Authentifizierung. Ich habe auch ein Serial UART Adapter direkt angeschlossen aber ich kann mich nicht einloggen, da Username und Passwort unbekannt (da kein Firmware Dump zur Hand).

      Der Jooki kommuniziert alles per HTTPS und ich konnte nichts per mitmproxy aufm Raspberry sehen.

      Gruß

      1. Hier meine Tags ausgelesen mit NFC Tools app da „Mifare++ Ultralight“ bei mir nicht funtzt:

        Tag Serial Payload
        Ghost 04:92:A7:6A:E7:4C:81 https://s.jooki.rocks/s/?s=Hjjpcx/mZwuveTF+
        Dragon 04:DA:B7:6A:E7:4C:80 https://s.jooki.rocks/s/?s=ruxow8lnn88uyeX+
        Whale 04:84:27:6A:E7:4C:80 https://s.jooki.rocks/s/?s=VZB/OLBwOiM5Mpnp
        Knight 04:33:B5:62:39:4D:80 https://s.jooki.rocks/s/?s=E0f2fmH5y2a4qk9g

        Da die box auch Offline funktioniert glaube ich nicht das die tags ausschließlich online geprüft werden. Vielleicht nur beim erstmaligem einrichten.

        1. Meine Figuren:
          https://pastebin.com/6CP0wGqf

          Ein Dump per Mifare++ bzw. der ersten 11×4 Byte sind interessant.
          Die scheinen immer identisch zu sein … bis auf die ersten 4 Byte (UID).

          xxxxxxxx (UID)
          5A314D80
          A6480000
          E1101200
          0103A00C
          340329D1
          01255504
          732E6A6F
          6F6B692E
          726F636B
          732F732F

          Ich habe leider meine „Magic“ Card geschrottet, da ich einfach ein paar Byte geändert habe und nun anscheind eine CRC Prüfsumme nicht stimmt und somit die Karte überhaupt nicht mehr gelesen werden kann.

          Naja ich habe noch ne neue bestellt:
          http://www.aliexpress.com/item/32964739752.html

          mEn sollte es möglich sein mit einem kompletten Dump eine Karte mit einer Figur von euch zu bespielen und dann zu nutzen.

          1. 04:46:8D:47 Drachen: jooki.rocks/s/?s=m2D29kX5NnmAKmhg
            04:C4:6E:26 Fuchs: jooki.rocks/s/?s=GqoCd44NNVB0q6KU
            04:98:98:8C Geist: jooki.rocks/s/?s=1RLkuDXrph6SZBpy
            04:27:8C:27 Ritter: jooki.rocks/s/?s=heGL6MeESfn9NOkd
            04:DE:67:35 Wal: jooki.rocks/s/?s=ytXjp/Xs/yaVe911

          2. Du brauchst keine Magic Karten. Du nimmst einfach eine NTAG213-Karte und beschreibst sie mit einem NDEF-Record, wie es der Jooki erwartet und schon akzeptiert der Jooki den Tag.

    1. Hi Han,

      kannst du ein paar mehr Details posten, wie ein gültiger NDEF-Record für einen NTAG213 aussieht? Ich habe es mit verschiedenen gültigen URLs versucht, die zu einer korrekten Hello-Seite führen (z.b. https://s.jooki.rocks/s/?s=ruxow8lnn88uyeX0 für den Drachen). Allerdings akzeptiert der Jooki das so einfach nicht. Hängt da die UID des Tags noch irgendwie mit drin?
      Und braucht es dafür ein extra Schreibgerät oder kann ich das auch mit einer Android-App wie NFC-Tools hinbekommen?

      Wäre für etwas Unterstützung dankbar.

      1. Hi,

        ich weiß leider nicht, wie Du diese URL dem Jooki bekannt gemacht hast, aber https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/jooki_notes.md findest Du Antworten auf die meisten Fragen.
        Der Parameter s in der obigen URL ist Base64 und da wiederum steckt die UID des Tags drinnen.

        Du kannst auch eine App nehmen, aber den Parameter müsstest Du dann händisch berechnen und dann die resultierende URL auf ein Tag schreiben. Viel leichter geht es mit dem Proxmark, da legst Du den Tag drauf und führst die Befehle aus der obigen Doku aus.

        Hoffe es hilft.

        1. Hi Han,

          Danke für den Link! Der hat mir weitergeholfen. Es war zwar nicht ganz trivial, weil die Base64 URL noch verschlüsselt ist, ich konnte mir die notwendingen Infos aber in https://github.com/RfidResearchGroup/proxmark3/blob/master/client/src/cmdhfjooki.c zusammensuchen.
          Ich hab daraus ein kleines Python-Skript gebastelt, mit dem ich meine NTAG213-Sticker erfolgreich beschreiben konnte.

          [code jooki_encode.py]
          #!/usr/bin/env python3

          import base64
          import sys

          #================================================
          ### INPUT AREA ###
          # UID of NFC card to write to
          uid = ‚04512c7aca6680‘

          ## Token ID
          tid = 2
          # 1 = Figurine, 2 = Flat

          ## Figurine ID
          fid = 0
          # Figurines:
          # 0 = Dragon, 1 = Fox, 2 = Ghost, 3 = Knight, 4 = ThankYou, 5 = Whale,
          # 6 = Black.Dragon, 7 = Black.Fox, 8 = Black.Knight, 9 = Black.Whale,
          # 10 = White.Dragon, 11 = White.Fox, 12 = White.Knight, 13 = White.Whale
          # Flats:
          # 0 = Generic Flat
          #================================================

          ### PROGRAM CODE ###
          # Set fixed requirements
          figurines = [
          ‚Dragon‘, ‚Fox‘, ‚Ghost‘, ‚Knight‘, ‚ThankYou‘, ‚Whale‘, ‚Black.Dragon‘,
          ‚Black.Fox‘, ‚Black.Knight‘, ‚Black.Whale‘, ‚White.Dragon‘, ‚White.Fox‘,
          ‚White.Knight‘, ‚White.Whale‘,
          ]
          iv = bytes([0x80, 0x77, 0x51]) # always the same?
          nfc_secret = bytes([0x03, 0x9c, 0x25, 0x6f, 0xb9, 0x2e, 0xe8,
          0x08, 0x09, 0x83, 0xd9, 0x33, 0x56])

          # Print input parameters to screen
          print(‚UID to encode: ‚, uid)
          if tid == 1:
          print(‚Token: Figurine‘)
          if fid < len(figurines):
          print('Figurine: ' + figurines[fid])
          else:
          sys.exit('Wrong Figurine ID! Aborting…')
          elif tid == 2:
          print('Token: Flat')
          if fid == 0:
          print('Figurine: Generic Flat')
          else:
          sys.exit('Wrong Figurine ID! Aborting…')
          else:
          sys.exit('Wrong Token ID! Aborting…')

          # Convert uid to byte representation
          uid_b = []
          for i in range(0,len(uid),2):
          uid_b.append(
          int('0x'+uid[i:i+2], 16)
          )

          # Combine all input into d
          d = iv + tid.to_bytes(1, 'little') + fid.to_bytes(1, 'little') + bytes(uid_b)

          # Use nfc_secret to encrypt d
          enc = []
          for i in range(0,12):
          if i<3:
          enc.append(d[i] ^ nfc_secret[i])
          else:
          enc.append(d[i] ^ nfc_secret[i] ^ d[i % 3])

          # Encode encrypted string in base64
          result = base64.b64encode(bytes(enc))

          # Print results to screen
          print('URL: https://s.jooki.rocks/s/?s=&#039; + result.decode('utf-8'))
          [/code]

          Benutzung ist etwas hemdsärmlich, aber relativ simpel:
          – UID der Karte auslesen und im Skript eintragen
          – FID und TID wählen, wie gewünscht
          – Skript ausführen
          – Ergebnis-URL auf Karte schreiben
          – Genießen

          1. Hallo Mainboand,

            das hat super funktioniert. Ich habe dein Script über Google Colab ausgeführt, dafür brauchte ich nicht Mal eine Python Entwicklungsumgebung auf meinem Computer.

            Ich bin davon ausgegangen, dass ich einen Klon bekomme und nun 2 „Figuren/Tags“ für ein und die selbe Playlist habe. In der Tat habe ich nun aber 2 eigenständige Tags, was ich natürlich viel besser finde.

            Ab morgen gehe ich in die hauseigene Produktion, nehme Kinderbücher auf und versehe sie mit einem NFC-Tag =).

            Vielen Dank.

            PS an alle: Ein persönliches Vorlesen ersetzt das natürlich nicht, aber es ist schön, wenn die Kinder damit spielen können.

          2. Hallo Mainboand,

            könntest Du Deine Anleitung vielleicht noch ein klein wenig für programmiertechnische Laien erweitern? Mir fehlen da noch ein paar Zusatzinfos…

            – Wie genau müssen die Karten/Chips beschaffen sein, die man als neue Token einsetzen möchte? Wo kann man die kaufen?
            – Benötigt man einen speziellen RFID-Reader? Ich habe als Smartphone ein Google Pixel 6 und ein Neuftech USB RFID Reader ID für 125khz.
            – „UID der Karte auslesen und im Skript eintragen“ ist damit gemeint, die UID der Karte auszulesen, die als neuer Token dienen soll, oder soll eine der Figuren ausgelesen werden?
            – „FID und TID wählen“: Wofür stehen FID und TID?

            Ich verstehe die Anleitung bis hierhin so, dass Dein Script mittels der aus dem neuen Tag (?) ausgelesenen Variable UID angepasst wird, und dann in Collaboratory ausgeführt eine URL generiert, welche wiederum auf das Tag (mit welcher Hardware/ Software?) wieder geschrieben wird.

          3. Hi Simon,

            ich denke schon, dass du das hinbekommst.

            – Wie genau müssen die Karten/Chips beschaffen sein, die man als neue Token einsetzen möchte? Wo kann man die kaufen?
            Such beim Online-Elektronikhändler deines Vertrauens nach NTAG213. Die sind standardisiert. Ich hab damals einfach nach Preis und Stückzahl ausgewählt.

            – Benötigt man einen speziellen RFID-Reader? Ich habe als Smartphone ein Google Pixel 6 und ein Neuftech USB RFID Reader ID für 125khz.
            Ich nutze mein >4 Jahre altes Android-Smartphone mit der App NFC Tools aus dem Google Play Store. Im Grunde sollte aber jede App, die NFC-Chips lesen und beschreiben kann funktionieren. Du musst nur die unique ID (UID) des Chips auslesen und später die vom Skrip generierte URL in den Speicher schreiben. Das ist keine Hexerei. Das größte Problem bei mir ist UID und URL zwischen Handy und PC zu kopieren. Wenn du das Skript via Online-Dienst auf dem Handy ausführen kannst, sollte das aber noch bequemer sein.

            – „UID der Karte auslesen und im Skript eintragen“ ist damit gemeint, die UID der Karte auszulesen, die als neuer Token dienen soll, oder soll eine der Figuren ausgelesen werden?
            Das Python-Skript bestimmt aus der UID des NFC-Chips die korrekte URL, mit welcher der Chip beschrieben wird. Der Jooki berechnet dann aus der URL wieder die UID und prüft ob diese mit der des aufgelegten Chips übereinstimmt. Daher kann man nicht einfach die URL von einer vorhandenen Figur kopieren. Du musst im Skript also die UID des Chips eintragen, den du beschreiben willst.

            – „FID und TID wählen“: Wofür stehen FID und TID?
            Das erfährst du im Anfangsbereich des Skripts unterhalb der Zeile, wo du die UID einträgst. Nach meiner Erfahrung ist das eigentlich nur dafür da, welches Bild in der Steuersoftware vom Jooki für eine Karte angezeigt wird.
            ## Token ID
            tid = 2
            # 1 = Figurine, 2 = Flat
            ## Figurine ID
            fid = 0
            # Figurines:
            # 0 = Dragon, 1 = Fox, 2 = Ghost, 3 = Knight, 4 = ThankYou, 5 = Whale,
            # 6 = Black.Dragon, 7 = Black.Fox, 8 = Black.Knight, 9 = Black.Whale,
            # 10 = White.Dragon, 11 = White.Fox, 12 = White.Knight, 13 = White.Whale
            # Flats:
            # 0 = Generic Flat
            –> Wenn du also einen White Knight erzeugen willst, wählst du tid = 1 (für Figurine) und fid = 12 (für White Knight).

            Ich verstehe die Anleitung bis hierhin so, dass Dein Script mittels der aus dem neuen Tag (?) ausgelesenen Variable UID angepasst wird, und dann in Collaboratory ausgeführt eine URL generiert, welche wiederum auf das Tag (mit welcher Hardware/ Software?) wieder geschrieben wird.
            Genau das tut es. Antwort auf die Fragen, siehe oben. Tag = Sticker.
            Viel Erfolg!

      2. Hi,
        die selbe Erfahrung hatte ich auch gemacht. Ich hatte NTAG213 … und selbst die geklonten (ohne UID) wurden abgelehnt.
        D.h. Han sollte nicht nur schreiben „NTAG213!“ – das war ja klar, sondern wo gekauft und wie sieht ein Dump von einem Tag aus, welcher selbst erstellt wurde ggü. einem originalen.

        1. Wieso stellst Du fragen, auf die Du schon die Antwort kennst? Du hast doch deutlich nach dem Tag gefragt, und ich habe Dir geantwortet, oder?

  3. Hallo mainboand, hallo schlaue Menschen,

    Wer von euch würde mir im Tausch gegen Aufwandsentschädigung solche Tokens basteln und zuschicken? Ich kann das nämlich nicht, auch mit der besten Beschreibung, aber ich hatte Spass beim Lesen 😁 Es wäre so schön, wenn meine Kleine mehr als nur 4 Figuren hätte… Bitte melden unter floh-riz ät Web in Deutschland. Danke vielmals!

  4. Ich bin wohl spät dran, möchte mich aber meinen Vorrednern trotzdem (partiell) anschließen und um Hilfestellung für Laien bitten. Ich habe zwar auch schon mal RFID-Karten ausgelesen und mit Daten bespielt, die Erstellung neuer Tokens scheint aber nicht so trivial zu sein.
    Vielleicht würde in meinem Fall aber schon eine ausführlichere Anleitung helfen.

    Was mir nämlich noch nicht ganz klar ist:
    – Wie genau müssen die Karten/Chips beschaffen sein, die man als neue Token einsetzen möchte? Wo kann man die kaufen?
    – Benötigt man einen speziellen RFID-Reader? Ich habe als Smartphone ein Google Pixel 6 und ein Neuftech USB RFID Reader ID für 125khz.
    – „UID der Karte auslesen und im Skript eintragen“ ist damit gemeint, die UID der Karte auszulesen, die als neuer Token dienen soll, oder soll eine der Figuren ausgelesen werden?
    – „FID und TID wählen“: Wofür stehen FID und TID?
    – Was benötige ich, um das o.g. Python-Script auszuführen? Ich habe es in einem Online-Interpreter auf https://lernenpython.com getestet, da hat es leider eine Fehlermeldung produziert.

    Die Diskussion darüber durchschaue ich als Programmierlaie leider nicht ganz, habe aber den Eindruck, dass es eigentlich möglich sein müsste, mit meinem Wissen (und dem richtigen Equipment…) zum Ziel zu kommen.

  5. Als Info für alle, die es sich wundern:
    Der Jooki (Generation 2) funktioniert auch mit NTAG 216-Tags, mit dem Skript, das oben abgebildet ist. Auf den Tags der Generation 2 existiert zusätzlich zu der URL auch ein j:s-Feld, das ich bisher nicht dekodieren konnte. Es wegzulassen, scheint den Jooki allerdings nicht zu stören.

Schreibe eine Antwort zu HanAntwort abbrechen