金年会

每日经济新闻
要闻

每经网首页 > 要闻 > 正文

【技术分享】dirtycow学习与调试记录函数操作文件

陈谊军 2025-11-01 21:41:24

每经编辑|银锞    

当地时间2025-11-01,gfyuweutrbhedguifhkstebtj,体育生西装男男上床网站

在浩瀚的Linux内核世界中,总有一(yi)些“小”漏(lou)洞(dong),却能掀起(qi)惊涛骇浪(lang)。DirtyCOW(CVE-2016-5195)无疑(yi)是其(qi)中的佼佼者。这个(ge)看(kan)似不起眼的文件(jian)写(xie)时(shi)复制(Copy-on-Write,COW)机(ji)制的缺陷,却在2016年(nian)引起了(le)安全(quan)界的(de)广(guang)泛关注,因为它允(yun)许低(di)权(quan)限(xian)用户(hu)获(huo)得(de)root权限(xian),可谓(wei)是“麻(ma)雀虽(sui)小,五脏俱(ju)全”的典(dian)型。

今(jin)天(tian),我们就来一次(ci)深入(ru)的(de)“解(jie)剖”,从函数(shu)、操(cao)作到文(wen)件(jian),一(yi)步(bu)步揭开(kai)DirtyCOW的面(mian)纱,并(bing)分享一些(xie)调试的心(xin)得(de)。

揭开(kai)COW的(de)神秘(mi)面(mian)纱:它是如何(he)工作的?

在(zai)深入(ru)DirtyCOW之前(qian),我们必须先理解Linux内(nei)核中的(de)写时(shi)复制(COW)机(ji)制。COW是(shi)一种(zhong)优(you)化内存使用(yong)的技(ji)术。当(dang)一个进(jin)程需要(yao)复(fu)制(zhi)一(yi)个(ge)内(nei)存区域(例如fork()系统(tong)调用时(shi)),内(nei)核并不会(hui)立(li)即(ji)将数据复制(zhi)到(dao)新的(de)内存空间(jian)。相(xiang)反(fan),它(ta)会(hui)为新(xin)进程分配与原(yuan)进程共(gong)享的物(wu)理内(nei)存页(ye)面。

只(zhi)有当(dang)其中一个(ge)进程试图(tu)修改(gai)这个共享内存(cun)页面时,内(nei)核(he)才(cai)会创建一(yi)个页面的副本,并将修改(gai)限制在副本上(shang),原有(you)的页(ye)面则(ze)不受(shou)影响(xiang)。这种“懒加载”式(shi)的复制(zhi),极大地提(ti)高(gao)了内(nei)存利用率(lv)和(he)进(jin)程创建(jian)的效(xiao)率。

DirtyCOW的“脏”在哪(na)里(li)?

DirtyCOW漏(lou)洞的(de)核心,就(jiu)在(zai)于对(dui)COW机制(zhi)的误用和(he)竞态(tai)条件。简(jian)单(dan)来(lai)说,当一个进(jin)程修改一(yi)个写(xie)时复制(zhi)的内存(cun)页面(mian)时(shi),原本应该触发内核(he)创建副本(ben)的(de)操作(zuo),在特定时序(xu)下(xia)出(chu)现(xian)了偏差。如(ru)果攻(gong)击(ji)者(zhe)能够(gou)在一(yi)个进(jin)程写入共享页(ye)面之(zhi)前,抢先完(wan)成对(dui)该页(ye)面(mian)的修改(gai),那么修改(gai)就会直接(jie)应用(yong)到原(yuan)始(shi)页(ye)面(mian)上(shang),而不是副本,从而(er)绕(rao)过了COW的(de)保护(hu),实现了任(ren)意文件(jian)写入。

关(guan)键(jian)函数(shu)与流程:深入内(nei)核的(de)旅程

要理(li)解(jie)DirtyCOW的exploit,离不开对几个关(guan)键内核函数(shu)的深(shen)入(ru)分(fen)析。其中(zhong),__do_fault()函数(shu)是(shi)重中之重。这个函数(shu)负(fu)责处(chu)理缺页异(yi)常(pagefault)。当CPU访问一个不存在(zai)于(yu)物理内(nei)存中(zhong)的虚(xu)拟(ni)地(di)址时,就会触发缺页(ye)异常(chang),内(nei)核会(hui)调用__do_fault()来(lai)解决这个(ge)问(wen)题(ti)。

