某安卓系统,我用netstat 查看正在监听的端口时,发现有127.0.0.1:8872打开着。
查找官方资料,关于这个端口是这样解释的。
https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/master/doc/btsnoop_net.md
下面来分析为什么有这样的端口存在。
在安卓系统全局搜索寻找是哪个文件开了这个8872端口侦听。费了一些周折终于找到了。
IDA pro逆向工具寻找socket server的IP和port_晓翔仔的博客-CSDN博客
逆向分析/system/lib/hw/bluetooth.default.so,可以发现bluetooth.default.so设置了socketserver(127.0.0.1:8872)。
既然这是蓝牙有关的文件,那查找资料了解"蓝牙进程与蓝牙堆栈通信"原理。
从一篇名为 “Android8.0 蓝牙进程与蓝牙堆栈通信源码分析” 的博客中查到:
Apps通过Binder IPC与蓝牙系统服务的通信,是由蓝牙服务AdapterService实现的。
AdapterService通过JNI接口调用蓝牙堆栈接口
JNI方法:/platform/packages/apps/bluetooth/jni/com_android_btservice_AdapterService.cpp
Android8.0 蓝牙进程与蓝牙堆栈通信源码分析_yurh的博客-CSDN博客_gabeldorsche功能堆栈
我从自己的安卓环境找到Bluetooth.apk,发现:
/system/app/Bluetooth/Bluetooth.apk的com_android_btservice_AdapterService里加载了/system/lib/libbluetooth_jni.so
代码:
static {
System.load("/system/lib/libbluetooth_jni.so");
classInitNative();
}
按照这里的目录,找到了libbluetooth_jni.so。那么libbluetooth_jni.so和bluetooth.default.so有什么关系呢?
libbluetooth_jni.so 相关反编译出来的代码:
NAME= "bluetooth";
if ( hw_get_module(NAME, &v9) )
{
_android_log_print(6, "BluetoothServiceJni", "No Bluetooth Library found");
}
查看hw_get_module函数源码,并分析。
源码地址:
https://android.googlesource.com/platform/hardware/libhardware/+/master/hardware.c
源码中的hw_get_module函数执行逻辑:
1.用property_get查找ro.hardware.NAME,若变量的值是VALUE,则找BasePath/NAME.VALUE.so是否存在。(没有ro.hardware.bluetooth环境变量)
2.循环遍历variant_keys,若variant_keys数组里的变量的值是VALUE.则找BasePath/NAME.VALUE.so是否存在(都不存在)
3.如果上一步找不到,找BasePath/NAME.defaule.so是否存在(/system/lib/hw/bluetooth.default.so存在,目标module成功get到了)
附:
variant_keys数组:
static const char *variant_keys[] = {
"ro.hardware", /* This goes first so that it can pick up a different
file on the emulator. */
"ro.product.board",
"ro.board.platform",
"ro.arch"
};
BasePath的定义
/** Base path of the hal modules */
#if defined(__LP64__)
#define HAL_LIBRARY_PATH1 "/system/lib64/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"
#define HAL_LIBRARY_PATH3 "/odm/lib64/hw"
#else
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
#define HAL_LIBRARY_PATH3 "/odm/lib/hw"
可以发现libbluetooth_jni.so用hw_get_module的方式载入了/system/lib/hw/bluetooth.default.so。
从开源网站找到127.0.0.1:8872有关服务端代码
static void* listen_fn_(UNUSED_ATTR void* context) {
int enable = 1;
prctl(PR_SET_NAME, (unsigned long)LISTEN_THREAD_NAME_, 0, 0, 0);
listen_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//......
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(LOCALHOST_);
addr.sin_port = htons(LISTEN_PORT_);
if (bind(listen_socket_, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
LOG_ERROR(LOG_TAG, "%s unable to bind listen socket: %s", __func__,
strerror(errno));
goto cleanup;
}
if (listen(listen_socket_, 10) == -1) {
LOG_ERROR(LOG_TAG, "%s unable to listen: %s", __func__, strerror(errno));
goto cleanup;
}
for (;;) {
int client_socket;
OSI_NO_INTR(client_socket = accept(listen_socket_, NULL, NULL));
if (client_socket == -1) {
if (errno == EINVAL || errno == EBADF) {
break;
}
LOG_WARN(LOG_TAG, "%s error accepting socket: %s", __func__,
strerror(errno));
continue;
}
/* When a new client connects, we have to send the btsnoop file header. This
* allows a decoder to treat the session as a new, valid btsnoop file. */
std::lock_guard lock(client_socket_mutex_);
safe_close_(&client_socket_);
client_socket_ = client_socket;
OSI_NO_INTR(send(client_socket_, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16, 0));
}
cleanup:
safe_close_(&listen_socket_);
return NULL;
}
发现 Server端的实现很简单,它在127.0.0.1:8872上监听前来连接的client。首次连接上,server会将16字节的header发送给client,这是HCI日志格式的一部分。后续一旦有数据在HCI层流动,server会将数据copy一份送给client。client无需发送给server任何消息,只要等待接收就行了。
这样,我们搞清楚了从Bluetooth.apk到bluetooth.default.so的关系,找到了127.0.0.1:8872打开的原因。
经过比较,上述分析和通用蓝牙模块框架是一致的。
图片摘自以下博客,感谢作者。
Android 蓝牙模块框架分析_Alex.Ke的博客-CSDN博客_bluetooth.default.so
如果你对打开该端口感兴趣,可以阅读以下博客了解安装系统中打开蓝牙HCI snoop文件的方法。
安卓系统中默认打开蓝牙 HCI snoop 文件的方法_坏小子VP的博客-CSDN博客