如何检查Linux中是否启用了USB3.0 UASP(USB附加SCSI协议)模式?

 USB 3.0 在数据量较多且零碎传输时,效能的表现会较差,主要原因是在于传输技术所造成的状况。

USB 采用半双工传输模式与 BOT (Bluk Only Transfer) 传输协议,半双工传输模式就像是再讲对讲机一样,一方说完另一方才能继续对话,也就是说数据的传输方向仅有单向传输功能。

BOT 传输协议则是一种单线程的传输架构,这个架构就像马路上只能行使一台车子,不管路有多宽,都必须等待这量车子行驶过后下一部车子才能继续通行。

USB 的加速方式
提升为全双工模式

当 USB 升级到 USB 3.0 时,将原来的半双工传输模式,改为全双工模式,并且提升十倍的带宽,不过其架构还是在 BOT 之下。

BOT 加速模式

 这个方式虽然还是在 BOT 的架构之下,但是是将原来在路上行使的轿车,换一台更大一点的公交车,将一次传送的数据量加大,就可以减少来回的次数,来达到加速的目的。

UASP 加速模式

BOT加速模式虽然可以有效的增加传输速度,不过还是没有在根本上解决无法多任务处理的问题,所以 USB-IF (USB Implementers Forum) 一个为开发 USB 规格的企业共同成立的非营利性机构,为了让传输效能更好,制定了UASP(USB Attached SCSI Protocol)传输架构,让 USB3.0 也能像 SCSI 传输协议的方式传输数据,不需等待上一笔数据传输完成后再进行传输数据的动作,并改善了在 CPU 的使用率、数据延迟及等待时间。

要达到 UASP 加速功能,请先确认您计算机端是否同样有支持 UASP 功能。
目前支持 UASP 的系统有 WIN 8 、Mac OS 8 & 9 ,除了以上系统,您也可以询问您购买的计算机公司,是否有提供相关的驱动程序。

继续阅读如何检查Linux中是否启用了USB3.0 UASP(USB附加SCSI协议)模式?

ubuntu 20.04系统AOSP(Android 11)集成Frida

参考 ubuntu 20.04编译Android 11源代码&模拟器 完成Android 11源代码的编译工作,保证能编译通过。

想自己手工编译`Frida`源代码的话,请参照下面:

$ git clone https://github.com/frida/frida.git

$ cd frida

$ make

$ export ANDROID_NDK_ROOT=/data/Android/android-sdk-linux/ndk/22.0.6917172

$ sudo apt-get install npm

$ sudo apt install python3-pip

$ pip3 install colorama prompt-toolkit pygments

$ rm -rf build

$ make core-android-x86_64

$ make core-android-x86

# 最后生成的文件在 build/frida-android-x86 build/frida-android-x86_64 
# 如果需要调整编译参数,在releng/setup-env.sh中进行调整 比如: meson_common_flags="['-g']"

如果想直接下载对应版本的`Frida`库并存放到已经编译过的库位置,由于`64`位系统需要兼容`32`位应用,因此需要安装两个版本的动态库:

$ cd ~/AndSrc/aosp/

$ cd out/target/product/generic_x86_64/system/lib64

$ wget https://github.com/frida/frida/releases/download/14.2.2/frida-gadget-14.2.2-android-x86_64.so.xz

$ xz -d frida-gadget-14.2.2-android-x86_64.so.xz

# Android要求动态库必须是lib开头
$ mv frida-gadget-14.2.2-android-x86_64.so libfrida-gadget-14.2.2-android-x86_64.so

$ cd ~/AndSrc/aosp/

$ cd out/target/product/generic_x86_64/system/lib

$ wget https://github.com/frida/frida/releases/download/14.2.2/frida-gadget-14.2.2-android-x86.so.xz

$ xz -d frida-gadget-14.2.2-android-x86.so.xz

# Android要求动态库必须是lib开头
$ mv frida-gadget-14.2.2-android-x86.so libfrida-gadget-14.2.2-android-x86.so

创建`Frida Gadget`库的配置文件

$ cd ~/AndSrc/aosp/

$ cd out/target/product/generic_x86_64/system/lib64

$ touch libfrida-gadget-14.2.2-android-x86_64.config.so

$ cd ~/AndSrc/aosp/

$ cd out/target/product/generic_x86_64/system/lib

$ touch libfrida-gadget-14.2.2-android-x86.config.so

里面的配置内容如下:

{
  "interaction": {
    "type": "listen",
    "address": "127.0.0.1",
    "port": 27042,
    "on_load": "resume"
  }
}

观察`Frida`源代码,发现在 `frida-core/lib/gadget/gadget-glue.c`中配置了`lib`库的入口函数

__attribute__ ((constructor)) static void
frida_on_load (void)
{
  frida_gadget_load (NULL, NULL, NULL);
}

这就意味着只要使用`dlopen`加载`frida-gadget`,我们就能实现对于指定应用的`Hook`。

我们只需要监听子进程,不需要在`Zygote`中加载,因此只需要在源代码` frameworks/base/core/jni/com_android_internal_os_Zygote.cpp` 的`com_android_internal_os_Zygote_nativeForkAndSpecialize`函数中增加加载代码:

    /*
     * 在虚拟机,系统框架初始化完成之后,加载frida框架
     * 需要增加头文件的引用 #include <dlfcn.h>
     */
