(一百七十二) WiFi如何分辨出不同加密方式的AP?

1. ie

之前获取扫描结果的流程中有个将从kernel获取的scan result转换成framework的过程

    /**
    * Fetch the latest scan result from kernel via wificond.
    * @param ifaceName Name of the interface.
    * @return Returns an ArrayList of ScanDetail.
    * Returns an empty ArrayList on failure.
    */
    public ArrayList<ScanDetail> getScanResults(@NonNull String ifaceName, int scanType) {
        ArrayList<ScanDetail> results = new ArrayList<>();
        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
        if (scannerImpl == null) {
            Log.e(TAG, "No valid wificond scanner interface handler");
            return results;
        }
        try {
            NativeScanResult[] nativeResults;
            if (scanType == SCAN_TYPE_SINGLE_SCAN) {
                nativeResults = scannerImpl.getScanResults();
            } else {
                nativeResults = scannerImpl.getPnoScanResults();
            }
            for (NativeScanResult result : nativeResults) {
                WifiSsid wifiSsid = WifiSsid.createFromByteArray(result.ssid);
                String bssid;
                try {
                    bssid = NativeUtil.macAddressFromByteArray(result.bssid);
                } catch (IllegalArgumentException e) {
                    Log.e(TAG, "Illegal argument " + result.bssid, e);
                    continue;
                }
                if (bssid == null) {
                    Log.e(TAG, "Illegal null bssid");
                    continue;
                }
                ScanResult.InformationElement[] ies =
                        InformationElementUtil.parseInformationElements(result.infoElement);
                InformationElementUtil.Capabilities capabilities =
                        new InformationElementUtil.Capabilities();
                capabilities.from(ies, result.capability);
                String flags = capabilities.generateCapabilitiesString();
                NetworkDetail networkDetail;
                try {
                    networkDetail = new NetworkDetail(bssid, ies, null, result.frequency);
                } catch (IllegalArgumentException e) {
                    Log.e(TAG, "Illegal argument for scan result with bssid: " + bssid, e);
                    continue;
                }

                ScanDetail scanDetail = new ScanDetail(networkDetail, wifiSsid, bssid, flags,
                        result.signalMbm / 100, result.frequency, result.tsf, ies, null);
                ScanResult scanResult = scanDetail.getScanResult();
                // Update carrier network info if this AP's SSID is associated with a carrier Wi-Fi
                // network and it uses EAP.
                if (ScanResultUtil.isScanResultForEapNetwork(scanDetail.getScanResult())
                        && mCarrierNetworkConfig.isCarrierNetwork(wifiSsid.toString())) {
                    scanResult.isCarrierAp = true;
                    scanResult.carrierApEapType =
                            mCarrierNetworkConfig.getNetworkEapType(wifiSsid.toString());
                    scanResult.carrierName =
                            mCarrierNetworkConfig.getCarrierName(wifiSsid.toString());
                }
                // Fill up the radio chain info.
                if (result.radioChainInfos != null) {
                    scanResult.radioChainInfos =
                        new ScanResult.RadioChainInfo[result.radioChainInfos.size()];
                    int idx = 0;
                    for (RadioChainInfo nativeRadioChainInfo : result.radioChainInfos) {
                        scanResult.radioChainInfos[idx] = new ScanResult.RadioChainInfo();
                        scanResult.radioChainInfos[idx].id = nativeRadioChainInfo.chainId;
                        scanResult.radioChainInfos[idx].level = nativeRadioChainInfo.level;
                        idx++;
                    }
                }
                results.add(scanDetail);
            }
        } catch (RemoteException e1) {
            Log.e(TAG, "Failed to create ScanDetail ArrayList");
        }
        if (mVerboseLoggingEnabled) {
            Log.d(TAG, "get " + results.size() + " scan results from wificond");
        }

        return results;
    }

从上面可以看到解析出ssid和bssid

