当前位置:首页 > 黑客技术 > 正文内容

详细分析Binder中的单指令竞态标准漏洞(一)

访客4年前 (2021-04-04)黑客技术456

在文中中,大家将为阅读者深层次详细介绍Binder中的单指令竞态标准漏洞以及利用方式。

在上年10月份的安卓系统安全性公示中,漏洞CVE-2020-0423被公布,实际叙述以下:

在binder.c的binder_release_work中,因为上锁不善,造成 UAF漏洞。这很有可能造成 核心中的当地提权漏洞,而不用附加的实行管理权限。而且,利用该漏洞时不用客户互动。

CVE-2020-0423是Android中另一个可造成 管理权限提高的漏洞。在本文中,大家将详细分析这一漏洞,并结构一个可用以在Android机器设备上获得root管理权限的exploit。

Android上的进程全是相互之间防护的,换句话说,他们没法立即浏览彼此之间的存储空间。殊不知,有时他们却必须那样做,比如,不论是在远程服务器和集群服务器互换数据信息,還是只是在2个进程中间共享资源信息内容的情况下。

Android上的进程间通信由Binder承担的。该核心部件出示了一个客户可浏览的标识符机器设备,可用以调用远程控制进程中的方法,并向其传送主要参数。事实上,Binder不但当做了2个每日任务中间的代理商,还承担在数据传输期内解决内存分配及其管理方法共享资源目标的生命期的每日任务。

假如您不了解Binder的内部构造,何不先参考这些方面的一些文章内容,比如Synacktiv编写的“Binder Transactions In The Bowels of the Linux Kernel”,这针对了解本文的一部分会很有协助。

CVE-2020-0423的补丁程序于10月10日upstream至Linux核心,并含有下列递交信息:

上边的文本粗略地简述了利用这一漏洞开启Use-After-Free或UAF漏洞需要的不一样流程。这种流程将在下一节中详尽多方面详细介绍,如今使我们先讨论一下补丁程序,以掌握漏洞的根本原因在哪儿。

实质上,这一补丁下载所做的事儿便是将涵数binder_dequeue_work_head的內容内联到binder_release_work涵数中。唯一的差别是,在依然对proc上锁的另外,载入binder_work结构体的type字段名。

// Before the patch

static struct binder_work *binder_dequeue_work_head(

struct binder_proc *proc,

struct list_head *list)

{

struct binder_work *w;

binder_inner_proc_lock(proc);

w=binder_dequeue_work_head_ilocked(list);

binder_inner_proc_unlock(proc);

return w;

}

static void binder_release_work(struct binder_proc *proc,

struct list_head *list)

