How to read the database of third-party applications? (PART 1)

Manager: "Tank, we need to access the database of a third-party APP"
ME: "This is simple, just use the Device File Explorer that comes with AS"
Manager: "No, I mean can you write an APP and print the others The database created by the application"
ME: "...can ROOT?"
Manager: "As long as you can get it, you can do anything"

What a magical dialogue~
To solve this demand, we must first know where the database created by the APP is located.
Generally speaking, the database created by the application will be stored in the data/data/application package name/databases directory. If you see this directory, you will understand how wonderful the demand is, right?
In versions after Android 7.0, the access rights of permissions have been modified, which can be roughly divided into public space and private space. External storage is public space, allowing all applications to read and access it, but the directory corresponding to data is private space. Under this mechanism, applications are not allowed to access the directory where the third-party application database is located.

How to do it? Should we tell the manager that the demand is difficult to achieve?

Haha, let’s review the dialogue at the beginning, there is our solution!
Yes, we can ROOT. Although Android does not like ROOT very much, it is a good thing for this demand.
As for how to ROOT, there are too many solutions on the Internet, so I won’t go into details here, but I will share with you a way I refer to:
ROOT solution

After ROOT, we try to traverse the file through File's listFile, and if nothing happens, a No such file error will be reported. We can see the corresponding file through the Device File Explorer. Is it because we still can’t access the data directory after ROOT?
Insert picture description here
Maybe it is not ROOT success? Let's use adb shell to authenticate:
First, we open the cmd window and enter the adb shell command to run. The result is as follows:
Insert picture description here
Enter su and run.
Insert picture description here
We see that $ becomes #, which shows that the phone is ROOT successful.
Now that we have opened cmd, how about using commands to view the directory where the database is located? As mentioned earlier, we can see the corresponding directory with the help of Device File Explorer. We can directly access a certain directory through the cd command, and print the list with ls.
Insert picture description here
Isn't it magical?
We can access the directory where the database is located through commands, so can we also access through commands in the Android code?
The answer is obviously yes.
We write a method to get the database list, the code is as follows:

private  List<String> getDbListByPkg(String pkgName){
        List<String> dbs = new ArrayList<>();
        ProcessBuilder pb = new ProcessBuilder("/system/bin/sh");
        pb.directory(new File("/"));//设置shell的当前目录。
        try {
            Process proc = pb.start();
            //获取输入流,可以通过它获取SHELL的输出。
            BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
            //获取输出流,可以通过它向SHELL发送命令。
            PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc
                    .getOutputStream())), true);
            out.println("pwd");
            out.println("su root");//执行这一句时会弹出对话框(以下程序要求授予最高权限...),要求用户确认。
            out.println("cd /data/data/"+pkgName+"/databases");//这个目录在系统中要求有root权限才可以访问的。
            out.println("ls -l");//这个命令如果能列出当前安装的APK的数据文件存放目录,就说明我们有了ROOT权限。
            out.println("exit");
            out.println("exit");
            // proc.waitFor();
            String line;
            while ((line = in.readLine()) != null) {
                if(line.endsWith(".db")){
                    String[] infos = line.split("\\s+");
                    if (infos.length == 8) {
                        dbs.add(infos[7]);
                    }
                }
            }
            in.close();
            out.close();
            proc.destroy();
        } catch (Exception e) {
            System.out.println("exception:" + e);
        }

        return dbs;
    }

Then we still query the database of com.android.providers.calendar, call the method with the package name as a parameter, and print the contents of the List, which is the database name. The effect is as follows:
Insert picture description here
Obviously, we can traverse the creation of an application through commands. database. But is it too shabby to just get the name of the database? In the next article, we will print the specific content in the database together.

Guess you like

Origin blog.csdn.net/RobinTan24/article/details/108473209