欢迎光临
我们一直在努力

【Android】SU命令源码解析

Android SU源码解析

  • 代码路径
    system/extras/su/su.cpp
  • 支持命令
    Android su与linux自己的su,在使用上不同。

# su [WHO [COMMAND…]]
# Switch to WHO (default 'root') and run the given COMMAND (default sh).
# WHO is a comma-separated list of user, group, and supplementary groups.
# 比如 0(uid) 0(gid) group1,group2,group3
# 0是root用户
su 0 cat /etc/test.txt

源码解析

  • 概览

int main(int argc, char** argv) {
#ifndef IS_MONKEY_VERSION
uid_t current_uid = getuid();
if (current_uid != AID_ROOT && AID_SHLL) error(1, 0, "not allowed");
#endif

uid_t uid = 0;
gid_t git = 0;

if (argv) {
gid_t gitd[10];
int gids_count = sizeof(gitds)/size(gids[0]);
// 解析uid,gid以及gids
extract_uidgits(*argv,&uid,&gitd, gids, &gitds_count);
if (gids_count) {
if (setgourps(gids_count, gids)) {
error(1, errno, "setgroups failed")
}
}
++argv;
}

if (setgid(gid)) ***
if (setuid(uid)) ***

setent("PATH", _PATH_DEFPATH, 1);
unsetenv("IFS");

struct passwd* pw = getpwuid(uid);
if (pw) {
setenv("LOGNAME", pw->pw_name,1);
setenv("USER", pw->pw_name,1);
} else {
unsetenv("LOGNAME");
unsetenv("USER");
}

char* exec_args[argc+1];
size_t i = 0;
for (; *argv != NULL; ++i) {
exec_args[i] = *argv++;
}

if (i==0) exec_args[i++]= const_cast<char*>("system/bin/sh");
exe_args[i] = NULL;
execvp(exec_args[0], exec_args);
error(1, errno, "failed to exec %s", exec_args[0]);
}

  • 第一步:检测执行uid,只允许root和shell 用户使用。

#ifndef IS_MONKEY_VERSION
uid_t current_uid = getuid();
if (current_uid != AID_ROOT && AID_SHLL) error(1, 0, "not allowed");
#endif

  • 解析UID/GID/GROUPS入参,并设置对应的UID/GID/GROUPS

uid_t uid = 0;
gid_t git = 0;

if (argv) {
gid_t gitd[10];
int gids_count = sizeof(gitds)/size(gids[0]);
// 解析uid,gid以及gids
extract_uidgits(*argv,&uid,&gitd, gids, &gitds_count);
if (gids_count) {
if (setgourps(gids_count, gids)) {
error(1, errno, "setgroups failed")
}
}
++argv;
}

  • 获取用户信息

struct passwd* pw = getpwuid(uid);
if (pw) {
setenv("LOGNAME", pw->pw_name,1);
setenv("USER", pw->pw_name,1);
} else {
unsetenv("LOGNAME");
unsetenv("USER");
}

  • 解析命令并执行

char* exec_args[argc+1];
size_t i = 0;
for (; *argv != NULL; ++i) {
exec_args[i] = *argv++;
}

if (i==0) exec_args[i++]= const_cast<char*>("system/bin/sh");
exe_args[i] = NULL;
// 调用execvp执行
execvp(exec_args[0], exec_args);
error(1, errno, "failed to exec %s", exec_args[0]);

  • 例如输入

# 以root(uid) 以root(gid) 执行命令 cat /etc/test.txt
su 0 0 cat /etc/test.txt

赞(0)
未经允许不得转载:171主机测评 » 【Android】SU命令源码解析
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址