我们会回来 We'll come back.
下一位演讲者是MaxVanAmerigon也被称为myexploit our next presenter is Max Van Amerigon otherwise known as my exploit.
他把他的标题动作说浏览器向下 He stuck his title Actions speak browser downwards,
利用末日来娱乐和盈利 exploiting end days for fun and profit.
非常感谢数学老师对直肠村的支持和对灰帽村的支持 Thank you so much math for supporting the rectum village for supporting grey hat,
言归正传 and without any further ado,
地板是你的 你可以把它带走 the floor is yours to take it away.
好吧 All right,
欢迎来到我关于利用浏览器的演讲 welcome to my talk on exploiting browser and days now.
我在这里说过 这是为了好玩和盈利 I said here that it's for fun and profit,
但这是用词不当 but that's kind of a misnomer,
因为整个过程只会带来痛苦和绝望 because this entire process causes nothing but pain and despair.
所以这是一个很好的开始 我是谁 一个Max或者更广为人知的剥削 So it's all good talk start who am I well a Max or better known as an exploit,
安全研究员Fsecure a security researcher F secure,
这意味着我可以做很多很酷的事情 which means I get to do a lot of really cool things,
我住在多雨的英格兰 and I live all over in rainy England.
我也在sql爱点自己的团队 I'm also on the sql loves Point own team.
我去年参加了东京的比赛 I got to participate in the Tokyo contest last year.
过几天我还会去那里 and I'll be there in a few days again,
但这一次我的主要爱好是浏览器和种族 but this time in a remote pastilles my main passions are browsers and races,
这似乎是两个截然不同的极端 and that might seem like opposite ends of the spectrum,
但我在嵌入式设备中见过一些Javascript解释器 这不是一个漂亮的景象 but I have seen a few Javascript interpreters in embedded devices and it's not a pretty sight.
今天我要讲些什么呢 So what am I going to be talking about today?
最近 Well recently,
我分析了她的两个浏览器漏洞 I analyzed in her exploits for two different browser vulnerabilities,
一个在InternetExplorer 一个在Firefox one in Internet Explorer and one in Firefox.
这就是他们的故事 So these are their stories.
我要讲一下这些弱点 I'm going to go over the vulnerabilities,
他是如何开始观察它们的 我是如何最终利用它们 并希望能给大家一些萨尔萨舞的经验教训 从整个过程中吸取教训 how he began looking at them and how I ended up exploiting them and hopefully give some salsa lessons That should be taken away from the entire process.
我还会避免使用太多的代码截图 I'm also going to avoid using too many code screenshots,
我指的是巨大的海港 and by that I mean giant blocks of seaports.
Plosser集合没有任何上下文 Plosser assembly without any context,
因为它有点失败 because it kind of defeats,
演讲的目的 the purpose of the talk.
如果唯一能理解我所展示的东西的人 If the only people that are going to understand what I'm showing,
所有已经非常了解这些系统的人 all the people who already have a very intimate knowledge of these systems.
我还漏掉了一些信息 I've also left out a couple of bits of information,
因为这些漏洞在一次谈话中可能会变得有些沉重 because these vulnerabilities can get a little bit heavy for a single talk.
但如果你对填补空缺感兴趣 But if you're interested in filling in some gaps,
很高兴阅读我那篇晦涩的实验室博客文章 如果你有问题 请给我发一条Twitter消息 pleased to read my obscure labs blog post and always send me a Twitter message if you've got questions.
最后 Finally,
这是一个激动人心的故事 在这个故事里 我可能因为嘲笑APC而惹恼了他们 this is an exciting tale in which I probably upset an APC by mocking them.
所以 当你可以装腔作态的时候 你为什么还要费心去写和利用呢 So why would you bother writing and exploits when you could just pose for zero days?
好吧 Well,
迫使一个利用 forcing an exploit?
人们常常把发展看作是同一件事的一部分 Development are often seen by people as part of the same thing.
虽然这是真的 and while that's true.
有 There are,
事实上 in fact,
两种截然不同的技能 two very different skill sets.
我们很容易假设浏览器的每次崩溃都是可以利用的 It's easy to assume that every crash in a browser is exploitable,
但事实并非如此 but that's really just not the case.
如果你理解了代码基于你可以操作它的方式 and if you understand the code based on the ways in which you can manipulate it,
你可以找出从一些崩溃到攻击的方法 you can figure out the ways in which you can go from some crashes into an exploit.
如果你知道如何在特定环境中触发崩溃 It's also really useful to note that if you know how to trigger crashes in a particular environment,
你可以用不同的方式构造测试用例 you can actually use this with your own father's by structuring test cases in different ways,
这可能会导致你发现不同的错误 你可能没有其他法庭 因为他们没有真正做任何值得注意的事情 and this could lead to you finding different bugs that you may not have otherwise court because they weren't really doing anything noticeable.
另一个原因是 实际上恒天然只是在利用漏洞 Another reason is that it's actually just really Fonterra exploits for bugs.
你们大多数人都知道没有什么比得到细胞更好的感觉了 Most of you know how there's really no better feeling than getting cell,
这只是一种更好的方式 and that's just a way better.
当你自己写这些的时候 When you write these exploits yourself.
最后 And finally,
这是伟大的建议 it's great suggest,
花点时间在这上面 invest time into this,
即使你不是为了工作才这么做 even if you don't do it for for a job,
我相信你们中的很多人都遇到过一个在交战中没有公开攻击的目标的弱点 I'm sure many of you have come across a vulnerability in a target during an engagement where there have been no public exploits.
为它 For it.
利用开发让你有机会变得有点创意和DIY An exploit development gives you the chance to get a bit creative and DIY,
用它 with it.
所以 So,
就像我说的 as I said,
这里有两个漏洞一个是ie的漏洞 一个是火狐的蝴蝶结 there were two bugs here there's an Internet Explorer bug and a Firefox bow.
ie的错误是免费用户的错误Firefox的错误是jit的错误 Now the Internet Explorer bug was a user of the free and the Firefox bug was a jit bug.
那么整件事的风格是怎样的呢 So how did this whole thing style?
好吧 Well,
我在推特上浏览 我看到一条关于这个虫子的推文 可以看到Be两千二或者三十 I was scrolling through Twitter and I saw a tweet about this bug could see B e two thousand and twenty or thirty,
6 six,
7 seven,
4 four,
据说是在野外使用的 which was supposedly used it in the wild.
早在1月 Back in January.
现在 Now,
因为我对浏览器的单相思 since I have an unrequited love of browsers,
我想我应该调查一下尽管我没有在J身上花太多时间 I thought I'd have a look into it despite not really spending any time on J.
脚本和样式 Scripts and styles.
之前 Previously.
所以我知道J脚本有点问题 So I knew there was a bug in J scripts somewhat,
但在这一点上 对于我和那些没有真正听说过Javascript黄色的人来说 这个引擎几乎是一个黑盒子 它是旧版本ie中使用的遗留Javascript引擎 but at this point the engine was pretty much a black box for me and for those who haven't really heard of Javascript yellow before it's the legacy Javascript engine that was used in old versions of Internet Explorer.
然而 However,
从兼容性角度看 for compatibility reasons,
这也是现在人们使用ie浏览器的唯一原因 which is the only reason anyone would ever use Internet Explorer these days,
网站可以加载它而不是一个新的引擎叫做JScript websites can actually cause it to be loaded instead of a new engine which is called J Script.
9点黄色 Nine dotted yellow,
这可以通过一些奇怪的操作来实现 and this can be done by doing some weird,
仓促 hasty,
更多的魔法 more magic.
佩奇的修道士们 So the monks of page,
当然 of course,
只是复制和粘贴的感觉就像是在某个地方的某个漏洞做了一些事情 just had the usual copy and paste feel about a beheading some vulnerability in some place that does some things,
但是这里没有真实的信息 but there's no real information there.
所以我转向了发现的来源 So I turned to the source of the discovery,
这是关键 which is key,
谁 who,
直到60岁 他写了一篇关于这次袭击的非常棒的博客文章 through sixty who had written a really great blog posts on this attack,
他们称它为双星攻击 因为它针对的是不同的浏览器 and they had called it the Double Star attack because it was targeting to different browsers.
这篇博文实际上包含了一小段代码 Now this blog post actually contained a small code snippet,
表明阵列点原型存在漏洞 which showed the vulnerability in the array dot prototype.
这类函数 That sort function.
现在我有 Now I have.
谷歌为普通话不太流利的人翻译了这条评论 Google translated the comment here for people who aren't super fluent in Mandarin,
它基本上说释放比较器函数中的变量A和B不会被垃圾收集器跟踪 and it basically says that the variables A and B in the function freeing comparator are not tracked by the garbage collector.
所以我做了你在这种情况下会做的任何研究 So I did what any research you would do in this sort of situation,
我深深跳入水中 期待着最好的结果 and I dove in deep and hope for the best.
所以我做的第一件事就是我从更新目录的标记中得到了两个版本的Jay sGroup So the first thing I did was I got both versions of Jay's Group from the marks of update catalogue,
这是一个很好的资源 which is a really great resource.
如果你想为mac做一些人事安排 If you want to do pat staffing for Macs of things.
然后我取了符号在二进制忍者中 Then I fetched the symbols so in binary Ninja,
这里有一个很好的选择 there's a really nice option for this in the same with either,
如果你在用deidre if you're using deidre,
如果您自己的窗口 这很容易做到 it's easily done if your own windows.
但如果你在其他主机上 but if you are on any other host,
虽然我还是要跑进去 though I still going to run in.
有些问题需要vm来代替 Some problems are going to need a vm instead.
接下来我做的是对两个版本进行差异调试 So the next thing I did was differential debugging against both versions,
在这里 你可以跟踪两个版本的执行情况 以找出发生了什么变化 and this is where you trace the execution of both versions to figure out what's changed.
为此 我使用了右边的这些小脚本 So for this I was using these small scripts on the right,
这或多或少会引发漏洞 which is supposed to trigger the vulnerability more or less.
另一种很有用的技术叫做二进制差异有很多很棒的工具 So the other really useful technique is called binary differing and there are lots of really great tools for this out there,
但无论是主对我们亲爱的论坛 都是聋子 but for either the main to our dear fora and been deaf.
我将此与差异调试结合起来 以找出两个经销商之间的这些变化中 哪一个实际上与函数的执行有关 And I use this in conjunction with differential debugging to figure out which of these many changes between the two dealers were actually relevant to the execution of the function.
这两种方法说明Javascript函数代码中有很多折射 So these two methods showed that there was a bunch of refraction done to the A Javascript function Cool code,
但其中一个关键点是添加了一个名为ScabVarList的新对象 but one of the key points was the addition of a new object called Scab Var List,
意思是拾荒 which stands for scavenge,
变量列表 variable list.
这个对象的初始化调用了一个函数IceScavengerBase链接到dc And the initialization of this object calls a function called Ice Scavenger Base linked to D C,
哪一个 which,
你可以想象 as you can imagine,
将东西链接到垃圾收集器 links things to the garbage collector.
所以在这一点上 以某种方式验证你的发现总是好的 So at this point is always good to verify your findings in some way.
所以对我来说 So for me,
我在scab中设置了一个断点 I set a breakpoint on the link to G C call in the scab,
Var列表初始化 Var list initialization,
当它到达时 我跳过了它 and then I skipped over it when it was reached.
这就触发了脆弱性 而目标 and this caused the vulnerability to be triggered and the target,
那次坠机证实了我的假设 the crash which had verified my assumptions.
所以我提到了从队列到60的帖子关于这个bug So I mentioned from the queue through sixty post a little bit about the bug.
我们知道它与垃圾收集器有关 以及它如何跟踪数组post类型排序函数调用中的一些参数 We know that it's related to the garbage collector and how its tracking some of the arguments in the array post type sort function call.
我们知道 如果一个物体没有被追踪 And we know that if an object isn't being tracked,
垃圾收集器冷却后 它会被释放 then it's gonna be freed when the garbage collector is cooled.
让我们快速地看一下它是什么样的 So let's say a quick overview of what that sort of looks like.
假设我们创建了一个对象 Let's say we create an object.
有了这个代码 and with this code,
我们有一个变量 we've got a variable,
A指向这个物体 A which points to this object.
如果我们创建第二个变量 If we create a second variable,
可以让它指向a点使得a和B指向同一个物体 could be and have it points at the point of a than both A and B will point to the same object.
现在我们总是知道变量本身什么时候在作用域内什么时候不在作用域内 Now we always know when variables themselves are going to be within the scope and where they're going out of scope.
例如 For example,
如果用let声明的变量只对当前的代码博客有效 if the variables declared with let that means is only going to be valid for the current code blog.
但是物体有点不同 But objects are a bit different,
所以说 so say,
当A和B都达到其作用域的尽头并被移除时 when A and B both reached the end of their scope and are removed.
我们怎么知道它们引用的对象没有被另一个变量引用 How do we know that the objects that they reference aren't being referenced by another variable,
这就是垃圾收集器应该考虑的 and this is what the garbage collector is supposed to take into account.
Javascript垃圾收集器实际上分三个阶段完成 So the Javascript garbage collector is actually done in three stages.
第一个阶段是标记阶段 The first stage is the mark stage,
它标记所有的对象已准备好被垃圾收集 which marks all the objects is ready to be garbage collected.
第二阶段是清道夫阶段这个没有标记的 The second stage is the scavenger stage and this unmarked,
所有被变量引用的对象 然后在每个对象上 all objects that are referenced by variables and then on each of these objects.
它会调用scavenge函数scavenge函数基本上被对象用来说明它们引用了哪些对象 It will call the scavenge function ah now the scavenge function is basically used by objects to say which objects that they reference.
所以 So,
例如 for example,
如果我有一个名为Dog的对象 它有一个名为Name的属性 if I had a an object called Dog and it had a property called Name.
在stock对象上调用清理后的函数时 When the scavenged function is called on the stock object,
它还需要说OK it would need to say OK also,
然后标记这个物体 and mark the object.
这是名义上的 因为我还在用它 That's in name because I'm still using it.
现在 Now,
最后 finally,
回收阶段将释放任何仍被标记的对象 the reclaim stage will free any objects that are still marked.
让我们看看原型排序函数的数组会发生什么 So let's have a look at what happens with the array of prototypes sort function.
而mock阶段则标记作为函数参数提供的对象 While the mock stage marks the object that's been given as an argument to the function.
鞘阶段 The scabbard stage,
然而 however,
因为被其中一个参数引用 所以应该打开该对象 is supposed to unmask this object since is referenced by one of the arguments.
但是由于该参数没有被垃圾收集器跟踪 But since the argument isn't being tracked by the garbage collector,
这是从来没有无名 it's never unmarked.
这意味着当回收阶段发生时 And this means that when the reclaim stage happens,
这个对象被释放 而A作为一个悬浮指针留下 this object's freed and A's left as a dangling pointer.
这就是我们如何得到我们的免费使用 And that's how we get our use of the free.
现在 Now,
为了真正利用这个漏洞 in order to actually exploit this bug,
隧道中的Javascript引擎至少需要被理解 the Javascript engine in tunnels needs to be at least understood.
少 Little.
就像攻击任何语言一样 And like attacking any language,
这涉及到一些关键的事情 比如理解 this kind of involves a few key things like understanding,
变量 variables,
对象表示 object representation,
堆分配和垃圾收集 heap allocation and garbage collection.
自我 Self.
现在你不需要知道所有的事情 Now you don't need to know everything,
这一点我再强调也不为过 and I really can't stress this enough.
很多人看到像这样复杂的目标就会感到很不高兴 因为它们实在太大了 A lot of people get very put off by looking at complex targets like this because of the sheer size of them.
但即使有一个盘子 But even with a plate,
百分之四十的理解你仍然可以相当熟练地攻击目标 forty percent understanding you could still be quite proficient and attacking a target.
一旦他也达到了这一点 And once he reached that point as well,
通过回顾过去 找出你不了解我的地方要容易得多 it's a lot easier to start figuring out the parts that you don't know me by looking at the past that you do.
Javascript中的变量是什么样的呢 So what are variables look like in Javascript?
好吧 Well,
它们由一个叫做Var的结构表示 they're represented by a structure called a Var,
它们在记忆中是这样的 and they look like this in memory.
每个条有三个分量有变量的类型 There are three components to each bar there's the type of the variable,
不管它是浮点数的字符串还是数组 and that's whether it's a string of float or an array,
作为对象指针 as the object pointer,
哪一个 which,
顾名思义 as the name suggests,
指向物体 points to the object.
但值得注意的是 如果Var类型是整数 But it's worth noting that if the Var type is for an integer,
那么这就不是一个指针了 then this isn't going to be a pointer.
它会被用作数字的内联存储 It's going to be used as inline storage for the number.
下一个文件指针并不总是被使用 Now the next file pointer isn't always used,
一般来说 这和这个bug没什么关系 and it's kind of pretty irrelevant for this bug in general,
所以这并不是一个很大的点 so it's not really a huge amount point going into it.
内存中的对象有两种类型 Now objects in memory come in two types you've got natives,
还有非当地人 and you got non natives.
所以当地人 So natives,
也被称为内建 also known as built ins,
被编入引擎本身 are programmed into the engine themselves,
这就像废品 so this is things like rejects,
P日期或数组 P date or an array.
非本地语言是指那些由Javascript编程的语言 And non natives are those that are programmed by Javascript,
Javascript开发者 the Javascript developer so,
例如 for example,
之前我举了非本土狗的例子 earlier I gave the example of the dog that would be a non native,
因为是我编的程序 because it's programmed by me,
Javascript开发人员 the Javascript developer.
现在我们可以释放变量 用另一个重新分配 Now we could free our variable and reallocated with another one,
但这没什么用除了让变量a的类型和以前不同 but that wouldn't really do much except made variable a a different type than it was before.
这对我们来说没什么用 And that doesn't really do anything useful for us.
所以另一种方法是用一些不同的更能控制的东西来取代这整个体积 So an alternative is to replace this entire volume with something that's different and more within our control.
当对象有属性时 And when objects have properties,
它们储存在一个叫做活体的结构中 they're stored in this structure called a vivo.
这个结构的长度是可变的 因为底部有SDR成员的名字 and this structure has a variable length because of the name SDR member at the bottom,
存储属性名称的 which stores the property name.
这使得它成为重新分配的完美选择 and this makes it a perfect choice for reallocation,
因为我们可以有选择地选择我们想要的大小 because we can both selectively choose the size we want it to be,
我们可以使用名称来选择内容 and we can choose the contents using the name.
字符串 string.
这是 And this is,
我想你也会在chromium漏洞中看到很多免费bug 其中Blob类型被用来重新分配东西 I think you'll see a lot in chromium exploits as well for use after free bugs in which the Blob type is used to reallocate things.
出于同样的原因 for these exact same reasons.
堆分配的关键部分之一是gc块结构 So one of the key parts of heap allocations is the G C block structure,
它能装上百个花瓶 which holds an array of up to a hundred vase.
现在 Now,
当自由后的使用发生时 when the use after free happens,
变量a我们之前叫它 the variable a as we call it earlier,
会指向这个区域的某个地方 willl actually point somewhere within this region.
现在我们需要释放整个gc块结构并在其上重新分配相同大小的东西 Now we need to free this entire gc block structure and reallocate on top of it with something of equal size,
但对我们更有用的东西 but something more useful to us,
这就是运载工具的来源 and that's where the vehicle comes.
在 in.
对于大多数Javascript引擎 Now with most Javascript engines,
如果你想触发垃圾收集器 if you want to trigger the garbage collector,
您需要通过创建大量对象来完成此任务 直到垃圾收集器完成 you need to do it by creating lots of objects until the garbage collector's cord.
但对于我们这些有幸利用同性恋脚本的人来说 But for those of us that are lucky enough to be exploiting gay script.
我们有一个很方便的函数叫做collectgarbage We've actually got a handy function which is called collect garbage,
它会在任何我们想要的时候运行垃圾收集器 and this will run the garbage collector whenever we want it to.
所以在这一点上我们已经得到了所有我们需要利用这个漏洞的部分 So at this point we've got all the pieces we need to ride the exploit for this bug,
所以过程很简单 so the process of them pretty straightforward.
所以我们做的第一件事是我们创造了大量的无迹花瓶然后我们用这些来填充一堆GC块结构我们会慢慢来 So first thing we do is we create a large number of untracked vase and then we use these to fill a bunch of G C block structures and we will slow.
这些未追踪的下落在一个数组中 These untracked falls in an array.
接下来我们调用垃圾收集器 Now the next thing we do is we call the garbage collector,
我们释放了所有创建的对象 将未跟踪的指针留在这个关节自由区域 which we're free all of the created objects and leave the untracked pointers in this joint free region.
接下来 Next,
我们使用重新分配 在我们的体内这样做 we use reallocation and we do this with our vivo.
现在您注意到 没有重新分配整个空闲空间 Now you notice that the entire free space was not reallocated.
原因是用于分配雌性的分配器被称为pvr运气它实际上只是分配了一大块空间所以当我们创建更多属性时 And the reason for this is that the allocator that's used for allocating females is called pvr luck and it actually just allocates a large chunk of space so that when we create more properties,
分配器不必经历分配更多内存的过程 the allocator doesn't have to go through the process of allocating more memory.
它只是返回一个指向下一个空闲空间的指针 It just returns a pointer to the next free space.
这对我们以后会很重要 And this is actually going to be quite crucial for us later.
我们将在这里使用的属性名本身被分解为几个部分 So the property name itself that we're going to be using here is broken down into several parts.
有八个字节的填充 There's eight bytes of padding,
我们用这个来对齐 and we use this in order to align.
我们的假的将会在哪里 真正的vars将会在哪里 where are fake of ours are going to be with where the real vars are expected to be in the G?
C块 C block.
下一部分是我们用字符串写的far The next part is the fake far which we've written as a string,
你注意到这些数字是用印度字节顺序表示的 and you notice that the numbers are represent represented in little Indian byte order,
因为这就是它们在内存中的期望 because that's how they are expected to be in memory.
第三部分是我们用的是假的far And the third part is that we're using this fake far,
我们正在复制它 and we're copying it.
直到达到我们想要的大小 Until we reached the desired size.
这将使PVAlaric分配的gc错误大小与此相似 That will make PV Alaric allocate a similar sized the gc bug.
现在接下来 Now next,
我们想遍历未跟踪的花瓶 检查其中哪些是数字 哪些也有值 we want to iterate over our untracked vase and check which of them are numbers and also have the value.
一个 One,
两个 two,
三 three,
四 four.
你可能会想 如果我们只想知道值 为什么还要检查类型呢 And you might be wondering why we're even bothering checking the type if we just want to know the value.
原因是 and the reason for that is,
比方说 let's say,
一份未被追踪的数据现在指向了垃圾数据 an untracked far now points to junk data.
那么 Well then,
如果关键部分的垃圾数据让它认为它是一个对象当它尝试引用时 对象指针中也会有垃圾数据 if the junk data in the vital part makes it think that it's an objects and there's going to be junk data in the object pointer when it tries to do reference,
这个值会崩溃 因为它不是一个真正的内存地址 That value is just going to crash because it's not a real memory address.
这就是我们首先检查Var类型的原因 So this is why we check the Var type first,
所以这一点 so that.
这样我们就不会引用这种不好的值 So that we don't cause this sort of bad value to be referenced.
所以在这一点上 So at this point,
我们已经设法引起了类型混淆 其中命名为string的属性被视为附属物 we've managed to cause a type confusion in which a property named string has been treated as a vassal.
现在我们可以用属性名重新分配对象 用各种假文件替换我们所选择的未跟踪Var的值 And we can now reallocate the object with the property name to replace the value of our chosen untracked Var with varying fake files.
所以目前 So currently,
由于单反的工作原理 because of how SLR works,
我们不知道记忆的位置 we don't know where in memory are,
物体会被定位 objects are going to be located.
所以他有两个选择 So there are two choices here for him,
对于泄漏 for leaks,
但我最喜欢的也是我将要使用的是将下一个代理点泄漏出飞行器 but my favourite one and the one that I'm going to use is to leak the next proxy points out of the vehicle,
这实际上是一项关于眼睛的技术 and this is actually a technique that was the eye.
我看到伊凡·弗雷德里克使用 I saw Ivan Frederick using.
如果你们中的任何人 and if any of you,
当我不得不更深入地研究J脚本的时候 我想要释放向导写的所有东西 因为这些东西都太棒了 when I have to do even more deep diving into J scripts pretty much to freed anything that guide written because it's all fantastic.
工作 work.
让我们再来看看发烧 So let's take another look at the fever.
这里我们看到有一个哈希 一个名称长度和下一个属性指针 Here we see that there's a hash a name length and a next property pointer.
散列用于快速比较namestr 而不需要逐个字节进行比较 And the hash is used to quickly compare the name str without having to do a byte by byte comparison.
例如 For example,
如果我创建一个有属性名的对象 if I create an object with a property name,
那有1000个字符那么长 that's a thousand characters long.
你可以想象每次尝试比较时 You can imagine that each time trying to compare,
这需要很长时间 it's going to take a very long time.
在这种情况下 So in that instance,
使用散列值要快得多 is much faster to use the hash value.
然后是长度 And then we have the name length,
它指定了名称STR的长度 下一个支柱指出的是指向下一个活体的指针 which specifies the length of the name STR and the next prop points out is the pointer to the next vivo.
所以 So,
例如 for example,
如果我有一个属性为A和B的物体 if I have an object with properties A and B,
下一个支柱点在V(A)中指向B的运载工具 the next prop points are in the V of A IS going to point to the vehicle for B.
现在哈希和名字长度都是四个字节 Now the hash and the name length are both four bytes,
这意味着它们被放在一起 形成一个单独的字节值 which means that they are placed next to each other to make a single a byte value.
然而 However,
因为电压值只期望为4字节 because the voltage value is only expected to be four bytes,
这意味着只对事件类型使用散列 this means that only the hash is used for the event type.
假设我们创建了一个对象 So let's say that we create an object.
我们有一段未被追踪的距离 we have an untracked far,
它指向的是交通工具的哈希值 and it's pointing to the hash value of a vehicle.
该位置的对象指针随后将与下一个农作物指针处于同一点 The object pointer of the location would then be at the same point as the next crop pointer.
如果哈希值以5结尾 So if we have the value of the hash ending up at the value five,
这是阀门类型四是64位浮子 which is the valve type four is sixty four bit float.
然后我们可以将下一个带进来的指针读取为一个浮点值 Then we could read the next brought pointer in line as a float value,
这将揭示部分pvr缺少区域的内存地址 and this would reveal the memory address of part of the pvr lacked region.
哈希算法本身很简单 我们可以用一个字符名来控制它 Now the hash algorithm itself is really simple We can actually just control it by using a single one character name.
在这个例子中 So in this instance,
只有值X的属性名所以5就是生成哈希值4或5的属性名 the property name with just the value of X so five would be the one that generates the hash four or five.
让我们从原来的地方开始 So let's start where we were.
我们创建了结构的视图 We create our view of our structure,
这会导致在gc块上分配你 which causes an allocation of thee on top of the gc block,
然后这里的属性名也将用于对齐水平 以便这个第二个活体的哈希 and then the property name here will also be used to align the level so that the hash of this second vivo.
我将被处理为阀门类型的跟踪指针 I will be treated as the valve type by an ontrack pointer.
接下来 Next,
我们又创建了两个属性 we create two more properties.
第一个必须是单个字符的名称 The first will have to be a single character name,
说它的哈希是外面的5 said its hash is the outer five.
我们创造的第二件事是让五边形的橡树地产 And the second we create is so that the oaks of fives property,
它是体内 it's vivo.
我们将有一个有效的下一个道具指针 We'll have a valid next prop pointer.
接下来我们遍历指针直到得到浮点值 And next we iterate over are on track pointers until we get a float value.
因为我们知道我们唯一的浮点值是下一个指针 and since we know that the only float value we have is going to be the next pointer,
我们用的就是这个 That's what we use.
从这里我们可以计算未跟踪距离的偏移量因为它总是静态的 So from here we can calculate the offsets the untracked far because it's always going to be static.
这将给我们带来敬畏的地址 And this will give us the address of awe on track.
下降 fall.
现在 Now,
既然我们现在知道自己在记忆中的位置 since we now know where in memory we are,
我们可以构造两个重要的原语 即读原语和原语的另一个原语 we can construct two important primitives and that's the read primitive and the other of primitive.
现在 读 Now read is,
当然是用来读取任意内存位置的 of course used to read arbitrary memory locations,
阿拉伯语是用来获取物体的地址 and Arab is used to get the address of objects.
现在 Now,
和大多数其他的壮举一样 with most other exploits,
你可能需要一个正确的原语 you'd probably need a right primitive,
但这次我不需要它 but for this one I didn't need it.
读原语实际上很简单 So the read primitive is actually pretty straightforward.
你只需要知道字符串是如何工作的 You just need to know how strings work.
以这一行Javascript为例 Take this Javascript line.
我们创建一个他们签名的可变SDR We create a variable SDR which they signed.
绳子可能是安全的 The string may be safe.
现在STR Now STR is,
当然会用病毒结构来表示字符串的阀门类型是8 of course going to be represented by a virus structure and the valve type for a string is eight.
现在对象直接指向字符串和实际字符串用作字符串长度之前的四个字节 Now the object's points directly to the string and the four bytes before our actual string is used for the length of the string.
这种布局被称为aBSDR And this layout is called a B SDR,
马歇尔发明的很多东西中都用到它 and it's actually used in a lot of things that Marshall developed.
你会注意到这个字符串的长度是6个字符 而abc只有3个字符 You'll notice that the size of this string says that its six characters long but A B C is just three characters,
这是因为年轻的Javascript字符串有16 而不是8 and this is down to the fact that Javascript strings are youths have sixteen instead of beauty of eight,
这意味着每个字符有两个字节 而不是一个 which means that we have two bytes per character instead of one.
然而 However,
它们的beSDR结构实际上是以字节来度量的 their be SDR structure actually measured things in bytes.
因此 我们可以使用SDRdockcaracoledup来获取位置开始处的字符ascii值 So we can use the SDR dock caracoled up to get the character ascii value at the start of the location.
换句话说 So in other words,
我们梦想我们的第一口 we dream our first bite.
我们现在需要做的就是点 And all we need to do now is point.
绳子指向目标 The string pointed out to the target.
穿你想读的衣服很好 dress you wanna read great.
啊 Ah,
好吧 well,
事实证明 这实际上是行不通的 it turns out that this doesn't actually work.
因为我们不能直接将对象指向目标地址因为SDR大小最终可能是no Because we can't just set the object points to the target address because the SDR size could end up being no,
这意味着字符Kodakzero实际上不会返回任何东西 除了undefined which means that character Kodak zero wouldn't actually return anything except undefined.
因为弦看起来没有长度 Because the string has seen as having no length.
我们能做的就是用长度来读取内存 What we can do is use the length to read memory.
让我们再来看看我们的记忆 So let's look at our memory loud again.
所以我们把字符串指针改为比目标地址早四个字节 这样交易就会 So we changed the string pointer to four bytes ahead of the target address so that the deal would,
目标地址现在位于SDR的长度部分中 at the target address is now in the length part of the SDR.
我们可以读取它的值 然后获取字符串的长度 We can read its value by then fetching the length of the string.
但实际上 But really,
我们现在要做的是 what we're doing here is we're getting the?
字符串I除以2是因为转换率除以2意味着右移一天 The strings I is divided by two because of the conversion rate and divided by two just means shifting right by one day.
假设它会在目标地址上添加两个字节 So say it will add two bites at the target address.
然后我们再移动7位 这样我们就得到了一行完整的字节 而不是一个位 Then we shift along seven more bits so that we have a line of full bytes instead of just a single bit.
它们会沿着另外8位移动 这样我们的目标by就在值的最不重要的位上 And they will shift along another eight bits so that our target by is in the least significant bits of the value.
然后我们可以过滤掉所有的咬通过使用bitwhatbitwiseAnd运算符 And then we can filter out all bite by using bit what the bit wise and operator.
这看起来可能有点让人困惑所以这是一种不同的分解方法 Now that might have been a bit confusing to look at so his a different way of breaking it down.
这是我们的目标地址 So here we have our target address alike.
7F啊 Seven F o,
B B,
一个对一个 one for a.
现在让我们假设到目前为止我们想要读取的字节 Now let's say the byte we want to read as I worked so far.
如果我们设置弦指向那个位置 If we set the string pointed to that location,
它在记忆中是这样的 it looked like this in memory.
这意味着我们在本例中需要的值当前不在bsd中 This means that the value we want in this case for is not currently in the bsd.
我们的长度 our length.
我们有两个字节到目标地址 So we had two bytes to the target address,
这意味着所有字符串指针的地址现在是在7fo which means that the address for all string pointer is now at seven F o,
B为C B one for C.
现在 Now,
当我们得到弦的长度时 when we get the length of the string,
我们真的得到并被2除了因为美丽的8的转换 we're really getting and divided by two again because of the conversion from beauty of eight.
这些都是十六岁 These are sixteen.
所以STR点的长度等于这个 So STR dot length gives us this,
我们的目标是得到最初的四个 and our aim is to get all the four that we had originally.
现在 Now,
如你所见 as you see,
我们的数字看起来和我们期望的有点不同 our numbers are looking a little bit different to what we are expecting them to be,
这是因为字节当前没有对齐 and that's because of the bytes are currently misaligned.
我们做的第一件事就是移动七八比特 这样我们一共移动了8个出价 So the first thing we do is shift along by seven or eight bits so that we've shifted a total of eight bids.
现在他又移动了8位 所以我们移动了值中最不重要的1/4位 And now he shifted eight more bits so that we moved the fourth of the least significant bits of the value.
最后 And finally,
我们使用bitwise和操作符来得到最后一口 we use the bit wise and operator to get the last bite,
这就是你如何组装一个真正的hacky并为Javascript提供真正的原语 and that's how you put together a really hacky and offer real primitive for Javascript.
所以接下来 So next,
我们只需要一个原始的地址 we just need an address of primitive,
这其实很简单 and it turns out to be really simple.
多亏了我们的邪恶老朋友 thanks to our old friend of evil.
现在你看到在这个载体的顶部有一个Var Now you see at the top of the vehicle there is a Var,
这样做的目的是为了让属性指向事物 and the purpose of this is because properties are supposed to point to things.
到目前为止 它是用来保存财产价值的 So this far is used to hold the value of the property.
既然我们知道这个feval结构在内存中的位置 And since we know where this feval structure is going to be in memory,
感谢我们的信息联盟 thanks to our info league,
我们可以分配目标对象 we can just assign the target object,
我们不会为这个财产披上外衣 that we won't be a dress of to this property.
然后我们使用代表来读取Var的对象指针 And then we use the representative to read the object pointer of the Var.
现在 Now,
最后 finally,
我们需要执行一些代码 we have got to get some code execution going,
这其实很简单 and this actually turns out to be really simple again.
首先 First,
我们制造一个赝品 we create a fake.
C+boss对象和一个假的V表 C Plus boss object with a fake V table.
然后我们创建一个假Var指向这个假对象 Then we create a fake Var that points to this fake object,
我们确保Var类型是Alex吃了一个 and we make sure that the Var type is Alex ate one.
现在 Now,
最后 finally,
我们称这个物体的类型为 we call the type of on this object,
结果发现 花瓶的类型是出口一个 and it turns out the vase with the type of exit one.
我们会从V表中调用一个函数来获取字符串类型 we'll actually call a function from their V table in order to get the type string.
现在我们可以把它指向任何我们想要的地方 Now we can point this anywhere we want,
因为我们控制了V表 because we control the V table.
但是我们在哪里跳得太好了如果他是残疾的还是有能力的 But where do we jumped too well since the if he is disabled or enabled,
我有不同的选择 I went with a different choice,
那就是在MspCRT中做一个栈柱 and that was to do a stack pillar in Msp CRT.
堆栈溢出基本上就是一个小工具 它将受控值移动到堆栈指针中 Now stack overflow is basically just a gadget that moves the controlled value into the stack pointer,
这允许我们将堆栈移动到其他地方 and this allows us to move the stack elsewhere.
在这种情况下 So in this case,
控制值实际上是在寄存器中因为V表是如何被访问的 the controlled value was actually in a register because of how the V table is being accessed,
由于我控制了V表 and since I controlled the V table,
现在我控制了堆栈指针 I now controlled the stack pointer.
这个技术非常有用如果你在堆栈上只有有限的空间或者你有一个像这样的小工具你想要移动 So this technique is really useful if you've got a limited amount of space on the stack or you've got a single gadget like this scenario and you want to kind of move.
炉渣在别处有更多的小玩意儿 The slag elsewhere with more gadgets.
在这种情况下 So in this case,
我选择的位置是我用一堆摇滚小玩意创建的一串 the chosen location for me was a string I'd created with a bunch of rock gadgets.
在里面 in it.
岩石链从这里开始运行 So from here the rock chain executes,
贝壳就这样诞生了 and the shell is born.
所以在释放了这个利用后的一周我的同事怂恿我做一个击球手的有效载荷 So week after releasing the exploit my mates from work who kind of egged me on to make a batter payload.
所以我想要一个明显的选择 So I want the obvious choice,
这是桌面应用 which was the desktop use.
我叫它黑暗的喇叭声 and I call it dark honk.
这是因为脆弱性被归因于黑暗的酒店 and this was because the vulnerability was attributed to dark hotel,
这可能不是我最聪明的 which is probably not my smartest,
也许有一天我会后悔的 and I'm probably going to regret it one day.
但你必须享受这些小事情 But you've got to enjoy the little things.
我们继续下一部分 So let's move on to the next part.
火狐Jitbug the Firefox Jit bug,
这部分不那么激烈 this section of a little less intense,
部分原因是火狐上已经有很多资源了 partly because there are quite a lot of resources already out there on Firefox,
我讲Javascript讲了很长时间 and also because I have talked quite a long time about Javascript.
这一切都始于1月份 So this all began back in January,
当我看到一些文章 when I saw some articles about a big,
可怕的弱点 scary vulnerability.
我做的第一件事就是更新了本地壁虎 So the first thing I did was I updated my local gecko.
德弗里教皇 Devry Pope,
我快速搜索了一下bugID and I did a quick search for the bug ID,
这让我对简二十一号有了特别的承诺 and this led me to a particular commit with the date Jane First twentieth.
一千九百七十年 Nineteen seventy.
这次提交表明有两个文件被更改了 And this commit had showed that there were two files that were changed.
有最早的分析没有看到PP There was the earliest analysis don't see PP.
默多克的H And the Murdoch H.
这些都是铁猴的一部分 And these are both part of iron Monkey,
这是SpiderMonkey的jit编译器 which is the jit compiler for Spider Monkey.
对于那些不知道的人 and for those that don't know.
蜘蛛猴是Firefox的Javascript引擎 Spider Monkey is the Javascript engine in Firefox.
这里最重要的变化是在温和孵化 Now the most important change here was in moderate hatch,
这通常得到别名设置函数 因为它不再被这两个鼻子覆盖 which usually get alias set function as it was no longer overridden by these two nose.
这听起来很熟悉 And this was actually something that sounded very familiar,
所以事实证明 这实际上是一个变种的病毒 在波兰使用了小组凶猛拥有twenty19 so it turns out it was actually a variant of a bug that was used in Poland to own twenty nineteen by team ferocity.
基本上 And basically,
Jit编译器没有考虑到一些操作可能会导致副作用的事实 the Jit compiler wasn't taking into account the fact that some operations can cause side effects,
正因为如此 你可以在不考虑这些变化的情况下执行一架飞机 and because of this you can cause a jet to be executed without taking these changes into account.
在讲到剥削之前 So before going on to exploitation,
我们应该明确地涵盖基本的 就连他的喷气机或喷气机仅仅意味着及时 we should definitely cover the basics as in what even his jet or jet just means just in time.
这是一种浏览器将Javascript代码编译为汇编的技术 compilation and it's a technique where your browser compiles your Javascript code to assembly,
如果它认为可以加快速度 它就会这么做 and it does this if it thinks it can speed things up.
所以我的意思是它认为它可以加快速度如果我们有一个函数叫做热函数 So what I mean by it thinks it can speed things up is if we've got a function which is called a hot function,
一个已经被执行了大约一万次 so one that has been executed a lot like ten thousand times or so.
浏览器实际上会认为花一点计算能力会更快 The browser will actually think that it's faster to spend a little bit of computation power.
编译这个函数 因为它经常被使用 Compiling this function because it's so constantly used.
但jit不能做完后就置之不理 But jit can't just be done and then left alone,
这需要考虑很多变化 it's gonna take a lot of changes into account.
以这个函数为例 So take this function.
例如 For example,
每次运行 every time is run.
它期望参数对象既是一个对象 又有一个名为X的属性 it expects the the argument object to be both an object and have a property called X.
当这个函数被编译后 And when this function gets compiled,
它会被简化成这样 it'll essentially be reduced to something like this,
它获取属性指针 然后改变第一个属性 which gets the properties pointer and then changes the first property,
它认为这是有价值的行为 which it assumes to be acts to value.
十个 Ten.
但是如果我给函数和对象没有任何属性会发生什么呢 But what happens if I give the function and object without any properties?
好吧 Well,
在这种情况下 in this case,
编译后的代码将不再有效 the compiled code would no longer be valid,
因为这个物体没有属性 and because we have no properties on this object,
编译后的代码最终会跳出边界 the compiled code would just end up rising out of bounds.
这就是为什么jet编译器需要考虑很多事情 并监控可能导致代码无效的变化 And this is why the jet compiler needs to take lots of things into account and monitor for changes that could actually invalidate the code.
所以ironmonkey并没有马上得到这个表达式 So iron monkey doesn't immediately end up with that representation.
事实上 In fact,
大多数jit编译都与cogeneration无关 most of jit compilation has nothing to do with cogeneration,
但主要是关于程序分析 but mostly about program analysis.
这是因为 如果你把一个Javascript函数安全地放到汇编程序中 And this is because if you confer a Javascript function safely into assembly,
除非将代码简化为必要的指令 否则不会导致任何显著的性能变化 you won't end up with any significant performance changes unless you reduce the code into only the instructions that are necessary.
所以我们可以看到最初的中间表示检查 So we can see that the initial intermediate representation checks,
数组范围内的眼睛 the eyes within the bounds of the array.
所以对我们来说 它每次都这样做 So to us and it does this every time,
每次它使用它们 every time it uses them,
对我们来说 and to us,
这看起来有点多余 因为我们需要检查 this kind of seems a little bit redundant because we are needed to check the.
我将在残骸中 I is going to be within the wreck,
数组的边界 the bounds of the array once,
因为两者之间没有变化 because nothing is being changed between it.
所以一旦所有复杂的程序分析完成 So once all the fancy program analysis is done,
第二张拒付支票已被移除 the second bounced cheque has been removed.
但如果有一种方法会对这个作业产生副作用呢 But what if there was a way to cause a side effect from this assignment?
这就是这个小虫的作用 And that's exactly what this bug is about.
我们的猴子使用不同的节点来表示不同的基本指令就像我刚才展示的一样 So our monkey works with by using different nodes to represent different basic instructions similar to how I showed a minute ago.
现在这两个节点在M存储元素时被改变了一个绝对正确的存储元素 Now the two nodes that were changed in the fix where M store element whole an infallible store element.
如果我有一个数组 并在一个melon中设置一个超出其边界的元素 那么整个AnnMstore元素就是 Ann M store element whole would be if I had an array and set in a melon an element outside the bounds of it.
一个可靠的存储元素是如果我有一个稠密的数组 An infallible store element would be if I had a dense array,
它是一个不丢失任何值的打包数组 which is an array that packs without any missing values.
然后我把一个元素放在数组的边界内 and then I sat an element within the bounds of the array.
但是这个数组 But this array,
你知道这次行动可能会失败 you know that this operation could fail,
因为 because,
例如 for example,
数组可以被冻结 the array could be frozen.
我提到过重要的一点是神经节集不再被覆盖 And I mentioned that one of the important points was that ganglia set was no longer overridden.
用Galea集来定义节点可以产生的效果 And Galea set is used to define what effect and node can have.
如果这是错的 And if this isn't correct,
它实际上会导致像之前的boucek这样的节点被消除 it can actually cause nodes like the boucek earlier to be eliminated.
不幸的是 And unfortunately,
这是这两个结点的情况 this was the case for these two nodes.
如何通过设置数组元素来产生副作用呢 So how do we cause a side effect by setting an array element?
好吧 Well,
我们可以在数组上使用definesetter函数来添加一个函数 该函数在设置数组元素时被触发 we can use the define setter function on an array in order to add a function that is triggered when an array element is set.
现在 Now,
不幸的是 unfortunately,
对我们来说 for us,
这并不是很有效 因为当我们 this doesn't quite work because when we,
当我们这样做的时候 when we do this,
祖先元素整个节点不再生成 the ancestral element whole node isn't generated anymore.
相反 Instead,
我们受困于有M个存储元素的节点 we get stuck with an M store element node,
这就没那么有趣了 which is just not as fun.
但如果我们定义setter或属性 But if we define a setter or a property,
amstel元素 the amstel element,
现在就生成了整个节点 whole node is now generated.
啊 Ah,
当然 这不会触发函数 but of course this isn't going to trigger the function.
当我们得到这个函数时 So when we get the function,
节点可以是一个总结 the nodes can be kind of summarize,
就像这样 like this we take,
我检查它是int32 I check that it's an int thirtytwo,
然后我们使用m存储元素洞的数组元素的眼睛和索引 and then we use m store element hole on the arrays elements with eyes and index.
然而 However,
这并没有说明在Javascript中使用数字-1 this says nothing about using the number minus one and in Javascript.
这不是数组索引 this isn't an array index.
这是一个性质 This is a property,
但它仍然是一个数字 将来也会是 but it's still a number and so will be.
我们会通过信息来检查的 We'll get past the info to check.
我们可以在属性上定义setter So we can define a setter on the property,
减去1 它会传递给杰克到达阿姆斯特尔元素 minus one which will pass that into those to Jack and reached the amstel element.
整个节点和这个注释将触发打印reach的函数 Whole node and this note will then trigger the function which will print reach.
但这并没有考虑到gay别名SAP函数 But this wasn't taken into account with the gay alias SAP function,
因此 我们可以在不使jit失效的情况下导致更改的发生 so we can cause changes to occur without a jit being invalidated.
让我们用这个函数在底部创建一个糟糕的数组它有一组定义为-1的属性 So let's take this function here will create an evil array at the bottom with a set of defined on the minus one property.
然后调用带有-1属性的jest函数 will then call the jest function with might with the minus one property and being a number one.
现在芯片函数创建了另一个数组Target Now the chip function creates another array called Target,
有三个元素 with three elements.
首先 它在目标数组上使用Jay的和索引 并将值设置为1 At first it uses Jay's and index on the target array and sets the value to one.
然后我们触发了所有的副作用 将利率目标的长度设置为零 Then we trigger all a side effect which sets the length of the target for rates to zero.
最后 And finally,
我们再次使用G作为索引 并将目标数组的值设置为1 we use G as the index again and set the value of the target array to one.
现在开始的时间和预期的一样 Now the initial hour is as expected.
值J在界限内被检查是平衡的 the value J is checked within the bounds is balanced.
检查两次 Checked twice.
因为jit编译器会看到这个 And because the jit compiler sees this.
当我们得到结果时 When we get the results and I are,
第二个弓 the second bows,
check被移动了 因为它认为没有必要 check is moved because it doesn't think there's a need for it.
但它没有考虑到函数的集合 But it didn't account for the set of function,
这使得目标阵列的长度为零 which has now made the length of the target array to zero.
这意味着第二个数组将会越界 And this means that the second array will now right out of bounds.
那么我们如何从外部边界到代码执行呢 So how do we go from an outer bounds right to code execution?
好吧 Well,
在Javascript开发中实现这一点的一种常见方法是使用数组 a common way to do this in Javascript exploitation is to use arrays.
这就是对象和数组在内存中的表示方式 And this is how objects and arrays are represented in memory.
蜘蛛猴 in Spider monkey.
于是小组成员指着一个结构 里面有物体的原型 So the group pointed to a structure which holds things like the prototype of the object,
但它也被用来做一些事情 比如飞机操作 比如类型影响 but it's also used for things like a certain jet operations like type influencing.
现在 形状指向一个定义属性名称和索引的结构 Now the shape points to a structure that defines the names and indexes of properties.
槽指针指向属性值所在的内存位置 And the slots pointer points to the memory location in which the properties have their values.
这就是形状和槽如何一起作用来塑造你 So that's how the shape and slots work together shape you.
获取您拥有值的名称槽 Get the name slots you have the values.
最后 And finally,
指针指向的元素 the elements pointer points to.
而是数组元素 but the array elements.
如果我们可以使用外部边界来覆盖对象的slot指针 So if we can use our outer bounds right to act to overwrite the slots pointer of an object,
我们可以将它指向任意内存位置 并通过检查属性读取值 we can point it to arbitrary memory locations and read the value by checking your property.
记住 在Javascript中 B个整数被存储在对象属性指针中 Now remember how in Javascript we have B integers being stored in line in the object property pointer.
不好意思 是Var的对象指针那已经完成了 I'm sorry the object pointer of the Var and that was done se space.
而在蜘蛛猴身上也发生了类似的事情 While a similar sort of thing actually happens in spider monkey.
每个值都存储为所谓的Nan框值 Each value is stored as what's called a Nan Box value.
在这里 值的一些最重要的位被用来定义值的类型 and this is where some of the most significant bits of the value are used to define the type of the value.
这是一个数值为1的整数 So this is an integer with the value one.
这也是一个整数 this is an integer with the value too.
这个物体的地址是x1对应81f And this is an object points out with the address of X one for eight one F E,
B B,
三 three,
八个 eight,
一个零 one zero.
这对于后面的读原语非常重要 And this is actually going to be quite important for our read primitive later.
这是我们的目标数组 我们可以看到元素 So here's our target array we can see the elements.
指针指向在它之后分配值为1的内存块 Pointer points to a block of memory allocated after it with the values one,
2和3 two and three.
现在 Now,
我们的第一反应 on our first rate,
我们也将值1写入索引 we write the value one to the index too.
然后我们用邪恶的数组调用副作用函数 And then we call our side effect function using our evil array,
这会将目标数组的长度设为0 and this will set the length of the target array to zero.
然后 Then,
当第二个右击发生时 when the second right happens,
这是越界的 this is gonna go out of bounds.
所以现在我们只是写入你释放的内存 So at the moment we're just writing to your freed memory.
所以我们真正需要的是写出一些有用的东西 So what we really need is to write something useful.
为此 我们将使用三个数组 So for this we're going to use three arrays.
第三种反应需要有一个性质 And the third rate will need to have a property.
现在我们再次写入目标偏移量 以便jit编译器将删除第二个弹出支票 Now we write to the target offset again so that the jit compiler will remove the second bounced cheque.
现在我们触发了副作用 And now we trigger our side effect,
它将数组的长度设置为0 which sets all the array length zero.
然后我们让它也引起垃圾收集器 And then we let it also cause the garbage collector,
这个重新分配数组 这三个擦除后的数组相邻 and this re allocates array the each of these three erased next to each other.
现在 Now,
当右外界发生时 when the outer bound right happens,
我们改变了 we changed.
第二个数组的元素区域长度为一个非常大的值 the second arrays length of its elements area to a very large value.
从这里我们实际上得到了一个非常稳定的读和写原语 我们不再需要使用jet漏洞 And from here we've actually got a very stable read and write primitive and we no longer need to use the jet vulnerability.
我们要做的是使用第二个数组来写第三个数组的slot So what we do is we use the second array to write to the slots points of the third array.
然后我们使用第三个数组来使用属性读写任意地址 And then we use this third array to read and write to arbitrary addresses using the property.
至少我们可以这样做 At least we can kind of do that.
要记住值是如何不装箱的 To remember how values are non boxed,
像这样的值可能会导致猴子引用它并崩溃 因为它不是一个有效的地址 a value like this could cause by the monkey to the reference it and crash because it is not a valid address.
所以我们在这里真正得到的是一个弱解读 So what we've really got here is a weak read,
写原始 write primitive.
我们需要找到一种方法使它成为强重定向原语 And we need to find a way to make it a strong redirect primitive.
这就是为什么要引入类型化数组 And this is why typed arrays come in.
如此下去 So afloat,
六十四年的数组 sixty four array,
例如 for example,
不会使用Nan装箱 而只是将64位浮点数存储在内存中 will not use Nan boxing but simply store the sixty four bit floats in memory,
为是 as is.
所以第一步是创建一个新的流 So step one is to create a new flow.
六十四年的大选 Sixty four race.
然后我们得到它的地址 And next we get its address,
为了避免修女的拳击 在半年的时间里读取一半的值 avoiding the nun boxing by reading half the value at half of the year,
现在一次只值一半 half the value at a time now.
我想深入讲讲这个原始的说法 I kind of wanted to go more into this address of primitive,
但我觉得我没有足够的时间去做 but I didn't feel I could have enough time to do it,
但 是的 but yeah,
基本上 basically,
它使用三个不同的属性一次读取地址的一部分 it's using three different properties to read part of the address at a time.
如果你想知道它是如何工作的 And if you're interested in kind of knowing how it really works,
一定要看看 时尚先生实验室 的博客 因为它已经开始了 do check out the Esquire Labs blog post because it goes into way,
更多细节 more detail.
因此 我们使用我们的wreakaweek原语来写入缓冲区指针的目标地址 So we use our wreak a week primitive to write to the target address of the buffer pointer.
最后 And finally,
我们使用流程 we use the flow.
对目标地址读取和写入64个速率的精确值 Sixty four rates are read and write exact values to the target address.
所以 So,
最后 finally,
我们需要 we need to get.
我们需要使用参数来执行代码 We need to use our parameters to get code execution.
现在我们不能像铬那样读写外壳代码来增加区域因为没有读取 Now we can't do the thing that we do with chromium and read and write shell code to a rise in region because there are no read,
写 write,
在SpiderMonkey中执行映射 execute mappings in Spider Monkey.
这就意味着你不得不写了 And this means that you've unfortunately got to write.
您的外壳代码是一系列浮点数 您可以在不同的函数中完成此操作 Your shell code is a series of floats and you do this in a different function.
现在你想一直这样做 Now you want to do this all the while,
避免常数合并 avoiding constant folding,
它会删除任何它认为是重复的或者与函数的执行无关的东西 which will basically remove anything that it thinks is a duplicate or not relevant to the execution of a function.
这并不是一个有趣的经历 And that's not really a fun experience.
现在你会注意到第一个值是AlexFull的对等流 Now you'll notice that the first value is the flow equivalent of Alex Full one for one for one.
一 for one.
这样做的原因是 我们可以在Jit区域找到shell代码 And the reason for this is so that we can find our shell code in the Jit region,
一旦我们这样做了 and once we do that,
我们可以更新jit we can update the jit.
喷射函数喷射指示器 The jetted functions jet pointer,
指向那个位置 to point to that location.
这意味着我们不会跳到函数的开始我们会把这些值当作数字 So this means that instead of jumping to the start of the function which we'll treat these values as just numbers,
我们跳到值本身 它们将被处理为shell代码 we jumped to the values themselves and they'll be treated a shell code.
因为这个区域是可读和可执行的 Because this area is mapped is readable and executable.
所以 So,
是的 yeah,
当在Firefox上禁用沙箱时 when the sandbox is disabled on Firefox,
你可以打开沙发 you can pop couch.
的屁股 Butt.
在真实世界的攻击中 这一弱点被广泛使用 This vulnerability was used in the wild in a real world attack.
那么他们是怎么做到的呢 So how did they do it?
沙箱启用了吗 with the with the sandbox being enabled?
好吧 Well,
早期的J脚本错误 that J script bug from early,
它实际上被再次使用 it was actually used again,
它是在Firefox沙箱内部完成的 and it was done inside from inside the Firefox sandbox.
这实际上利用了W And this actually exploited the fact the W,
一个学校的博士或网络代理自动发现可以执行Javascript脚本配置代理和谷歌项目做了一个令人难以置信的记录这几年前 Phd or Web proxy auto discovery for a school can execute Javascript scripts to configure proxies and Google Project Zero did a really incredible writeup of this a few years back?
所以这并不是什么新技术 So this isn't exactly a new technique,
但它显示了即使是老的虫子 but it shows how even bugs in old,
非常古老的Javascript引擎仍然可以在现实世界中使用 very ancient Javascript engines can still be used in real world.
的税 The tax.
我想这是最后的笔记 So I guess just some final notes.
这两个漏洞都是差异 Both of these vulnerabilities were variance.
这个Javascript漏洞是微软的老手 微软曾多次尝试修补 但都失败了 The Javascript bug was a veteran of the bug that Microsoft had tried and failed to patch multiple times.
我想他们已经训练了三年了 I think they've been trained for about three years.
这批货 The batch of this one.
火狐的bug是一个人自身bug的变体 And the Firefox bug was a variant of a person's own bug.
这里的要点是 So the take away point is really.
如果你想要零天 If you want some zero days,
对新的bug做一些方差分析 just do some variance analysis on new bugs.
我在chromiumbug跟踪器中见过几次 I've actually seen this a couple of times in the chromium bug tracker,
如果有人报告了一个漏洞 where someone has reported a bug,
几个月后 and then a few months later,
有人报告了一个看起来完全一样的bug someone reports a bug that looks exactly the same.
现在 Now,
虽然在整个过程中有很多工作要做 while there's lots of work that's involved in this entire process,
写这段旅程其实很有趣 it's actually quite a lot of fun to write the ride the exploits,
所以我推荐大家去他的店 so I do recommend people give his shop.
当然 And of course,
不要害怕超级大的 don't be afraid of the super big,
可怕的目标 scary targets.
一旦你从末日开始 Once you start with the end days,
找到零天你会感觉舒服得多 you'll feel a lot more comfortable finding zero days.
太好了 Great,
感谢您观看演示并回答您的任何问题 thank you for watching with presentation and appeared to answer any questions you might have,
或者你可以在Twitter上给我发问题 如果你愿意的话 or you can just message me questions on Twitter if you prefer doing.