2019年哪些安全大会的议题值得学习

“2019年哪些安全大会值得参加?”或者这更符合多数人心中的标题,但为何不这么写呢?

因为有些拥有好议题的大会一般都会公开PPT,尤其是国外会议,来回参会成本比较高,如果有现成的PPT供学习,自然不用每次都参加。当然,也有因作者拒绝公开的议题,这种只能现场听了。

评价安全大会的好坏,是多方面的,绝不是单纯的议题质量这一维度。但这里我主要想从技术者的角度来看评价,所以后面你发现很多知名大会未在此列,请不要惊讶。

即使是同一举办方,也无法保证每年的议题质量呈上升状态,有些会议也开始没落了,所以这里以2019年为时间点来点评。

下面来聊聊2019年哪些安全大会的议题值得学习,有些已经举办过,有些尚未开始。

推荐的安全会议

1、BlackHat

image-20190511125059375

官网https://www.blackhat.com

如果你不知道BlackHat,说明你不在安全圈混。

USA是主会场,议题质量和数量也是最高的,议题类型覆盖面也很广,除此之外还有欧洲和亚洲等分会场,质量相对次一些。

这次BlackHat USA的议题也陆续公开了:https://www.blackhat.com/us-19/briefings/schedule/index.html

早几年的议题水平参差不齐,很水的也有,打广告也有。最近几年反而议题质量提高,不少华人面孔出现,为了PR效果而竞争,促进大家都拿出干货来分享,这也是其有利的一面。

每年都有几千个议题投稿,竞争很大,但这很好地促进议题质量的提高。

每年会后,官方都会放出PPT与视频,非常开放地分享知识。

所以,首推BlackHat,自然无疑。

但如果你以为接下我会写Defcon,那我会告诉你:No!

2、OffensiveCon

offensivecon

官网https://www.offensivecon.org/

我之前还专门写了篇文章《今年的OffensiveCon大会议题质量不错》介绍2019年大会中一些不错的议题。

虽然OffensiveCon是从2018年才开始举办的,但议题质量一直保持不错,演讲者中包括Project Zero、Google syzkaller作者、Pwn2Own与Hack2Win获奖者等等。

