大家好,最近一直在研究android下的溢出获取root权限,目前研究的成果是: 已经对一个设备进行溢出,让pc指针跳入了预定好的函数中;在获取要获取权限的时候遇到了如下难题。
1、在4.3+ 开启SELinux 的情况下,根本就没法从/proc/kallsyms获取函数地址。(有人可能说可以暴力搜索,参照android_run_root_shell 的方式)
对于上述的问题,我想到了一个小技巧来解决,那就是直接暴力搜索进程的cred结构;直接对结构中的设置在内核模式中做修改;以达到提权的目的,但又遇到了问题。
那就是 从什么地址开始搜索 ,搜到哪才算正确,到哪里结束;
之前一直都是玩windows下逆向,一下子转到android下 有很多不懂的地方;习惯了用之前解决windows下问题的习惯来弄android,可能会走弯路,还请众大神多多指教~
贴上cred结构的解释和原型
原型
passwd程序用户是root,且设置SETUID标志,用于普通用户在执行passwd时可以修改需要root权限的/etc/passwd文件。
当运行passwd时,实际用户uid=500(redhat)不变,保存用户suid、有效用户euid均变成0(root),此时权限关系如下:
cap_permitted=cap_inheritable+cap_bset
cap_effective=cap_permitted
iii.uid
内核中主要有三个用户:uid(实际用户)、euid(有效用户)、suid(保存用户),可通过setuid、seteuid、setreuid系统调用实现用户切换。
setuid规则:
1.当有超级用户权限,修改uid,euid,suid为新用户
2.当没有超级用户权限,新用户id参数等于uid或suid时,修改euid为新用户
3.其它情况不允许,报EPERM错误
三个用户含义如下:
uid:实际用户,只有拥有超级用户权限的进程才能修改uid;在登录/用户切换时,login/su有超级用户权限,调用setuid设置uid,euid,suid为登录用户/切换用户;uid一般保持不变
euid:有效用户,exec时如果SETUID置位则设置成程序文件用户ID,否则euid不变。可以通过setuid设置euid为uid或suid
suid:保存用户,exec时设置成euid。
三个uid之间的关系如下图所示:
1、在4.3+ 开启SELinux 的情况下,根本就没法从/proc/kallsyms获取函数地址。(有人可能说可以暴力搜索,参照android_run_root_shell 的方式)
对于上述的问题,我想到了一个小技巧来解决,那就是直接暴力搜索进程的cred结构;直接对结构中的设置在内核模式中做修改;以达到提权的目的,但又遇到了问题。
那就是 从什么地址开始搜索 ,搜到哪才算正确,到哪里结束;
之前一直都是玩windows下逆向,一下子转到android下 有很多不懂的地方;习惯了用之前解决windows下问题的习惯来弄android,可能会走弯路,还请众大神多多指教~
贴上cred结构的解释和原型
引用:
I.credential管理 linux系统中,一个对象操作另一个对象时通常要做安全性检查。如一个进程操作一个文件,要检查进程是否有权限操作该文件。 linux内核中,credential机制的引入,正是对象间访问所需权限的抽象;主体提供自己权限的证书,客体提供访问自己所需权限的证书,根据主客体提供的证书及操作做安全性检查。 证书管理术语: 客体:指用户空间程序直接可以操作的系统对象,如进程、文件、消息队列、信号量、共享内存等;每个客体都有一组凭证,每种客体有不同的凭证集 客体所有者:客体凭证集有一部分表示客体所有者;如文件中uid表示文件的所有者 主体:操作客体的对象;除进程外大多数系统对象都不是主体,但在特殊环境下某些对象是主体,如文件在设置F_SETOWN后可以发送SIGIO信号到进程,这时文件就是主体,进程就是客体 行为:主体怎样操作客体,如读写执行文件等 客体上下文:客体被访问时所需权限凭证集 主体上下文:主体的权限凭证集 规则:主体操作客体时,用于安全检查 当主体操作客体时,根据主体上下文、客体上下文、操作来做安全计算,查找规则看主体是否有权限操作客体。 II.进程凭证集 i.cred 进程的凭证集可用结构cred表示,即可以表示主体权限凭证集,也可表示客体被访问时所需权限凭证集;进程描述符中cred和real_cred字段分别指向主体与客体的证书 |
代码:
93 /*
94 * The security context of a task
95 *
96 * The parts of the context break down into two categories:
97 *
98 * (1) The objective context of a task. These parts are used when some other
99 * task is attempting to affect this one.
100 *
101 * (2) The subjective context. These details are used when the task is acting
102 * upon another object, be that a file, a task, a key or whatever.
103 *
104 * Note that some members of this structure belong to both categories - the
105 * LSM security pointer for instance.
106 *
107 * A task has two security pointers. task->real_cred points to the objective
108 * context that defines that task's actual details. The objective part of this
109 * context is used whenever that task is acted upon.
110 *
111 * task->cred points to the subjective context that defines the details of how
112 * that task is going to act upon another object. This may be overridden
113 * temporarily to point to another security context, but normally points to the
114 * same context as task->real_cred.
115 */
116 struct cred {
117 atomic_t usage;
118 #ifdef CONFIG_DEBUG_CREDENTIALS
119 atomic_t subscribers; /* number of processes subscribed */
120 void *put_addr;
121 unsigned magic;
122 #define CRED_MAGIC 0x43736564
123 #define CRED_MAGIC_DEAD 0x44656144
124 #endif
125 uid_t uid; /* real UID of the task */
126 gid_t gid; /* real GID of the task */
127 uid_t suid; /* saved UID of the task */
128 gid_t sgid; /* saved GID of the task */
129 uid_t euid; /* effective UID of the task */
130 gid_t egid; /* effective GID of the task */
131 uid_t fsuid; /* UID for VFS ops */
132 gid_t fsgid; /* GID for VFS ops */
133 unsigned securebits; /* SUID-less security management */
134 kernel_cap_t cap_inheritable; /* caps our children can inherit */
135 kernel_cap_t cap_permitted; /* caps we're permitted */
136 kernel_cap_t cap_effective; /* caps we can actually use */
137 kernel_cap_t cap_bset; /* capability bounding set */
138 #ifdef CONFIG_KEYS
139 unsigned char jit_keyring; /* default keyring to attach requested
140 * keys to */
141 struct key *thread_keyring; /* keyring private to this thread */
142 struct key *request_key_auth; /* assumed request_key authority */
143 struct thread_group_cred *tgcred; /* thread-group shared credentials */
144 #endif
145 #ifdef CONFIG_SECURITY
146 void *security; /* subjective LSM security */
147 #endif
148 struct user_struct *user; /* real user ID subscription */
149 struct group_info *group_info; /* supplementary groups for euid/fsgid */
150 struct rcu_head rcu; /* RCU deletion hook */
151 };
当运行passwd时,实际用户uid=500(redhat)不变,保存用户suid、有效用户euid均变成0(root),此时权限关系如下:
cap_permitted=cap_inheritable+cap_bset
cap_effective=cap_permitted
iii.uid
内核中主要有三个用户:uid(实际用户)、euid(有效用户)、suid(保存用户),可通过setuid、seteuid、setreuid系统调用实现用户切换。
setuid规则:
1.当有超级用户权限,修改uid,euid,suid为新用户
2.当没有超级用户权限,新用户id参数等于uid或suid时,修改euid为新用户
3.其它情况不允许,报EPERM错误
三个用户含义如下:
uid:实际用户,只有拥有超级用户权限的进程才能修改uid;在登录/用户切换时,login/su有超级用户权限,调用setuid设置uid,euid,suid为登录用户/切换用户;uid一般保持不变
euid:有效用户,exec时如果SETUID置位则设置成程序文件用户ID,否则euid不变。可以通过setuid设置euid为uid或suid
suid:保存用户,exec时设置成euid。
三个uid之间的关系如下图所示: