Wi-Fi dan banyak singkatan lainnya. Cara mendapatkan data tentang node Wi-Fi di aplikasi Android tanpa membengkak

Suatu hari saya perlu memindai jaringan Wi-Fi dari aplikasi Android dan mendapatkan data detail tentang titik akses.

Di sini kami harus menghadapi beberapa kesulitan: dokumentasi off.Android banyak dari kelas yang dijelaskan menjadi tidak digunakan lagi (API level > 26), yang tidak tercermin di dalamnya; deskripsi beberapa hal dalam dokumentasi sangat minim (misalnya, bidang kemampuan kelas hasil scan pada saat penulisan, hampir tidak ada yang dijelaskan, meskipun mengandung banyak data penting). Kesulitan ketiga mungkin terletak pada kenyataan bahwa ketika Anda pertama kali mengenal Wi-Fi, selain membaca teori dan mengatur router melalui localhost, Anda harus berurusan dengan sejumlah singkatan yang tampaknya dapat dimengerti satu per satu. Namun mungkin tidak jelas bagaimana menghubungkan dan menyusunnya (penilaian bersifat subyektif dan bergantung pada pengalaman sebelumnya).

Artikel ini membahas cara mendapatkan data komprehensif tentang lingkungan Wi-Fi dari kode Android tanpa NDK, peretasan, tetapi hanya menggunakan Android API dan memahami cara menafsirkannya.

Jangan menunda lagi dan mulai menulis kode.

1. Buat proyek

Catatan ini ditujukan bagi mereka yang telah membuat proyek Android lebih dari satu kali, jadi kami menghilangkan detail item ini. Kode di bawah ini akan disajikan di Kotlin, minSdkVersion=23.

2. Izin akses

Untuk bekerja dengan Wi-Fi dari aplikasi, Anda perlu mendapatkan beberapa izin dari pengguna. Menurut dokumentasi, untuk memindai jaringan pada perangkat dengan versi OS setelah 8.0, selain akses untuk melihat status lingkungan jaringan, Anda memerlukan akses untuk mengubah status modul Wi-Fi perangkat, atau akses ke koordinat (perkiraan atau tepat). Mulai versi 9.0, Anda harus meminta pengguna untuk keduanya, dan juga secara eksplisit meminta pengguna untuk mengaktifkan layanan lokasi. Jangan lupa dengan gagah menjelaskan kepada pengguna bahwa ini adalah keinginan Google, dan bukan keinginan kami untuk memata-matainya :)

Jadi, di AndroidManifest.xml kita akan menambahkan:

    <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"/>

Dan dalam kode yang berisi link ke Aktivitas saat ini:

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. Buat BroadcastReceiver dan berlangganan acara pembaruan data tentang pemindaian lingkungan jaringan Wi-Fi

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
}

Metode WiFiManager.startScan dalam dokumentasi ditandai sebagai tidak digunakan lagi sejak API versi 28, tetapi tidak aktif. membimbing menyarankan untuk menggunakannya.

Secara total, kami menerima daftar objek hasil scan.

4. Lihat ScanResult dan pahami istilahnya

Mari kita lihat beberapa bidang di kelas ini dan jelaskan maksudnya:

SSID β€” Service Set Identifier adalah nama jaringan

BSSID – Pengidentifikasi Set Layanan Dasar – Alamat MAC adaptor jaringan (titik Wi-Fi)

tingkat β€” Indikator Kekuatan Sinyal yang Diterima [dBm (dBm Rusia) β€” Desibel, daya referensi 1 mW.] β€” Indikator kekuatan sinyal yang diterima. Mengambil nilai dari 0 hingga -100, semakin jauh dari 0, semakin banyak daya sinyal yang hilang sepanjang jalur dari titik Wi-Fi ke perangkat Anda. Rincian lebih lanjut dapat ditemukan, misalnya, di Wikipedia. Di sini saya akan memberitahu Anda bahwa menggunakan kelas Android Manajer Wifi Anda dapat mengkalibrasi level sinyal pada skala dari sangat baik hingga buruk pada langkah yang Anda pilih:

        val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
        val numberOfLevels = 5
        val level = WifiManager.calculateSignalLevel(level, numberOfLevels)