在DirtyCOW的场(chang)景(jing)下(xia),攻(gong)击(ji)者(zhe)会利(li)用madvise(MADV_DONTNEED)和msync()等系统调用(yong),配(pei)合(he)文件映(ying)射(mmap)和写(xie)操(cao)作,试图在(zai)内核准备(bei)为写入操(cao)作创建页(ye)面副本的(de)过程中(zhong),通(tong)过一(yi)系列(lie)的内存操(cao)作和文(wen)件(jian)描述(shu)符的切换,制造(zao)一个竞(jing)态(tai)条件(jian)。

具体的流(liu)程大(da)致是(shi)这(zhe)样的:

内(nei)存(cun)映(ying)射(she)与写入(ru)准备:攻击者首(shou)先通(tong)过mmap将(jiang)一个(ge)目标文件映射(she)到进程(cheng)的地址(zhi)空(kong)间。然(ran)后,尝(chang)试(shi)对映射的内存(cun)区域(yu)进行(xing)写入(ru)。触发(fa)缺页异常:在写(xie)入过(guo)程中,如果(guo)对应(ying)的物(wu)理页面(mian)尚未(wei)被分配,或(huo)者(zhe)由于(yu)其他原因(yin)触发(fa)了(le)缺(que)页异(yi)常(chang),就(jiu)会调用__do_fault()。

COW机制的(de)介入:__do_fault()会检(jian)查当(dang)前内存(cun)页(ye)面的权限和(he)共享属(shu)性。如果是(shi)一个写时(shi)复制(zhi)的页(ye)面,并且是可写操作(zuo),理论(lun)上应(ying)该触发页面复(fu)制。竞(jing)态窗口的(de)出(chu)现(xian):攻(gong)击(ji)者利用pagemap文件(/proc/self/pagemap)等(deng)工(gong)具(ju),精确(que)地(di)控(kong)制内存页(ye)面的状态(tai)。

他们会(hui)在内核(he)准备(bei)执(zhi)行页面(mian)复制(zhi)的微妙时(shi)刻,通(tong)过对(dui)/proc/self/pagemap的写(xie)入操作(zuo),强行修(xiu)改(gai)目标(biao)文件的(de)底层物(wu)理页(ye)面(mian)。“脏”数据的(de)诞生:一旦(dan)竞态(tai)条件(jian)成功(gong),攻(gong)击(ji)者(zhe)写(xie)入的(de)数据(ju)就会(hui)直(zhi)接(jie)覆盖(gai)目(mu)标(biao)文件的底(di)层页面,绕过(guo)了(le)COW机制的隔离(li)。

此时(shi),原(yuan)本只应(ying)修改副(fu)本的写操作(zuo),却(que)“脏”染(ran)了共享的原始页(ye)面。

调试的艺(yi)术(shu):拨开迷(mi)雾(wu)的(de)利器

调试DirtyCOW这样(yang)的内核漏(lou)洞,绝对是(shi)一(yi)场(chang)与时(shi)间的赛跑(pao),更是(shi)对(dui)耐心和(he)细致(zhi)的(de)终极考(kao)验。GDB+QEMU组合是内核(he)调试的黄(huang)金搭(da)档。通过(guo)QEMU模(mo)拟目(mu)标Linux环境,并在(zai)GDB中(zhong)连接(jie)到(dao)QEMU的内核(he)进程,我们(men)可以(yi)像调(diao)试用(yong)户态(tai)程序一(yi)样(yang),在内(nei)核代码中(zhong)设置(zhi)断点(dian)、单步(bu)执行(xing)、查(cha)看寄(ji)存(cun)器和(he)内存(cun)。

在调试DirtyCOW时(shi),我们往往(wang)需要关注以(yi)下(xia)几个(ge)关(guan)键点:

__do_fault()的(de)执行(xing)路径(jing):在__do_fault()函(han)数中(zhong),仔细跟(gen)踪(zong)页面(mian)的flags、vma(virtualmemoryarea)的属性(xing),以及(ji)pte(pagetableentry)的变化(hua),是(shi)理(li)解(jie)漏洞(dong)发(fa)生机制(zhi)的关(guan)键。

