adb调试问题集锦

1 Android adb基本知识
1.1 adbd authentication
adbd authentication is introduced in 08-2012.

Windows private key file:
%USERPROFILE%\.android\adbkey
adbd public key file:
/data/misc/adb/adb_keys, from Windows
%USERPROFILE%\.android\adbkey.pub, sent by USB EPOUT.

generate adbkey pair:
adb keygen adbkey

- PC连接手机,手机向PC发送AUTH TOKEN报文,包含源自/dev/urandom的20字节的随机数。
- PC用自己的私钥对该随机数进行签名(SHA1 + RSA),放在发往手机的SIGNATURE报文中。
- 手机检查签名,如果正确,响应CONNECT报文,否则向主机发送新的AUTH TOKEN报文,提供新的随机数。
- PC尝试另一个私钥,如果PC已经尝试完所有私钥,则向手机发送AUTH RSAPUBLICKEY报文,包含一个主机公钥。
- 手机端的adbd将PC公钥发往framework,后者弹出信息框,询问是否允许(或永久允许)PC使用USB调试接口,该信息框中一般会显示PC公钥的指纹(MD5),而不是PC公钥本身。

1.2 mount参数suid和nosuid
mount时的参数nosuid会禁止该分区的程序执行setuid()和setgid()切换到root的权限。

su的源码中,有对文件系统mount时候挂载了suid特性的检测,由此可知setuid特性可以在mount的-o(options)中关闭掉。具体可以参考man 2 setuid,man mount等等。

/data/local/tmp文件夹,即使是user版本也可以adb push,并且可以在这个目录下执行命令。

1.3 iptables防火墙规则
如果遇到网络adb不能使用的问题,需要用以下的命令查看下iptables的配置。
iptables-save -c:dump已配置的规则,格式是[packets, bytes];可以用“>”重定向到一个文件中,格式是[packets, bytes]
iptables -D xxx:-D与-A对应,表示删除一条规则

1.4 Android 8.0 adbd settings
settings put global development_settings_enabled 1
settings put global adb_enabled 1
svc usb getFunction

2 Windows adb
2.1 Win10临时关闭驱动签名
This PC - Advanced system settings - Advanced - Environment Variables

开始 - 设置 - 更新和安全 - 恢复 - 点击右边高级启动项下方的立即重启,进入高级启动 - 选择疑难解答 - 高级选项 - 启动设置 - 重启 - 再按数字键7或F7禁止驱动签名
期间可能要求输入Bitlocker Recovery Key,提前从如下的网址中获取,或者在别人电脑登录获取。
https://myaccount.microsoft.com/device-list

2.2 WinUSB
Use Zadig to install WinUSB as adb driver, adb does not work.
adb可执行调用了自定义库AdbWinApi.dll,AdbWinApi.dll库会检查当前使用的是legacy驱动(ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR,ReadFile,WriteFile和DeviceIoControl)还是WinUSB(2011),如果使用的是WinUSB,那么就加载AdbWinUsbApi.dll库。
github host/windows/usb/api/adb_winusb_endpoint_object.cpp

%CompositeAdbInterface% = USB_Install, USB\Class_FF&SubClass_42&Prot_01
%SingleAdbInterface% = USB_Install, USB\Class_FF&SubClass_42&Prot_03

2.3 添加USB VID到白名单
%HOMEDRIVE%%HOMEPATH%:表示CMD进入后的初始位置

查看环境变量方法:
echo "%HOMEDRIVE%%HOMEPATH%"
echo "%path%"

md "%HOMEDRIVE%%HOMEPATH%\.android"
echo 0xabcd >> "%HOMEDRIVE%%HOMEPATH%\.android\adb_usb.ini"
或者
md "%USERPROFILE%\.android"
echo 0xabcd >> "%USERPROFILE%\.android\adb_usb.ini"

2.4 adb调试
Windows:
adb kill-server
set ADB_TRACE=all / ADB_TRACE=
adb shell
echo %Temp% --- adb.log文件

