天天看點

Android WIFI密碼檢視器執行個體(在擷取Root權限下檢視系統檔案)Android WIFI密碼檢視器執行個體

Android WIFI密碼檢視器執行個體

實作原理:使用shell指令檢視儲存WIFI密碼的系統檔案

涉及的知識

  1. 界面展示
  2. 基本的Shell指令
  3. shell檢視WIFI密碼
  4. ShellUtil的使用
  5. 正規表達式解析字元串
  6. ExpandableListView的使用

界面展示

主界面隻包含一個

ExpandableListView

Android WIFI密碼檢視器執行個體(在擷取Root權限下檢視系統檔案)Android WIFI密碼檢視器執行個體

基本的Shell指令

1.shel由

adb shell

進入,基本指令于Linux下的指令相同,這邊示範幾個常用的指令

Android WIFI密碼檢視器執行個體(在擷取Root權限下檢視系統檔案)Android WIFI密碼檢視器執行個體
Android WIFI密碼檢視器執行個體(在擷取Root權限下檢視系統檔案)Android WIFI密碼檢視器執行個體

因為是在手機的系統檔案下操作,是以部分指令不友善示範,下面直接進入檢視wifi密碼的指令

首先執行

su

擷取root權限
Android WIFI密碼檢視器執行個體(在擷取Root權限下檢視系統檔案)Android WIFI密碼檢視器執行個體
執行

cat /data/misc/wifi/wpa_supplicant.conf

來檢視本地的WIFI資訊
Android WIFI密碼檢視器執行個體(在擷取Root權限下檢視系統檔案)Android WIFI密碼檢視器執行個體

在應用内部執行shell指令

此處我們用到是ShellUtil的java檔案,來源于網絡,封裝了一寫方法用于執行shell指令,代碼如下

注釋都在代碼内部,此處不多加解釋

package com.brioal.poswermanager;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

public class ShellUtils {

    public static final String COMMAND_SU = "su"; // 擷取root權限的指令
    public static final String COMMAND_SH = "sh"; // 執行sh檔案的指令
    public static final String COMMAND_EXIT = "exit\n"; // 退出的指令
    public static final String COMMAND_LINE_END = "\n"; // 執行指令必須加在末尾

    private ShellUtils() {
        throw new AssertionError();
    }
    //檢測root狀态
    public static boolean checkRootPermission() {
        return execCommand("echo root", true, false).result == ;
    }
    //執行單行指令,實際還是調用的執行多行 ,傳入指令和是否需要root
    public static CommandResult execCommand(String command, boolean isRoot) {
        return execCommand(new String[]{command}, isRoot, true);
    }
    //執行List<String>中的指令 , 傳入List和是否需要root
    public static CommandResult execCommand(List<String> commands, boolean isRoot) {
        return execCommand(commands == null ? null : commands.toArray(new String[]{}), isRoot, true);
    }
    //執行多行指令
    public static CommandResult execCommand(String[] commands, boolean isRoot) {
        return execCommand(commands, isRoot, true);
    }

    public static CommandResult execCommand(String command, boolean isRoot, boolean isNeedResultMsg) {
        return execCommand(new String[]{command}, isRoot, isNeedResultMsg);
    }

