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:
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
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.
Secara total, kami menerima daftar objek
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
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
/* ΠΏΠΎ ΡΠ°ΡΡΠΎΡΠ΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΠΌ Π½ΠΎΠΌΠ΅Ρ ΠΊΠ°Π½Π°Π»Π° */
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
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
Terima kasih
Jika menurut Anda ada yang perlu ditambahkan atau diperbaiki, tulis di kolom komentar :)
Sumber: www.habr.com