Android:
setprop persist.adb.trace_mask all / setprop persist.adb.trace_mask ""
stop adbd
start adbd
logcat | grep adbd

2.5 编译Windows版本的adb
adbd版本号宏:ADB_SERVER_VERSION
1)apt-get install mingw32
2)make USE_MINGW=y adb
3)make USE_MINGW=y fastboot

2.6 Android 8.0 data分区执行su
:: dp means Drive Path
set BAT_PATH=%~dp0

adb push %BAT_PATH%su /data/
adb shell "chgrp shell /data/su"
adb shell "chmod a+x /data/su"
adb shell "chmod +s /data/su"
adb shell "chcon u:object_r:su_exec:s0 /data/su"

:: let su get the permission to run setuid() and setgid()
adb shell "mount -o remount,rw,seclabel,suid,nodev,noatime,discard,noauto_da_alloc,errors=panic,data=ordered /data"

3 Android adb root
3.1 源代码修改
diff --git a/adb/Android.mk b/adb/Android.mk
index a815c77..56b66d8 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -121,7 +121,7 @@ endif
 LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter -Werror
 LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
 
-ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+ifneq (,$(filter userdebug eng user,$(TARGET_BUILD_VARIANT)))
 LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1
 endif

diff --git a/adb/adb.c b/adb/adb.c
index 4300754..d2aa962 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -1280,7 +1280,7 @@ static int should_drop_privileges() {
             // ... except we allow running as root in userdebug builds if the
             // service.adb.root property has been set by the "adb root" command
             property_get("ro.debuggable", value, "");
-            if (strcmp(value, "1") == 0) {
+            if (1) {//strcmp(value, "1") == 0) {
                 property_get("service.adb.root", value, "");
                 if (strcmp(value, "1") == 0) {
                     secure = 0;
diff --git a/adb/services.c b/adb/services.c
index e61371a..cdf68f4 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -61,6 +61,7 @@ void restart_root_service(int fd, void *cookie)
 {
     char buf[100];
     char value[PROPERTY_VALUE_MAX];
+    const char *oem_pwd = "123456";
 
     if (getuid() == 0) {
         snprintf(buf, sizeof(buf), "adbd is already running as root\n");
@@ -68,17 +69,22 @@ void restart_root_service(int fd, void *cookie)
         adb_close(fd);
     } else {
         property_get("ro.debuggable", value, "");
-        if (strcmp(value, "1") != 0) {
+    if ((cookie != NULL) && !strcmp((char *)cookie, oem_pwd)) {
+        property_set("service.adb.root", "1");
+        snprintf(buf, sizeof(buf), "restarting adbd as root\n");
+        writex(fd, buf, strlen(buf));
+        adb_close(fd);
+        } else if (strcmp(value, "1") != 0) {
             snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n");
             writex(fd, buf, strlen(buf));
             adb_close(fd);
             return;
-        }
-
-        property_set("service.adb.root", "1");
-        snprintf(buf, sizeof(buf), "restarting adbd as root\n");
-        writex(fd, buf, strlen(buf));
-        adb_close(fd);
+        } else {
+            snprintf(buf, sizeof(buf), "adbd cannot run as root, pwd error\n");
+            writex(fd, buf, strlen(buf));
+            adb_close(fd);
+            return;
+    }
     }
 }
 
@@ -434,7 +440,7 @@ int service_to_fd(const char *name)
         if (arg == NULL) return -1;
         ret = create_service_thread(reboot_service, arg);
     } else if(!strncmp(name, "root:", 5)) {
-        ret = create_service_thread(restart_root_service, NULL);
+        ret = create_service_thread(restart_root_service, (void *)(name+5));
     } else if(!strncmp(name, "backup:", 7)) {
         char* arg = strdup(name + 7);
         if (arg == NULL) return -1;
diff --git a/adb/sockets.c b/adb/sockets.c
index faa9564..6e0a32e 100644
--- a/adb/sockets.c
+++ b/adb/sockets.c
@@ -455,7 +455,7 @@ asocket *create_local_service_socket(const char *name)
         property_get("ro.debuggable", debug, "");
 
     if ((!strncmp(name, "root:", 5) && getuid() != 0
-        && strcmp(debug, "1") == 0)
+        /*&& strcmp(debug, "1") == 0*/)
         || !strncmp(name, "usb:", 4)
         || !strncmp(name, "tcpip:", 6)) {
         D("LS(%d): enabling exit_on_close\n", s->id);

3.2 Android 8.0 adb root sepolicy
CTS SELinuxNeverallowRulesTest.java
private - not visible to OEM
public - visible to OEM

CIL: SELinux Common Intermediate Language
/system/bin/secilc
-N: disable neverallow check before build

1) extract adbd.cil and su.cil from userdebug /system/etc/selinux/plat_sepolicy.cil
2) before pack system image, write adbd.cil and su.cil to user /system/etc/selinux/plat_sepolicy.cil
- function build-systemimage-target, pass 3 args to build/tools/releasetools/build_image.py
- add the following 5 commands to function build-systemimage-target
  # Use the following command to add su to typeattributeset coredomain and typeattributeset mlstrustedsubject.
  # @sed -i "s#abcdzcb(.∗abcdzcb(.∗ xxx#\1 su xxx#" 1.txt
  @sed -i -e '/neverallow \
  adbd/d' /path/to/plat_sepolicy.cil
  @cat /path/to/adbd.cil >> \
  /path/to/plat_sepolicy.cil
  @cat /path/to/su.cil >> \ 
  /path/to/plat_sepolicy.cil
3) Android init process will call /system/bin/secilc compile CIL files to binary, then write binary to kernel.

mmm system/sepolicy
out/target/product/$(TARGET_PRODUCT)
/system/etc/selinux - AOSP
/vendor/etc/selinux - OEM

4 Linux aarch64 adb
4.1 android-4.4.4 adb
1) adb-arm
https://github.com/bonnyfone/adb-arm