    public static CommandResult execCommand(List<String> commands, boolean isRoot, boolean isNeedResultMsg) {
        return execCommand(commands == null ? null : commands.toArray(new String[]{}), isRoot, isNeedResultMsg);
    }
    //執行指令,獲得傳回的資訊
    public static CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) {
        int result = -;
        if (commands == null || commands.length == ) {
            return new CommandResult(result, null, null);
        }

        Process process = null;
        BufferedReader successResult = null;
        BufferedReader errorResult = null;
        StringBuilder successMsg = null;
        StringBuilder errorMsg = null;
        DataOutputStream os = null;
        try {
            process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
            os = new DataOutputStream(process.getOutputStream());
            for (String command : commands) {
                if (command == null) {
                    continue;
                }
                os.write(command.getBytes());
                os.writeBytes(COMMAND_LINE_END);
                os.flush();
            }
            os.writeBytes(COMMAND_EXIT);
            os.flush();

            result = process.waitFor();
            // get command result
            if (isNeedResultMsg) {
                successMsg = new StringBuilder();
                errorMsg = new StringBuilder();
                successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
                errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                String s;
                while ((s = successResult.readLine()) != null) {
                    successMsg.append(s);
                }
                while ((s = errorResult.readLine()) != null) {
                    errorMsg.append(s);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (successResult != null) {
                    successResult.close();
                }
                if (errorResult != null) {
                    errorResult.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (process != null) {
                process.destroy();
            }
        }
        return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null
                : errorMsg.toString());
    }
    //封裝了傳回資訊
    public static class CommandResult {

        public int result;
        public String successMsg; //成功資訊
        public String errorMsg; // 錯誤資訊

        public CommandResult(int result) {
            this.result = result;
        }

        public CommandResult(int result, String successMsg, String errorMsg) {
            this.result = result;
            this.successMsg = successMsg;
            this.errorMsg = errorMsg;
        }
    }
}
           

在應用内部執行

cat /data/misc/wifi/wpa_supplicant.conf

指令

到了這一步就很簡單了,直接看代碼

strings = new ArrayList<>();
strings.add("cd data/" + ShellUtils.COMMAND_LINE_END);
strings.add("cd misc/" + ShellUtils.COMMAND_LINE_END);
strings.add("cd wifi/" + ShellUtils.COMMAND_LINE_END);
strings.add("ls" + ShellUtils.COMMAND_LINE_END);
strings.add("cat wpa_supplicant.conf" + ShellUtils.COMMAND_LINE_END);
ShellUtils.CommandResult result = ShellUtils.execCommand(strings, true, true);
//擷取傳回的結果
String wifis = result.successMsg;
           

此時傳回的資訊就包含了

wpa_supplicant.conf

檔案内部的所有資訊,此時我們需要做的就是解析WIFI名稱和密碼然後顯示到界面

利用正規表達式解析傳回的資料

首先檢視我們擷取到的傳回資訊,其中wifi的名稱格式是

ssid="......"

密碼的格式是

psk="......"

,這樣我們就可以用正規表達式來截取名稱和密碼

注:部分機型中文的wifi名稱會顯示為字母和數字的組合,且沒有雙引号,另開放的網絡沒有wifi密碼,密碼一欄的顯示是這樣的

key_mgmt=NONE

,是以第一步執行的是講其中的

key_mgmt=NONE

替換為

key_mgmt="無密碼"

.這樣就不會出現名稱的個數和密碼的個數不相符的問題

解析wifi的名稱

Pattern pattern = null;
        Matcher matcher = null;
        listID = new ArrayList<>();
        listPass = new ArrayList<>();
        //擷取使用者名
        String rexId = "ssid=[\\S]+[\\s]";
        pattern = Pattern.compile(rexId);
        matcher = pattern.matcher(wifis);

        while (matcher.find()) {
            listID.add(matcher.group());
        }
           

解析wifi的密碼

//擷取密碼
        String rexPass = "psk=\"[^\"]+\"";
        pattern = Pattern.compile(rexPass);
        matcher = pattern.matcher(wifis);
        while (matcher.find()) {
            listPass.add(matcher.group());
        }
           
經過這兩步之後我們就擷取到了兩個包含wifi名稱和wifi密碼的LIst
封裝一個儲存wifi資訊的base類
package com.brioal.wifipassword.base;

/**
 * Created by Brioal on 2016/3/21.
 */
public class WifiItem {
    private String mId ;
    private String mPass ;

    public WifiItem(String mId, String mPass) {
        this.mId = mId;
        this.mPass = mPass;
    }

    public String getmId() {
        return mId;
    }

    public void setmId(String mId) {
        this.mId = mId;
    }

    public String getmPass() {
        return mPass;
    }

    public void setmPass(String mPass) {
        this.mPass = mPass;
    }
}
           
擷取

List<WifiItem>

for (int i = ; i < listID.size(); i++) {
            String mId = listID.get(i);
            String mPass = listPass.get(i);
            mId = mId.substring(, mId.length() - );
            mPass = mPass.substring(, mPass.length() - );
            WifiItem item = new WifiItem(mId, mPass);
            wifiList.add(item);
        }
           

接下來就是最後一步,将wifi資訊顯示到ExpandableListView當中

顯示wifi資訊

這一部分比較簡單,就直接上代碼吧

建立Adapter

private class MyAdapter implements ExpandableListAdapter {


        @Override
        public void registerDataSetObserver(DataSetObserver observer) {

        }

        @Override
        public void unregisterDataSetObserver(DataSetObserver observer) {

        }

        @Override
        public int getGroupCount() {
            return listID.size();
        }

        @Override
        public int getChildrenCount(int groupPosition) {
            return ;
        }

        @Override
        public Object getGroup(int groupPosition) {
            return listID.get(groupPosition);
        }

        @Override
        public Object getChild(int groupPosition, int childPosition) {
            return listPass.get(groupPosition);
        }

        @Override
        public long getGroupId(int groupPosition) {
            return groupPosition;
        }

        @Override
        public long getChildId(int groupPosition, int childPosition) {
            return groupPosition;
        }

        @Override
        public boolean hasStableIds() {
            return false;
        }

        @Override
        public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
            TextView textView = new TextView(MainActivity.this);
            textView.setTextSize();

            textView.setGravity(Gravity.CENTER_VERTICAL);
            textView.setText("     "+wifiList.get(groupPosition).getmId());
            textView.setSingleLine();
            textView.setMaxWidth();
            textView.setTypeface(Typeface.SANS_SERIF);
            textView.setEllipsize(TextUtils.TruncateAt.END);
            return textView;
        }

        @Override
        public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
            TextView textView = new TextView(MainActivity.this);
            textView.setTextSize();
            textView.setGravity(Gravity.CENTER_VERTICAL);
            textView.setText("      "+wifiList.get(groupPosition).getmPass());
            textView.setTypeface(Typeface.SANS_SERIF);

            return textView;
        }

        @Override
        public boolean isChildSelectable(int groupPosition, int childPosition) {
            return false;
        }

        @Override
        public boolean areAllItemsEnabled() {
            return false;
        }

        @Override
        public boolean isEmpty() {
            return false;
        }

        @Override
        public void onGroupExpanded(int groupPosition) {

        }

        @Override
        public void onGroupCollapsed(int groupPosition) {

        }

        @Override
        public long getCombinedChildId(long groupId, long childId) {
            return ;
        }

        @Override
        public long getCombinedGroupId(long groupId) {
            return ;
        }
    }
           

ExpandableLIstView

設定

Adapter

adapter = new MyAdapter();
        listView.setAdapter(adapter);
           

至此大功告成

源碼已分享到Github,有興趣的同學歡迎下載下傳檢視

歡迎聯系作者交流,作者QQ:821329382