Grenton – komunikacja z telefonem

Spędziłem już trochę czasu z Grentonem. W tym poście chciałem się podzielić wiedzą jak odbywa się komunikacja między CLU a telefonem.

Na początku zainstalowałem aplikację “Packet Capture” na Android, żeby sprawdzić jak odbywa się komunikacja. Ale wyszło na to, że aplikacja pozwala sprawdzić ruch na protokole HTTP/HTTPS. Aplikacja Grentona wysłała kilka komunikatów “do bazy”, ale nie było tam nic interesującego (na tę chwilę). Komunikacja musi się odbywać na innym protokole.

Drugim pomysłem, było połączenie telefonu przez proxy i obserwowanie ruchu. Nie bardzo miałem ochotę się w to bawić. Na szczęście, okazało się, że w OM (object manager – aplikacja do programowania Grentona) ma symulator GUI. Wystarczyło włączyć Wiresharka, żeby podejrzeć ruch.

Adres 192.168.2.100 to adres mojego komputera, a adres 192.168.2.200 to adres, który nadałem CLU. Wiadomości są wysyłane na port 1234 przy pomocy protokołu UDP.

Wysłałem polecenie zapalenia światła (przycisk w GUI). Został wysłany jeden komunikat o długości 64 bajtów. Następnie, mój komputer i CLU wymieniło wzajemnie jeszcze kilka komunikatów.

Komunikat wygląda następująco:

0000 10 63 61 85 29 5a 6d bd 45 67 0d 1e 05 db 7d 45
0010 b4 d7 db 60 c1 28 a1 48 c5 40 df 76 16 91 e2 5f
0020 3f 53 19 39 e8 d7 b0 c6 3f 2e e8 e0 da d1 77 70
0030 20 82 31 05 94 79 5a de 7d 38 df 16 f8 af 7e 1b

Postanowiłem wysłać go raz jeszcze za pomocą PHP.

<?php
$host = '192.168.2.200';
$port = 1234;
$message = hex2bin($bin);

$package = <<<BIN
\x10\x63\x61\x85\x29\x5a\x6d\xbd\x45\x67\x0d\x1e\x05\xdb\x7d\x45\xb4\xd7\xdb\x60\xc1\x28\xa1\x48\xc5\x40\xdf\x76\x16\x91\xe2\x5f\x3f\x53\x19\x39\xe8\xd7\xb0\xc6\x3f\x2e\xe8\xe0\xda\xd1\x77\x70\x20\x82\x31\x05\x94\x79\x5a\xde\x7d\x38\xdf\x16\xf8\xaf\x7e\x1b
BIN;

$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_connect($socket, $host, $port);
socket_send($socket, $package, strlen($package), 0);
socket_close($socket);

Po wykonaniu tego kodu udało się włączyć światło. Teraz pora na wyłączenie światła.

0000 10 63 61 85 29 5a 6d bd 45 67 0d 1e 05 db 7d 45
0010 b2 05 d5 80 32 72 26 4d e5 11 4b b0 ff d6 32 ca
0020 5c 1a ae 71 c2 f7 c5 aa 86 6d 2c f3 e9 58 a3 30
0030 1c 20 31 84 4d 19 73 b0 05 50 f6 1f c4 0c 72 8a

Po resecie CLU mój skrypt w PHP w dalszym ciągu działa. Wydawało mi się, że CLU ustala jakieś sesje, ale wygląda na to, że nie. W zasadzie na ten moment oznacza, że mogę sterować CLU za pomocą aplikacji lub skryptu napisanego przeze mnie. Jedynym problem będzie zebranie zestawu wiadomości. Nie jest to idealne rozwiązanie, ale to “zawsze coś”. Może moduł Gate pozwoli na łatwiejszą komunikację?

Początek komunikatu dla obu wiadomości jest taki sam (dla pozostałych przycisków również). Na ten moment skończyły mi się pomysły i postanowiłem sprawić co jest wysyłane do aplikacji na telefon, tzw. “plik interfejsu”.

Jestem ciekaw w jaki sposób wiadomość została zaszyfrowana. Postanowiłem się przyjrzeć plikowi interfejsu, który wysyłany jest na telefon.