frekuensi β€” frekuensi pengoperasian titik Wi-Fi [Hz]. Selain frekuensinya sendiri, Anda mungkin tertarik dengan apa yang disebut saluran. Setiap titik memiliki kemurnian pengoperasiannya sendiri. Pada saat artikel ini ditulis, rentang titik Wi-Fi paling populer adalah 2.4 GHz. Namun, lebih tepatnya, titik tersebut mengirimkan informasi ke telepon Anda pada frekuensi bernomor yang mendekati frekuensi yang disebutkan. Jumlah saluran dan frekuensi yang sesuai terstandarisasi. Hal ini dilakukan agar titik-titik terdekat beroperasi pada frekuensi yang berbeda, sehingga tidak saling mengganggu dan tidak saling mengurangi kecepatan dan kualitas transmisi. Dalam hal ini, titik-titik beroperasi tidak pada satu frekuensi, tetapi pada rentang frekuensi (parameter lebar saluran), disebut lebar saluran. Artinya, titik-titik yang beroperasi pada saluran yang berdekatan (dan tidak hanya berdekatan, tetapi bahkan 3 saluran yang terpisah) saling mengganggu. Anda mungkin menemukan kode sederhana ini berguna, yang memungkinkan Anda menghitung nomor saluran dari nilai frekuensi untuk titik dengan frekuensi 2.4 dan 5 Ghz:


    /* ΠΏΠΎ частотС опрСдСляСм Π½ΠΎΠΌΠ΅Ρ€ ΠΊΠ°Π½Π°Π»Π° */
    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
            }
        }

kemampuan - bidang yang paling menarik untuk dianalisis, pengerjaannya membutuhkan banyak waktu. Di sini β€œkemampuan” poin tersebut dituliskan pada baris. Dalam hal ini, Anda tidak perlu mencari detail interpretasi string di dokumentasi. Berikut adalah beberapa contoh dari apa yang mungkin ada di baris ini:

