Android Root方法原理解析及Hook(二) udev漏洞

android并没有实现linuxudev,其功能由vold进程实现,其包含VolumeManagerNetlinkManagerCommandListenermodules

 

vold工作机制:

       kernel检测到硬件事件,然后广播出去,Native层的init进程通知vold(root权限)去处理该广播信息,vold再通知JNI层的MountService,其与Java应用层交互

       vold进程可以将用户态数据copykernel,由kernel写入设备文件(恶意程序的依赖)

       vold进程应该只处理kernel发送的deviceNETLINKsocket消息,但实际上并未检测NETLINKsocket消息的来源,

       这样可以广播add devicesocket信息,触发硬件处理事件,将恶意代码传入kernel,由其写入设备文件

 

修改方法:

首先在代码中设置socket参数,可以让接受者知道发送者的uidgid

setsockopt(s,SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));

我机器的源码,在system/core/libcutils/uevent.c uevent_open_socket函数中已经有了这个设置语句,是android打过patch的;

/system/core/init/device.c中,修订版本的代码如下:

while((n = uevent_kernel_multicast_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) {}

用了这个函数uevent_kernel_multicast_recv(),取代了之前的简单的recv函数。

system/core/libcutils/uevent.c中,uevent_kernel_multicast_recv()代码实现了对socket消息的来源的判断


Myhook code:

loglogcat


#include <cutils/log.h>
#define LOG_TAG “netlink hooker”

ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) {
…
…
if (addr.nl_groups == 0 || addr.nl_pid != 0) {  //判断socket来源的gid和uid
	LOGW(“non-kernel or unicast netlink message”);
    goto out;
}

struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr);
if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
	LOGW(“netlink message with no sender credentials”);
    goto out;
}

struct ucred *cred = (struct ucred *)CMSG_DATA(cmsg);
if (cred->uid != 0) {
     LOGW(“netlink message from non-root user”);
    goto out;
}

return n;

out:
/* clear residual potentially malicious data */
bzero(buffer, length);
errno = EIO;
return -1;
}



你可能感兴趣的:(android,socket,struct,buffer,hook,credentials)