加密方式没怎么看的到,抽出来看下这一段

                ScanResult.InformationElement[] ies =
                        InformationElementUtil.parseInformationElements(result.infoElement);
                InformationElementUtil.Capabilities capabilities =
                        new InformationElementUtil.Capabilities();
                capabilities.from(ies, result.capability);
                String flags = capabilities.generateCapabilitiesString();
                NetworkDetail networkDetail;
                try {
                    networkDetail = new NetworkDetail(bssid, ies, null, result.frequency);
                } catch (IllegalArgumentException e) {
                    Log.e(TAG, "Illegal argument for scan result with bssid: " + bssid, e);
                    continue;
                }

                ScanDetail scanDetail = new ScanDetail(networkDetail, wifiSsid, bssid, flags,
                        result.signalMbm / 100, result.frequency, result.tsf, ies, null);
                ScanResult scanResult = scanDetail.getScanResult();

看下capabilities.from

        /**
         * Parse the Information Element and the 16-bit Capability Information field
         * to build the InformationElemmentUtil.capabilities object.
         *
         * @param ies -- Information Element array
         * @param beaconCap -- 16-bit Beacon Capability Information field
         */

        public void from(InformationElement[] ies, BitSet beaconCap) {
            protocol = new ArrayList<Integer>();
            keyManagement = new ArrayList<ArrayList<Integer>>();
            groupCipher = new ArrayList<Integer>();
            pairwiseCipher = new ArrayList<ArrayList<Integer>>();

            if (ies == null || beaconCap == null) {
                return;
            }
            isESS = beaconCap.get(CAP_ESS_BIT_OFFSET);
            isPrivacy = beaconCap.get(CAP_PRIVACY_BIT_OFFSET);
            for (InformationElement ie : ies) {
                if (ie.id == InformationElement.EID_RSN) {
                    parseRsnElement(ie);
                }

                if (ie.id == InformationElement.EID_VSA) {
                    if (isWpaOneElement(ie)) {
                        parseWpaOneElement(ie);
                    }
                    if (isWpsElement(ie)) {
                        // TODO(b/62134557): parse WPS IE to provide finer granularity information.
                        isWPS = true;
                    }
                }
            }
        }



        // RSNE format (size unit: byte)
        //
        // | Element ID | Length | Version | Group Data Cipher Suite |
        //      1           1         2                 4
        // | Pairwise Cipher Suite Count | Pairwise Cipher Suite List |
        //              2                            4 * m
        // | AKM Suite Count | AKM Suite List | RSN Capabilities |
        //          2               4 * n               2
        // | PMKID Count | PMKID List | Group Management Cipher Suite |
        //        2          16 * s                 4
        //
        // Note: InformationElement.bytes has 'Element ID' and 'Length'
        //       stripped off already
        private void parseRsnElement(InformationElement ie) {
            ByteBuffer buf = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN);

            try {
                // version
                if (buf.getShort() != RSNE_VERSION) {
                    // incorrect version
                    return;
                }

                // found the RSNE IE, hence start building the capability string
                protocol.add(ScanResult.PROTOCOL_WPA2);

                // group data cipher suite
                groupCipher.add(parseRsnCipher(buf.getInt()));

                // pairwise cipher suite count
                short cipherCount = buf.getShort();
                ArrayList<Integer> rsnPairwiseCipher = new ArrayList<>();
                // pairwise cipher suite list
                for (int i = 0; i < cipherCount; i++) {
                    rsnPairwiseCipher.add(parseRsnCipher(buf.getInt()));
                }
                pairwiseCipher.add(rsnPairwiseCipher);

                // AKM
                // AKM suite count
                short akmCount = buf.getShort();
                ArrayList<Integer> rsnKeyManagement = new ArrayList<>();

                for (int i = 0; i < akmCount; i++) {
                    int akm = buf.getInt();
                    switch (akm) {
                        case WPA2_AKM_EAP:
                            rsnKeyManagement.add(ScanResult.KEY_MGMT_EAP);
                            break;
                        case WPA2_AKM_PSK:
                            rsnKeyManagement.add(ScanResult.KEY_MGMT_PSK);
                            break;
                        case WPA2_AKM_FT_EAP:
                            rsnKeyManagement.add(ScanResult.KEY_MGMT_FT_EAP);
                            break;
                        case WPA2_AKM_FT_PSK:
                            rsnKeyManagement.add(ScanResult.KEY_MGMT_FT_PSK);
                            break;
                        case WPA2_AKM_EAP_SHA256:
                            rsnKeyManagement.add(ScanResult.KEY_MGMT_EAP_SHA256);
                            break;
                        case WPA2_AKM_PSK_SHA256:
                            rsnKeyManagement.add(ScanResult.KEY_MGMT_PSK_SHA256);
                            break;
                        default:
                            // do nothing
                            break;
                    }
                }
                // Default AKM
                if (rsnKeyManagement.isEmpty()) {
                    rsnKeyManagement.add(ScanResult.KEY_MGMT_EAP);
                }
                keyManagement.add(rsnKeyManagement);
            } catch (BufferUnderflowException e) {
                Log.e("IE_Capabilities", "Couldn't parse RSNE, buffer underflow");
            }
        }