#if defined(__x86_64__) || defined(__i386__)
      {
          #if defined(__x86_64__)
              #define FRIDA_LIB "/system/lib64/libfrida-gadget-14.2.2-android-x86_64.so"
          #else
              #define FRIDA_LIB "/system/lib/libfrida-gadget-14.2.2-android-x86.so"
          #endif
          const char *name = env->GetStringUTFChars(nice_name, 0);
          void* frida = dlopen(FRIDA_LIB, RTLD_NOW);
          if(NULL == frida) {
              ALOGE("(%s) load frida-gadget(%s) failed, err= %d\n", name, FRIDA_LIB, errno);
          } else {
              ALOGI("(%s) load frida-gadget(%s) success\n", name, FRIDA_LIB);
          }
          env->ReleaseStringUTFChars(nice_name, name);
      }
#endif

具体添加位置如下:

static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
        jint runtime_flags, jobjectArray rlimits,
        jint mount_external, jstring se_info, jstring nice_name,
        jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
        jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
        jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list,
        jboolean mount_data_dirs, jboolean mount_storage_dirs) {
    jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);

    if (UNLIKELY(managed_fds_to_close == nullptr)) {
      ZygoteFailure(env, "zygote", nice_name, "Zygote received a null fds_to_close vector.");
    }

    std::vector<int> fds_to_close =
        ExtractJIntArray(env, "zygote", nice_name, managed_fds_to_close).value();
    std::vector<int> fds_to_ignore =
        ExtractJIntArray(env, "zygote", nice_name, managed_fds_to_ignore)
            .value_or(std::vector<int>());

    std::vector<int> usap_pipes = MakeUsapPipeReadFDVector();

    fds_to_close.insert(fds_to_close.end(), usap_pipes.begin(), usap_pipes.end());
    fds_to_ignore.insert(fds_to_ignore.end(), usap_pipes.begin(), usap_pipes.end());

    fds_to_close.push_back(gUsapPoolSocketFD);

    if (gUsapPoolEventFD != -1) {
      fds_to_close.push_back(gUsapPoolEventFD);
      fds_to_ignore.push_back(gUsapPoolEventFD);
    }

    if (gSystemServerSocketFd != -1) {
        fds_to_close.push_back(gSystemServerSocketFd);
        fds_to_ignore.push_back(gSystemServerSocketFd);
    }

    pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true);

    if (pid == 0) {
      SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                       capabilities, capabilities,
                       mount_external, se_info, nice_name, false,
                       is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
                       is_top_app == JNI_TRUE, pkg_data_info_list,
                       whitelisted_data_info_list,
                       mount_data_dirs == JNI_TRUE,
                       mount_storage_dirs == JNI_TRUE);

    /*
     * 在虚拟机,系统框架初始化完成之后,加载frida框架
     * 需要增加头文件的引用 #include <dlfcn.h>
     */
#if defined(__x86_64__) || defined(__i386__)
      {
          #if defined(__x86_64__)
              #define FRIDA_LIB "/system/lib64/libfrida-gadget-14.2.2-android-x86_64.so"
          #else
              #define FRIDA_LIB "/system/lib/libfrida-gadget-14.2.2-android-x86.so"
          #endif
          const char *name = env->GetStringUTFChars(nice_name, 0);
          void* frida = dlopen(FRIDA_LIB, RTLD_NOW);
          if(NULL == frida) {
              ALOGE("(%s) load frida-gadget(%s) failed, err= %d\n", name, FRIDA_LIB, errno);
          } else {
              ALOGI("(%s) load frida-gadget(%s) success\n", name, FRIDA_LIB);
          }
          env->ReleaseStringUTFChars(nice_name, name);
      }
#endif

    }
    return pid;
}

编译并重新生成系统镜像:

$ cd ~/AndSrc/aosp/

$ export USE_CCACHE=1  

$ source build/envsetup.sh

$ lunch aosp_x86_64-eng

$ cd frameworks/base

$ mmm

# 如果只是替换镜像里面的so文件,不修改源代码,则需要执行 make snod 才能重新生成镜像
# cd ~/AndSrc/aosp/
# make snod
运行镜像

选择system-qemu.img和vendor-qemu.img,这两个镜像是专门为qemu运行制作的,如果选择system.img 和vendor.img,则avd运行失败。

$ cd ~/AndSrc/aosp

$ export ANDROID_BUILD_TOP=~/AndSrc/aosp

$ export PATH=$PATH:$ANDROID_BUILD_TOP/out/host/linux-x86/bin

$ export ANDROID_SWT=$ANDROID_BUILD_TOP/out/host/linux-x86/framework

$ export ANDROID_PRODUCT_OUT=$ANDROID_BUILD_TOP/out/target/product/generic_x86_64

$ ./prebuilts/android-emulator/linux-x86_64/emulator -system ./out/target/product/generic_x86_64/system-qemu.img -data ./out/target/product/generic_x86_64/data.img -ramdisk ./out/target/product/generic_x86_64/ramdisk-qemu.img -vendor ./out/target/product/generic_x86_64/vendor-qemu.img -verbose -show-kernel

上面运行起来的镜像是从`~/AndSrc/aosp/out/debug/target/product/generic/hardware-qemu.ini`即可读取配置信息的,但是这个文件直接修改无效,我们如果需要修改参数,只能从启动参数中设置。
比如我们如果需要增大内存,开启`GPU`的支持,则执行如下命令:

$ ./prebuilts/android-emulator/linux-x86_64/emulator -system ./out/target/product/generic_x86_64/system-qemu.img -data ./out/target/product/generic_x86_64/data.img -ramdisk ./out/target/product/generic_x86_64/ramdisk-qemu.img -vendor ./out/target/product/generic_x86_64/vendor-qemu.img -gpu on -memory 4096 -verbose -show-kernel

参考链接