Wygenerowany plik jest w formacie zip. W środku znajdują się wszystkie grafiki i konfiguracja layoutu. W sumie całość zajmuje coś około 5MB.

Mnie zainteresowały pliki config.xml, page.xml oraz page1.xml.

Config.xml

Konfiguracja jest umieszczona w głównym node “config”, który zawiera kolejne sekcje:

    <general 
        appskin="BasicSkin_Large" 
        communicationType="3" 
        height="1920" 
        isMenu="false" 
        key="B3D7854EF687F1E94E52F1829F319757939908A022D97D9633ED494A7CC7552B96F1427042C4B7E10C6955C5AD7730579D0E51A29BC005ADA61FCE57E1E1E5CFFC076A05DB794260719B280BE9FA3D7E23C19CBD9A0D2072BA4693DB2B7B429F" 
        menuImage="" 
        name="auto_generated" 
        projectId="" 
        vertical="true" 
        width="1080"
    />

Interesująca jest wartość w polu “key” mam nadzieję, że jest to klucz, który jest używany podczas komunikacji.

<pages> 
    <page icon="" index="0" isMenu="true" name="page"/> 
    <page icon="" index="1" isMenu="true" name="page1"/> 
</pages>

Konfiguracja ekranów w aplikacji.

<commandsToUpdateTime>
    <command 
        getTime="192.168.2.200 req:local_ip:00b5bd:null:get(13)" 
        ip="192.168.2.200" setTime="192.168.2.200 req:local_ip:002b9a:null:execute(2, $currentTime$)"/>
</commandsToUpdateTime>

Sekcja komend. Czy jest możliwe wykonanie jakieś własnej komendy na CLU?

<clus>
    <clu ip="192.168.2.200" name="DOM"/>
</clus>

Namiary na CLU.

<mappings>
    <mapping index="0" innerName="0aba9a19" name="x180001305_DIN1" type="3"/>
    <mapping index="1" innerName="0aba9a19" name="x180001305_DIN2" type="3"/>
    <mapping index="2" innerName="0aba9a19" name="x180001305_DIN3" type="3"/>
    <mapping index="3" innerName="0aba9a19" name="x180001305_DIN4" type="3"/>
    ...
    <mapping index="0" innerName="0bebce50" name="x200003152_DOUT1" type="4"/>
    <mapping index="1" innerName="0bebce50" name="x200003152_DOUT2" type="4"/>
    <mapping index="2" innerName="0bebce50" name="x200003152_DOUT3" type="4"/>
    ...
    <mapping index="0" innerName="1b6b0ca8" name="x460000424_AnalogOUT1" type="13"/>
    <mapping index="1" innerName="1b6b0ca8" name="x460000424_AnalogOUT2" type="13"/>
    ...
    <mapping index="0" innerName="06c003ce" name="x113247182_ONEW_SENSOR1" type="23"/>
</mappings>

Sekcja w której mapowane są wejścia z CLU na przyciski w GUI. Widać też, że typ == 3 oznacza moduł DIGITAL IN typ == 4 oznacza DIGITAL OUT.

<thermostats>
    <thermostat name="Termostat">
        <getState>192.168.2.200 req:local_ip:0093a6:Thermostat_007d37:get(6)</getState>
        <getPointValue>192.168.2.200 req:local_ip:00394e:Thermostat_007d37:get(3)</getPointValue>
        <getControlOutValue>192.168.2.200 req:local_ip:005194:Thermostat_007d37:get(13)</getControlOutValue> 
    ...
    ...
</thermostats>

Sekcja w której zdefiniowane są termostaty i ich właściwości.

W pliku page.xml znajduje się chyba to czego szukam.

<component type="toggleButton">
    <appereance height="160" skin="AppSkin" skinName="Oswietlenie_Toggle" width="160" x="190" y="160"/>
    <general id="ToggleButton17" textOff="Światło salon" textOn="Światło salon"/>
<events sync="1">
    <event name="Source">192.168.2.200 req:local_ip:0012a5:DOUT_4243:get(0)</event>
    <event name="ONSWITCHON">192.168.2.200 req:local_ip:00e405:DOUT_4243:execute(1, 0)</event>
    <event name="ONSWITCHOFF">192.168.2.200 req:local_ip:0038fc:DOUT_4243:execute(2, 0)</event>