{

struct binder_work *w;

while (1){

w=binder_dequeue_work_head(proc, list);

if (!w)

return;

switch (w->type){

//[...]

// After the patch

static void binder_release_work(struct binder_proc *proc,

struct list_head *list)

{

struct binder_work *w;

enum binder_work_type wtype;

while (1){

binder_inner_proc_lock(proc);

w=binder_dequeue_work_head_ilocked(list);

wtype=w ? w->type : 0;

binder_inner_proc_unlock(proc);

if (!w)

return;

switch (wtype){

//[...]

在这个补丁下载以前,能够让一个binder_work结构体撤出序列,释放出来另一个线程并分配,随后变更binder_release_work的控制流。下一节中,大家将更深层次地表述怎么会产生这类个人行为,及其它是怎样被随意开启的。

在这节中,做为一个实例,使我们想像有两个进程应用binder开展通讯,在其中,一个进程为推送方,另一个进程为接受方。

这时,开启该漏洞必须三个前提条件:

从推送方线程调用binder_release_work

从推送方线程的todo目录中出列的binder_work结构体

从接受方线程中释放出来的一个binder_work结构体

使我们逐一开展科学研究,并试着找到完成他们的方式。

完成这一必要条件比较简单。如前所述,当应用binder解决每日任务时,binder_release_work是清除方法的一部分。我们可以应用ioctl指令binder_thread_exit在线程中显式调用它。

// Userland code from the exploit

int binder_fd=open("/dev/binder", O_RDWR);

//[...]

ioctl(binder_fd, BINDER_THREAD_EXIT, 0);

这一ioctl最后将调用坐落于drivers/android/binder.c文档中的核心涵数binder_ioctl。

随后,binder_ioctl将抵达BINDER_THREAD_EXIT支系,并调用binder_thread_release涵数。在其中,thread是一个binder_thread结构体,储存当今开展ioctl调用的线程的信息内容。

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

{

//[...]

case BINDER_THREAD_EXIT:

binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit

",

proc->pid, thread->pid);

binder_thread_release(proc, thread);

thread=NULL;

break;

//[...]

在binder_thread_release涵数的尾端,发生了对binder_release_work涵数的调用。

static int binder_thread_release(struct binder_proc *proc,

struct binder_thread *thread)

{

//[...]

binder_release_work(proc, &thread->todo);

binder_thread_dec_tmpref(thread);

return active_transactions;

}

一定要注意,在调用bind_release_work时,主要参数list_head *list的数值&thread->todo。在我们试着用binder_work结构体添充该目录时,将涉及到一二节的內容。

static void binder_release_work(struct binder_proc *proc,

struct list_head *list)

{

struct binder_work *w;

while (1){

w=binder_dequeue_work_head(proc, list);

if (!w)

return;

//[...]

即然大家知道怎样开启易受攻击的涵数,那麼使我们来明确怎样用随意的binder_work结构体来添充线程的TODO目录。

binder_work结构体被安插到thread->todo的2个部位处:

binder_enqueue_deferred_thread_work_ilocked

static void

binder_enqueue_deferred_thread_work_ilocked(struct binder_thread *thread,

struct binder_work *work)

{

binder_enqueue_work_ilocked(work, &thread->todo);

}

binder_enqueue_thread_work_ilocked

static void

binder_enqueue_thread_work_ilocked(struct binder_thread *thread,

struct binder_work *work)

{

binder_enqueue_work_ilocked(work, &thread->todo);

thread->process_todo=true;

}

这种涵数在编码中的不一样地区都是有采用,可是大家很感兴趣的编码途径是以binder_translate_binder逐渐的那一个。当线程发送包含BINDER_TYPE_BINDER或BINDER_TYPE_WEAK_BINDER的事务时将调用该函数。

  之后,从binder对象创建一个binder节点,并令接收端进程的引用计数器加1。只要接收进程持有对该节点的引用,它就会在Binder的内存中保持活动状态。但是,如果进程释放该引用,那么该节点将被销毁,这也是我们稍后将尝试实现的触发UAF的功能。

  首先,让我们解释一下在调用binder_inc_ref_for_node的过程中,binder节点和thread -> todo列表的关系。

  static int binder_translate_binder(struct flat_binder_object *fp,

  struct binder_transaction *t,

  struct binder_thread *thread)

  {

  // [...]

  ret=binder_inc_ref_for_node(target_proc, node,

  fp->hdr.type==BINDER_TYPE_BINDER,

  &thread->todo, &rdata);

  // [...]

  }

  binding_inc_ref_for_node的参数如下所示:

  structinder_proc * proc:保存对节点的引用的进程

  struct binder_node * node:目标节点

  bool strong:true=强引用,false=弱引用

  struct list_head * target_list:如果节点增加,则使用的工作列表

  struct binder_ref_data * rdata:引用的ID/引用计数数据

  当前路径中的target_list是thread->todo。该参数仅在调用binder_inc_ref_olocked的binder_inc_ref_for_node中使用。

  static int binder_inc_ref_for_node(struct binder_proc *proc,

  struct binder_node *node,

  bool strong,

  struct list_head *target_list,

  struct binder_ref_data *rdata)

  {

  // [...]

  ret=binder_inc_ref_olocked(ref, strong, target_list);

  // [...]

  }

  然后,binder_inc_ref_olocked会调用binder_inc_node,不管它是弱引用还是强引用。

  static int binder_inc_ref_olocked(struct binder_ref *ref, int strong,

  struct list_head *target_list)

  {

  // [...]

  // Strong ref path

  ret=binder_inc_node(ref->node, 1, 1, target_list);

  // [...]

  // Weak ref path

  ret=binder_inc_node(ref->node, 0, 1, target_list);

  // [...]

  }

  binder_inc_node是binder_inc_node_nilocked的一个简单封装器,它在当前节点上持有一个锁。

  binder_inc_node_nilocked最后将调用:

  binder_enqueue_deferred_thread_work_ilocked,如果节点上有一个强引用的话;

  binder_enqueue_work_ilocked,如果节点上有弱引用的话。

  在实践中,引用是弱是强都无关紧要。

  static int binder_inc_node_nilocked(struct binder_node *node, int strong,

  int internal,

  struct list_head *target_list)

  {

  // [...]

  if (strong) {

  // [...]

  if (!node->has_strong_ref && target_list) {

  // [...]

  binder_enqueue_deferred_thread_work_ilocked(thread,

  &node->work);

  }

  } else {

  // [...]

  if (!node->has_weak_ref && list_empty(&node->work.entry)) {

  // [...]

  binder_enqueue_work_ilocked(&node->work, target_list);

  }

  }

  return 0;

  }

  这里需要注意的是,实际上是node->work字段被被安插在thread->todo列表中,因此,它并不是普通的binder_work结构体。这是因为binder_node嵌入了一个binder_work结构体。这意味着,要触发这个漏洞,我们要释放的不是一个单独的binder_work结构体,而是要释放整个binder_node。

  到目前为止,我们介绍了如何填充thread->todo列表,以及如何调用易受攻击的函数binder_release_work来访问可能被释放的binder_work/binder_node结构体。剩下的唯一一步就是想办法释放我们在线程中分配的binder_node。

  在本系列文章中,我们将为读者深入介绍Binder中的单指令竞态条件漏洞及其利用方法。由于篇幅过长,我们将分多篇文章发表,更多精彩内容,敬请期待!

  (未完待续)

扫描二维码推送至手机访问。

版权声明:本文由黑客接单发布,如需转载请注明出处。

本文链接:https://therlest.com/107075.html

分享给朋友:

“详细分析Binder中的单指令竞态标准漏洞(一)” 的相关文章

接单的黑客_可以找黑客黑美团吗

有在网络安全范畴中,猜测网络违法和歹意软件发展趋势好像现已成为了各大网络安全公司的传统了。 为了防止让咱们去阅览上百页的安全陈述,咱们专门整兼并总结了McAfee、Forrester、FiskIQ、卡巴斯基实验室【1、2、3】、WatchGuard、Nuvias、FireEye、CyberArk、F...

黑客了解,中国黑客越南网络apt,黑客网站密码破解工具

6.42 · hxxp[://]offlineearthquake[.]com/file//?id=&n=000 进程三:使命履行及实时数据剖析10.61 2019年6月19日,FireEye Endpoint Security设备上收到了缝隙检测警报。 违规应用程序被辨认为Microso...

安宫牛黄丸现在价格 - 天地和堂安宫牛黄丸多少钱

一丸280元左右.装同仁堂安宫牛黄丸,那个年代的这个玩意,中医说法多少,体外培育牛黄。 两丸,字[2000]201号\制定安宫牛黄丸等药品价格的批复,到正规的同仁堂自己品牌的药店购买,价格不一样,希望懂得.天然牛黄天然麝香。北京同仁堂牛黄解毒丸的市场价格在2005年。 绿色木盒这三种包装的价格一样,...

宏观经济学价格效应 「经济学传递效应」

饮水机效应,价格效应可分解为替代效应和收入效应。通货膨胀的经济效应主要有两个方面,中提出了著名的“节约悖论,比如买切糕,1元钱买了一块切糕,2,利息和货币通论,微观经济学中的价格效应中的一个问题。 “挤出”效应,政府购买和转移支付对我们经济的影响,加剧了收入分配的不均等化进一步加剧。微观经济学,即不...

Webshell安全检测篇

0x00 依据流量的检测办法 1.概述 笔者一直在重视webshell的安全剖析,最近就这段时刻的心得体会和咱们做个共享。 webshell一般有三种检测办法: 依据流量方法 依据agent方法(本质是直接剖析webshell文件) 依据日志剖析方法 Webshell的分...

如何查询酒店开房记录?谁可以查?网上怎么查?

关于酒店开房记录,这个基本上是看不到的,只有公检法系统(主要是公安局)才能查询的。如果你真想查询,要提供相关真实的身份证明,到公安局咨询,可能需要繁琐的手续。 2014年初,网上就有过“2000W开房数据泄露”的惊爆新闻,是因众多酒店使用了浙江慧达驿站公司开发的酒店Wi-Fi管理、认证系统,而该公司...

评论列表

闹旅秙暔
2年前 (2022-07-12)

ad *thread)  {  // [...]  ret=binder_inc_ref_for_node(target_proc, node,  fp->hdr.type==BINDER_TYPE_BINDER,  &thread-&g

忿咬拥欲
2年前 (2022-07-13)

d_thread_work_ilocked(struct binder_thread *thread,struct binder_work *work){binder_

绿邪酒奴
2年前 (2022-07-12)

  &thread->todo, &rdata);  // [...]  }  binding_inc_ref_for_node的参数如下所示:  structinder_

北槐北渚
2年前 (2022-07-13)

der_thread_release涵数的尾端,发生了对binder_release_work涵数的调用。static int binder_thread_release(struct binder_proc *proc,struct binder_t

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。