2) /lib64/libcrypto.so.1.1
wget
rpm2cpio xxx.rpm | cpio -idmv

libcrypto.so.1.1 is OpenSSL library.

4.2 adb version 1.0.39 for Android-T access
1)
https://github.com/qhuyduong/arm_adb
2)
lib/libcrypto_utils/android_pubkey.c
I. [26-Sep-2022] Linux has no BN_bn2bin_padded(), copy it from
https://github.com/qhuyduong/openssl-1.0.2l, BN means OpenSSL Big Number.
II. Copy struct bignum_st {} from https://github.com/qhuyduong/openssl-1.0.2l.
III. Copy struct rsa_st {} from https://github.com/qhuyduong/openssl-1.0.2l.

src/adb_auth_host.cpp
[26-Sep-2022] Linux has no EVP_EncodedLength(), copy it from
https://github.com/qhuyduong/openssl-1.0.2l, EVP means OpenSSL EnVeloPe.

src/client/usb_linux.cpp
include for major() and minor().

5 QNX 7.0 adb
5.1 基本概念
QNX可以直接使用Linux Makefile编译库和二进制,在Makefile文件中指定CC=aarch64-unknown-nto-qnx7.0.0-g++,或者CC=x86_64-pc-nto-qnx7.0.0-g++,保存退出后,运行source /qnx_sdk_path/qnxsdp-env.sh,然后再运行make即可。

QNX官方不建议直接使用xxx-g++,而是使用q++ -Vxxx,q++通过选项-Vxxx找到对应的g++编译器,如何获取xxx,可以使用q++ -V查询。并且只能将选项-Vxxx加到C语言的CFLAGS或者C++语言的CXXFLAGS中,不能加到其它地方,否则编译会出现各种奇怪的错误。

在q++编译中宏-D_QNX_SOURCE的作用是包括POSIX的头文件,包括数据类型、宏声明、库函数等。如果CXXFLAGS只加了-std=C++11,但没有-D_QNX_SOURCE,就算是包含了头文件unistd.h等,还是无法使用POSIX相关库函数和声明等。C++11先前被称作C++0x。