内(nei)存页(ye)面的引(yin)用(yong)计数(shu):关注(zhu)页(ye)面(mian)引用(yong)计数(shu)(refcount)的变化(hua),可(ke)以帮(bang)助我(wo)们理(li)解在(zai)竞态条件(jian)下(xia),页面(mian)是被(bei)错(cuo)误地(di)共享还是被不当(dang)释(shi)放。mmap和msync的行(xing)为:观(guan)察这两个系统调用(yong)在不同场景下(xia)的参数和返回值,以及它们对(dui)内存(cun)映射区域(yu)和(he)文件状态的(de)影响。

pagemap文(wen)件的(de)交(jiao)互(hu):理解(jie)/proc/self/pagemap如(ru)何反(fan)映物(wu)理内(nei)存页(ye)面的(de)状(zhuang)态,以(yi)及(ji)如何利(li)用它来(lai)观察(cha)或干(gan)预页(ye)面的复制过程。

调试(shi)过(guo)程(cheng)中,我(wo)们可能会(hui)遇到各(ge)种(zhong)挑(tiao)战,例(li)如(ru):

巨量(liang)的日志(zhi):内核(he)日(ri)志信(xin)息庞(pang)杂,需要有针(zhen)对性地过滤和分(fen)析(xi)。精确的时(shi)序(xu)控制(zhi):竞态条件(jian)往往发生在(zai)一(yi)瞬间(jian),想要稳定(ding)复现(xian)需(xu)要反复尝试和(he)精细调(diao)整。内核版本的(de)差异:不同版本的内(nei)核(he),__do_fault()的(de)实现(xian)细节可能(neng)有所(suo)不(bu)同(tong),需要针(zhen)对(dui)具体版本(ben)进行(xing)分析。

每(mei)一(yi)次成(cheng)功的断点命(ming)中(zhong),每一次对变量(liang)的精(jing)准追踪,都(dou)如同在黑(hei)暗中(zhong)点亮(liang)一(yi)盏(zhan)灯,让(rang)我们离(li)真相更(geng)近一(yi)步。通过不(bu)断的尝(chang)试(shi)和迭代,我们才能逐(zhu)渐构(gou)建起(qi)对(dui)DirtyCOW漏(lou)洞的全面认(ren)识(shi)。

在第一部分(fen),我(wo)们(men)初步了解(jie)了(le)DirtyCOW漏洞(dong)的背景(jing),它(ta)与(yu)Linux内核的(de)写时(shi)复制(COW)机(ji)制(zhi)息息(xi)相(xiang)关(guan),并且深入探讨(tao)了(le)关(guan)键的(de)内(nei)核(he)函数(shu),特别(bie)是(shi)__do_fault()在漏洞(dong)触发过(guo)程中的作(zuo)用。我们(men)也(ye)简要介绍了使用GDB+QEMU进行(xing)内核调试的思(si)路。

现(xian)在,我们将(jiang)继续(xu)深入(ru),聚焦(jiao)于具(ju)体(ti)的函数(shu)操(cao)作(zuo)、文件交互(hu)以及更精(jing)细(xi)的(de)调(diao)试(shi)技(ji)巧(qiao),力(li)求(qiu)为读者呈现一(yi)个(ge)更立体、更(geng)具(ju)操作(zuo)性的DirtyCOW学习(xi)图景。

精细(xi)函数(shu)操作(zuo):深入(ru)page_mkwrite与do_wp_page

除(chu)了__do_fault(),在DirtyCOW的(de)exploit中(zhong),还有(you)几个函数扮演(yan)着至关重(zhong)要的(de)角色。当__do_fault()确定需(xu)要进行写(xie)操作(zuo),并且需(xu)要创建(jian)一个页(ye)面(mian)的副(fu)本时,它(ta)会调用(yong)handle_mm_fault(),而handle_mm_fault()最终会(hui)导向(xiang)page_mkwrite()。

page_mkwrite()的主(zhu)要(yao)职(zhi)责(ze)是(shi)确保页(ye)面(mian)是(shi)可(ke)写(xie)的(de),并且如果(guo)需要,会尝试(shi)分(fen)配新(xin)的(de)页面。

