转载请注明出处:http://hi.baidu.com/androidhacker/blog/item/59faabfda34b71f57709d707.html

这篇文章是上一篇博客的后续分析,主要介绍向init进程发送热拔插信息后init进程的处理流程

首先我们来了解一个数据结构,uevent,如下

代码:
struct uevent {                                                                                

    const char *action;                                                                        

    const char *path;                                                                          

    const char *subsystem;                                                                     

    const char *firmware;                                                                      

    int major;                                                                                 

    int minor;                                                                                 

};  
 

内核收到的信息如下,ACTION=addDEVPATH=/../data/local/tmpSUBSYSTEM=firmwareFIRMWARE=../../../data/local/tmp/hotplug
通过如下函数parse_event进行解析

代码:
static void parse_event(const char *msg, struct uevent *uevent) 

{

 

    while(*msg) {                                                                              

        if(!strncmp(msg, "ACTION=", 7)) {                                                      

            msg += 7;                                                                          

            uevent->action = msg;                                                              

        } else if(!strncmp(msg, "DEVPATH=", 8)) {                                              

            msg += 8;                                                                          

            uevent->path = msg;                                                                

        } else if(!strncmp(msg, "SUBSYSTEM=", 10)) {                                           

            msg += 10;                                                                         

            uevent->subsystem = msg;                                                           

        } else if(!strncmp(msg, "FIRMWARE=", 9)) {                                             

            msg += 9;                                                                          

            uevent->firmware = msg;                                                            

        } else if(!strncmp(msg, "MAJOR=", 6)) {                                                

            msg += 6;                                                                          

            uevent->major = atoi(msg);                                                         

        } else if(!strncmp(msg, "MINOR=", 6)) {                                                

            msg += 6;                                                                          

            uevent->minor = atoi(msg);                                                         

        }

         while(*msg++);

    }           

}
经过解析之后,uevent的结构为:
action="add"
path="/../data/local/tmp"
subsystem="firmware"
firmware="../../../data/local/tmp/hotplug"


之后来到处理firmware的核心函数

代码:
static void process_firmware_event(struct uevent *uevent)

{

    l = asprintf(&root, SYSFS_PREFIX"%s/", uevent->path);

    //root为/sys/../data/local/tmp/=/data/local/tmp/

    

    l = asprintf(&loading, "%sloading", root);

    //loading为/data/local/tmp/loading

    

    l = asprintf(&data, "%sdata", root);

    //data为/data/local/tmp/data   其内容为指向/proc/sys/kernel/hotplug的符号链接

    

    l = asprintf(&file, FIRMWARE_DIR"/%s", uevent->firmware);

    //file为/etc/firmware/../../../data/local/tmp/hotplug=/data/local/tmp/hotplug

    

    loading_fd = open(loading, O_WRONLY);

    

    data_fd = open(data, O_WRONLY); 

    

    fw_fd = open(file, O_RDONLY);

    

    load_firmware(fw_fd, loading_fd, data_fd);

}

 

最后来到load_firmware函数,把hotplug中的数据写到/proc/sys/kernel/hotplug中
其内容变为/data/local/tmp/exploid

代码:
static int load_firmware(int fw_fd, int loading_fd, int data_fd)

{

    while (len_to_copy > 0) {

        char buf[PAGE_SIZE];

 

 

        nr = read(fw_fd, buf, sizeof(buf));

                                                                         

        len_to_copy -= nr;                                                                     

        while (nr > 0) {                                                                       

                                                                                               

            nw = write(data_fd, buf + nw, nr);                                                 

 

            nr -= nw;

        }

    }

}
 

终于/proc/sys/kernel/hotplug中写入了我们的恶意程序了,只要再次受到如wifi打开、usb插入等热拔插信息,内核就会以root权限加载我们的程序再一次执行,从而达到提权的目的