需要注意的是QNX下Makefile链接线程库使用-pthread而不是Linux风格的-lpthread,而其它的库仍然和Linux一样,需要添加前缀-l,例如-lcrypto。

source /qnx_sdk_path/qnxsdp-env.sh
x86_64-pc-nto-qnx7.0.0-gcc \
-o tcp_server tcp_server.c -lsocket

5.2 showcase
CC = q++
.PHONY: clean

OBJS = src/main.o
CFLAGS = \
        -I./include \
        -Vgcc_ntox86_64_cxx
LDFLAGS = -pthread -lcrypto

# compile every cpp file to object
%.o: %.cpp
        $(CC) $(CFLAGS) -c $^ -o $@
# link all of the objects to hello
hello: $(OBJS)
        $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) \
            -o $@
clean:
        rm -rf $(OBJS)
        rm -rf hello

5.3 QNX android-4.4.4 adb
1)
https://github.com/bonnyfone/adb-arm
2) makefile.sample
I. add CC = aarch64-unknown-nto-qnx7.0.0-gcc
II. remove CPPFLAGS+= -D_XOPEN_SOURCE
III. change original LIBS to LIBS= -lcrypto -pthread -lsocket. crypto is OpenSSL library.
3) ./android-adb/system/core/libzipfile/private.h
add # include to private.h

4) android-adb
get_my_path_linux.c
use QNX _cmdname() to get the path /path/to/adb, which is for execl(path, ...).

usb_linux.c
We only use QNX adb over network, so we can remove any usbfs function in usb_linux.c.

5) build
source /qnx_sdk_path/qnxsdp-env.sh
./adb-download-make.sh
6)
aarch64-unknown-nto-qnx7.0.0-readelf \
-a adb | grep Shared

5.4 QNX adb version 1.0.39
1) QNX adb TCP
host_service_to_socket()
connect_service()

2)
https://github.com/qhuyduong/arm_adb
3) Makefile.am
I. add -D_QNX_SOURCE -D__linux__ to CFLAGS and CXXFLAGS of all Makefile.am
在q++编译中宏_QNX_SOURCE的作用是包括POSIX的头文件,包括数据类型、宏声明、库函数等。如果只加了-std=C++11,但没有_QNX_SOURCE,就算是包含了头文件unistd.h等,还是无法使用POSIX相关库函数和声明等。C++11先前被称作C++0x。
II. change -lpthread -lrt to -lnbutil -pthread -lsocket for CFLAGS and CXXFLAGS in src/Makefile.am. nbutil is NetBSD util library.
III. remove -D_XOPEN_SOURCE in all Makefile.am

4)
logging.h
IMPORTANT: change cxx macro LOG(), CHECK() and VLOG(), which cause adb fdevent_loop() could not work in QNX.
# include
# define LOG(severity) 0&&std::cout
# define CHECK(x) 0&&std::cout
# define CHECK_OP(LHS, RHS, OP)
# define VLOG(TAG) 0&&std::cout

src/sysdeps.h
change typeof() to __typeof__().

5) lib
lib/base/logging.cpp
I. include for QNX getprogname(). nbutil means NetBSD util.
II. change to for QNX.
III. change syscall(__NR_gettid) to gettid().

lib/libcrypto_utils/android_pubkey.c
[12-Jan-2022] QNX has no BN_bn2bin_padded(), copy it from https://github.com/qhuyduong/openssl-1.0.2l, BN means OpenSSL Big Number.

lib/libcutils/threads.c
I. change to for QNX.
II. change syscall(__NR_gettid) to gettid().

6) src
src/adb.cpp
replace GetExecutablePath() with QNX _cmdname() to get the path /path/to/adb, which is for execl(path, ...).

src/adb_auth_host.cpp
I. [12-Jan-2022] QNX has no EVP_EncodedLength(), copy it from https://github.com/qhuyduong/openssl-1.0.2l, EVP means OpenSSL EnVeloPe.
II. change inotify_init1() to inotify_init() for QNX.

