Un diwrnod roedd angen i mi sganio rhwydweithiau Wi-Fi o gymwysiadau Android a chael data manwl am bwyntiau mynediad.
Yma bu'n rhaid i ni wynebu sawl anhawster:
Mae'r erthygl hon yn trafod sut i gael data cynhwysfawr am yr amgylchedd Wi-Fi o god Android heb NDK, haciau, ond dim ond defnyddio'r API Android a deall sut i'w ddehongli.
Gadewch i ni beidio ag oedi a dechrau ysgrifennu cod.
1. Creu prosiect
Mae'r nodyn hwn wedi'i fwriadu ar gyfer y rhai sydd wedi creu prosiect Android fwy nag unwaith, felly rydym yn hepgor manylion yr eitem hon. Bydd y cod isod yn cael ei gyflwyno yn Kotlin, minSdkVersion=23.
2. Caniatâd mynediad
I weithio gyda Wi-Fi o'r rhaglen, bydd angen i chi gael sawl caniatâd gan y defnyddiwr. Yn unol â
Felly, yn AndroidManifest.xml byddwn yn ychwanegu:
<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"/>
Ac yn y cod sy'n cynnwys dolen i'r Gweithgaredd cyfredol:
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. Creu BroadcastReceiver a thanysgrifio i ddigwyddiadau diweddaru data am sganio'r amgylchedd rhwydwaith 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
}
Mae'r dull WiFiManager.startScan yn y ddogfennaeth wedi'i nodi fel un sydd wedi'i amddifadu ers fersiwn API 28, ond i ffwrdd.
Yn gyfan gwbl, cawsom restr o wrthrychau
4. Edrychwch ar ScanResult a deall y termau
Edrychwn ar rai meysydd o'r dosbarth hwn a disgrifio'r hyn y maent yn ei olygu:
SSID — Dynodwr Set Gwasanaeth yw enw'r rhwydwaith
BSSID - Dynodwr Set Gwasanaeth Sylfaenol - cyfeiriad MAC addasydd y rhwydwaith (pwynt Wi-Fi)
lefel — Dangosydd Cryfder Signalau a Dderbyniwyd [dBm (dBm Rwsiaidd) — Decibel, pŵer cyfeirio 1 mW.] — Dangosydd o gryfder y signal a dderbyniwyd. Yn cymryd gwerth o 0 i -100, po bellaf o 0, y mwyaf o bŵer signal a gollwyd ar hyd y ffordd o'r pwynt Wi-Fi i'ch dyfais. Ceir rhagor o fanylion, er enghraifft, yn
val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
val numberOfLevels = 5
val level = WifiManager.calculateSignalLevel(level, numberOfLevels)
amledd — amledd gweithredu'r pwynt Wi-Fi [Hz]. Yn ychwanegol at yr amlder ei hun, efallai y bydd gennych ddiddordeb yn y sianel fel y'i gelwir. Mae gan bob pwynt ei burdeb gweithredu ei hun. Ar adeg ysgrifennu, yr ystod fwyaf poblogaidd o bwyntiau Wi-Fi yw 2.4 GHz. Ond, i fod yn fwy manwl gywir, mae'r pwynt yn trosglwyddo gwybodaeth i'ch ffôn ar amlder wedi'i rifo yn agos at yr un a enwir. Nifer y sianeli ac amleddau cyfatebol
/* по частоте определяем номер канала */
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
}
}
galluoedd - y maes mwyaf diddorol ar gyfer dadansoddi, gwaith yr oedd angen llawer o amser ag ef. Yma mae “galluoedd” y pwynt wedi'u hysgrifennu yn y llinell. Yn yr achos hwn, nid oes rhaid i chi edrych am fanylion dehongli llinynnol yn y ddogfennaeth. Dyma rai enghreifftiau o'r hyn a allai fod yn y llinell hon:
[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. Deall byrfoddau a galluoedd dosrannu
Mae'n werth nodi bod dosbarthiadau'r pecyn android.net.wifi.* yn cael eu defnyddio o dan y cwfl gan gyfleustodau Linux
Byddwn yn gweithredu’n gyson. Yn gyntaf, gadewch i ni ystyried allbwn fformat lle mae elfennau y tu mewn i gromfachau yn cael eu gwahanu gan arwydd “-“:
[WPA-PSK-TKIP+CCMP]
[WPA2-PSK-CCMP]
Mae'r ystyr cyntaf yn disgrifio'r hyn a elwir. dull dilysu. Hynny yw, pa ddilyniant o gamau gweithredu y mae'n rhaid i'r ddyfais a'r pwynt mynediad eu perfformio er mwyn i'r pwynt mynediad ganiatáu iddo'i hun gael ei ddefnyddio a sut i amgryptio'r llwyth tâl. Ar adeg ysgrifennu'r swydd hon, yr opsiynau mwyaf cyffredin yw WPA a WPA2, lle mae naill ai pob dyfais gysylltiedig yn uniongyrchol neu drwy'r hyn a elwir. Mae'r gweinydd RADIUS (WPA-Enterprice) yn darparu'r cyfrinair dros sianel wedi'i hamgryptio. Yn fwyaf tebygol, mae'r pwynt mynediad yn eich cartref yn darparu cysylltiad yn unol â'r cynllun hwn. Y gwahaniaeth rhwng yr ail fersiwn a'r cyntaf yw bod ganddo seiffr cryfach: AES yn erbyn y TKIP ansicr. Mae WPA3, sy'n fwy cymhleth a datblygedig, hefyd yn cael ei gyflwyno'n raddol. Yn ddamcaniaethol, efallai y bydd opsiwn gyda'r datrysiad enterprice CCKM (Cisco Centralized Key Management), ond nid wyf erioed wedi dod ar ei draws.
Mae'n bosibl bod y pwynt mynediad wedi'i ffurfweddu i ddilysu yn ôl cyfeiriad MAC. Neu, os yw'r pwynt mynediad yn darparu data gan ddefnyddio'r algorithm WEP sydd wedi dyddio, yna nid oes unrhyw ddilysu mewn gwirionedd (yr allwedd gyfrinachol yma yw'r allwedd amgryptio). Rydym yn dosbarthu opsiynau o'r fath fel ARALL.
Mae yna hefyd ddull sy'n boblogaidd mewn wi-fi cyhoeddus gyda Canfod Porth Caethus cudd - cais dilysu trwy borwr. Mae pwyntiau mynediad o'r fath yn ymddangos i'r sganiwr fel rhai agored (y maent o safbwynt y cysylltiad ffisegol). Felly, rydym yn eu dosbarthu fel AGORED.
Gellir dynodi'r ail werth fel algorithm rheoli allweddol. Mae hwn yn baramedr o'r dull dilysu a ddisgrifir uchod. Sôn am yn union sut mae allweddi amgryptio yn cael eu cyfnewid. Gadewch i ni ystyried yr opsiynau posibl. Mae EAP - a ddefnyddir yn y WPA-Enterprice y soniwyd amdano, yn defnyddio cronfa ddata i wirio'r data dilysu a gofnodwyd. SAE - a ddefnyddir mewn WPA3 datblygedig, yn fwy gwrthsefyll grym 'n ysgrublaidd. PSK - yr opsiwn mwyaf cyffredin, sy'n golygu mynd i mewn i gyfrinair a'i drosglwyddo ar ffurf wedi'i amgryptio. IEEE8021X - yn unol â safon ryngwladol (yn wahanol i'r hyn a gefnogir gan deulu WPA). Mae OWE (Amgryptio Di-wifr Opportunistic) yn estyniad o safon IEEE 802.11 ar gyfer pwyntiau a ddosbarthwyd gennym fel AGORED. Mae OWE yn sicrhau diogelwch data a drosglwyddir dros rwydwaith anniogel trwy ei amgryptio. Mae opsiwn hefyd yn bosibl pan nad oes allweddi mynediad, gadewch i ni alw'r opsiwn hwn DIM.
Y trydydd paramedr yw'r hyn a elwir. cynlluniau amgryptio — sut yn union y defnyddir y seiffr i ddiogelu'r data a drosglwyddir. Gadewch i ni restru'r opsiynau. WEP - yn defnyddio cipher ffrwd RC4, yr allwedd gyfrinachol yw'r allwedd amgryptio, a ystyrir yn annerbyniol ym myd cryptograffeg modern. TKIP - a ddefnyddir yn WPA, CKIP - yn WPA2. TKIP + CKIP - gellir ei nodi mewn pwyntiau sy'n gallu WPA a WPA2 ar gyfer cydweddoldeb yn ôl.
Yn lle tair elfen, gallwch ddod o hyd i farc WEP unig:
[WEP]
Fel y trafodwyd uchod, mae hyn yn ddigon i beidio â nodi'r algorithm ar gyfer defnyddio allweddi, nad yw'n bodoli, a'r dull amgryptio, sydd yr un peth yn ddiofyn.
Nawr ystyriwch y braced hwn:
[ESS]
Mae'n Modd gweithredu Wi-Fi neu Topoleg rhwydwaith Wi-Fi. Efallai y byddwch yn dod ar draws modd BSS (Set Gwasanaeth Sylfaenol) - pan fydd un pwynt mynediad y mae dyfeisiau cysylltiedig yn cyfathrebu drwyddo. Gellir dod o hyd iddo ar rwydweithiau lleol. Fel rheol, mae angen pwyntiau mynediad i gysylltu dyfeisiau o wahanol rwydweithiau lleol, felly maent yn rhan o Setiau Gwasanaeth Estynedig - ESS. Mae'r math IBSSs (Setiau Gwasanaeth Sylfaenol Annibynnol) yn nodi bod y ddyfais yn rhan o rwydwaith Cyfoedion i Gyfoedion.
Efallai y byddwch hefyd yn gweld baner WPS:
[WPS]
Protocol ar gyfer cychwyn rhwydwaith Wi-Fi yn lled-awtomatig yw WPS (Gosodiad Gwarchodedig Wi-Fi). I gychwyn, mae'r defnyddiwr naill ai'n mynd i mewn i gyfrinair 8-cymeriad neu'n pwyso botwm ar y llwybrydd. Os yw'ch pwynt mynediad o'r math cyntaf a bod y blwch ticio hwn yn ymddangos wrth ymyl enw eich pwynt mynediad, fe'ch cynghorir yn gryf i fynd i'r panel gweinyddol ac analluogi mynediad WPS. Y ffaith yw y gellir dod o hyd i'r PIN 8 digid yn aml wrth y cyfeiriad MAC, neu gellir ei ddatrys mewn amser rhagweladwy, y gall rhywun yn anonest fanteisio arno.
6. Creu model a swyddogaeth dosrannu
Yn seiliedig ar yr hyn a ddarganfuwyd uchod, byddwn yn disgrifio beth ddigwyddodd gan ddefnyddio dosbarthiadau 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.
}
Nawr, gadewch i ni ysgrifennu swyddogaeth a fydd yn dosrannu'r maes galluoedd:
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. Gweler y canlyniad
Byddaf yn sganio'r rhwydwaith ac yn dangos i chi yr hyn a ddarganfyddais. Dangosir canlyniadau allbwn syml trwy Log.d:
Capability of Home-Home [WPA2-PSK-CCMP][ESS][WPS]
...
capabilities=[Capability(authScheme=WPA2, keyManagementAlgorithm=PSK, cipherMethod=CCMP)], topologyMode=ESS, availableWps=true
Roedd y mater o gysylltu â'r rhwydwaith o'r cod cais yn parhau heb ei archwilio. Ni fyddaf ond yn dweud, er mwyn darllen cyfrineiriau sydd wedi'u cadw o OS dyfais symudol, bod angen hawliau gwraidd arnoch a pharodrwydd i chwilota trwy'r system ffeiliau i ddarllen wpa_supplicant.conf. Os yw rhesymeg y cais yn gofyn am fewnbynnu cyfrinair o'r tu allan, gellir gwneud y cysylltiad trwy'r dosbarth
Diolch
Os ydych chi'n meddwl bod angen ychwanegu neu gywiro rhywbeth, ysgrifennwch y sylwadau :)
Ffynhonnell: hab.com