I kekahi lā pono wau e nānā i nā pūnaewele Wi-Fi mai nā polokalamu Android a loaʻa ka ʻikepili kikoʻī e pili ana i nā wahi komo.
Ma ʻaneʻi ua loaʻa iā mākou kekahi mau pilikia:
Kūkākūkā kēia ʻatikala pehea e loaʻa ai ka ʻikepili piha e pili ana i ke kaiapuni Wi-Fi mai ka Android code me ka ʻole o NDK, hacks, akā hoʻohana wale i ka Android API a hoʻomaopopo i ka wehewehe ʻana.
Mai hoʻokaʻulua a hoʻomaka kākou e kākau code.
1. Hana i kahi papahana
Kuhi ʻia kēia memo no ka poʻe i hana i kahi papahana Android ma mua o hoʻokahi manawa, no laila e haʻalele mākou i nā kikoʻī o kēia mea. E hōʻike ʻia ke code ma lalo nei ma Kotlin, minSdkVersion=23.
2. Nā ʻae komo
No ka hana ʻana me Wi-Fi mai ka noi, pono ʻoe e kiʻi i nā ʻae mai ka mea hoʻohana. I kulike ai me
No laila, ma AndroidManifest.xml mākou e hoʻohui:
<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"/>
A ma ke code i loaʻa kahi loulou i ka hana o kēia manawa:
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. Hana i kahi BroadcastReceiver a kau inoa i nā hanana hōʻano hou e pili ana i ka nānā ʻana i ke kaiapuni pūnaewele 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
}
ʻO ke ala WiFiManager.startScan i loko o ka palapala i hōʻailona ʻia ʻo ia ka mea i hoʻopau ʻia mai ka API version 28, akā ua hala.
I ka huina, ua loaʻa iā mākou kahi papa inoa o nā mea
4. E nānā iā ScanResult a hoʻomaopopo i nā huaʻōlelo
E nānā kākou i kekahi mau māhele o kēia papa a wehewehe i ke ʻano o ia mau mea:
SSID — ʻO ka Service Set Identifier ka inoa o ka pūnaewele
Nā BSSID - Mea hoʻonohonoho hoʻonohonoho maʻamau - helu MAC o ka mea hoʻopili pūnaewele (wahi Wi-Fi)
ilikai — Loaʻa ka hōʻailona hōʻailona ikaika [dBm (Russian dBm) - Decibel, mana kuhikuhi 1 mW.] - He hōʻailona o ka ikaika hōʻailona i loaʻa. Lawe i kahi waiwai mai 0 a -100, ʻoi aku ka nui mai ka 0, ʻoi aku ka nui o ka mana hōʻailona i nalowale ma ke ala mai ka lae Wi-Fi i kāu hāmeʻa. Hiki ke loaʻa nā kikoʻī hou aku, no ka laʻana, ma
val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
val numberOfLevels = 5
val level = WifiManager.calculateSignalLevel(level, numberOfLevels)
alapine (frequency) — ka alapine hana o ke kiko Wi-Fi [Hz]. Ma waho aʻe o ke alapine ponoʻī, makemake paha ʻoe i ke kahawai i kapa ʻia. Loaʻa i kēlā me kēia wahi kona maʻemaʻe hana ponoʻī. I ka manawa e kākau ai, ʻo 2.4 GHz ka laulā kaulana loa o nā wahi Wi-Fi. Akā, no ka ʻoi aku ka pololei, hoʻouna ke kiko i ka ʻike i kāu kelepona ma kahi alapine helu kokoke i ka mea i kapa ʻia. Ka helu o nā kaha a me nā alapine kūpono
/* по частоте определяем номер канала */
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
}
}
nā mea hiki - ke kahua hoihoi loa no ka nānā ʻana, hana me ka mea e pono ai ka manawa nui. Maanei ua kākau ʻia nā "hiki" o ke kiko ma ka laina. I kēia hihia, ʻaʻole pono ʻoe e ʻimi i nā kikoʻī o ka wehewehe ʻana i ke kaula i ka palapala. Eia kekahi mau laʻana o ka mea i loko o kēia laina:
[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. Ka hoʻomaopopo ʻana i nā pōkole a me nā hiki ke koho
Pono e ʻōlelo ʻia e hoʻohana ʻia nā papa o ka android.net.wifi.* ma lalo o ka puʻupuʻu e kahi pono Linux.
E hana mau mākou. E noʻonoʻo mua i ka hoʻopuka ʻana o kahi ʻano i hoʻokaʻawale ʻia nā mea i loko o nā pale e kahi hōʻailona "-":
[WPA-PSK-TKIP+CCMP]
[WPA2-PSK-CCMP]
ʻO ka manaʻo mua e wehewehe i ka mea i kapa ʻia. ʻano hōʻoia. ʻO ia hoʻi, he aha ke ʻano o nā hana e pono ai ka mea hana a me ka wahi hiki ke hana i mea e hiki ai i ka wahi hiki ke ʻae iā ia iho e hoʻohana ʻia a pehea e hoʻopili ai i ka uku uku. I ka manawa e kākau ai i kēia pou, ʻo nā koho maʻamau ʻo WPA a me WPA2, kahi i pili pono ai kēlā me kēia mea pili a i ʻole ma o ka mea i kapa ʻia. Hāʻawi ke kikowaena RADIUS (WPA-Enterprice) i ka ʻōlelo huna ma luna o kahi kahawai i hoʻopili ʻia. ʻO ka mea maʻamau, ʻo ka wahi komo i kou home e hāʻawi i kahi pilina e like me kēia hoʻolālā. ʻO ka ʻokoʻa ma waena o ka ʻaoʻao ʻelua a me ka mea mua, ʻoi aku ka ikaika o ka cipher: AES me ka TKIP paʻa ʻole. ʻO ka WPA3, ʻoi aku ka paʻakikī a me ka holomua, ke hoʻokomo lohi ʻia nei. ʻO ka manaʻo, aia paha kahi koho me ka hoʻonā enterprice CCKM (Cisco Centralized Key Management), akā ʻaʻole au i ʻike.
Ua hoʻonohonoho ʻia paha ka wahi komo e hōʻoia e ka helu MAC. A i ʻole, inā hāʻawi ka wahi komo i ka ʻikepili me ka hoʻohana ʻana i ka algorithm WEP kahiko, a laila ʻaʻohe hōʻoia ʻoiaʻiʻo (ʻo ke kī huna ma ʻaneʻi ke kī hoʻopunipuni). Hoʻokaʻawale mākou i nā koho e like me OTHER.
Aia kekahi ala kaulana i ka lehulehu wi-fi me ka huna Captive Portal Detection - kahi noi hōʻoia ma o ka polokalamu kele pūnaewele. Hōʻike ʻia kēlā mau wahi komo i ka scanner ma ke ʻano he hāmama (ʻo ia mai ka ʻike o ka pili kino). No laila, hoʻokaʻawale mākou iā lākou he OPEN.
Hiki ke kuhikuhi ʻia ka waiwai ʻelua algorithm hooponopono kī. He palena kēia o ke ʻano hōʻoia i hōʻike ʻia ma luna. Kūkākūkā e pili ana i ka hoʻololi ʻana i nā kī hoʻopunipuni. E noʻonoʻo kākou i nā koho hiki. EAP - hoʻohana ʻia i ka WPA-Enterprice i ʻōlelo ʻia, hoʻohana i kahi waihona e hōʻoia i ka ʻikepili hōʻoia i hoʻokomo ʻia. SAE - hoʻohana ʻia i ka WPA3 kiʻekiʻe, ʻoi aku ke kūpaʻa i ka ikaika. ʻO PSK - ke koho maʻamau, pili i ke komo ʻana i kahi ʻōlelo huna a hoʻouna iā ia ma ke ʻano i hoʻopili ʻia. IEEE8021X - e like me ke kūlana honua (ʻokoʻa i ka mea i kākoʻo ʻia e ka ʻohana WPA). ʻO OWE (Opportunistic Wireless Encryption) he hoʻonui ia o ka maʻamau IEEE 802.11 no nā helu a mākou i helu ʻia ʻo OPEN. Mālama ʻo OWE i ka palekana o ka ʻikepili i hoʻouna ʻia ma luna o kahi pūnaewele paʻa ʻole ma o ka hoʻopili ʻana iā ia. Hiki nō hoʻi ke koho inā ʻaʻohe kī komo, e kāhea kākou i kēia koho NONE.
ʻO ke kolu o ka parameter ka mea i kapa ʻia. nā papahana hoʻopunipuni - pehea e hoʻohana pono ʻia ai ka cipher no ka pale ʻana i ka ʻikepili i hoʻouna ʻia. E papa inoa i nā koho. WEP - hoʻohana i ka RC4 stream cipher, ʻo ke kī huna ke kī hoʻopunipuni, i manaʻo ʻia ʻaʻole i ʻae ʻia i ka honua o ka cryptography hou. TKIP - hoʻohana ʻia ma WPA, CKIP - ma WPA2. TKIP+CKIP - hiki ke kuhikuhi ʻia i nā kiko i hiki iā WPA a me WPA2 no ka hoʻokō ʻana i hope.
Ma kahi o ʻekolu mau mea, hiki iā ʻoe ke loaʻa kahi māka WEP mehameha:
[WEP]
E like me kā mākou i kūkākūkā ai ma luna, ua lawa kēia ʻaʻole e wehewehe i ka algorithm no ka hoʻohana ʻana i nā kī, ʻaʻole i loaʻa, a me ke ʻano hoʻopunipuni, ʻo ia ka mea like me ka paʻamau.
I kēia manawa e noʻonoʻo i kēia bracket:
[ESS]
keia ʻO ke ʻano hana Wi-Fi ai ole ia, Topology pūnaewele Wi-Fi. Hiki iā ʻoe ke hālāwai me ke ʻano BSS (Basic Service Set) - ke loaʻa hoʻokahi wahi komo e kamaʻilio ai nā mea pili. Hiki ke loaʻa ma nā pūnaewele kūloko. Ma ke ʻano maʻamau, pono nā wahi komo e hoʻopili ai i nā polokalamu mai nā pūnaewele kūloko like ʻole, no laila he ʻāpana lākou o Extended Service Sets - ESS. Hōʻike ke ʻano IBSS (Independent Basic Service Sets) he ʻāpana ka mea hana o kahi pūnaewele Peer-to-Peer.
Hiki iā ʻoe ke ʻike i ka hae WPS:
[WPS]
ʻO WPS (Wi-Fi Protected Setup) kahi protocol no ka hoʻomaka semi-akomi o kahi pūnaewele Wi-Fi. No ka hoʻomaka ʻana, hoʻokomo ka mea hoʻohana i kahi huaʻōlelo 8-ʻano a i ʻole kaomi i kahi pihi ma ke alalai. Inā ʻo ka ʻano mua kāu wahi e komo ai a ʻike ʻia kēia pahu pahu ma ka ʻaoʻao o ka inoa o kāu wahi komo, pono ʻoe e hele i ka ʻaoʻao admin a hoʻopau i ke komo WPS. ʻO ka ʻoiaʻiʻo, hiki ke ʻike pinepine ʻia ka PIN 8-helu e ka helu MAC, a i ʻole hiki ke hoʻokaʻawale ʻia i ka manawa i ʻike ʻia, hiki i kekahi ke hoʻohana pono ʻole.
6. E hana i kahi hoʻohālike a me ka hana parsing
Ma muli o ka mea a mākou i ʻike ai ma luna, e wehewehe mākou i ka mea i hana me ka hoʻohana ʻana i nā papa ʻikepili:
/* схема аутентификации */
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.
}
I kēia manawa, e kākau kāua i kahi hana e hoʻokaʻawale i ke kahua kaha:
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. E nana i ka hopena
E nānā au i ka pūnaewele a hōʻike iā ʻoe i kaʻu mea i loaʻa ai. Hōʻike ʻia nā hopena o ka hoʻopuka maʻalahi ma o Log.d:
Capability of Home-Home [WPA2-PSK-CCMP][ESS][WPS]
...
capabilities=[Capability(authScheme=WPA2, keyManagementAlgorithm=PSK, cipherMethod=CCMP)], topologyMode=ESS, availableWps=true
ʻAʻole i noʻonoʻo ʻia ka pilikia o ka hoʻopili ʻana i ka pūnaewele mai ke code noi. E ʻōlelo wale wau no ka heluhelu ʻana i nā huaʻōlelo i mālama ʻia mai ka OS o kahi polokalamu kelepona, pono ʻoe i nā kuleana aʻa a me ka makemake e ʻimi i ka ʻōnaehana faila e heluhelu ai wpa_supplicant.conf. Inā makemake ka loiloi noi e hoʻokomo i kahi ʻōlelo huna mai waho mai, hiki ke hana ʻia ka pilina ma o ka papa
Спасибо
Inā manaʻo ʻoe he pono e hoʻohui a hoʻoponopono ʻia paha, e kākau i loko o nā manaʻo :)
Source: www.habr.com