会后,一般是由演讲者选择是否公开ppt,多数人是在Twitter上公开的,官网上我没找到资源(https://github.com/riusksk/SecConArchive/tree/master/OffensiveCon2019),所以之前收集的ppt都是从twitter上扒下来的。

3、HITB (Hack In The Box)

image-20190511133408850

官网:https://conference.hitb.org/

这几天HITB刚在荷兰阿姆斯特丹举办完,议题PPT也一并公开(https://conference.hitb.org/hitbsecconf2019ams/materials/)。

如果要说国内外安全会议中,哪个公开PPT最快的,一定是HITB,他们一般是现场演讲完,就直接扔官网下载。然后过一段时间,也同样发布演讲视频。

他们有时会同时搞两个演讲会场,一个是收费的主会场,议题质量高一些,一个是免费的,叫CommSec,用来提携新人,议题质量相对比较次,每个议题分享时间也比较短,最多半小时。

之前去新加坡参加过一次HITB,人数不多,场地也不大,但可以感受到与国内安全会议的区别:更注重技术交流,而非搞关系。

2018年开始,HITB也开始与京东合作,在北京举办分会场,没去过,不作评价,但国际会议本土化,总会产生一些差异的。

4、InfiltrateCon

image-20190511134410680

官网:https://infiltratecon.com

从2011年开始举办的,已经走过8个年头。

看了今年的议题,还是有干货的,但只有4个议题ppt在twitter上公开。

以前,会后都会在官网上公开PPT和视频,但目前官方还没公开。

今年的议题涉及Chrome RCE、iOS与Android提权、Pwn TEE、浏览器JS Fuzzing等等,只能坐等官方公开PPT了。

5、Chaos Communication Congress(C3)

image-20190511141920353

官网:https://www.ccc.de/

德国混淆黑客大会,常叫C3会议,常在C3前面加上第几届,比如今年第35届,所以叫35C3,历史非常悠久。

以前大多是聚焦在无线电安全,所以一些什么2G\3G\4G短信、电话窃听经常出自该会议。熟悉无线电安全的同学,应该都听过。2018年也有一些不错的软件安全相关的议题,这些在之前写的文章《推荐今年C3黑客大会上的几个议题》介绍过了。

除了大会议题,不得不提下他们的CTF,非常具有实战价值,比如2018年的题目,直接拿pwn2own漏洞当比赛,从safari代码执行到提权,还有VisualBox沙盒逃逸题目,需要利用到0Dday,出题者是ProjectZero的人,早就将其卖给ZDI,刷了不少VBox漏洞。这些CTF题目在网上都有相应的WriteUp可供学习。

这些议题只有演讲视频公开,没有PPT,官方会放在https://media/ccc.de,可在线或下载观看。

都是在每年的12月份举办,2019的还有半年呢……

6、CanSecWest

image-20190511143022033

官网:https://cansecwest.com

CanSecWest都是与Pwn2Own一块出现的,以前议题PPT都是放在https://www.slideshare.net/上分享,但从2018年开始又不搞了。

每年议题不多,但质量还是可以的,不过感觉这两年的质量略有下降。

今年3月的议题也没看到有下载,也是混Twitter找ppt的,只看了《vs com.apple.security.sandbox》这个议题,今年我感兴趣的议题没几个,大家根据自己喜好选择吧。

如果你各个议题PPT,也欢迎分享下。

7、MOSEC 移动安全技术峰会

image-20190511145201148

官网:http://mosec.org

MOSEC是从2015年开始举办的,由盘古与韩国POC联合举办,聚集移动安全领域,包括Android、iOS、IoT以及无线电等领域。虽然起步晚,但议题干货满满的,应该是目前国内最好的安全会议了。

今年的议题也已经陆续公开了,包括iOS越狱、Android提权、LTE、基带、卫星系统等等。

官网是不公开大会的议题PPT,由演讲者选择,所以想学习的同学,可能还是得去参会。

从2015年第一届我就开始参加,本月底还会去。去年参会,早上出酒店一辆车都打不到,又不在地铁口,最后骑了1个多小时的单车到会场,不容易啊……

8、POC

img

官网:http://powerofcommunity.net/

POC(PowerOfCommunity)起始于2006年,在韩国举办的。单从议题质量看,确实不错,大多漏洞研究领域的前沿技术,但它经常是”二手货”,也就是在其它安全会议讲过后,但去韩国观光旅游顺便讲下。

还有个意思的现象就是,每年的议题超过一半是中国人讲的。

所以,你推荐也对,你不推荐也没错。

不过,有个好处就是,POC议题PPT都是提供下载的。有时在其它会议找不到PPT时,到POC官网翻下,偶有小惊喜。

另外还有个会议叫ZeroNights,同一举办方,更多是面向老外的。

那些未提及的知名大会

1、Defcon

很多时候,Defcon议题都是BlackHat挑剩的,有的人也会直接议题双投。上面的议题质量更是参差不齐,相对BlackHat要求更低,更开放。我很少看Defcon议题,偶而网上有人发才看。

2、RSA

RSA是一个充满商业气息的大会,如果你看过官网的PPT,就会发现里面充满诸多广告,有的议题可能就几页图片,所以从技术角度来看,是没有多少学习的价值。

但是,RSA有时也反应出的安全的风向标,虽有炒作的成分,但显然PR得甚是成功。比如当年的APT、数据可视化、威胁情报等等

RSA的创新沙盒是一项不错的活动,很多创业公司把他们研发的新产品拿出来比赛,从中可以反映出一些行业发展的方向。

所以,RSA比较适合管理者、创业者以及产品运营者。

3、XCon

以前国内安全会议很少,基本唯XCon为首。以前参加都是为了跟圈内朋友相聚聊天,有时场外比场内还热闹。

但这几年开始,XCon逐渐没落了。如果你参加过XCon2018,相信会有很大的体会,会场已经没几个人,有时在场人数可能达到个位数,找个同行聊天都难,且门票还是国内同类会议最贵的。

4、KCon

KCon应该算是国内比较有自己特色的会议,2018年的议题质量也还可以,中场休息的摇滚音乐很赞,场地与音效很好。

之前几届的议题质量忽上忽下,2019年的议题还没出来,大家可以关注下先。

若是在2018年,我还是会给个推荐的。

5、BlueHat

以前微软的闭门邀请制会议,从今年开始在上海举办国内版,议题列表已经放出,感觉质量一般。但跟MOSEC时间联着,可以考虑一并参加下。

6、RECON

因为多数议题自己不感兴趣,它比较偏向于逆向工程,以及系统底层、硬件、固件等方向,对此方向感兴趣的话,依然可以看看。

7、Syscan/Syscan360

官网已经打不开了,聊啥……

后话

评价一个会议的好坏真是很容易,但要举办一个好的会议却是不容易,影响的因素特别多,且非一人之力可以搞定。

无论最终质量如何,对于为行业提供沟通交流平台的一些会议,还是值得点赞的。

读《一本小小的蓝色逻辑书》:识别常见的逻辑漏洞

最近读了一本书叫《一本小小的蓝色逻辑书》,算是逻辑推理入门书籍,觉得不错,推荐给大家。

这本书在微信读书上可以找到,大概需要4个多小时的阅读时间。

img

什么是逻辑推理

在生活、学习与工作中,我们总是要运用到逻辑推理能力,甚至我们自己也经常挂在嘴边,但若问什么是逻辑推理呢,估计没多少人能说清。

所谓”逻辑推理”,在广义上被定义为”我们评估信息的过程”。要想做出正确的决定,我们首先要占有充分的信息,而要想占有充分的信息,就必须提出正确的问题。所以那些擅长逻辑推理的人,往往也比较善于提出问题,搜集相关信息,用”正确的”方式对这些信息进行评估。最重要提,他们可以在不受他人干扰的情况下独立完成这一过程。

在我记忆中,整个学生时代,几乎没有过这门课程,大部分的逻辑推理能力都是基于以往的中学数学课程训练,比如真假命题、逆命题、证明题等等,本书中也有讲到这些。

也许我们的日常数学真的只需要加减乘除的运算,但以前的数学课程培养出来的逻辑思维,却可以运用一生。

推翻前提找答案

这里说的”推翻前提找答案”,其实是想说”水平思考法“,一种摆脱前提设想而进行创意思考的方式,不走寻常路,换个角度看待问题,而不是接受他人提出的前提条件。我们多数人一般都是使用“垂直思考法”,却沿着原定的逻辑路线思考下去,就是我们俗语常说的“直脑筋”,多少略带有点贬义。

下面是两种思考方法的对比表:

image-20190503101519293

可能还是太抽象了,因此作者讲了一个故事:

许多年前,一个倒霉的商人欠了别人一大笔钱。由于没钱还债,商人很可能会被债主投进大牢。

债主是个脾气又坏又丑的糟老头,但他却看上了商人年轻貌美的女儿。于是他告诉商人:”我有个办法,不仅可以把你的债务一笔勾销,还能让你的女儿免于因为你入狱而流落街头。”

具体办法是:债主把一黑一白的小石头放进空袋子,让商人女儿摸一块。如果摸到白石头,则她父亲的债一笔勾销,她也无须嫁给债主;如果摸到的是黑石头,债务仍然可以一笔勾销,但她必须嫁给债主。如果她不答应这个游戏,那么她父亲会被立刻投进监狱。

商人父女别无选择,只好答应。

于是三人来到债主花园内铺满鹅卵石的小路上,债主俯身捡两块黑石头扔进袋子里,他自以为神不知鬼不觉,却不知这一切都被商人女儿看在眼里。

如果是个”直脑筋”的人,可能就想到下面两种做法:

  1. 当场揭穿糟老头的阴谋,然后商人进监狱;
  2. 女儿认命,抽到黑石头,嫁给糟老头,债务一笔勾销。

最后的结局是这样:

商人的女儿摸出一块石头,但故意把它掉到地上,跟一堆鹅卵石混到一起。然后一边假装寻找石头,一边若有所思地说道,”但没关系,只要看看袋子里的那块石头是什么颜色,就可以判断我刚才摸出的那块石头是什么颜色了。”

债主一时愣住了,不知道该说什么,只好让那个女孩拿出袋子里的石头,结果可想而知。

这就是水平思考法,我们可以回顾下这个故事,若要想免债的话,其中的”前提条件”是:

前提条件:从袋子中摸出白石头。

现在通过改变该前提条件来思考,比如这样:

  1. 从袋子中摸出石头:现场改变规则,摸出黑石头可免债。
  2. 摸出石头后,根据剩下的石头颜色来判断是否摸到的是白石头,正如故事中所做的。

日常生活中,阻碍我们进行创意思考的是,不假思索的程序性反应,就是不费脑子的事情,比如商店购物、开车等等,但有时遇到一些新情况,这些程序性反应就不灵了,这时就需要启动非程序性反应。

书中还给了一道训练”水平思考法”的题目,大家可以先试着做下,一开始我也没做出来(答案见文末附录):

用最多4条直线(笔尖不离纸)把下面的9个点连接起来。

image-20190503105014426

还有另一道题,是当年面试微信支付时被问到的类似题目,但微信的更难一点(拿3个桶倒出想要的重量),答案亦见文末附录:

马戏团老板派小丑去附近河边打水给大象喝。因为想在里面加入一种特殊健康浓缩剂。所以需要整整7加仑水,不能多,也不能少。他给了小丑两个水桶,一个5加仑,一个3加仑,让小丑去打整整7加仑水。请问小丑该怎么办?

效用概率做决策

如果大家经常逛知乎的话,会发现很多人在问:

  1. 做安全需不需要考研?
  2. 选择什么样的学校和专业好就业?
  3. 选择什么样的职业更适合自己?
  4. 其它…….

相信很多人做决策的时候,多会先分析出各项选择的优缺点再打分对比,选择出最佳方案,这叫利弊分析法

有时,我们又会先列出在意的点,根据重要程度作个加权值,然后给个选择打分,根据分数高低来排序选择,这叫加权排序法

还有决策法、矩阵分析法、概率树等等多种决策分析方法,在我们在决策时,能够给我们提供很大的帮助。

不过我在这里,重点是想介绍下效用分析法,即分析某个结果对我们的价值,通常跟概率一块使用。

打个比方,一名大四学生在规划自己的人生。摆在他面前的有三种选择:

  1. 成为旅行作家;
  2. 加入外交部;
  3. 成为公司销售人员。

这里肯定不能只从金钱回报来考虑这个问题,因为这名学生真正看重的并不是赚多少钱,而是自己从事这份工作时的内心感受。

若是以前,我可能会列出收入、职业前景、兴趣、工作环境等多个维度来考虑。但是某些场景下,我们常常忽略实现这一结果的概率,比如我想当皇帝,这种不是靠努力就能实现的。

因此这里最好的办法就是去计算每份职业的期望值(Expected Value, 简称EV)。EV计算公式:

EV = 效用(某种结果带给我们的心理满足度) x 出现这种结果的概率

根据上述公式,我们得到:

image-20190503120444342

这里每种结果存在实现概率,是因为该结果要求一定的技能,而这名学生此时并不完全具备这些技能。

根据上面的分析,该学生选择加入外部部的期望值最高,所以理性地说,他应该选择这份工作。

五大常见推理漏洞

通常说的推理漏洞,大多是指那些跟我们所做假设相关的漏洞。书中列举出五大常见推理漏洞:

  1. 比较和类比假设漏洞:偷换概念

把两个虽然不同,但逻辑上却相等的事物进行对比。

比如拿橘子和苹果作比较。再比如说,医学院校经常拿小白鼠做实验,然后把在动物身上得到的实验结果当作参考,但是若因小白鼠身上实验某种药物时发生某种并发症,就认为人类在使用这种药物时也会出现同样的并发症,就是错误的。

  1. 代表性假设漏洞:以偏概全

不能拿特殊案例来代表整体,统计的样本要足够多才行,否则它就会弱化我们的论断。

比如《思考,快与慢》中曾举过一个例子:

最近,某大医院出生婴儿1000人, 某小医院出生婴儿50人, 问哪家医院生男婴的比例大于60%的可能性较大?

我们都知道生男生女的概率分别是50%,统计样本越多就越会接进这个数值,但如果你若去小医院,它的波动概率就很大,可能生男80%,也可以40%,所以小医院生男婴的比例就越有可能大于60%。

  1. “好证据”假设漏洞:对相关证据视而不见

当我们不经验证就想当然地认为自己的证据有效时,就很容易犯此错误。那些比较客观、相关、精确、真实的证据有利于强化我们的论述;而主观、不具代表性、不精确的论据则只会弱化我们的论述。

比如,一个不愿意戒烟的人总是会看到吸烟有利的一面,而对那些支持戒烟的事实会视而不见。

  1. 因果假设漏洞:混淆因果关系

当我们错误地做出因果假设,或者在没有证据的情况下就认定一件事会导致另外一件事时,就会犯这种错误。

比如,每个活过百岁的人都喝过白开水,所以就认定经常喝白开水就能长命百岁,这显然是错误,它们不存在直接的因果关系。很多学术界的社会/生物健康调查相关的报导就经常出现这种错误。

  1. 实施假设漏洞:在执行计划时没有提前考虑可能出现的瓶颈

当我们没有预料到计划实施过程可能出一的瓶颈,或者盲目地相信自己的计划会轻而易举地得到落实时,我们就会犯这种错误。

比如,几年前,西方某旅行杂志曾登过一篇文章说:”因为如今搭乘飞机很方便,而且人们手头余钱也越来越多,所以很快大家都会去非洲看狮子了。”

这显然就是错误的,去不去非洲看狮子,并非单纯考虑金钱和交通就行,比如先问问你有没有年假再说吧!

识别常见的逻辑漏洞

根据书中列举的常见逻辑漏洞,我画了张思维导图:

常见逻辑漏洞识别

附录

1、9点连线的答案:多数人会受限于前提条件:只能在9个点内形成的长方形之内画线,如果能够摆脱该前提条件,那么答案就会有很多种:

image-20190503110749773image-20190503113506286image-20190503113329718

2、水桶题目的答案:先倒满5加仑的水桶,再把它倒进3加仑水桶,把3加仑水桶里的水倒掉,把5加仑水桶里剩下的2加仑水倒进3加仑水桶里,重新装满5加仑水桶(5加仑 + 2加仑 = 7加仓)。

RSS: 优秀的个人情报来源

早些年,关注了一些技术博客,但不知道它是否更新文章,就只好偶而去翻翻看。关注的博客量少的时候,还应付得来,一旦多了,就觉得甚是费时间。

后来才发现有RSS(聚合内容)这款神器,大大地节省时间,不用再不停地翻看别人的博客,一有更新,在自己的订阅网站或app上就可以查看到。

image-20190330095736471

以前用Google Reader,现在用Inoreader(https://www.inoreader.com),还提供手机APP,特别适合利用碎片时间查看和学习。

我现在基本保持每天翻看,一定要把未读消息消灭掉。

由于多年订阅源的收集积累,每天都有不少更新的消息,即使前天刚把失效的订阅源清理掉,也还有700多个。

以前曾看到某同事的RSS订阅,上千条未读消息,平时看得少,结果越堆越多,导致未能发挥RSS应有的价值。

我觉得RSS应该是每个想保持学习进步的人应该必备的工具。

对于我个人而言,RSS有以下作用:

  1. 应急响应:及时获取外部曝光的漏洞,包括公司产品漏洞,以及可能影响公司产品的第三方通用组件/开源项目漏洞,以便能够及时响应处理;
  2. 刷CVE:及时获知某些主流软件的攻击面,或者一些漏洞挖掘技巧,然后主动尝试去挖掘。以前有不少人在乌云上曝光某一通用漏洞,就经常有一大堆去刷SRC,或者在乌云上不停地刷别人的漏洞,这种行为我觉得挺无聊的。这里刷CVE主要是指Microsoft、Apple、Adobe等一系列主流厂商的产品的0day,而不是以往乌云上这种相同漏洞在不同平台刷洞的行为。
  3. 技术与工具的收集:包括技术文章和工具的收集与学习,对于好的工具,会下载学习其源码,并应用实践;对于好的文章,会保存到印象笔记,方便以后查询复习。
  4. 安全资讯:看看一些发安全界发生哪些安全事件,比如入侵事件、facebook信息泄露事件等等,也学习下别人如何就应对此类事件。除此之外,当然也包括安全界的一些八卦。
  5. 新书资讯:专门订阅一些出版社的相关博客/官网,以便能够及时获取即将出版的新书。
  6. 其它:更多的用途靠自己去挖掘,毕竟每个人的期望的目标不一样。

对于那些未提供RSS功能,又非常不错的网站,推荐使用Feed43(https://feed43.com/feed.html?action=new)自定义规则来生成RSS,可直接导入到Inoreader,使用教程参考:《利用 Feed43,将任意网页制作成 RSS 订阅源》https://sspai.com/post/34320

最后分享一下个人收集的RSS,共731个,Inoreader免费版最多支持500个,不想付费的可以找下其它免费RSS工具,或者选择部分订阅。

下载地址:http://riusksk.me/media/riusksk_RSS_20190330.xml

image-20190330103252935

今年的OffensiveCon大会议题质量不错

年前曾在微博上推荐过OffensiveCon 2019大会议题,议题列表与介绍可参见官网(https://www.offensivecon.org/agenda/),很多专注于漏洞挖掘与利用的干货分享,目前只有部分议题ppt公开,文末附打包下载链接(包含8个议题),包括ppt、paper和code。

会议结束后,Twitter上赞声一片,议题质量很赞。

本文主要聊聊已公开的一些议题,学习下思路。

议题列表

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    1. Modern Source Fuzzing
    2. IPC You Outside the Sandbox: One bug to Rule the Chrome Broker
    3. 3D Accelerated Exploitation
    4. Bugs so Nice they Patched them Twice! A (Continuing)? Story About Failed Patches
    5. Attacking Hardware Root of Trust from UEFI Firmware
    6. OSX XPC Revisited - 3rd Party Application Flaws
    7. Growing Hypervisor 0day with Hyperseed
    8. Attacking Edge Through the JavaScript Just-In-Time compiler
    9. Coverage-Guided USB Fuzzing with Syzkaller
    10. Updated Analysis of PatchGuard on Windows RS4: Is the Mouse Finally Caught?
    11. iOS Dual Booting Demystified
    12. macOS: How to Gain Root with CVE-2018-4193 in < 10s
    13. Reverse Engineering of Error-Correcting Codes
    14. Glitch in the Matrix: Exploiting Bitcoin Hardware Wallets
    15. Attack Surface of a Connected Vehicle
    16. Bypass Windows Exploit Guard ASR
    17. FuzzIL: Guided Fuzzing for JavaScript Engines

Modern Source Fuzzing

这是作者Ned Willliamson在353c大会上的《Attack Chrome IPC》议题的扩展补充,我之前还写过《安全研究者的自我修养》一文,里面介绍的就是作者提及的二进制漏洞研究的学习思路。

目前作者没公开这次会议的ppt,大家还是看353C的演讲视频吧:https://media.ccc.de/v/35c3-9579-attacking_chrome_ipc

##IPC You Outside the Sandbox: One bug to Rule the Chrome Broker

作者已经在github上公布此漏洞的利用代码hack2win-chrome,点击”阅读原文“可下载到。

本议题讲的是Chrome沙盒逃逸漏洞,漏洞位于应用缓存(AppCache)子系统上,主要方便从本地读取数据进行离线浏览,访问速度更快,还能缓解服务器压力。

img

AppCache位于沙盒之外的高权限进程browser,沙盒内低权限的renderer进程通过发送IPC消息与browser进程交互的,当AppCache出漏洞时,就有可能逃逸出沙盒。

漏洞成因

这次的ppt写得比较模糊,没那么清楚,还是直接看patch diff:

image-20190223095905435

移动CancelUpdate()函数到newest_complete_cache_=nullptr;之后,直接看看CancelUpdate里面的逻辑:

img

在调用AppCacheGroup::RemoveCache清除缓存时,newest_complete_cache_指向的是被销毁的对象,所以后面才要把它置空,但在销毁之前调用了CancelUpdate =>

AppCacheUPdateJob::~AppCacheUpdateJob => AppCacheGroup::SetUpdateAppCacheStatus => AppCacheHost::OnupdateComplete =>

SetSwappableCache

最后的SetSwappableCache用于设置新的交换缓存(swap cache),会引用到newest_complete_cache_,而此时它还未被置NULL,导致出现Use After Free漏洞。

####漏洞利用:

  1. 【泄露地址】:使用与AppCache对象大小相同的net::CanonicalCookie对象来占用释放对象的内存,而CanonicalCookie对象开头是个cookie名称,即字符串指针,再从浏览器中读取cookie信息来达到信息泄露的目的,从而拿到可控数据的堆地址绕过ASLR。

  2. 【代码执行】:使用与AppCache对象大小相同的Blob对象对占用释放内存,再伪造AppCacheGroup对象,当它析构释放时,在~AppCacheGroup中会调用到已被填充控制的虚函数指针,再结合ROP绕过DEP,从而达到代码执行。

整个过程还是需要自己动手调试一遍才比较清楚,估计足够调上几天了,国内似乎也没有一遍完整的文章分析过该漏洞的利用细节,期待有人分享。

3D Accelerated Exploitation

image-20190223123509759

image-20190223123527727

该议题主要介绍VirsualBox 3D加速器的攻击面和漏洞利用,由于VBox是开源的,因此可以直接使用AFL 去Fuzzing,fuzz目标就是通过发送畸形chromium messages来触发漏洞。他们应该是自己写个构造发送消息的程序,输入文件即chromium messages内容,样本可能是收集550操作码的信息去构造,也可能通过hook去直接抓取真实数据作为样本,然后用 afl去跑。更具体的实现方式,作者也没细说。

MWR Labs这几年经常曝光一些Pwn2Own级别的漏洞,分享很多经典文章,还开源了不少Fuzzer工具,连ppt都做得非常工整,具有独特风格,哪怕没logo,你看一眼都能猜出是他们写的。具备牛X的技能能力,又乐分享,这点是比较难得的。

Attacking Edge Through the JavaScript Just-In-Time compiler

一直以来,chakra被曝的漏洞非常多,导致微软最终还是放弃了。

从今年开始,微软将打算把Edge的Chakra引擎改用Google Chromium引擎,估计最近这两个月就会发布,以后就可能没什么人再搞Chakra内核了。

这议题里面讲了很多chakra的js对象内存结构等基础知识,重点讲了JIT优化编译器的漏洞原理与利用技巧,整个ppt有120页,很多。

我没搞过chakra,未来可能也用不上了,有兴趣的同学可以看下,作者把exploit代码也公布了,我已附在本文的打包资料里面。

Coverage-Guided USB Fuzzing with Syzkaller

image-20190223130009940

搞过Linux/Android内核漏洞挖掘的人,应该都知道Syzkaller这款神器,发现超过2500个内核bug,它是基于代码覆盖率+API调用模板来Fuzzing内核的工具,对于发现崩溃的漏洞,还能自动生成C代码帮助复现,是由Google的Dmitry Vyukov开发的,已在Github上开源多年(https://github.com/google/syzkaller)。

这次作者用syzkaller fuzz USB驱动共发现了80+个bug,它先开启kcov去收集代码覆盖率信息,写了两个usb操作的描述模板(vusb.txt用来生成usb消息,vusb_ids.txt用于提取与USB设备驱动相匹配的USB ID列表),ppt里面有链接,所有的usb fuzzer代码都已经嵌入到syzkaller项目里面了

image-20190223130949191

整个syzkaller的使用过程就是先去寻找内核的攻击面,然后构造api调用模板,剩下交由syzkaller基于代码覆盖驱动的方式去Fuzzing,有点类似api fuzzing。只是这里作者又写了个USB内核模块,方便通过用户层发送USB消息去测试。

作者还专门搞了个树莓派来重现漏洞,演示通过USB去让Windows/Linux系统崩溃。

FuzzIL: Guided Fuzzing for JavaScript Engines

image-20190223135223721

这议题最大的亮点在于:自定义一套中间语言IL,通过IL可以翻译成JS代码,然后通过变异IL来生成JS代码,与以往基于JS语法模板生成代码的方式不同。

image-20190223135445955

直接通过一行行删除IL的方式来验证是否崩溃或产生新路径,以此用来精简样本。

整个Fuzzing过程如下:

image-20190223140416987

作者未来会在github上开源(https://github.com/googleprojectzero/fuzzilli),拭目以待。

结语

访问 https://github.com/riusksk/SecConArchive可获取议题的打包资料,除上述推荐的议题资料外,还有3个议题,包括”Bypass_Windows_Defender_ASR“、”macOS-How to Gain Root with CVE-2018-4193“,以及”OSX Privileged Helper Tool“,有兴趣的同学自行下载阅读。

image-20190223141538809

winafl中基于插桩的覆盖率反馈原理

最近winafl增加支持对Intel PT的支持的,但是只支持x64,且覆盖率计算不全,比如条件跳转等,所以它现在还是不如直接用插桩去hook的方式来得准确完整,这里主要想分析也是基于 DynamoRIO插桩的覆盖率反馈原理。

之前曾有人在《初识 Fuzzing 工具 WinAFL》(https://paper.seebug.org/323/#32)中“3.2.2 插桩模块”一节中简单分析过其插桩原理,但没有找到我想要的答案,因此只好自动动手分析下源码。

比如,我想知道:

  1. 通过循环调用fuzzing的目标函数来提高速度,但DynamoRIO的覆盖率信息是如何同步给fuzzer主进程的?

  2. 具体是如何实现寄存器环境的记录与恢复,从而实现目标函数的不断循环?

  3. 覆盖率信息是如何记录与分析的?

覆盖率信息记录与分析原理

第3个问题发现已经有人分析过afl,可以参见这里《AFL内部实现细节小记》(http://rk700.github.io/2017/12/28/afl-internals/),简单总结下:

  1. AFL在编译源码时,为每个代码生成一个随机数,代表位置地址;

  2. 在二元组中记录分支跳转的源地址与目标地址,将两者异或的结果为该分支的key,保存每个分支的执行次数,用1字节来储存;

  3. 保存分支的执行次数实际上是一张大小为64K的哈希表,位于共享内存中,方便target进程与fuzzer进程之间共享,对应的伪代码如下:

    1
    2
    3
    cur_location = <COMPILE_TIME_RANDOM>;
    shared_mem[cur_location ^ prev_location]++;
    prev_location = cur_location >> 1;
  4. fuzzer进程通过buckets哈希桶来归类这些分支执行次数,如下结构定义,左边为执行次数,右边为记录值trace_bits:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    static const u8 count_class_lookup8[256] = {
    [0] = 0,
    [1] = 1,
    [2] = 2,
    [3] = 4,
    [4 ... 7] = 8,
    [8 ... 15] = 16,
    [16 ... 31] = 32,
    [32 ... 127] = 64,
    [128 ... 255] = 128
    };
  5. 对于是否触发新路径,主要通过计算各分支的trace_bits的hash值(算法:u32 cksum **=** hash32(trace_bits, MAP_SIZE常量, HASH_CONST常量);)是否发生变化来实现的

覆盖信息的传递原理

  1. 先在fuzzer进程中先创建命名管道,其中fuzzer_id为随机值:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //afl-fuzz.c
    pipe_name = (char *)alloc_printf("\\\\.\\pipe\\afl_pipe_%s", fuzzer_id);

    pipe_handle = CreateNamedPipe(
    pipe_name, // pipe name
    PIPE_ACCESS_DUPLEX | // read/write access
    FILE_FLAG_OVERLAPPED, // overlapped mode
    0,
    1, // max. instances
    512, // output buffer size
    512, // input buffer size
    20000, // client time-out
    NULL); // default security attribute
  2. 创建drrun进程去运行目标程序并Hook,在childpid_(%fuzzer_id%).txt的文件中记录子进程id,即目标进程ID,然后等待管道连接,并通过读取上述txt文件以获取目标进程id,主要用来后面超时中断进程的:

    1
    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
    //afl-fuzz.c    
    pidfile = alloc_printf("childpid_%s.txt", fuzzer_id);
    if (persist_dr_cache) {
    cmd = alloc_printf(
    "%s\\drrun.exe -pidfile %s -no_follow_children -persist -persist_dir \"%s\\drcache\" -c winafl.dll %s -fuzzer_id %s -drpersist -- %s",
    dynamorio_dir, pidfile, out_dir, client_params, fuzzer_id, target_cmd);
    } else {
    cmd = alloc_printf(
    "%s\\drrun.exe -pidfile %s -no_follow_children -c winafl.dll %s -fuzzer_id %s -- %s",
    dynamorio_dir, pidfile, client_params, fuzzer_id, target_cmd);
    }
    ......
    if(!CreateProcess(NULL, cmd, NULL, NULL, inherit_handles, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
    FATAL("CreateProcess failed, GLE=%d.\n", GetLastError());
    }
    ......
    if(!OverlappedConnectNamedPipe(pipe_handle, &pipe_overlapped)) {
    FATAL("ConnectNamedPipe failed, GLE=%d.\n", GetLastError());
    }

    watchdog_enabled = 0;

    if(drioless == 0) {
    //by the time pipe has connected the pidfile must have been created
    fp = fopen(pidfile, "rb");
    if(!fp) {
    FATAL("Error opening pidfile.txt");
    }
    fseek(fp,0,SEEK_END);
    pidsize = ftell(fp);
    fseek(fp,0,SEEK_SET);
    buf = (char *)malloc(pidsize+1);
    fread(buf, pidsize, 1, fp);
    buf[pidsize] = 0;
    fclose(fp);
    remove(pidfile);
    child_pid = atoi(buf);
    free(buf);
    ck_free(pidfile);
    }
    else {
    child_pid = pi.dwProcessId;
    }
  3. 在插桩模块winafl.dll中打开前面创建的命名管道,然后通过管道与fuzzer主进程进行交互:

    1
    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
    //winafl.c
    static void
    setup_pipe() {
    pipe = CreateFile(
    options.pipe_name, // pipe name
    GENERIC_READ | // read and write access
    GENERIC_WRITE,
    0, // no sharing
    NULL, // default security attributes
    OPEN_EXISTING, // opens existing pipe
    0, // default attributes
    NULL); // no template file

    if (pipe == INVALID_HANDLE_VALUE) DR_ASSERT_MSG(false, "error connecting to pipe");
    }
    ......
    char ReadCommandFromPipe()
    {
    DWORD num_read;
    char result;
    ReadFile(pipe, &result, 1, &num_read, NULL);
    return result;
    }

    void WriteCommandToPipe(char cmd)
    {
    DWORD num_written;
    WriteFile(pipe, &cmd, 1, &num_written, NULL);
    }
  4. 当插桩模块winafl.dll监测到程序首次运行至目标函数入口时,pre_fuzz_handler函数会被执行,然后通过管道写入’P’命令,代表开始进入目标函数,afl-fuzz.exe进程收到命令后,会向目标进程写入管道命令’F’,并监测超时时间和循环调用次数。afl-fuzz.exe与目标进程正是通过读写管道命令来交互的,主要有’F’(退出目标函数)、’P’(进入目标函数)、’K’(超时中断进程)、’C’(崩溃)、’Q’(退出进程)。覆盖信息通过文件映射方法(内存共享)写入winafl_data.afl_area

    1
    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
    //winafl.c
    pre_fuzz_handler(void *wrapcxt, INOUT void **user_data)
    {
    ......
    if(!options.debug_mode) {
    WriteCommandToPipe('P');
    command = ReadCommandFromPipe();

    if(command != 'F') {
    if(command == 'Q') {
    dr_exit_process(0);
    } else {
    DR_ASSERT_MSG(false, "unrecognized command received over pipe");
    }
    }
    } else {
    debug_data.pre_hanlder_called++;
    dr_fprintf(winafl_data.log, "In pre_fuzz_handler\n");
    }
    ......
    memset(winafl_data.afl_area, 0, MAP_SIZE); // 用于存储覆盖率信息

    if(options.coverage_kind == COVERAGE_EDGE || options.thread_coverage) {
    void **thread_data = (void **)drmgr_get_tls_field(drcontext, winafl_tls_field);
    thread_data[0] = 0;
    thread_data[1] = winafl_data.afl_area; //如果开启-thread_coverage选项,则会将覆盖率信息写入线程TLS中
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //winafl.c
    static void
    setup_shmem() {
    HANDLE map_file;

    map_file = OpenFileMapping(
    FILE_MAP_ALL_ACCESS, // read/write access
    FALSE, // do not inherit the name
    options.shm_name); // name of mapping object

    if (map_file == NULL) DR_ASSERT_MSG(false, "error accesing shared memory");

    winafl_data.afl_area = (unsigned char *) MapViewOfFile(map_file, // handle to map object
    FILE_MAP_ALL_ACCESS, // read/write permission
    0,
    0,
    MAP_SIZE);

    if (winafl_data.afl_area == NULL) DR_ASSERT_MSG(false, "error accesing shared memory");
    }

篡改目标函数循环调用的原理

此步的关键就在于进入目标函数前调用的pre_fuzz_handler函数,以及函数退出后调用的post_fuzz_handler函数。

进入pre_fuzz_handler函数时,winafl.dll会先获取以下信息

1
2
3
4
5
6
app_pc target_to_fuzz = drwrap_get_func(wrapcxt);	//获取目标函数地址
dr_mcontext_t *mc = drwrap_get_mcontext_ex(wrapcxt, DR_MC_ALL); //获取目标函数当前内存上下文信息
drcontext = drwrap_get_drcontext(wrapcxt); //获取DynamoRIO上下文

fuzz_target.xsp = mc->xsp; // 保存栈指针,xsp是各平台下的通用标记变量
fuzz_target.func_pc = target_to_fuzz; // 目标函数地址

其中内存上下文信息支持各平台的寄存器记录:

1
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
typedef struct _dr_mcontext_t {
/**
* The size of this structure. This field must be set prior to filling
* in the fields to support forward compatibility.
*/
size_t size;
/**
* The valid fields of this structure. This field must be set prior to
* filling in the fields. For input requests (dr_get_mcontext()), this
* indicates which fields should be written. Writing the multimedia fields
* frequently can incur a performance hit. For output requests
* (dr_set_mcontext() and dr_redirect_execution()), this indicates which
* fields will be copied to the actual context.
*/
dr_mcontext_flags_t flags;

#ifdef AARCHXX
reg_t r0; /**< The r0 register. */
reg_t r1; /**< The r1 register. */
reg_t r2; /**< The r2 register. */
reg_t r3; /**< The r3 register. */
reg_t r4; /**< The r4 register. */
reg_t r5; /**< The r5 register. */
reg_t r6; /**< The r6 register. */
reg_t r7; /**< The r7 register. */
reg_t r8; /**< The r8 register. */
reg_t r9; /**< The r9 register. */
reg_t r10; /**< The r10 register. */
reg_t r11; /**< The r11 register. */
reg_t r12; /**< The r12 register. */
# ifdef X64 /* 64-bit */
reg_t r13; /**< The r13 register. */
reg_t r14; /**< The r14 register. */
reg_t r15; /**< The r15 register. */
reg_t r16; /**< The r16 register. \note For 64-bit DR builds only. */
reg_t r17; /**< The r17 register. \note For 64-bit DR builds only. */
reg_t r18; /**< The r18 register. \note For 64-bit DR builds only. */
reg_t r19; /**< The r19 register. \note For 64-bit DR builds only. */
reg_t r20; /**< The r20 register. \note For 64-bit DR builds only. */
reg_t r21; /**< The r21 register. \note For 64-bit DR builds only. */
reg_t r22; /**< The r22 register. \note For 64-bit DR builds only. */
reg_t r23; /**< The r23 register. \note For 64-bit DR builds only. */
reg_t r24; /**< The r24 register. \note For 64-bit DR builds only. */
reg_t r25; /**< The r25 register. \note For 64-bit DR builds only. */
reg_t r26; /**< The r26 register. \note For 64-bit DR builds only. */
reg_t r27; /**< The r27 register. \note For 64-bit DR builds only. */
reg_t r28; /**< The r28 register. \note For 64-bit DR builds only. */
reg_t r29; /**< The r29 register. \note For 64-bit DR builds only. */
union {
reg_t r30; /**< The r30 register. \note For 64-bit DR builds only. */
reg_t lr; /**< The link register. */
}; /**< The anonymous union of alternative names for r30/lr register. */
union {
reg_t r31; /**< The r31 register. \note For 64-bit DR builds only. */
reg_t sp; /**< The stack pointer register. */
reg_t xsp; /**< The platform-independent name for the stack pointer register. */
}; /**< The anonymous union of alternative names for r31/sp register. */
/**
* The program counter.
* \note This field is not always set or read by all API routines.
*/
byte *pc;
union {
uint xflags; /**< The platform-independent name for condition flags. */
struct {
uint nzcv; /**< Condition flags (status register). */
uint fpcr; /**< Floating-Point Control Register. */
uint fpsr; /**< Floating-Point Status Register. */
}; /**< AArch64 flag registers. */
}; /**< The anonymous union of alternative names for flag registers. */
# else /* 32-bit */
union {
reg_t r13; /**< The r13 register. */
reg_t sp; /**< The stack pointer register.*/
reg_t xsp; /**< The platform-independent name for the stack pointer register. */
}; /**< The anonymous union of alternative names for r13/sp register. */
union {
reg_t r14; /**< The r14 register. */
reg_t lr; /**< The link register. */
}; /**< The anonymous union of alternative names for r14/lr register. */
/**
* The anonymous union of alternative names for r15/pc register.
* \note This field is not always set or read by all API routines.
*/
union {
reg_t r15; /**< The r15 register. */
byte *pc; /**< The program counter. */
};
union {
uint xflags; /**< The platform-independent name for full APSR register. */
uint apsr; /**< The application program status registers in AArch32. */
uint cpsr; /**< The current program status registers in AArch32. */
}; /**< The anonymous union of alternative names for apsr/cpsr register. */
# endif /* 64/32-bit */
/**
* The SIMD registers. We would probably be ok if we did not preserve the
* callee-saved registers (q4-q7 == d8-d15) but to be safe we preserve them
* all. We do not need anything more than word alignment for OP_vldm/OP_vstm,
* and dr_simd_t has no fields larger than 32 bits, so we have no padding.
*/
dr_simd_t simd[NUM_SIMD_SLOTS];
#else /* X86 */
union {
reg_t xdi; /**< The platform-independent name for full rdi/edi register. */
reg_t IF_X64_ELSE(rdi, edi); /**< The platform-dependent name for
rdi/edi register. */
}; /**< The anonymous union of alternative names for rdi/edi register. */
union {
reg_t xsi; /**< The platform-independent name for full rsi/esi register. */
reg_t IF_X64_ELSE(rsi, esi); /**< The platform-dependent name for
rsi/esi register. */
}; /**< The anonymous union of alternative names for rsi/esi register. */
union {
reg_t xbp; /**< The platform-independent name for full rbp/ebp register. */
reg_t IF_X64_ELSE(rbp, ebp); /**< The platform-dependent name for
rbp/ebp register. */
}; /**< The anonymous union of alternative names for rbp/ebp register. */
union {
reg_t xsp; /**< The platform-independent name for full rsp/esp register. */
reg_t IF_X64_ELSE(rsp, esp); /**< The platform-dependent name for
rsp/esp register. */
}; /**< The anonymous union of alternative names for rsp/esp register. */
union {
reg_t xbx; /**< The platform-independent name for full rbx/ebx register. */
reg_t IF_X64_ELSE(rbx, ebx); /**< The platform-dependent name for
rbx/ebx register. */
}; /**< The anonymous union of alternative names for rbx/ebx register. */
union {
reg_t xdx; /**< The platform-independent name for full rdx/edx register. */
reg_t IF_X64_ELSE(rdx, edx); /**< The platform-dependent name for
rdx/edx register. */
}; /**< The anonymous union of alternative names for rdx/edx register. */
union {
reg_t xcx; /**< The platform-independent name for full rcx/ecx register. */
reg_t IF_X64_ELSE(rcx, ecx); /**< The platform-dependent name for
rcx/ecx register. */
}; /**< The anonymous union of alternative names for rcx/ecx register. */
union {
reg_t xax; /**< The platform-independent name for full rax/eax register. */
reg_t IF_X64_ELSE(rax, eax); /**< The platform-dependent name for
rax/eax register. */
}; /**< The anonymous union of alternative names for rax/eax register. */
# ifdef X64
reg_t r8; /**< The r8 register. \note For 64-bit DR builds only. */
reg_t r9; /**< The r9 register. \note For 64-bit DR builds only. */
reg_t r10; /**< The r10 register. \note For 64-bit DR builds only. */
reg_t r11; /**< The r11 register. \note For 64-bit DR builds only. */
reg_t r12; /**< The r12 register. \note For 64-bit DR builds only. */
reg_t r13; /**< The r13 register. \note For 64-bit DR builds only. */
reg_t r14; /**< The r14 register. \note For 64-bit DR builds only. */
reg_t r15; /**< The r15 register. \note For 64-bit DR builds only. */
# endif
union {
reg_t xflags; /**< The platform-independent name for
full rflags/eflags register. */
reg_t IF_X64_ELSE(rflags, eflags); /**< The platform-dependent name for
rflags/eflags register. */
}; /**< The anonymous union of alternative names for rflags/eflags register. */
/**
* Anonymous union of alternative names for the program counter /
* instruction pointer (eip/rip). \note This field is not always set or
* read by all API routines.
*/
union {
byte *xip; /**< The platform-independent name for full rip/eip register. */
byte *pc; /**< The platform-independent alt name for full rip/eip register. */
byte *IF_X64_ELSE(rip, eip); /**< The platform-dependent name for
rip/eip register. */
};
byte padding[PRE_XMM_PADDING]; /**< The padding to get ymm field 32-byte aligned. */
/**
* The SSE registers xmm0-xmm5 (-xmm15 on Linux) are volatile
* (caller-saved) for 64-bit and WOW64, and are actually zeroed out on
* Windows system calls. These fields are ignored for 32-bit processes
* that are not WOW64, or if the underlying processor does not support
* SSE. Use dr_mcontext_xmm_fields_valid() to determine whether the
* fields are valid.
*
* When the fields are valid, on processors with AVX enabled (i.e.,
* proc_has_feature(FEATURE_AVX) returns true), these fields will
* contain the full ymm register values; otherwise, the top 128
* bits of each slot will be undefined.
*/
dr_ymm_t ymm[NUM_SIMD_SLOTS];
#endif /* ARM/X86 */
} dr_mcontext_t;

接下来就是获取和设置fuzzed的目标函数参数:

1
2
3
4
5
6
7
8
9
10
//save or restore arguments
if (!options.no_loop) {
if (fuzz_target.iteration == 0) {
for (i = 0; i < options.num_fuz_args; i++)
options.func_args[i] = drwrap_get_arg(wrapcxt, i); //首次运行先获取运行参数
} else {
for (i = 0; i < options.num_fuz_args; i++)
drwrap_set_arg(wrapcxt, i, options.func_args[i]); //设置运行参数
}
}

当目标函数退出后,执行post_fuzz_handler函数,会恢复栈顶指针和pc地址,以此实现目标函数的循环调用:

1
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
static void
post_fuzz_handler(void *wrapcxt, void *user_data)
{
dr_mcontext_t *mc;
mc = drwrap_get_mcontext(wrapcxt); //获取上下文信息

if(!options.debug_mode) {
WriteCommandToPipe('K');
} else {
debug_data.post_handler_called++;
dr_fprintf(winafl_data.log, "In post_fuzz_handler\n");
}

/* We don't need to reload context in case of network-based fuzzing. */
if (options.no_loop)
return; //网络型Fuzzing无需重载上下文信息

//超过循环次数就退出进程
fuzz_target.iteration++;
if(fuzz_target.iteration == options.fuzz_iterations) {
dr_exit_process(0);
}

mc->xsp = fuzz_target.xsp; //恢复栈顶指针
mc->pc = fuzz_target.func_pc; //篡改pc地址加原目标函数地址
drwrap_redirect_execution(wrapcxt); //篡改执行流
}

总结

总结下整个winafl执行流程:

  1. afl-fuzz.exe通过创建命名管道与内存映射来实现与目标进程交互,其中管道用来发送和接收命令相互操作对方进程,内存映射主要用来记录覆盖率信息;
  2. 覆盖率记录主要通过drmgr_register_bb_instrumentation_event去设置BB执行的回调函数,通过instrument_bb_coverage或者instrument_edge_coverage来记录覆盖率情况,如果发现新的执行路径,就将样本放入队列目录中,用于后续文件变异,以提高代码覆盖率;
  3. 目标进程执行到目标函数后,会调用pre_fuzz_handler来存储上下文信息,包括寄存器和运行参数;
  4. 目标函数退出后,会调用post_fuzz_handler函数,记录恢复上下文信息,以执行回原目标函数,又回到第2步;
  5. 目录函数运行次数达到指定循环调用次数时,会中断进程退出。

聊聊那些黑客小说

系统宕,
资料泄,
挂马黑站何时了?
安全知多少!
告警昨夜又响起,
往事不堪回首月明中。
漏洞应犹在,
只是域名改。
问君能有几多愁?
恰似行行代码错误留。

黑客小说:培养对信息安全的兴趣

之前在《漏洞战争》的前言里面有提到,鄙人初入象牙塔之时,曾看过多本黑客小说,包括《黑客传说》、《地狱黑客》(后改名为《禁区之门》,参考凯文·米特尼克事迹写的,后来又出了第2部,但好像没写完)、《指间的黑客》等等,后来也因此对安全产生兴趣,入了这行道。

但,道归道,兴趣归兴趣!

因为曾有多少人,来了兴趣多年,却未曾自学过。

“我对安全很感兴趣,求师傅教教我!”这种老套路的提问,大家见得还少吗?

正如许多人宁愿被动受苦,也不愿主动吃苦学习一样,这个问题在知乎上也曾被热烈讨论过。被动受苦大多不用多动脑,久而久之,身体也会慢慢地适应,也就逐渐被生活、被制度所驯化。

不过,此处想说的重点是,黑客小说可以培养人们对信息安全的兴趣,而学习的过程本身就是孤独单调的,如有兴趣相伴,则更易独行久远!

行业人写小说:有始无终,多半夭折

安全圈里面其实也有一些人写过黑客小说,不乏某些知名人士,但基本上都是开了个头,却没多久就夭折收场。反正,我是没见过有人写完出版的。

于是,我上Google搜索了下起点网,通过一些安全专业名词进行搜索,找到几部相关小说:

  “第一节操作系统原理、第二节系统及命令详解、第三节溢出漏洞原理、第四节web原理、第五节http协议、tcp/ip协议第六节sql注入原理、上传漏洞、XSS、CSRF……”

​ ——《别说我是黑客》

  过了十多分钟,jsky的界面左侧刷出来许多asp文件和几个目录。右栏则是标注着绿色和红色叹号的几列英文。
  看到扫描结果出来,杨风面带微笑进行下一步操作。他的运气不错,得到了xss与sqlinjection漏洞,这是网站暴露出来的跨站脚本漏洞和sql注入漏洞。
  杨风转到育民高中主页,随手选取了一个注入地址,提交上引号。
  返回错误。
  接着提交and1=1语句。
  返回正常。
  继续提交and1=2语句。
  返回错误。
  杨风做这两步,主要是测试网站程序设计者是否在其中过滤了关键字,如果过滤就不能被注入。

​ ——《黑客记事本》

​ “尊敬的孙诚先生,请允许我对你和你的团队–塞伯坦工作室致以敬意。我们的检测人员已经验证了你所寄过来的数据,并证实了ios漏洞的存在,在对你们表示感谢的同时,Zerodium会按照约定,向你的团队支付共计五万四千美元的报酬,并希望你们能尽快将后续数据补完。在邮件中,你们提到找到了ios的两处极为隐秘的高危漏洞,Zerodium上下都对此非常感兴趣。希望能够尽快收到你的回复,报酬方面请不用担心,Zerodium是一个非常有信誉的平台!”

​ ——《从变形金刚开始》

“我明白了,灵根这个电源,就相当于是有着固定编码的反编译器,每个灵根都有一个固定编码,就是所谓的灵根属性。灵根可以把跟自己编码一样的灵气团,进行逆向反编译,把编译好的灵气团分解成单纯由0和1构成的信息流,就是所谓的灵力!”

​ ——《程序员修真之路》

从教你用jsky黑站(PS:为啥不推荐wvs呢),到黑客穿越、程序员修仙等,各种奇思妙想,在网络小说领域也算是另类的存在。

但是从这些专业名词看,作者即使不是安全圈的,至少也是IT技术行业的,对一些常见的安全事件、技术名词都比较了解。

文学与IT技术本身就是两个不同的领域,要同时兼顾就有一定难度。如果算程序员里面写的小说,比较火的,应该是那本《疯狂的程序员》吧!

懵懂之美:似懂非懂才是最大的乐趣

我已经很久没看黑客小说,尤其是入了行之后,就更不看了。

如果要推荐的话,还是开头提到的那3本小说:《黑客传说》、《禁区之门》、《指间的黑客》,不过那是我大学时的口味了,现在重新看也不一定就如当初那般喜欢。

因为当你对安全行业熟悉后,再去看这些小说的时候,可能就容易较真,少了些许乐趣。

我当初看上面的小说的时候,其实也还没入门安全,所以看得特别起劲。

所以,如果要看这类小说,就把那些行业知识都抛诸脑后,享受那当初的懵懂之美,才是读小说的乐趣所在。

后话

也许是性格使然,在文字世界里,鄙人老喜欢委婉地批判人和事(俗称:骂人)。不过文学世界里,一千个读者就有一千个哈姆雷特,应该支持下这种多元文化。不然就像娱乐圈里,谁演孙悟空,都要被六小龄童骂一般,少了胸怀,甚至阻碍了行业发展。

安全研究者的自我修养(续)

接上篇继续聊安全研究者的自我修养,上篇重点讲技术修炼,本篇聊聊行业现象、谈谈沉淀、情怀等等。

11、工具与方法论沉淀

虽说代码审计是项必备技能,但终究是项体力活。

有些漏洞(比如逻辑漏洞)可能就需要人工审计,但也有不少漏洞是可以自动化Fuzzing,一些能自动化或半自动化实现的,尽量写程序自动化。

因为,纯人工审计终究熬不过年纪,熬不过团队人员的离散变迁,熬不过互联网的快速发展……

比如,2012年刚开始写《漏洞战争》时,单身一人,从早上8点多起床吃饭,然后开始调代码、看代码,一直奋战到晚上12点,身体无压力。近7年过去了,现在要是这么折腾,身体就要散架了……

比如,团队里的人分工做不同领域的代码审计,若无工具和方法论沉淀,那么有人走的话,此人对应的领域可能就无法持续产出;若有新人加入,代码审计的技能又不好传承,很多得自己重头来。所以,一直觉得,好的团队应该是,即使人员离散变迁,依然能够独立运作、持续产出的。

比如,Linux内核在2018年净增87万行代码,很多类似复杂庞大的项目,看代码有时看都看不过来,一般都是针对性地挑模块作代码审计。

比如,Fuzzer开发里面就有很多共用功能是可以直接做成框架沉淀下来,文件变异、崩溃监控、样本去重精简等等,很多时候有个新的攻击面需要测试,就可以直接在框架的基础上写fuzzer,将会高效很多。下文提到的一个IE漏洞挖掘案例就是基于这思路挖到的。

我曾经想开发两个漏洞挖掘系统,一个二进制,一个Web,名字都想好了,合称”冰弓玄箭“,但业余一直都没什么时间开发,仅写了个界面,希望2019年能够完成:

image-20190112143451515

”冰弓“的Logo直接用的是“破甲弓”,感觉很酷……

再说说方法论,这词虽有点虚,但其实本质上就是一种技术方法的总结而已。

比如,渗透测试的时候,总有些人每次都能搞到RCE,无论啥网站,完全摆脱“随机挖洞”的命运。多数情况下,他们都会有一套自己测试方法,或者将一些经验转换成工具,测试时就拿自己的工具和以往总结的方法论开搞。

比如,STRIDE威胁建模本身就是一套方法论,一套简单的风险助记符,当然我这里不是说安全研究要用它,只是举个方法论的例子,它也没有那么万能。

写这么多,总结起来就一句话:多总结,多沉淀!

12、漏洞研究风向标:安全公告

如果大家有关注四大厂商(Google、Microsoft、Apple、Adobe)的安全公告的话,会发现有段时间会出现很多类似漏洞的公告,出现一个新的攻击面之后,一帮研究人员就蜂捅而上狂刷一波。

这种情况一向是先下手为强,而上文提到的工具和方法论就更显得尤为重要了,否则最后都只能捡剩的。

比如本周 Microsoft 安全公告出来后,我仔细分析了下,然后下班回家写了个Fuzzer,挂着跑了一天,出来个Crash,再用几分钟成功构造出PoC,实现IE浏览器的远程代码执行,可见也是个品相极佳的神洞:

image-20190112153428430

但不幸的是,我打了1月的补丁后,发现修复了,成功“撞洞”,真的是欲哭无泪……

但至少证明,通过安全公告寻找新的攻击面,然后挖掘一些类似漏洞,一直是一种高效的漏洞研究方式。

13、老一辈研究者都去哪儿了?

img

最近腾讯AILab张潼离职的事传得很火,还有之前各大厂聘请的AI科学家陆续辞职,回归学术界,很多人因此唱起科学家之于科技公司的无用论,主要有以下几点原因:

  1. 研究成果无法落地为产品:做安全研究也是如此,很多事情是无法落地的,圈内很多研究团队都是拿漏洞来打比赛赚影响力,真正能实现为公司营利的(打比赛赚奖金的忽略不计,因为那些都不够给研究者们的工资),我只知道有1个研究团队/实验室今年营利了。
  2. 长期无产出,KPI压力大:研究了很长时间,最后仍一无所获,那KPI咋办、PPT怎么写、晋级怎么答辩。安全行业有句老话来形容安全研究工作,叫“三年不开锅,开锅吃三年”,但多数个人和企业都等不到三年。之前同事说王小云为何能破解出MD5,是因为她在学校里很长时间没搞出东西的时候,领导没找她麻烦,没有KPI压力,以致能够长期专注于此。具体原因我不确定,但学术界自然是没有企业有这般KPI压力。
  3. 业务数据不共享:业务部门的产品数据基本不太可能共享给实验室作研究的,一般都是实验室以SDK的形式提供给业务用,数据由业务自主控制。这种情况对于安全研究的影响相对较少一些。

头两点是多数安全研究者的困境,也跟圈内同行讨论过,下面聊聊这帮老一代“知青”最后都去哪儿了?这里我主要总结一些圈内人的应对方法(其实多数都是转型),具体不作点评,总结为主,也欢迎私信讨论(新注册的公众号已不允许留言)。

  1. 坚持研究:这帮人主要还是那些研究能力较强的,且有一定研究成果的人,围观下各大实验室就知道个大概,不多说;
  2. 转型安全产品开发与运营:有产品就能解决落地问题,帮助企业解决实际问题,有不少人走这条道,去做威胁情报系统、漏洞扫描器、WAF、云安全产品等等;
  3. 转型业务安全:跟研究工作差异较大,因为业务安全的主要问题很多时候并非漏洞,而是跟业务产品相关的黑灰产对抗等等;
  4. 自由研究者:国外很多此类研究者,靠拿漏洞赏金过活,俗称“赏金猎人”,国内相对少一些,也有一些国内自由研究者后来又进企业做研究的,这里讲的几种转型都可以来回转换,有些人就干过。
  5. 创业:这里包括安全行业内的创业,也包括那些开淘宝店、奶茶店、服装生意、卖水果的……

14、个人终究干不过团队

有时想搞的研究太多了,但发现一个人根本搞不过来,需要多人协作才可能完成。但需要多人在研究领域上有交集,否则拉在一块也是各搞各的。

前篇第7点讲到“进入研究者团队或社区,互相学习”,也是一大影响因素,互相学习也是一种提高效率和产出的方式。

算了,不多说了!

后话

这次真的结束了,没有续篇了。

思考了很多,总结了很多,有些也是写了删,删了写。

安全研究领域一直也没人写过这些,出来唠叨几句,也欢迎大家私信讨论。

最后奉一首酒桌上的《苦行僧》结束本话题,听过这首歌很多个版本,包括原唱,但终究还是觉得视频里这位老哥唱得更具江湖气、更具情感、更具感染力……旁边一老哥听着听着都偷偷抹泪了!

之所以点这首歌,是因为:每一个研究者都是独立自行的苦行僧!

安全研究者的自我修养

在上篇文章《推荐今年C3黑客大会上的几个议题》中提到”Attacking Chrome IPC“这个议题,我觉得该议题最大的亮点是在前半场,作者nedwill是之前在hack2win大赛上因攻破Chrome浏览器而一战成名,他讲了如何训练漏洞研究能力的过程,讲述自己这几年在漏洞研究上的历程和心得,很励志,其建议也非常具有可操作性,值得效仿学习。我反复看了多遍,对其作了一些总结和补充。

1、刻意练习10000小时

这份“鸡汤”道理,想必大家都懂,就不解释了,不懂的自行百度,或者去读读《异类》这本经典书籍。

作者建议以月为单位来制定研究目标,他曾连续花了6个月的时间来研究Chrome Sandbox,但最终一无所获。

所以,有时坚持了不一定能达到目标,但不坚持,就更没戏了。

2、训练挖洞的双技能

(1)看洞:哪里看?历史漏洞的git log、bug报告、代码质量报告等等

(2)识洞:就是肉眼看代码找漏洞,即代码审计,难点也就是在这上面,训练方法继续往下看

3、代码审计训练

(1)根据自己目标定位,寻找相应的历史漏洞案例进行学习,比如要搞chrome就找chrome的历史漏洞

(2)掌握漏洞所在的模块或子系统,但不看完整的漏洞细节描述,尝试在漏洞版本中找出对应的漏洞

(3)如果(2)中未能找出漏洞,就去看漏洞细节描述,对比自己的审计过程,看遗漏了哪一步骤

(4)不断重复上述训练,直至相信:挖洞只是体力消耗,而非能力问题

这第4点说得,非常励志,因为挖洞挖久了,有时真的容易怀疑自己的能力,目标难度越大,越容易打击人。

作者第一次训练的漏洞是j00ru(Project Zero成员)的IDA漏洞:https://j00ru.vexillium.org/2014/10/secure-2014-slide-deck-and-hex-rays-ida-pro-advisories-published/,2014年的文章了

4、3~5年的训练计划

1~2年:做做 CTF 或 WarGames 题目,网上有很多CTF writeup可以参考学习

2~3年:简单点的目标,就是找相对容易挖的产品

3~5年:困难点的目标

目标的难易程度可以直接参考相应的产品的漏洞奖励计划或私有市场的价格,挑选出一份目标清单,按难易程度排序,逐一去实现它。

5、Fuzzing训练

作者代码审计2年后,才开始尝试Fuzzer开发。

(1)拿已公开的历史漏洞问自己:如何写fuzzer挖掘到此漏洞?

(2)如果自己不知道此漏洞,那又能够挖掘到呢?

(3)不断重复训练并改进fuzzer,相信会有更多漏洞被意外发现

6、努力往往比运气和天赋更重要

虽然挖洞也需要一定运气和天赋,但多数你认为的挖洞天才,其实只不过是花了比你多100倍,甚至更多的时间在这项技术研究上而已

7、进入研究者团队或社区,互相学习

国外的交流氛围会比国内的更好一些,也更愿意分享。

很多时候自己的交流圈,大多是一些熟识的同行,或者同事,一般可交流的人还是比较少的。

经常在网上看到不少人会问,如何认识xx大牛、黑客,但其实很多时候却是:

努力提高自己的专业能力,圈子最终会吸纳你进去认识更多圈内人。

8、建立自己的漏洞信息来源

RSS订阅无疑是自己最好的方式,这个需要依赖平时自己去不断收集订阅。

很多漏洞相关的博文,往往曝露出某些软件新的攻击面,抢占先机就显得尤为重要,比如当年Android stagefirght mp4漏洞、word公式编辑器、adobe图片转换器等等,如果能及时关注并尝试去挖掘,往往可以收获不少漏洞的。

9、收集和学习开源的漏洞挖掘工具

比如afl、honggfuzz、libfuzzer等很多优秀的漏洞挖掘工具,都是值得好好阅读代码,学习其中的fuzzing思路,可以更好地应用到未来的漏洞挖掘研究上。

10、很多不愿搞研究工作的挖洞人,只不过是为了权衡利弊

在《从0到1:开启商业与未来的秘密》一书中有一章叫做“秘密”,漏洞研究可以当作挖掘秘密,为什么人们不探索秘密呢?书中提到4种原因,我觉得同样适用于漏洞研究领域:

(1)渐进主义:把目标定得低一些,更容易取得好成绩;

(2)风险规避:人们害怕秘密是因为怕犯错,除此之外,可能也担心KPI没法完成,又或者挖洞拿到的奖金又该如何跟公司“分赃”呢?

(3)自满:很多时候,某些人可以坐享其成,又何必自己去挖掘秘密;国内研究氛围又喜欢搞营销吹牛逼,牛逼吹多了吹大了,有时连自己都信了;

(4)扁平化:任何一个拥有雄心壮志的人,在涉及某一研究领域之前都会问自己一个问题:如果有可能挖掘到漏洞,难道全球人才库中更加聪明、更加有技术能力的人还没有发现吗?这种怀疑的声音阻止了不少人去探索秘密,从事研究工作,因为身处的世界似乎大到任何个人都无法做出独特的贡献。

结语

今年因个人原因,已从安全研究转向业务安全,深知研究的不易。

相信安全领域有秘密的存在,虽会导致黑产的诞生,但肯定也会因此诞生一些优秀的研究者。

最后以白桦的《船》致谢所有仍在安全研究道路上前进的人:

我有过多次这样的奇遇,
从天堂到地狱只在瞬息之间:
每一朵可爱、温柔的浪花
都成了突然崛起、随即倾倒的高山。

每一滴海水都变脸色,
刚刚还是那样的美丽、蔚蓝;
旋涡纠缠着旋涡,
我被抛向高空又投进深渊……

当时我甚至想到过轻生,
眼前一片苦海无边;
放弃了希望就像放弃了舵柄,
在暴力之下只能沉默和哀叹。

今天我才有资格嘲笑昨天的自己,
为昨天落叶似的惶恐感到羞惭;
虚度了多少年华,
船身多次被礁石撞穿……

千万次在大洋里撒网,
才捕获到一点点生活的经验,
才恍然大悟,
啊!道理原是如此浅显;

你要航行吗
必然会有千妖百怪出来阻拦;
暴虐的欺凌是它们的游戏,
制造灭亡是它们唯一的才干。

命中注定我要常常和它们相逢,
因为我的名字叫做船;
面对强大于自身千万倍的对手,
能援救自己的只有清醒和勇敢。

恐惧只能使自己盲目,
盲目只能夸大魔鬼的狰狞嘴脸;
也许我的样子比它们更可怕,
当我以命相拼,一往无前!

只要我还有一根完整的龙骨,
绝不驶进避风的港湾;
把生命放在征途上,
让勇敢来决定道路的宽窄、长短。

我完完全全的自由了,
船头成为埋葬它们的铁铲;
我在波浪中有节奏地跳跃,
就像荡着一个巨大的秋千。

即使它们终于把我撕碎,
变成一些残破的木片,
我不会沉沦,决不!
我还会在浪尖上飞旋。

后来者还会在残片上认出我,
未来的诗人会唱然长叹:
“这里有一个幸福的灵魂,
它曾经是一艘前进着的航船……”

推荐今年C3黑客大会上的几个议题

最近几天在德国举办的 The 35th Chaos Communication Congress (35C3) 黑客大会,在Twitter上传得火热,在国内却无人问津。

从这可以看出同为微博的安全圈氛围是完全不同的,新浪微博还是偏娱乐些的,而且国外的圈子自然比天朝的要大得多,很多国家的人在上面交流。

所以,我现在经常混Twitter,当作获取安全资讯的途径,新浪微博就真的当作看新闻的了……

德国C3混沌黑客大会

Chaos Communication Congress(C3)大会是每年在德国举办的黑客大会,直译过来就是”混沌通信大会“,圈内通常叫”C3“,今年是第35届,所以叫35c3,今年还有CTF比赛,一些打过pwn2own的人出了一些浏览器实际漏洞的题目,也蛮具有实战价值的。

每年这大会都会以演讲视频的方式分享出各个议题,以前大多是聚焦在无线电安全,所以一些什么2G\3G\4G短信、电话窃听经常出自该会议。今年也有一些不错的软件安全相关的议题,下面推荐几个鄙人自认为不错的几个议题。

From Zero to Zero Day

image-20181230193447667

大会上有个议题叫 “From Zero to Zero Day”,演讲者是位高中生,讲述他自己如何在一年之内,从无任何安全基础到挖掘到第一枚Edge浏览器远程执行代码漏洞的经历。

总结来讲就是:

1、学习编程语言(C/C++、asm等等)

2、学习操作系统原理

3、学习常见二进制漏洞原理

4、打打CTF,写写write-up

5、学习并实践去分析真实的漏洞案例,就是直接看代码,调代码

6、不断重复上述练习

我直接帖几张关键截图,也推荐大家去听听(视频链接:https://media.ccc.de/v/35c3-9657-from_zero_to_zero_day):

image-20181230192405638

image-20181230192425929

image-20181230192131880

image-20181230192320182

image-20181230192254473

Attack Chrome IPC

image-20181230193950157

这个议题之前作者在韩国PoC大会上讲过,并在网上公布过pdf(https://data.hackinn.com/ppt/2018韩国POC安全大会/ned.pdf),主要讲他之前在Hack2Win bevx黑客大赛上用于黑掉Chrome浏览器的IPC漏洞,此次C3大会的演讲视频参见:https://media.ccc.de/v/35c3-9579-attacking_chrome_ipc

这议题里面讲了作者一些研究二进制漏洞的一些学习和研究的方法,比如做代码审计、打CTF,也介绍了他这几年的安全研究历程,比国内流行晒crash+CVE的方式更接地气。

最后介绍如何使用 libfuzzer+libprotobuf-mutator去fuzz chrome IPC,并开源fuzzer代码合并到chroium项目中。

image-20181230194648886

Jailbreaking iOS From past to present

image-20181230202552499

讲iOS越狱发展史的,可以学习到iOS上各种安全机制的原理以及绕过方法,画了不少原理图,通俗易懂不少。对于想了解整个iOS越狱技术发展历程的同学,这确实是份不错的资料。

作者这次也在推持上放出了pdf和视频:

pdf: https://api.tihmstar.net/35c3slides.pdf

video: https://media.ccc.de/v/35c3-9618-jailbreaking_ios

整个议题主要围绕以下几点展开:

  • 越狱类型(非完美越狱、完美越狱……)
  • Exploit mitigations (ASLR, iBoot-level AES, KPP, KTRR, PAC)
  • Kernel patches (h3lix)
  • Kppless jailbreaks
  • 越狱的未来趋势

The Layman’s Guide to Zero-Day Engineering

image-20181230211151217

Ret2公司分享如何寻找webkit攻击面并fuzz的方法,是基于MozillaSecurity的dharma语法生成框架写的js fuzzer,以及如何借助IDA+Lighthouse开源插件(正是Ret2团队开发的,曾获得过IDA插件比赛的二等奖)来分析代码覆盖率问题。

除此之外,也介绍如何利用frida去hook mach_msg,用来fuzz WindowServer,最后用WindowServer的漏洞来实现root提权。

他们在其博客(https://blog.ret2.io)上也分享过不少漏洞研究方面的干货,这次分享的内容也大部分就是来自博客上的一些文章。

里面还提到长亭的real world ctf比赛了。

这里有张比较有意思的图,发出来给大伙看下:

image-20181230213304029

视频链接:https://media.ccc.de/v/35c3-9979-the_layman_s_guide_to_zero-day_engineering

Modern Windows Userspace Exploitation

image-20181230214817405

视频链接:https://media.ccc.de/v/35c3-9660-modern_windows_userspace_exploitation

微软MSRC的人过来分享下windows平台下的一些二进制漏洞利用方法,包括ROP绕过DEP、信息泄露绕过ASLR、绕过CFG、ACG、CIG等等,并现场给了一些演示,不过看起来像是一些CTF赛题,演示的相关代码已放在作者的github上:https://github.com/saaramar

都是一些利用系统漏洞防御技术的原理与绕过技术的总结,连各种漏洞缓解机制绕过的微软奖励都给大家标注上了,其实有点类似上面Jailbreaking iOS议题的Windows版本。

最后来张Exploit Mitigations清单:

image-20181230215938958

结语

后面官方可能还会继续更新演讲视频,可以关注官方twitter(@c3voc_releases)获取消息。

另外,对于英语不好的同学,不妨下个”腾讯翻译“同声翻译试下,虽然中文翻译没那么准确,但看看显示的英文单词也能知道个大意:

image-20181230195201468

2018年读过的书

从2018年开始一直坚持每月读2本书以上,庆幸自己坚持下来了,共读了38本书,也希望明年能够继续坚持。

有些是实体书,有些是在微信读书上看的电子版,在手机app上看书确实会高效很多,今年有一半的书是在微信读书上看的,非常适合空闲时间阅读,以及像坐地铁、等地铁这种零碎的时间。

下面是我今年读过的书单,分别都打个分数,8分及以上的代表推荐,6分以下的别看:

  1. 《人性的弱点》(6分)
  2. 《代码整洁之道》(8分)
  3. 《如何阅读一本书》(8分)
  4. 《两晋南北朝那些事》(7分)
  5. 《软技能:代码之外的生存指南》(8分)
  6. 《秋叶:如何高效读懂一本书》(6分)
  7. 《横向领导力》(7分)
  8. 《程序员成长课》(8分)
  9. 《英语写作手册》(8分)
  10. 《爆款文案》(7分)
  11. 《运营之光》(8分)
  12. 《威胁建模》(7分)
  13. 《程序员的英语》(7分)
  14. 《冰鉴全鉴》(2分)
  15. 《内向者沟通圣经》(4分)
  16. 《灰度决策》(4分)
  17. 《启功行书技法》(8分)
  18. 《见识》(9分)
  19. 《半小时漫画中国史1、2》(7分)
  20. 《Web安全之机器学习入门》(6分)
  21. 《秦崩》(8分)
  22. 《启功给你讲书法》(8分)
  23. 《思考,快与慢》(10分)
  24. 《三国志》(8分)
  25. 《季羡林谈写作》(6分)
  26. 《Android应用安全防护与逆向分析》(7分)
  27. 《精进:如何成为一个很厉害的人》(8分)
  28. 《非暴力沟通》(9分)
  29. 《系统架构设计》(7分)
  30. 《人人都是产品经理》(8分)
  31. 《漏洞》(7分)
  32. 《风格感觉:21世纪写作指南》(8分)
  33. 《态度》(8分)
  34. 《高效阅读》(5分)
  35. 《写给大家看的设计书》(10分)
  36. 《硅谷钢铁侠:埃隆·马斯克的冒险人生》(8分)
  37. 《八卦医学史2》(6分)
  38. 《从0到1:开启商业与未来的秘密》(7分)

所以8分以上的推荐书籍有:

《代码整洁之道》(8分)

《如何阅读一本书》(8分)

《软技能:代码之外的生存指南》(8分)

《程序员成长课》(8分)

《英语写作手册》(8分)

《运营之光》(8分)

《启功行书技法》(8分)

《见识》(9分)

《秦崩》(8分)

《启功给你讲书法》(8分)

《思考,快与慢》(10分)

《三国志》(8分)

《精进:如何成为一个很厉害的人》(8分)

《非暴力沟通》(9分)

《人人都是产品经理》(8分)

《风格感觉:21世纪写作指南》(8分)

《态度》(8分)

《写给大家看的设计书》(10分)

《硅谷钢铁侠:埃隆·马斯克的冒险人生》(8分)