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
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
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
II. change
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
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
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的包)