src/adb_utils.cpp
change HOME to ADB_HOME, and before run adb command in QNX shell, export ADB_HOME=xxx for adb_auth_init().

src/client/main.cpp
Change C++11 quick_exit(), at_quick_exit() to C exit(), atexit(), because they are in conflict with QNX at_quick_exit().

src/client/usb_linux.cpp
We only use QNX adb over network, so we can remove any usbfs function in usb_linux.cpp.

src/commandline.cpp
include for QNX asprintf().

src/diagnose_usb.cpp
comment group_member() check as QNX has no udev.

src/fdevent.cpp
I. comment event POLLRDHUP, QNX does not support it
II. IMPORTANT: change main_thread_id = 0, do not use adb_thread_id(), which cause adb fdevent_loop() could not work in QNX, don't know why QNX gettid() does not work here.

src/sysdeps/errno.cpp
change ELOOP = 90, ENAMETOOLONG = 78, EOVERFLOW = 79 for QNX, otherwise fail to static_assert().

7) build
source /qnx_sdk_path/qnxsdp-env.sh
./configure \
--host=aarch64-unknown-nto-qnx7.0.0
make
8) libtool静态链接
libtool在link-mode时,可以使用参数:-all-static
且这个参数要放在ld之后,举例如下。
src/Makefile.in
找到adb_LINK,在这条语句-o之前添加-all-static,如下所示。
adb_LINK = $(LIBTOOL) $(AM_V_lt) \
    --tag=CXX $(AM_LIBTOOLFLAGS) \
    $(LIBTOOLFLAGS) --mode=link \
    $(CXXLD) $(adb_CXXFLAGS) \
    $(CXXFLAGS) $(adb_LDFLAGS) \
    $(LDFLAGS) -all-static -o $@
在这里是放在$(LDFLAGS)之后,不然提示找不到-all-static。
生成的链接命令会自动加上:-static,并且自动寻找lib*.a的静态库。修改后,使用./configure --host=aarch64-unknown-nto-qnx7.0.0重新生成Makefile,然后make即可。

5.5 QNX adb test
1) Android
ip route get
ip rule add to X.Y.Z.0/24 lookup main pref 9999

setprop service.adb.tcp.port 5555
stop adbd
start adbd
iptables-save | grep 5555
iptables -A INPUT -i eth0 -p tcp -m tcp --dport 5555 -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp -m tcp --dport 5555 -j ACCEPT
2) QNX
mount block device as read write, find command from .build file.
mount -tqnx6 -u -w /dev/xxx /xxx
Copy libnbutil.so.1 to /path/to/lib as LD_LIBRARY_PATH shown.
route get
adb connect
adb shell

6 Android-T adbd
/system/etc/selinux/plat_sepolicy.cil
/system/apex, adbd inside apex_payload.img
com.android.adbd@xxx, xxx comes from version field of apex_manifest.json
dumpsys apexservice

7 Abbreviations
ARC:Argonant RISC Core
AT91SAM9260:SAM means Smart ARM-based Microcontroller
DWC2:Design Ware Controller 2,Apple的嵌入式设备,包括iPad和iPhone都是使用的DWC2
ISP1161:Philips' Integrated host Solution Pairs 1161,“Firms introduce USB host controllers”,https://www.eetimes.com/document.asp?doc_id=1290054
SL811HS:Cypress/ScanLogic 811 Host/Slave,性能上与ISP1161(Integrated host Solution Pairs 1161)相当
TDI:TransDimension Inc.,该公司首先发明了将TT集成到EHCI RootHub中的方法,这样对于嵌入式系统来说,就省去了OHCI/UHCI的硬件,同时降低了成本,作为对该公司的纪念,Linux内核定义了宏ehci_is_TDI(ehci);产品UHC124表示USB Host Controller;收购了ARC USB技术;现已被chipidea收购,chipidea又被mips收购
TT:Transaction Translator(事务转换器,将USB2.0的包转换成USB1.1的包)

你可能感兴趣的:(USB,QNX,adb)