Cum funcționează aplicația iBus care arată pozițiile autobuzelor din Chișinău?
Un mic exercițiu de reverse-engineering - de unde preia datele aplicația iBus
? Ofer aici un rezumat a pașilor întreprinși pentru a găsi răspuns la întrebarea dată. Explicația nu conține ilustrații sau instrucțiuni exacte, e superficială, dar suficient de detaliată ca un om care știe să „conecteze punctele” să poată replica pașii fără dificultate. Informația este oferită cu un scop exclusiv didactic, ce faci cu ea - e doar responsabilitatea ta.
Metoda prezentată aici nu este neapărat optimală, e doar calea pe care am parcurs-o, având la îndemână instrumentele pe care le aveam la moment.
Primii pași, interceptarea HTTP
- Am încercat MitM proxy, cu speranța că aplicația lucrează prin HTTP. După ce am instalat certificatul propriu și am configurat telefonul să treacă tot traficul prin proxy, am constatat că nu am prins niciun request care să-mi pară interesant. Posibil undeva în logica programului se spune că setările de proxy a sistemului trebuie să fie ignorate.
- Alternativa ar fi că aplicația se conectează undeva direct prin TCP, deci am nevoie de un sniffer clasic. Cu regret, telefonul meu curent nu e „rooted” și nu pot rula pe el Wireshark (sau ceva similar) direct.
- De aceea am recurs la HTTPToolkit. Deși denumirea spune doar „HTTP”, principiul de funcționare e acela că în Android se configurează un VPN server, prin care trece tot traficul.
- Mecanismul e foarte user-friendly și în scurt timp vedeam unde se conectează aplicațiile din telefon. În log am găsit și o eroare care spunea că una din aplicații a refuzat să se conecteze. Setând anumite filtre, ca să mă asigur că e anume aplicația iBus - am confirmat că ea e. Concluzia este că în aplicație se folosește „certificate pinning”, adică ea știe din start care va fi certificatul serverului la care se conectează și refuză conexiunile dacă vede că certificatul e schimbat. E o practică bună, dar în cazul nostru înseamnă că problema e mai complexă.
În rezultat am constatat că aplicația, cel mai probabil, totuși folosește HTTP pentru a primi date.
Android binary decompilation
- Următorul pas era să extrag aplicația din telefon, am utilizat APK extractor.
- Am lansat
strings ibus.apk > lines.txt
cu speranța că voi găsi acolo ceva bun, de exemplu parole sau adrese hardcodate, sau ceva de acest gen. O inspecție vizuală a rezultatelor nu a arătat nimic promițător. - Am hotărât să sap mai adânc cu ajutorul APK tool.
- Conform instrucțiunilor, am executat
apktool d ibus.apk
, iar apoi am început să inspectez cu ochiul neînarmat rezultatele. - Prin intuiție am decis să caut peste tot stringuri precum
socket
,connect
sauhttp://
. Ultima căutare a dat un rezultat, înMainActivity
am găsit un URL promițător, pe care l-am deschis în browser:nimbus.wialon.com/locator/5f59baffc............
.
Am văzut același ecran pe care-l văd în aplicația Android. Astfel am ajuns la concluzia că aplicația este un webView care vizualizează această pagină. La etapă curentă nu mai e necesar să fac ceva cu telefonul pentru că site-ul poate fi examinat și la un calculator ordinar, cu ecran mare și tastatură zmeurie.
Analiza site-ului
Utilizatorul atent a atras atenție faptului că aplicația nu cere nicio parolă. Așadar putem presupune că nu se face nicio autentificare sau că datele de acces sunt înscrise chiar în codul aplicației.
- Am deschis pagina și în același timp am deschis „browser developer tools” prin
ctrl+shift+i
ca să văd ce mai este interesant pe acolo. - M-am uitat în lista requesturilor, am văzut ceva legat de websockets și am încercat să inspectez traficul.
- Nu era niciun trafic. Deoarece era noapte târzie, am presupus că datele chiar nu vin pentru că nu le trimite nimeni, deci ar trebui să revin la problemă a doua zi.
- Într-adevăr, peste câteva ore venea un flux continuu de date în format JSON. Cum să mă conectez ca să-l primesc și eu?
- Codul Javascript era minificat, adică nu era cine-știe-ce-human-readable. Dar știind că se conectează la un server care conține
mqtt
în denumire, am presupus că o face cu ajutorul librărieipaho mqtt
, cu care sunt familiar. - Știind care sunt denumirile parametrilor pe care le primesc funcțiile, și că în varianta JS a acestei librării parametrii se transmit ca stringuri, am căutat
userName
și am pus un breakpoint în locul unde se apelează funcția care se conectează la server și facesubscribe
la anumite topic'uri.
Aici admit că am avut un pic de noroc deoarece sunt familiar cu ideologia protocolului MQTT și cu instrumentariul Paho, de aceea știam ce să caut și cum să identific că ceea ce am găsit este ceea ce căutam. La breakpoint am văzut care sunt valorile variabilelor în momentul când ne conectăm la server. Parola e goală, username e hardcoded. L-am încercat cu un MQTT client alternativ și am văzut că primesc și eu JSON'urile pe care le așteptam.
Răspunsul definitiv
Așadar, știm că aplicația iBus este un webView care vizualizează un URL, care la rândul său execută un Javascript care preia datele de pe un MQTT server a unui third party, care distribuie fluxul de date prin websockets. Adresa serverului, portul și numele de utilizator pot fi extrase din codul paginii.
Cum arată mesajele propriu-zise:
{
"tm": 1609151367,
"id": 20464445,
"msg": {
"r": 20690,
"pos": {
"c": 91,
"y": 47.0378283,
"s": 20,
"x": 28.8112483
},
"t": 1609151365,
"o": 519,
"tt": 275981,
"i": 13.5
}
}
tm
- unix time, timpul expedierii mesajului. msg/r
- pare a fi un identificator de vehicul, pos
- coordonatele și posibil viteza și azimutul.
Pentru a-mi simplifica munca, am verificat dacă pot să primesc datele și prin MQTT-over-TCP, cu ajutorul mosquitto_sub
. Da, e posibil, aici e comanda dată în base64 bW9zcXVpdHRvX3N1YiAtdSAyQWJsZllqQUpDNU0xempETk02OFdLb2tscGdSZko4N2E3 aGRUcUJzUXg0RlVkOXhONXR5REhHT1VNdVhrcVRrIC1oIG1xdHQuZmxlc3BpLmlvIC10I G5pbWJ1cy9sb2NhdG9yLzVmNTliYWZmYzM3MTQ0YTM5MzlkMjFiZDhhY2M1ZTQ1LyM=
Comparație cu Roataway
iBus nu divizează informația pe rute, ci transmite întotdeauna toate datele. Dacă sunt 121 vehicule, și dimensiunea unui pachet JSON este de 230 octeți, într-o oră consumi ~10MB de trafic, chiar dacă nu ai nevoie de toate datele pentru că te interesează doar o rută anumită. Așadar, dacă te uiți în aplicație timp de 6 minute, consumi 1 MB de trafic.
În Roataway datele vin selectiv, doar pentru rutele alese de utilizator, ceea ce constituie un avantaj pentru oamenii care au traficul redus.
Concluzie
Am aflat cum aplicația preia datele de la server și care este formatul pachetului de date. Această informație ar face posibilă integrarea datelor în alte sisteme sau elaborarea unui mecanism alternativ de vizualizare.
3 comments
Comment from: zed Visitor
Comment from: gr8dude Member
@zed, где сказано что я придумал эту штуку или назвал её?
Comment from: zed Visitor
Не сказано, вот и спрашиваю…
Однако меткое название иБусь, сам придумал?