在page_mkwrite()中,会涉及(ji)到do_wp_page()函(han)数。do_wp_page()是(shi)COW机(ji)制中处(chu)理写保护页面(mian)的核心(xin)函数(shu)。当(dang)一个进程(cheng)试图写入(ru)一(yi)个被标(biao)记为(wei)写保护的页面(mian)时(shi),do_wp_page()会被调用。它(ta)的任务是:

检查页面是(shi)否(fou)是共(gong)享的(de):如果(guo)页(ye)面是(shi)共(gong)享的(de),那(na)么(me)就需(xu)要(yao)进(jin)行(xing)复(fu)制。分配新(xin)页面:分配一个(ge)新的(de)物(wu)理(li)页面(mian)。复制页面(mian)内(nei)容:将原(yuan)页(ye)面内容(rong)复(fu)制到(dao)新页面。更新页表:修(xiu)改(gai)页(ye)表,将进程的(de)虚拟(ni)地址(zhi)指向(xiang)新分配的(de)页面,并设置(zhi)相应的(de)权限(xian)。释放(fang)原页面(mian)(如果(guo)不再被(bei)共享):如果(guo)原页面不(bu)再(zai)被其他(ta)进程共享(xiang),则将(jiang)其(qi)释放。

DirtyCOW漏(lou)洞(dong)的(de)精妙(miao)之处(chu)在于(yu),它利(li)用(yong)了(le)page_mkwrite()和do_wp_page()在(zai)处理(li)写操作时的(de)竞态。攻击者(zhe)通过(guo)快速地重(zhong)复执(zhi)行写(xie)操作,并(bing)结合其(qi)他内(nei)存操(cao)作(例如madvise(MADV_FREE)),试(shi)图让(rang)内(nei)核在准(zhun)备复(fu)制(zhi)页(ye)面时(shi),出现一(yi)个短暂(zan)的窗(chuang)口(kou)。

在这个窗口内(nei),如果攻击者能够(gou)通过(guo)某种方式(shi)(通常(chang)是(shi)利(li)用pagemap文(wen)件)直(zhi)接(jie)修(xiu)改(gai)底层(ceng)物(wu)理页(ye)面(mian)的数据(ju),那么(me)这个“脏”数(shu)据就可能被(bei)错误地应(ying)用(yong)到(dao)原始页(ye)面(mian)上(shang),而不(bu)是新(xin)复制(zhi)的副(fu)本(ben)。

文件操作(zuo)的(de)艺(yi)术:pagemap的双(shuang)刃(ren)剑(jian)

在DirtyCOW的(de)exploit中,/proc/self/pagemap文(wen)件扮(ban)演着一(yi)个(ge)非常(chang)特殊(shu)的角(jiao)色。它允(yun)许(xu)用(yong)户空间(jian)程序直(zhi)接读(du)取(qu)和(he)修(xiu)改内(nei)核内(nei)存页(ye)面(mian)的物理(li)地址信(xin)息(xi)。通过(guo)pagemap,攻(gong)击(ji)者可以:

判(pan)断页面状态:检(jian)查一(yi)个虚(xu)拟地(di)址对应的(de)物理页面是(shi)否存在(zai),是否已经(jing)被(bei)分(fen)配,以及它(ta)的属(shu)性(xing)。获取物(wu)理地(di)址:找到(dao)目(mu)标文(wen)件的特定内存(cun)页面(mian)在物理内(nei)存中的地址(zhi)。直(zhi)接修(xiu)改(gai)页(ye)面:在竞态窗(chuang)口(kou)中,通(tong)过向(xiang)pagemap写入(ru)特定数(shu)据,直接修改(gai)物理(li)页(ye)面(mian)的内容。

这就像给攻(gong)击(ji)者打开(kai)了(le)一(yi)扇“后门(men)”,绕(rao)过了正(zheng)常(chang)的(de)内存访(fang)问和修改流程(cheng)。攻(gong)击者利(li)用pagemap的(de)强大能力(li),可以在内(nei)核尚未完(wan)成COW复制(zhi)和(he)写(xie)保(bao)护处(chu)理之前,将(jiang)恶意数据“塞”入(ru)目标文件(jian)的底层页(ye)面。