这边不怎么看的懂了,但大概就是将加密方式解析出来了

然后生成Capabilities显示成我们常见的加密方式

        /**
         * Build the ScanResult.capabilities String.
         *
         * @return security string that mirrors what wpa_supplicant generates
         */
        public String generateCapabilitiesString() {
            String capabilities = "";
            // private Beacon without an RSNE or WPA IE, hence WEP0
            boolean isWEP = (protocol.isEmpty()) && isPrivacy;

            if (isWEP) {
                capabilities += "[WEP]";
            }
            for (int i = 0; i < protocol.size(); i++) {
                capabilities += "[" + protocolToString(protocol.get(i));
                if (i < keyManagement.size()) {
                    for (int j = 0; j < keyManagement.get(i).size(); j++) {
                        capabilities += ((j == 0) ? "-" : "+")
                                + keyManagementToString(keyManagement.get(i).get(j));
                    }
                }
                if (i < pairwiseCipher.size()) {
                    for (int j = 0; j < pairwiseCipher.get(i).size(); j++) {
                        capabilities += ((j == 0) ? "-" : "+")
                                + cipherToString(pairwiseCipher.get(i).get(j));
                    }
                }
                capabilities += "]";
            }
            if (isESS) {
                capabilities += "[ESS]";
            }
            if (isWPS) {
                capabilities += "[WPS]";
            }

            return capabilities;
        }
    }


        private String keyManagementToString(int akm) {
            switch (akm) {
                case ScanResult.KEY_MGMT_NONE:
                    return "None";
                case ScanResult.KEY_MGMT_PSK:
                    return "PSK";
                case ScanResult.KEY_MGMT_EAP:
                    return "EAP";
                case ScanResult.KEY_MGMT_FT_EAP:
                    return "FT/EAP";
                case ScanResult.KEY_MGMT_FT_PSK:
                    return "FT/PSK";
                case ScanResult.KEY_MGMT_EAP_SHA256:
                    return "EAP-SHA256";
                case ScanResult.KEY_MGMT_PSK_SHA256:
                    return "PSK-SHA256";
                default:
                    return "?";
            }
        }


看下AccessPoint怎么获取加密方式的

    private static int getSecurity(ScanResult result) {
        if (result.capabilities.contains("WEP")) {
            return SECURITY_WEP;
        } else if (result.capabilities.contains("PSK")) {
            return SECURITY_PSK;
        } else if (result.capabilities.contains("EAP")) {
            return SECURITY_EAP;
        }
        return SECURITY_NONE;
    }

可以看到是和上面对应的,虽然这边就是简单的判断是否包含字符串。

 

2.总结

看了个大概,加密方式大概是从扫描结果中的ie解析出来放在一个叫做capabilities里的,后续上面判断加密方式就简单判断下是否包含特定加密方式的字符串就好了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值