Android WIFI密码查看器实例(在获取Root权限下查看系统文件)

Android WIFI密码查看器实例

实现原理:使用shell命令查看保存WIFI密码的系统文件

涉及的知识

  1. 界面展示
  2. 基本的Shell命令
  3. shell查看WIFI密码
  4. ShellUtil的使用
  5. 正则表达式解析字符串
  6. ExpandableListView的使用

界面展示

主界面只包含一个ExpandableListView

Android WIFI密码查看器实例(在获取Root权限下查看系统文件)_第1张图片

基本的Shell命令

1.shel由 adb shell进入,基本命令于Linux下的命令相同,这边演示几个常用的命令
Android WIFI密码查看器实例(在获取Root权限下查看系统文件)_第2张图片

因为是在手机的系统文件下操作,所以部分命令不方便演示,下面直接进入查看wifi密码的命令

首先执行su获取root权限

执行cat /data/misc/wifi/wpa_supplicant.conf来查看本地的WIFI信息

Android WIFI密码查看器实例(在获取Root权限下查看系统文件)_第3张图片

在应用内部执行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 == 0;
    }
    //执行单行命令,实际还是调用的执行多行 ,传入命令和是否需要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 = -1;
        if (commands == null || commands.length == 0) {
            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 = 0; i < listID.size(); i++) {
            String mId = listID.get(i);
            String mPass = listPass.get(i);
            mId = mId.substring(6, mId.length() - 2);
            mPass = mPass.substring(5, mPass.length() - 1);
            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 1;
        }

        @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(22);

            textView.setGravity(Gravity.CENTER_VERTICAL);
            textView.setText(" "+wifiList.get(groupPosition).getmId());
            textView.setSingleLine();
            textView.setMaxWidth(100);
            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(15);
            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 0;
        }

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

ExpandableLIstView设置Adapter

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

至此大功告成

源码已分享到Github,有兴趣的同学欢迎下载查看

欢迎联系作者交流,作者QQ:821329382

你可能感兴趣的:(android,shell,实例,密码,Wi-Fi)