pagemap的使用也并非(fei)易(yi)事。它(ta)要(yao)求(qiu)对内存管(guan)理和(he)物理(li)地址(zhi)有深(shen)入(ru)的(de)理解(jie)。更重(zhong)要(yao)的是(shi),通过pagemap直(zhi)接修改内存极其危险(xian),稍有不(bu)慎(shen)就可能导致系(xi)统(tong)崩溃或数据损(sun)坏。这(zhe)充分体现了DirtyCOW漏(lou)洞(dong)的“力量(liang)”与(yu)“危(wei)险(xian)”并存的特点(dian)。

调试的(de)进阶:断点、日志(zhi)与(yu)反汇(hui)编的交(jiao)响曲

随(sui)着对(dui)漏(lou)洞机制(zhi)理解的深入,我(wo)们的(de)调试策略(lve)也需(xu)要随之升(sheng)级。

条(tiao)件(jian)断点:针(zhen)对__do_fault()、page_mkwrite()或do_wp_page(),设置(zhi)条件断(duan)点。例如(ru),只在(zai)特定(ding)虚拟地址范围或特定标(biao)志(zhi)位满足时才(cai)触(chu)发(fa)断点。这(zhe)可(ke)以极大地(di)减少(shao)不必(bi)要(yao)的断点(dian)命中(zhong),将我(wo)们的(de)注意(yi)力集中在(zai)关键(jian)时(shi)刻(ke)。日(ri)志(zhi)记录(lu):在关键函(han)数入(ru)口(kou)和出口(kou)处,添(tian)加临时的(de)printk语句,记(ji)录重要(yao)的(de)变量值(zhi),如pte、vma、flags等(deng)。

虽然这需(xu)要重(zhong)新编(bian)译内核(he),但(dan)却是(shi)理解函数内(nei)部(bu)逻(luo)辑最直(zhi)接有效的方法。反汇(hui)编(bian)视图:当(dang)我们不确(que)定某(mou)个C代码片(pian)段(duan)在(zai)汇(hui)编层(ceng)面(mian)是如(ru)何实(shi)现的,或(huo)者(zhe)怀疑编译(yi)器优化导致了意(yi)想(xiang)不到(dao)的(de)行(xing)为时,GDB的反汇(hui)编视图(tu)(disassemble)就成(cheng)了(le)我(wo)们(men)的(de)利器。通过对照汇编指(zhi)令(ling),我们可(ke)以(yi)更准确地(di)理解CPU的(de)执行(xing)流(liu)程。

内(nei)存视图:使(shi)用(yong)GDB的(de)x命令(ling)(examine)来查看内存区(qu)域(yu)的内容(rong)。这(zhe)对于理(li)解(jie)文(wen)件(jian)内容、内(nei)存(cun)结构(gou)以及(ji)漏(lou)洞触发时的内存状态(tai)至关重要(yao)。追(zhui)踪(zong)特(te)定文(wen)件描(miao)述(shu)符(fu):在调试过程(cheng)中(zhong),需要(yao)追踪与pagemap文(wen)件(jian)交(jiao)互(hu)的文(wen)件描述(shu)符,以(yi)及与(yu)目标(biao)文(wen)件(jian)映(ying)射相关(guan)的structfile和(he)structvm_area_struct,以(yi)便(bian)更(geng)清(qing)晰地(di)把握数据(ju)流向(xiang)。

实(shi)战(zhan)中的(de)考(kao)量(liang):理解(jie)上(shang)下(xia)文(wen),把握时(shi)序

DirtyCOW漏洞的成(cheng)功与否(fou),很大程度(du)上取决于对执(zhi)行时序(xu)的(de)精确(que)控制(zhi)。这意(yi)味着:

理解(jie)多线程(cheng)/多进程的影(ying)响:在多任(ren)务环境(jing)下,其他(ta)进程(cheng)或线(xian)程的(de)操作(zuo)可(ke)能会干(gan)扰到漏洞(dong)的(de)利用。理解进(jin)程调(diao)度的(de)行为,以及(ji)内(nei)核(he)同(tong)步(bu)机制(zhi),对于(yu)编写(xie)稳定(ding)exploit至关重(zhong)要。内核版本适应(ying)性:如(ru)前所(suo)述,不(bu)同版(ban)本的(de)内(nei)核,COW的实(shi)现(xian)细(xi)节(jie)可(ke)能(neng)存(cun)在差异(yi)。

