Bir gün mənə Android proqramlarından Wi-Fi şəbəkələrini skan etməli və giriş nöqtələri haqqında ətraflı məlumat almalı oldum.
Burada bir sıra çətinliklərlə üzləşməli olduq:
Bu məqalədə NDK, sındırmalar olmadan, lakin yalnız Android API-dən istifadə etməklə Android kodundan Wi-Fi mühiti haqqında hərtərəfli məlumatların necə əldə ediləcəyi müzakirə olunur və onu necə şərh edəcəyinizi başa düşülür.
Gecikməyək və kod yazmağa başlayaq.
1. Layihə yaradın
Bu qeyd bir dəfədən çox Android layihəsi yaradanlar üçün nəzərdə tutulub, ona görə də bu elementin təfərrüatlarını buraxırıq. Aşağıdakı kod Kotlin-də təqdim olunacaq, minSdkVersion=23.
2. Giriş icazələri
Tətbiqdən Wi-Fi ilə işləmək üçün istifadəçidən bir neçə icazə almalısınız. Uyğun olaraq
Beləliklə, AndroidManifest.xml-də biz əlavə edəcəyik:
<uses-permission android_name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android_name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android_name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android_name="android.permission.ACCESS_FINE_LOCATION"/>
Və cari Fəaliyyətə keçid olan kodda:
import android.app.Activity
import android.content.Context
import android.location.LocationManager
import androidx.core.app.ActivityCompat
....
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
ActivityCompat.requestPermissions(
activity,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CHANGE_WIFI_STATE),
1
)
makeEnableLocationServices(activity.applicationContext)
} else {
ActivityCompat.requestPermissions(
activity,
arrayOf(Manifest.permission.CHANGE_WIFI_STATE),
1
)
}
/* включает экран включения службы по определению местоположения */
fun makeEnableLocationServices(context: Context) {
// TODO: перед вызовом этой функции надо рассказать пользователю, зачем Вам доступ к местоположению
val lm: LocationManager =
context.applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val gpsEnabled: Boolean = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
val networkEnabled: Boolean = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!gpsEnabled && !networkEnabled) {
context.startActivity(Intent(ACTION_LOCATION_SOURCE_SETTINGS));
}
}
3. BroadcastReceiver yaradın və Wi-Fi şəbəkə mühitinin skan edilməsi ilə bağlı məlumat yeniləmə tədbirlərinə abunə olun
val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
val wifiScanReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)
if (success) {
scanSuccess()
}
}
}
val intentFilter = IntentFilter()
/* подписываемся на сообщения о получении новых результатов сканирования */
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
context.registerReceiver(wifiScanReceiver, intentFilter)
val success = wifiManager.startScan()
if (!success) {
/* что-то не получилось при запуске сканирования, проверьте выданые разрешения */
}
....
private fun scanSuccess() {
/* вот они, результаты сканирования */
val results: List<ScanResult> = wifiManager.scanResults
}
Sənədlərdəki WiFiManager.startScan metodu API versiyası 28-dən bəri depricated kimi qeyd olunub, lakin söndürülüb.
Ümumilikdə obyektlərin siyahısını aldıq
4. ScanResult-a baxın və şərtləri anlayın
Gəlin bu sinfin bəzi sahələrinə baxaq və onların nə demək olduğunu təsvir edək:
SSID — Xidmət Dəsti İdentifikatoru şəbəkənin adıdır
BSSİD – Əsas Xidmət Seti İdentifikatoru – Şəbəkə adapterinin MAC ünvanı (Wi-Fi nöqtəsi)
səviyyə — Qəbul edilmiş siqnal gücü göstəricisi [dBm (Rus dBm) — Desibel, istinad gücü 1 mVt.] — Qəbul edilmiş siqnal gücünün göstəricisi. 0-dan -100-ə qədər qiymət alır, 0-dan nə qədər uzaq olsa, Wi-Fi nöqtəsindən cihazınıza gedən yolda bir o qədər çox siqnal gücü itirilir. Daha ətraflı, məsələn, burada tapa bilərsiniz
val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
val numberOfLevels = 5
val level = WifiManager.calculateSignalLevel(level, numberOfLevels)
tezliyi — Wi-Fi nöqtəsinin işləmə tezliyi [Hz]. Tezliyin özünə əlavə olaraq, sözdə kanalla maraqlana bilərsiniz. Hər bir nöqtənin öz əməliyyat təmizliyi var. Yazı zamanı Wi-Fi nöqtələrinin ən populyar diapazonu 2.4 GHz-dir. Amma, daha dəqiq desək, nöqtə məlumatı adı çəkilən birinə yaxın nömrələnmiş tezlikdə telefonunuza ötürür. Kanalların sayı və müvafiq tezliklər
/* по частоте определяем номер канала */
val channel: Int
get() {
return if (frequency in 2412..2484) {
(frequency - 2412) / 5 + 1
} else if (frequency in 5170..5825) {
(frequency - 5170) / 5 + 34
} else {
-1
}
}
imkanları - təhlil üçün ən maraqlı sahə, onunla işləmək çox vaxt tələb edir. Burada nöqtənin “imkanları” sətirdə yazılıb. Bu halda, sənədlərdə simli şərhin təfərrüatlarını axtarmaq lazım deyil. Bu xəttdə ola biləcək bəzi nümunələr bunlardır:
[WPA-PSK-TKIP+CCMP][WPA2-PSK-TKIP+CCMP][WPS][ESS]
[WPA2-PSK-CCMP][ESS]
[WPA2-PSK-CCMP+TKIP][ESS]
[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][ESS]
[ESS][WPS]
5. İxtisarlar və təhlil imkanlarını başa düşmək
Qeyd etmək lazımdır ki, android.net.wifi.* paketinin sinifləri Linux yardım proqramı tərəfindən başlıq altında istifadə olunur.
Biz ardıcıl hərəkət edəcəyik. Əvvəlcə mötərizə daxilində elementlərin “-” işarəsi ilə ayrıldığı formatın çıxışını nəzərdən keçirək:
[WPA-PSK-TKIP+CCMP]
[WPA2-PSK-CCMP]
Birinci məna sözdə təsvir edir. autentifikasiya üsulu. Yəni, giriş nöqtəsinin özünün istifadəsinə icazə verməsi və faydalı yükü necə şifrələməsi üçün cihaz və giriş nöqtəsi hansı hərəkətlərin ardıcıllığını yerinə yetirməlidir. Bu yazını yazarkən ən çox yayılmış seçimlər WPA və WPA2-dir, bunlarda hər bir cihaz birbaşa və ya sözdə qoşulmuşdur. RADIUS serveri (WPA-Enterprice) şifrələnmiş kanal üzərindən parol təmin edir. Çox güman ki, evinizdəki giriş nöqtəsi bu sxemə uyğun bir əlaqə təmin edir. İkinci versiya ilə birincisi arasındakı fərq ondan ibarətdir ki, onun daha güclü şifrəsi var: təhlükəsiz olmayan TKIP-ə qarşı AES. Daha mürəkkəb və təkmil olan WPA3 də tədricən tətbiq olunur. Teorik olaraq, CCKM (Cisco Mərkəzləşdirilmiş Açar İdarəetmə) müəssisə həlli ilə bir seçim ola bilər, lakin mən buna heç vaxt rast gəlməmişəm.
Giriş nöqtəsi MAC ünvanı ilə autentifikasiya etmək üçün konfiqurasiya edilmiş ola bilər. Yaxud, əgər giriş nöqtəsi köhnəlmiş WEP alqoritmindən istifadə edərək məlumat verirsə, əslində heç bir identifikasiya yoxdur (burada gizli açar şifrələmə açarıdır). Bu cür variantları DİGƏR kimi təsnif edirik.
Gizli Captive Portal Detection ilə ictimai Wi-Fi-da məşhur olan bir üsul da var - brauzer vasitəsilə autentifikasiya sorğusu. Belə giriş nöqtələri skanerə açıq görünür (fiziki əlaqə baxımından bunlardır). Buna görə də biz onları AÇIQ kimi təsnif edirik.
İkinci dəyər kimi qeyd edilə bilər əsas idarəetmə alqoritmi. Bu, yuxarıda təsvir edilən autentifikasiya metodunun parametridir. Şifrələmə açarlarının necə dəyişdirildiyi haqqında danışır. Mümkün variantları nəzərdən keçirək. EAP - qeyd olunan WPA-Enterprice-də istifadə olunur, daxil edilmiş autentifikasiya məlumatlarını yoxlamaq üçün verilənlər bazasından istifadə edir. SAE - qabaqcıl WPA3-də istifadə olunur, kobud gücə daha davamlıdır. PSK - ən çox yayılmış seçim, parolun daxil edilməsini və şifrələnmiş formada ötürülməsini nəzərdə tutur. IEEE8021X - beynəlxalq standarta uyğun (WPA ailəsi tərəfindən dəstəklənəndən fərqli). OWE (Opportunistik Simsiz Şifrələmə) AÇIQ kimi təsnif etdiyimiz nöqtələr üçün IEEE 802.11 standartının genişləndirilməsidir. OWE qorunmayan şəbəkə üzərindən ötürülən məlumatların təhlükəsizliyini şifrələməklə təmin edir. Heç bir giriş düymələri olmadıqda bir seçim də mümkündür, gəlin bu seçimi NONE adlandıraq.
Üçüncü parametr sözdə olandır. şifrələmə sxemləri — ötürülən məlumatları qorumaq üçün şifrənin necə dəqiq istifadə edildiyi. Variantları sadalayaq. WEP - RC4 axın şifrəsindən istifadə edir, gizli açar müasir kriptoqrafiya dünyasında qəbuledilməz hesab edilən şifrələmə açarıdır. TKIP - WPA-da, CKIP - WPA2-də istifadə olunur. TKIP+CKIP - geriyə uyğunluq üçün WPA və WPA2-yə qadir olan nöqtələrdə göstərilə bilər.
Üç elementin əvəzinə tənha bir WEP işarəsi tapa bilərsiniz:
[WEP]
Yuxarıda müzakirə etdiyimiz kimi, bu, mövcud olmayan açarlardan istifadə alqoritmini və standart olaraq eyni olan şifrələmə üsulunu təyin etməmək üçün kifayətdir.
İndi bu mötərizəni nəzərdən keçirin:
[ESS]
O Wi-Fi iş rejimi və ya Wi-Fi şəbəkə topologiyası. Siz BSS (Basic Service Set) rejimi ilə qarşılaşa bilərsiniz - qoşulmuş cihazların əlaqə saxladığı bir giriş nöqtəsi olduqda. Yerli şəbəkələrdə tapıla bilər. Bir qayda olaraq, müxtəlif yerli şəbəkələrdən cihazları birləşdirmək üçün giriş nöqtələri lazımdır, buna görə də onlar Genişləndirilmiş Xidmət Dəstlərinin bir hissəsidir - ESS. IBSSs (Müstəqil Əsas Xidmət Setləri) növü cihazın Peer-to-Peer şəbəkəsinin bir hissəsi olduğunu göstərir.
Siz həmçinin WPS bayrağını görə bilərsiniz:
[WPS]
WPS (Wi-Fi Protected Setup) Wi-Fi şəbəkəsinin yarı avtomatik işə salınması üçün protokoldur. Başlamaq üçün istifadəçi ya 8 simvoldan ibarət parol daxil edir, ya da marşrutlaşdırıcıda düyməni sıxır. Əgər giriş nöqtəniz birinci tipdirsə və bu qeyd xanası giriş nöqtənizin adının yanında görünürsə, admin panelinə keçməyiniz və WPS girişini deaktiv etməyiniz tövsiyə olunur. Fakt budur ki, tez-tez 8 rəqəmli PİN-i MAC ünvanı ilə tapmaq olar və ya onu yaxın vaxtda sıralamaq olar ki, kimsə vicdansızlıqla istifadə edə bilər.
6. Model və təhlil funksiyası yaradın
Yuxarıda tapdıqlarımıza əsasən, məlumat siniflərindən istifadə edərək baş verənləri təsvir edəcəyik:
/* схема аутентификации */
enum class AuthMethod {
WPA3,
WPA2,
WPA, // Wi-Fi Protected Access
OTHER, // включает в себя Shared Key Authentication и др. использующие mac-address-based и WEP
CCKM, // Cisco
OPEN // Open Authentication. Может быть со скрытым Captive Portal Detection - запрос аутентификации через браузер
}
/* алгоритм ввода ключей */
enum class KeyManagementAlgorithm {
IEEE8021X, // по стандарту
EAP, // Extensible Authentication Protocol, расширяемый протокол аутентификации
PSK, // Pre-Shared Key — каждый узел вводит пароль для доступа к сети
WEP, // в WEP пароль является ключом шифрования (No auth key)
SAE, // Simultaneous Authentication of Equals - может быть в WPA3
OWE, // Opportunistic Wireless Encryption - в роутерах новых поколений, публичных сетях типа OPEN
NONE // может быть без шифрования в OPEN, OTHER
}
/* метод шифрования */
enum class CipherMethod {
WEP, // Wired Equivalent Privacy, Аналог шифрования трафика в проводных сетях
TKIP, // Temporal Key Integrity Protocol
CCMP, // Counter Mode with Cipher Block Chaining Message Authentication Code Protocol,
// протокол блочного шифрования с кодом аутентичности сообщения и режимом сцепления блоков и счетчика
// на основе AES
NONE // может быть без шифрования в OPEN, OTHER
}
/* набор методов шифрования и протоколов, по которым может работать точка */
data class Capability(
var authScheme: AuthMethod? = null,
var keyManagementAlgorithm: KeyManagementAlgorithm? = null,
var cipherMethod: CipherMethod? = null
)
/* Режим работы WiFi (или топология сетей WiFi) */
enum class TopologyMode {
IBSS, // Эпизодическая сеть (Ad-Hoc или IBSS – Independent Basic Service Set).
BSS, // Основная зона обслуживания Basic Service Set (BSS) или Infrastructure Mode.
ESS // Расширенная зона обслуживания ESS – Extended Service Set.
}
İndi imkanlar sahəsini təhlil edəcək bir funksiya yazaq:
private fun parseCapabilities(capabilitiesString: String): List < Capability > {
val capabilities: List < Capability > = capabilitiesString
.splitByBrackets()
.filter {
!it.isTopology() && !it.isWps()
}
.flatMap {
parseCapability(it)
}
return
if (!capabilities.isEmpty()) {
capabilities
} else {
listOf(Capability(AuthMethod.OPEN, KeyManagementAlgorithm.NONE, CipherMethod.NONE))
}
}
private fun parseCapability(part: String): List < Capability > {
if (part.contains("WEP")) {
return listOf(Capability(
AuthMethod.OTHER,
KeyManagementAlgorithm.WEP,
CipherMethod.WEP
))
}
val authScheme = when {
part.contains("WPA3") - > AuthMethod.WPA3
part.contains("WPA2") - > AuthMethod.WPA2
part.contains("WPA") - > AuthMethod.WPA
else - > null
}
val keyManagementAlgorithm = when {
part.contains("OWE") - > KeyManagementAlgorithm.OWE
part.contains("SAE") - > KeyManagementAlgorithm.SAE
part.contains("IEEE802.1X") - > KeyManagementAlgorithm.IEEE8021X
part.contains("EAP") - > KeyManagementAlgorithm.EAP
part.contains("PSK") - > KeyManagementAlgorithm.PSK
else - > null
}
val capabilities = ArrayList < Capability > ()
if (part.contains("TKIP") || part.contains("CCMP")) {
if (part.contains("TKIP")) {
capabilities.add(Capability(
authScheme ? : AuthMethod.OPEN,
keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
CipherMethod.TKIP
))
}
if (part.contains("CCMP")) {
capabilities.add(Capability(
authScheme ? : AuthMethod.OPEN,
keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
CipherMethod.CCMP
))
}
} else if (authScheme != null || keyManagementAlgorithm != null) {
capabilities.add(Capability(
authScheme ? : AuthMethod.OPEN,
keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
CipherMethod.NONE
))
}
return capabilities
}
private fun parseTopologyMode(capabilitiesString: String): TopologyMode ? {
return capabilitiesString
.splitByBrackets()
.mapNotNull {
when {
it.contains("ESS") - > TopologyMode.ESS
it.contains("BSS") - > TopologyMode.BSS
it.contains("IBSS") - > TopologyMode.IBSS
else - > null
}
}
.firstOrNull()
}
private fun parseWPSAvailable(capabilitiesString: String): Boolean {
return capabilitiesString
.splitByBrackets()
.any {
it.isWps()
}
}
private fun String.splitByBrackets(): List < String > {
val m = Pattern.compile("[(.*?)]").matcher(this)
val parts = ArrayList < String > ()
while (m.find()) {
parts.add(m.group().replace("[", "").replace("]", ""))
}
return parts
}
private fun String.isTopology(): Boolean {
return TopologyMode.values().any {
this == it.name
}
}
private fun String.isWps(): Boolean {
return this == "WPS"
}
8. Nəticəyə baxın
Şəbəkəni skan edib tapdığımı sizə göstərəcəyəm. Log.d vasitəsilə sadə çıxışın nəticələri göstərilir:
Capability of Home-Home [WPA2-PSK-CCMP][ESS][WPS]
...
capabilities=[Capability(authScheme=WPA2, keyManagementAlgorithm=PSK, cipherMethod=CCMP)], topologyMode=ESS, availableWps=true
Tətbiq kodundan şəbəkəyə qoşulma məsələsi araşdırılmamış qaldı. Yalnız onu deyim ki, mobil cihazın OS-dən saxlanmış parolları oxumaq üçün sizə kök hüquqları və wpa_supplicant.conf-u oxumaq üçün fayl sistemini dolaşmağa hazır olmaq lazımdır. Tətbiq məntiqi kənardan parol daxil etməyi tələb edirsə, əlaqə sinif vasitəsilə edilə bilər
Təşəkkür
Nəsə əlavə etmək və ya düzəliş etmək lazım olduğunu düşünürsünüzsə, şərhlərdə yazın :)
Mənbə: www.habr.com