AOSP系统沙箱-集成gumjs引擎

最近想在沙箱中使用frida的hook能力,有三个方案:

1 集成frida-server到系统

2 内置frida-gadget.so,然后将其加载到应用中

3 集成gumjs引擎

考虑到使用的体验性,最终打算用第三种方案

一、编译gumjs

1.1 先去frida官网下载gumjs的头文件和静态库

1.2 创建工程,导入gumjs.a和头文件

编译成动态库

二、创建Hook管理类

/frameworks/base/core/java/android/app/HookUtils.java

package android.app;


import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.os.FileUtils;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import dalvik.system.DexClassLoader;
import org.json.JSONObject;
import org.json.JSONArray;

public class HookUtils {
    public static final String TAG = "HookUtils";
    public static HookJs hookjs;

    public static class HookJs{
        public boolean open = false;
        public String[] packageName;
        public String arm32SoPath;
        public String arm64SoPath;
        public HookJs(JSONObject js){
            try{
                open = js.getBoolean("open");
                JSONArray names = js.getJSONArray("packageName");
                if (names != null){
                    packageName = new String[names.length()];
                    for (int i = 0; i < names.length(); i++){
                        packageName[i] = names.getString(i);
                    }
                }
                arm32SoPath = js.getString("ArmSoPath");
                arm64SoPath = js.getString("Arm64SoPath");
            } catch(Exception e){
                Log.e(TAG, "HookJs:" + e.toString());
            }

        }
    }

    public static void getConfig() {
        try{
            String conf = readConfig();
            //Log.i(TAG, "getConfig -> " + conf);
            JSONObject arr = new JSONObject(conf);

            hookjs = new HookJs(arr.getJSONObject("hookJs"));
            Log.i(TAG, String.valueOf(hookjs.open));
            if (hookjs.packageName != null){
                for (int i = 0; i < hookjs.packageName.length; i++){
                    Log.i(TAG, hookjs.packageName[i]);
                }
            }
            Log.i(TAG, hookjs.arm32SoPath.toString());
            Log.i(TAG, hookjs.arm64SoPath.toString());
        } catch (Exception e){
            Log.e(TAG, "getConfig error:" + e.toString());
        }
    }

    public static String readConfig(){
        try {
            return readFileAll("/data/local/tmp/config.js");
        }catch (Exception e) {
            Log.e(TAG, e.toString());
        }
        return null;
    }

    public static String readFileAll(String path) {
        File file = new File(path);
        StringBuilder sb=new StringBuilder();
        if (file != null && file.exists()) {
            InputStream inputStream = null;
            BufferedReader bufferedReader = null;
            try {
                inputStream = new FileInputStream(file);
                bufferedReader = new BufferedReader(new InputStreamReader(
                        inputStream));
                String outData;
                while((outData=bufferedReader.readLine())!=null){
                    sb.append(outData+"\n");
                }
            } catch (Throwable t) {
            } finally {
                try {
                    if (bufferedReader != null) {
                        bufferedReader.close();
                    }
                } catch (Exception e) {
                    Log.e(TAG, "readFileAll" + e.toString());
                }
                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                } catch (Exception e) {
                    Log.e(TAG, "readFileAll" + e.toString());
                }
            }
        }
        return sb.toString();
    }

    public static boolean checkHookJs(String processName){
        try{
            if (processName != null){
                if (hookjs != null){
                    if (hookjs.open){
                        if (hookjs.packageName != null){
                            for (String s:hookjs.packageName){
                                if (processName.contains(s)){
                                    //Log.i(TAG, "hook -> " + String.valueOf(processName));
                                    return true;
                                }
                            }
                        }else{
                            return true;
                        }
                    }
                }
            }
        }catch (Exception e){
            Log.e(TAG, "checkHookJs:" + e.toString());
        }
        return false;
    }

    public static void moveSoToData(String dstFileName){
        String srcFileName;
        if(System.getProperty("os.arch").indexOf("64") >= 0) {
            srcFileName = hookjs.arm64SoPath;
        }else{
            srcFileName = hookjs.arm32SoPath;
        }

        deleteDataFile(dstFileName);
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(srcFileName);
            out = new FileOutputStream(dstFileName);
            byte[] bytes = new byte[1024];
            int i;
            while ((i = in.read(bytes)) != -1)
                out.write(bytes, 0, i);
        } catch (IOException e) {
            Log.e(TAG, e.toString());
        } finally {
            try {
                if (in != null)
                    in.close();
                if (out != null){
                    out.flush();
                    out.close();
                }
            } catch (IOException e) {
                Log.e(TAG, e.toString());
            }
            setPermission(dstFileName);
        }
    }

    public static void deleteDataFile(String fileName){
        try {
            File file = new File(fileName);
            if (file.exists()){
                file.delete();
            }
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }
    }

    public static void setPermission(String path){
        try{
            File file = new File(path);
            if (file.exists()){
                int perm = FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IRWXO;
                FileUtils.setPermissions(path, perm, -1, -1);//将权限改为777
            }

        }catch (Exception e) {
            Log.e(TAG, e.toString());
        }
    }


    public static void startHook(Context context){
        try{
            //Log.i(TAG, "in HookUtils startHook");
            loadPluginSo("/data/data/" + context.getPackageName() + "/yooha.so");
        }  catch (Exception e) {
            Log.e(TAG, e.toString());
        }

    }

    public static void loadPluginSo(String soPath){
        try{
            File file = new File(soPath);
            if (file.exists()){
                //Log.i(TAG, "load so src:" + soPath);
                System.load(soPath);
                file.delete();
            }
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }

    }
}