[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. Memahami singkatan dan kemampuan parsing

Perlu disebutkan bahwa kelas paket android.net.wifi.* digunakan secara tersembunyi oleh utilitas Linux wpa_supplicant dan hasil keluaran pada kolom ability adalah salinan dari kolom flag saat memindai.

Kami akan bertindak secara konsisten. Pertama mari kita pertimbangkan output dari format di mana elemen di dalam tanda kurung dipisahkan oleh tanda β€œ-β€œ:

[WPA-PSK-TKIP+CCMP]
[WPA2-PSK-CCMP]

Arti pertama menggambarkan apa yang disebut. metode otentikasi. Yaitu, urutan tindakan apa yang harus dilakukan perangkat dan titik akses agar titik akses dapat digunakan dan bagaimana mengenkripsi payload. Pada saat penulisan posting ini, opsi yang paling umum adalah WPA dan WPA2, di mana masing-masing perangkat terhubung secara langsung atau melalui apa yang disebut. Server RADIUS (WPA-Enterprice) menyediakan kata sandi melalui saluran terenkripsi. Kemungkinan besar, titik akses di rumah Anda menyediakan koneksi sesuai dengan skema ini. Perbedaan antara versi kedua dan versi pertama adalah ia memiliki sandi yang lebih kuat: AES versus TKIP yang tidak aman. WPA3, yang lebih kompleks dan canggih, juga diperkenalkan secara bertahap. Secara teoritis, mungkin ada opsi dengan solusi perusahaan CCKM (Cisco Centralized Key Management), tapi saya belum pernah menemukannya.

Jalur akses mungkin telah dikonfigurasi untuk mengautentikasi berdasarkan alamat MAC. Atau, jika titik akses menyediakan data menggunakan algoritma WEP yang sudah ketinggalan zaman, maka sebenarnya tidak ada otentikasi (kunci rahasia di sini adalah kunci enkripsi). Kami mengklasifikasikan opsi tersebut sebagai LAINNYA.
Ada juga metode yang populer di wi-fi publik dengan Captive Portal Detection yang tersembunyi - permintaan otentikasi melalui browser. Titik akses tersebut tampak terbuka bagi pemindai (dilihat dari sudut pandang koneksi fisik). Oleh karena itu, kami mengklasifikasikannya sebagai TERBUKA.

Nilai kedua dapat dilambangkan sebagai algoritma manajemen kunci. Ini adalah parameter metode autentikasi yang dijelaskan di atas. Berbicara tentang bagaimana tepatnya kunci enkripsi dipertukarkan. Mari pertimbangkan opsi yang memungkinkan. EAP - digunakan dalam WPA-Enterprice yang disebutkan, menggunakan database untuk memverifikasi data otentikasi yang dimasukkan. SAE - digunakan pada WPA3 tingkat lanjut, lebih tahan terhadap kekerasan. PSK - opsi paling umum, melibatkan memasukkan kata sandi dan mengirimkannya dalam bentuk terenkripsi. IEEE8021X - menurut standar internasional (berbeda dengan yang didukung oleh keluarga WPA). OWE (Enkripsi Nirkabel Oportunistik) merupakan perpanjangan dari standar IEEE 802.11 untuk titik yang kami klasifikasikan sebagai TERBUKA. OWE memastikan keamanan data yang dikirimkan melalui jaringan tidak aman dengan mengenkripsinya. Sebuah opsi juga dimungkinkan ketika tidak ada kunci akses, sebut saja opsi ini TIDAK ADA.

Parameter ketiga adalah yang disebut. skema enkripsi β€” bagaimana tepatnya sandi digunakan untuk melindungi data yang dikirimkan. Mari kita daftar pilihannya. WEP - menggunakan stream cipher RC4, kunci rahasianya adalah kunci enkripsi, yang dianggap tidak dapat diterima di dunia kriptografi modern. TKIP - digunakan di WPA, CKIP - di WPA2. TKIP+CKIP - dapat ditentukan dalam titik berkemampuan WPA dan WPA2 untuk kompatibilitas mundur.

Alih-alih tiga elemen, Anda dapat menemukan tanda WEP yang sepi:

[WEP]

Seperti yang telah kita bahas di atas, ini cukup untuk tidak menentukan algoritma untuk menggunakan kunci, yang tidak ada, dan metode enkripsi, yang sama secara default.

Sekarang perhatikan braket ini:

[ESS]

Itu Mode pengoperasian Wi-Fi ΠΈΠ»ΠΈ Topologi jaringan Wi-Fi. Anda mungkin menemukan mode BSS (Basic Service Set) - ketika ada satu titik akses yang melaluinya perangkat yang terhubung berkomunikasi. Dapat ditemukan di jaringan lokal. Biasanya, titik akses diperlukan untuk menghubungkan perangkat dari jaringan lokal yang berbeda, sehingga merupakan bagian dari Extended Service Sets - ESS. Jenis IBSS (Independent Basic Service Sets) menunjukkan bahwa perangkat merupakan bagian dari jaringan Peer-to-Peer.

Anda juga mungkin melihat bendera WPS:

[WPS]

WPS (Wi-Fi Protected Setup) adalah protokol untuk inisialisasi semi-otomatis jaringan Wi-Fi. Untuk menginisialisasi, pengguna memasukkan kata sandi 8 karakter atau menekan tombol di router. Jika jalur akses Anda adalah tipe pertama dan kotak centang ini muncul di sebelah nama jalur akses Anda, Anda sangat disarankan untuk membuka panel admin dan menonaktifkan akses WPS. Faktanya, seringkali PIN 8 digit dapat diketahui berdasarkan alamat MAC, atau dapat diurutkan dalam waktu yang dapat diperkirakan, yang dapat dimanfaatkan oleh seseorang yang tidak jujur.

6. Membuat model dan fungsi parsing

Berdasarkan apa yang kami temukan di atas, kami akan menjelaskan apa yang terjadi menggunakan kelas data:

/* схСма Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ */
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.
}

Sekarang mari kita tulis sebuah fungsi yang akan mengurai bidang kemampuan:


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. Lihat hasilnya

Saya akan memindai jaringan dan menunjukkan apa yang saya temukan. Tampil hasil output sederhana melalui Log.d:

Capability of Home-Home [WPA2-PSK-CCMP][ESS][WPS]
...
capabilities=[Capability(authScheme=WPA2, keyManagementAlgorithm=PSK, cipherMethod=CCMP)], topologyMode=ESS, availableWps=true

Masalah menghubungkan ke jaringan dari kode aplikasi masih belum terselesaikan. Saya hanya akan mengatakan bahwa untuk membaca kata sandi yang disimpan dari OS perangkat seluler, Anda memerlukan hak root dan kemauan untuk mengobrak-abrik sistem file untuk membaca wpa_supplicant.conf. Jika logika aplikasi mengharuskan memasukkan kata sandi dari luar, koneksi dapat dilakukan melalui kelas android.net.wifi.WifiManager.

Terima kasih Egor Ponomarev untuk tambahan yang berharga.

Jika menurut Anda ada yang perlu ditambahkan atau diperbaiki, tulis di kolom komentar :)

Sumber: www.habr.com

Tambah komentar