</events>
<misc color="RGB {192, 192, 192}" fontName="Verdana" height="8" style="0"/>
</component>

To jest to czego szukałem. Komenda, która jest wysyłana, aby włączyć / wyłączyć światło wpięte w DIN OUT 1.

Wygląda na to, że wiem jak wygląda wiadomość, mam klucz. Problem polega na tym, że nie wiem w jaki sposób wiadomości są szyfrowane. Kod OM napisany jest w Javie tak samo jak aplikacja na Android. W obu aplikacjach znalazłem jara w którym znajdują się pakiety w namespace: pl.kipertech.om. Oba jary zdekompilowałem za pomocą fernflowera.

Po dłuższym przeszukiwaniu i analizowaniu kodów źródłowych znalazłem metodę generującą klucz. Klucz powstaje podczas tworzenia nowego projektu. Potem wraz z projektem wgrywany jest na CLU. Ten sam klucz jest wysyłany do GUI w parametrze “key”.

Klucz wygląda następująco:

String key = "B3D7854EF687F1E94E52F1829F319757939908A022D97D9633ED494A7CC7552B96AAAAAA42C4B7E10C6955C5AD7730579D0E51A29BC005BDA61FCE57E1E1E5CBFC076A05DB794290719B280BE9FA3D7E23C19CBD9A0D2072BA4693DB2B7B429F";

I nie jest to czysty klucz. W tym stringu zaszyte są dwie wartości:

Algorytm, którym zaszyfrowana jest wiadomość to “AES“.

Znalazłem fragment kodu odpowiedzialny za rozdzielenie obu parametrów:

String var1 = var0.substring(var0.length() - 32);
byte[] var3 = b(var0.substring(0, var0.length() - 32));
byte[] var4 = b(var1);
CipherKey var5 = new CipherKey(Test5.b, var4);


Oraz metodę "b"

private static byte[] b(String var0) {
    byte[] var3 = new byte[var0.length() / 2];

    for(int var1 = 0; var1 < var0.length() - 1; var1 += 2) {
        int var2 = Integer.valueOf(var0.charAt(var1) + String.valueOf(var0.charAt(var1 + 1)), 16);
        var3[var1 / 2] = (byte)var2;
    }

    return var3;
}

Niestety nie udało mi się jeszcze zdekodować klucza. Oprócz obfuskacji jest on zakodowany kolejnym kluczem ukrytym w OM i GUI. Dodatkowo wygląda na to, że kluczowa metoda potrzebna mi do odszyfrowania klucza nie pozwoliła się zdekompilować. Jak znajdę trochę czasu to postaram się do tego wrócić.

Samo szyfrowanie wiadomości wygląda już prosto. Użyta jest biblioteka Cipher z pakietu javax.crypto.

Podsumowanie:

  • Grenton używa sprawdzonych narzędzi i algorytmów do komunikacji.
  • Komunikacja odbywa się za pomocą protokołu UDP. Głównie na porcie 1234.
  • Można napisać aplikację na “Raspberry PI”, która będzie sterowała naszym CLU. Wystarczy do tego Wireshark i odrobina wolnego czasu.
  • Z drugiej strony atakujący nie musi deszyfrować wiadomości. Wystarczy, że będzie wiedział, że dany ciąg znaków rozbraja alarm. Dlatego komunikacja między telefonem a CLU powinna odbywać się przez zabezpieczone wifi / vpn.
  • Podczas tworzenia nowego projektu tworzy się nowy klucz.
  • Myślałem, że między GUI a CLU następuje wymiana kluczy (https://pl.wikipedia.org/wiki/Wymiana_klucza), ale wygląda na to że nie. Czy to źle? To nie system bankowy.
  • Wymiana kluczy następuje podczas łączenia się do CLU z OM.
  • GUI wysyła jakieś statystki gdzieś w internet. Jeszcze się temu przyjrzę.

Pozdraiwam,

T

 

Please follow and like us:

Jedna myśl na temat “Grenton – komunikacja z telefonem

Leave a Reply to Piotr Cancel reply

Your email address will not be published.