三、添加注入点

/frameworks/base/core/java/android/app/Application


   /* package */ final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
        // add start
        try{
            int flags = context.getApplicationInfo().flags;
            if (flags > 0 && ((flags & ApplicationInfo.FLAG_SYSTEM)!=1)){
                if (isHook == false){
                    JLog.print_info("HookUtils", "ProcessName:" + getProcessName());
                    HookUtils.getConfig();
                    if (HookUtils.checkHookJs(getProcessName())){
                        HookUtils.moveSoToData("/data/data/" + context.getPackageName() + "/yooha.so");
                        HookUtils.startHook(context);
                        isHook = true;
                    }
                }
            }
        } catch(Exception e){
            Log.e("HookUtils", e.toString());
        }
        // add end
    }

四、配置文件及hook文件

libYooha.so(集成gumjs动态库)/data/local/tmp/lib/ANDROID_ABI/
hook.js(hook脚本)/data/local/tmp/
config.js(配置文件)/data/local/tmp/{
    "hookJs":{
        "open":true,
        "packageName":[
            "com.learn.development",
            "me.wsj.fengyun"
        ],
        "ArmSoPath":"/data/local/tmp/lib/armeabi-v7a/libYooha.so",
        "Arm64SoPath":"/data/local/tmp/lib/arm64-v8a/libYooha.so"
    }
}

日志TAG:FRIDA-LOG

五、编译刷机

日志TAG:FRIDA-LOG

效果图:

hook startActivity

hook open

(看出来了吗,它在检测frida  ^v^)

要在Android 7.1 AOSP中添加屏幕密度选项并实现功能选项的功能,可以按照以下步骤进行操作: 1. 在AOSP源代码中找到Settings应用程序的代码目录,路径为packages/apps/Settings。 2. 在该目录下找到res/values/arrays.xml文件,并打开该文件。 3. 在该文件中添加一个新的数组,用于表示屏幕密度选项的值。例如: ``` <string-array name="screen_density_values"> <item>120</item> <item>160</item> <item>240</item> <item>320</item> <item>480</item> <item>640</item> </string-array> ``` 4. 在该文件中添加一个新的数组,用于表示屏幕密度选项的标签。例如: ``` <string-array name="screen_density_labels"> <item>@string/screen_density_120</item> <item>@string/screen_density_160</item> <item>@string/screen_density_240</item> <item>@string/screen_density_320</item> <item>@string/screen_density_480</item> <item>@string/screen_density_640</item> </string-array> ``` 5. 在该文件中添加对应的字符串资源,例如: ``` <string name="screen_density_120">Low Density (120)</string> <string name="screen_density_160">Medium Density (160)</string> <string name="screen_density_240">High Density (240)</string> <string name="screen_density_320">Extra High Density (320)</string> <string name="screen_density_480">Extra Extra High Density (480)</string> <string name="screen_density_640">Extra Extra Extra High Density (640)</string> ``` 6. 在Settings应用程序的代码中,找到DisplaySettings.java文件,并打开该文件。 7. 在该文件中找到屏幕密度选项的相关代码,在onCreate方法中添加以下代码: ``` mScreenDensityPreference = (ListPreference) findPreference(KEY_SCREEN_DENSITY); mScreenDensityPreference.setEntries(R.array.screen_density_labels); mScreenDensityPreference.setEntryValues(R.array.screen_density_values); mScreenDensityPreference.setValue(String.valueOf(currentDensity)); mScreenDensityPreference.setOnPreferenceChangeListener(this); ``` 其中,KEY_SCREEN_DENSITY是一个常量,表示屏幕密度选项对应的键值。currentDensity是当前屏幕密度的值。 8. 在该文件中实现功能选项的功能,在onPreferenceChange方法中添加以下代码: ``` if (preference == mScreenDensityPreference) { int density = Integer.parseInt((String) newValue); DisplayMetrics metrics = getResources().getDisplayMetrics(); metrics.densityDpi = density; getBaseContext().getResources().updateConfiguration(getResources().getConfiguration(), metrics); try { IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); if (wm != null) { wm.updateSettings(); } } catch (RemoteException e) { Log.e(TAG, "Unable to update window manager settings", e); } return true; } ``` 其中,newValue是用户选择的屏幕密度的值。该代码将用户选择的屏幕密度值更新到系统的DisplayMetrics中,并更新配置信息。然后,它调用IWindowManager接口更新窗口管理器的设置。 9. 构建AOSP源代码并运行生成的系统镜像。 10. 在系统设置中,找到显示选项,即可看到屏幕密度选项,并且可以根据用户选择的屏幕密度值来改变屏幕的显示效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值