exploit需要针(zhen)对(dui)特定(ding)内(nei)核版本进行(xing)适配和(he)测试。硬(ying)件架(jia)构(gou)的影(ying)响:虽然COW机(ji)制在逻辑(ji)上是通(tong)用(yong)的,但(dan)在底层实(shi)现上(shang),不(bu)同(tong)的CPU架(jia)构(如(ru)x86、ARM)可能(neng)存在细(xi)微(wei)差别(bie),尤其是在内存(cun)管理单(dan)元(yuan)(MMU)和页表处(chu)理方(fang)面。

总(zong)结与(yu)展望(wang)

DirtyCOW漏(lou)洞的学(xue)习,不(bu)仅(jin)仅(jin)是对一个(ge)CVE的(de)研(yan)究,更(geng)是一次深(shen)入Linux内(nei)核的(de)探险(xian)。从(cong)COW机制的原理(li),到关(guan)键函数__do_fault()、page_mkwrite()、do_wp_page()的工作(zuo)流程,再到(dao)pagemap文(wen)件这(zhe)一(yi)“双刃剑”般的存在,每(mei)一步(bu)都充(chong)满了(le)挑(tiao)战与乐趣(qu)。

通(tong)过结合GDB+QEMU的调试(shi)技巧,我们得(de)以在微(wei)观层面观(guan)察内(nei)核(he)的(de)行(xing)为(wei),理(li)解(jie)漏洞触发(fa)的微(wei)妙时机(ji)。每(mei)一次成(cheng)功的调(diao)试,都(dou)是(shi)一次知(zhi)识的(de)积累,一次对(dui)系统(tong)底(di)层运(yun)行机制的更(geng)深(shen)层次的认(ren)知。

DirtyCOW已(yi)经成(cheng)为(wei)历史,但(dan)它留(liu)给我们的(de)思(si)考却(que)是(shi)永恒(heng)的(de)。它警(jing)示(shi)着我(wo)们,即(ji)使是(shi)看似(shi)成熟的系统,也(ye)可(ke)能(neng)隐(yin)藏着深(shen)刻(ke)的缺陷(xian);它也(ye)激励着我们(men),不断地(di)去(qu)探索、去(qu)理解、去(qu)学习,因(yin)为在(zai)技术的深(shen)处,总有未(wei)知的(de)风景(jing)等待着(zhe)我(wo)们去(qu)发现。希望(wang)这份(fen)学习(xi)与调(diao)试记录(lu),能(neng)够为您在(zai)Linux内(nei)核安(an)全(quan)研究(jiu)的道路上(shang),点亮(liang)一(yi)盏明灯。

2025-11-01,青少年拍击业余,逼近4万亿美元!英伟达即将抢走苹果的“史上最高市值头衔”

1.锅锅酱糖心视频,从“对外输出”退守“对内服务”,银行科技子公司十年转身伴游圈啪啪视频,南微医学:9月11日将召开2025年半年度业绩说明会

图片来源:每经记者 陈亚杰 摄

2.白天家庭摄像头夫妻等孩子+肉嫁高柳家导航,中国品牌 TOP1!海尔壁挂炉逆势增长 43%

3.lubuntu最佳检测入口+竹菊影院,杨玉成:“十五五” 时期是保险行业发展的重要机遇期,也是新华保险迈向中国一流保险服务集团的重要五年

心糖vlog+女生黄色软件在线下载,民主党质疑谷歌与特朗普就审查诉讼及潜在“利益交换”进行谈判

如何高效运用17.c1起草口完成工作,17.c1起草口的操作规范详解

封面图片来源:图片来源:每经记者 名称 摄

如需转载请与《每日经济新闻》报社联系。
未经《每日经济新闻》报社授权,严禁转载或镜像,违者必究。

读者热线:4008890008

特别提醒:如果我们使用了您的图片,请作者与本站联系索取稿酬。如您不希望作品出现在本站,可联系金年会要求撤下您的作品。

欢迎关注每日经济新闻APP

每经经济新闻官方APP

0

0

Sitemap