ASLR编译
❶ c#使用命令行编译生成dll文件
C#使用csc.exe编译程序,csc使用/target:library(缩写: /t:library)参数生成Dll文件。
其它参数如下:
Visual C# 编译器选项
- 输出文件 -
/out:<文件> 指定输出文件名(默认值: 包含主类的文件或第一个文件的基名称)
/target:exe 生成控制台可执行文件(默认) (缩写: /t:exe)
/target:winexe 生成 Windows 可执行文件 (缩写: /t:winexe)
/target:library 生成库 (缩写: /t:library)
/target:mole 生成能添加到其他程序集的模块 (缩写: /t:mole)
/target:appcontainerexe 生成 Appcontainer 可执行文件 (缩写: /t:appcontainerexe)
/target:winmdobj 生成 WinMDExp 使用的 Windows 运行时中间文件 (缩写: /t:winmdobj)
/doc:<文件> 要生成的 XML 文档文件
/platform:<字符串> 限制可以在其上运行此代码的平台: x86、Itanium、x64、arm、anycpu32bitpreferred 或 anycpu。默认值为 anycpu。
- 输入文件 -
/recurse:<通配符> 根据通配符规范,包括当前目录和子目录下的所有文件
/reference:<别名>=<文件> 使用给定的别名从指定的程序集文件引用元数据 (缩写: /r)
/reference:<文件列表> 从指定的程序集文件引用元数据 (缩写: /r)
/addmole:<文件列表> 将指定的模块链接到此程序集中
/link:<文件列表> 嵌入指定的互操作程序集文件中的元数据 (缩写: /l)
- 资源 -
/win32res:<文件> 指定 Win32 资源文件(.res)
/win32icon:<文件> 对输出使用此图标
/win32manifest:<文件> 指定 Win32 清单文件(.xml)
/nowin32manifest 不包括默认 Win32 清单
/resource:<资源信息> 嵌入指定的资源 (缩写: /res)
/linkresource:<资源信息> 将指定的资源链接到此程序集 (缩写: /linkres)
其中 resinfo 的格式是 <file>[,<string name>[,public|private]]
- 代码生成 -
/debug[+|-] 发出调试信息
/debug:{full|pdbonly} 指定调试类型(“full”是默认类型,可以将调试程序附加到正在运行的程序)
/optimize[+|-] 启用优化 (缩写: /o)
- 错误和警告 -
/warnaserror[+|-] 将所有警告报告为错误
/warnaserror[+|-]:<警告列表> 将特定警告报告为错误
/warn:<n> 设置警告等级(0-4) (缩写: /w)
/nowarn:<警告列表> 禁用特定的警告消息
- 语言 -
/checked[+|-] 生成溢出检查
/unsafe[+|-] 允许“不安全”代码
/define:<符号列表> 定义条件编译符号 (缩写: /d)
/langversion:<字符串> 指定语言版本模式: ISO-1、ISO-2、3、4、5 或 Default
- 安全性 -
/delaysign[+|-] 仅使用强名称密钥的公共部分对程序集进行延迟签名
/keyfile:<文件> 指定强名称密钥文件
/keycontainer:<字符串> 指定强名称密钥容器
/highentropyva[+|-] 启用高平均信息量的 ASLR
- 杂项 -
@<文件> 有关更多选项,请阅读响应文件
/help 显示此用法信息 (缩写: /?)
/nologo 取消编译器版权信息
/noconfig 不要自动包含 CSC.RSP 文件
- 高级 -
/baseaddress:<地址> 要生成的库的基址
/bugreport:<文件> 创建“Bug 报告”文件
/codepage:<n> 指定打开源文件时要使用的代码页
/utf8output 以 UTF-8 编码格式输出编译器消息
/main:<类型> 指定包含入口点的类型(忽略所有其他可能的入口点) (缩写: /m)
/fullpaths 编译器生成完全限定路径
/filealign:<n> 指定用于输出文件节的对齐方式
/pdb:<文件> 指定调试信息文件名(默认值: 扩展名为 .pdb 的输出文件名)
/errorendlocation 输出每个错误的结束位置的行和列
/preferreilang 指定首选输出语言名称。
/nostdlib[+|-] 不引用标准库(mscorlib.dll)
/subsystemversion:<字符串> 指定此程序集的子系统版本
/lib:<文件列表> 指定要在其中搜索引用的附加目录
/errorreport:<字符串> 指定如何处理内部编译器错误: prompt、send、queue 或 none。默认值为 queue。
/appconfig:<文件> 指定一个包含程序集绑定设置的应用程序配置文件
/moleassemblyname:<字符串> 此模块所属程序集的名称
❷ windows 7中内存保护机制不包括哪项技术
Windows操作系统为解决栈溢出漏洞的问题引入了一个对策——GS编译保护技术。
GS编译保护技术是通过编译时添加相关代码而实现的,开启GS 编译选项后会在函数的开头和结尾添加代码来阻止栈溢出漏洞的利用。当应用程序启动时,程序的cookie被计算出来(伪随机数)并保存在.data 节段中,在函数的开头这个 cookie 被拷贝到栈中,位于返回地址和局部变量的中间。
函数调用完后系统检测cookie值是否被修改。
1.2 绕过方法
计算/猜测cookie值
覆盖虚函数表
堆栈布局:[局部变量][cookie][入栈寄存器][返回地址][参数][虚表指针]。
覆盖对象和虚函表指针,如果你把这个指针指向一个用于欺骗的虚函数表,你就可以重定向这个虚函数的调用,并执行恶意的代码。
覆盖SHE
SEH句柄用于指向异常处理函数,这个句柄被存在SecurityCookie的上方,这使得攻击者不需要覆盖到SecurityCookie就可以修改SEH句柄指向的位置。
同时替换掉栈中和.data段中的cookie值
通过替换加载模块.data 节中的cookie 值(可写)来绕过栈上的 cookie 保护,并用相同的值替换栈中的cookie。
2 SafeSEH机制
2.1 基本原理
通过覆盖SEH可以绕过GS编译保护,所以微软又引入了一种SEH的安全校验机制——SafeSEH。
通过启用/SafeSEH编译选项来把这种机制应用到所有的执行模块上,当异常处理器被执行前,SafeSEH会验证异常处理链是否被修改过。系统会从头到尾遍历异常处理链表,并逐个验证它们的有效性。
如果覆盖SEH,这将破坏链表并触发SafeSEH机制。
2.2 绕过方法
利用未开启SafeSEH保护的模块
寻找程序中加载的未开启SafeSEH保护的模块来绕过,比如软件本身自带的dll文件。
利用堆绕过
SafeSEH允许其异常处理句柄位于除栈空间之外的非映像页面。如果你将shellcode写在堆空间中 ,再覆盖SEH链表的地址。使程序异常处理句柄指向堆空间,就可以绕过SafeSEH的检测了。
覆盖虚函数表(同上)
3 SEH覆盖保护
3.1 基本原理
SEH覆盖保护(SEHOP)可作为SEH的扩展,用于检测SEH是否被覆写。
SEHOP的核心特性是用于检测程序栈中的所有SEH结构链表的完整性,特别是对最后一个SHE结构的检测。在最后一个SEH结构中拥有一个特殊的异常处理函数指针,指向一个位于ntdll中的函数ntdll!FinalExceptHandler()。
3.2 绕过方法
利用未开启SEHOP保护的模块
覆盖虚函数表
伪造SEH链表
4 数据执行保护(DEP)
4.1 基本原理
数据执行保护 (DEP) 是一套软硬件技术,能够在内存上执行额外检查以防止在不可运行的内存区域上执行代码。
DEP 有两种模式,如果 CPU 支持内存页 NX 属性, 就是硬件支持的 DEP。如果 CPU 不支持, 那就是软件支持的 DEP 模式,这种 DEP 不能阻止在数据页上执行代码,但可以防止其他的 exploit(如SEH覆盖)。
4.2 绕过方法
ret2libc
ret2libc是一种通过retn指令在库函数中寻找可用代码的攻击方式。由于其所有代码都是从libc中找到的,所以不存在不可执行的问题。
关闭进程的DEP (NtSetInformationProcess)
因为 DEP 可以设置不同的模式,操作系统需要能动态关闭DEP,因此系统肯定有API来启用或关闭NX,如果黑客可以找到这个NTDLL中的 API,就能绕过硬件DEP保护。一个进程的DEP设置标志保存在内核结构中(KPROCESS结构),这个标志可以用函数NtQueryInformationProcess和NtSetInformationProcess通过设置ProcessExecuteFlags类来查询和修改,用内核调试器也可以达到同样的目的。
利用可写可执行内存
有些程序可能由于配置的问题或者其他原因,在进程中存在可读可写可执行的区域。如果攻击者可以将shellcode写入这部分空间中并劫持流程,就可以绕过DEP。
利用TEB突破DEP(局限于XP SP2以下的版本)
利用WPN与ROP技术
利用SEH
5 地址随机化(ASLR)
5.1 基本原理
ASLR(地址空间布局随机化)技术的主要功能是通过对系统关键地址的随机化,防止攻击者在堆栈溢出后利用固定的地址定位到恶意代码并加以运行。它主要对以下四类地址进行随机化:堆地址、栈基址、PE文件映像基址、PEB地址。
适用范围:Windows Vista,Windows 2008 server,Windows 7下是默认启用。
5.2 绕过方法
覆盖部分返回地址
虽然模块加载基地址发生变化,但是各模块的入口点地址的低字节不变,只有高位变化。部分返回地址覆盖,可以使得覆盖后的地址相对于基地址的距离是固定的,可以从基地址附近找可以利用的跳转指令。这种方法的通用性不是很强,因为覆盖返回地址时栈上的Cookie会被破坏。不过具体问题具体分析,为了绕过操作系统的安全保护机制需要考虑各种各样的情况。
❸ win7有何优越性能
你好,Windows 7 使基本操作变得前所未有的简单。借助家庭组,您可以与家里另外运行 Windows 7 的电脑轻松共享音乐、文档、打印机及任何其他内容。 Windows Search 免去从众多文件夹和子文件夹中查找资料的繁琐。更优的任务栏预览允许您更好地查看正在运行的任务,并且只需单击一下右键,Jump List 就会为您列出最近访问的文件。 如果电脑不能按照您希望的方式顺畅运行,不需要您的电脑有很多功能就能解决。Windows 7 旨在帮助您的电脑更快速地休眠和恢复。 Windows 7 支持最先进的电脑硬件,例如 64 位计算及多核处理器;同时经过改善的内存使用率可帮助硬件充分发挥性能潜力。 一旦您的电脑变得更快、更简单,您就会发现一些很酷的新功能。例如:不管在家中、办公室或是咖啡店,您只需双击鼠标就可以连接到网络;并且借助 Windows 触控功能(以及合适的硬件),您很快就可以用手指翻阅文件、处理图片甚至“画图”。 希望我的回答能够帮助你。
❹ 漏洞分析的内容导读
本书分为5篇,共33章。
第1篇 漏洞利用原理(初级)
第1章 基础知识
本章着重对漏洞挖掘中的一些基础知识进行介绍。首先是漏洞研究中的一些基本概念和原理;然后是对Windows平台下可执行文件的结构和内存方面的一些基础知识的介绍;最后介绍了一些漏洞分析中经常使用的软件工具。包括调试工具、反汇编工具、二进制编辑工具等。您会在后面的调试实验中反复见到这些工具的身影。在这章的最后一节,我们设计了一个非常简单的破解小实验,用于实践工具的应用,消除您对二进制的恐惧感,希望能够给您带来一些乐趣。
第2章 栈溢出原理与实践
基于栈的溢出是最基础的漏洞利用方法。本章首先用大量的示意图,深入浅出地讲述了操作系统中函数调用、系统栈操作等概念和原理;随后通过三个调试实验逐步讲解如何通过栈溢出,一步一步地劫持进程并植入可执行的机器代码。即使您没有任何汇编语言基础,从未进行过二进制级别的调试,在本章详细的实验指导下也能轻松完成实验,体会到exploit的乐趣。
第3章 开发shellcode的艺术
本章紧接第2章的讨论,比较系统地介绍了溢出发生后,如何布置缓冲区、如何定位shellcode、如何编写和调试shellcode等实际的问题。最后两小节还给出了一些编写shellcode的高级技术,供有一定汇编基础的朋友做参考。
第4章 用MetaSploit开发Exploit
MetaSploit是软件工程中的Frame Work(架构)在安全技术中的完美实现,它把模块化、继承性、封装等面向对象的特点在漏洞利用程序的开发中发挥得淋漓尽致。使用这个架构开发Exploit要比直接使用C语言写出的Exploit简单得多。本章将集中介绍如何使用这个架构进行Exploit开发。
第5章 堆溢出利用
在很长一段时间内,Windows下的堆溢出被认为是不可利用的,然而事实并非如此。本章将用精辟的论述点破堆溢出利用的原理,让您轻松领会堆溢出的精髓。此外,这章的一系列调试实验将加深您对概念和原理的理解。用通俗易懂的方式论述复杂的技术是本书始终坚持的原则。
第6章 形形色色的内存攻击技术
在了解基本的堆栈溢出后,本章将为大家展示更为高级的内存攻击技术。本章集中介绍了一些曾发表于Black Hat上的着名论文中所提出的高级利用技术,如狙击Windows异常处理机制、攻击虚函数、off by one、 Heap Spray等利用技巧。对于安全专家,了解这些技巧和手法不至于在分析漏洞时错把可以利用的漏洞误判为低风险类型;对于黑客技术爱好者,这些知识很可能成为激发技术灵感的火花。
第7章 手机里的缓冲区溢出
在PC机上的溢出攻击进行的如火如荼的时候,您是否也想了解手机平台上的缓冲区溢出问题?那就不要错过本章!本章以ARM和Windows Mobile为例,介绍手机平台上编程和调试技巧。并在最后以一个手机上的exploit me为大家揭开手机里缓冲区溢出的神秘面纱。
第8章 其他类型的软件漏洞
缓冲区溢出漏洞只是软件漏洞的一个方面,我们来看看其他一些流行的安全漏洞。如格式化串漏洞、SQL注入、XPath注入、XSS等安全漏洞产生的原因、利用技巧及防范措施。
第2篇 漏洞利用原理(高级)
第9章 Windows安全机制概述
微软在Windows XP SP2和Windows 2003之后,向操作系统中加入了许多安全机制。本章将集中讨论这些安全机制对漏洞利用的影响。
第10章 栈中的守护天使:GS
针对缓冲区溢出时覆盖函数返回地址这一特征,微软在编译程序时使用了一个很酷的安全编译选项——GS。本章将对GS编译选项的原理进行详细介绍,并介绍几种绕过GS的溢出技巧。
第11章 亡羊补牢:SafeSEH
攻击S.E.H已经成为windows平台下漏洞利用的经典手法。为了遏制日益疯狂的攻击,微软在Windows XP SP2及后续版本的操作系统中引入了着名的S.E.H校验机制SafeSEH。本章将会对这一安全机制进行详细的分析,并介绍其中的不足和绕过方法。
第12章 数据与程序的分水岭:DEP
溢出攻击的根源在于现代计算机对数据和代码没有明确区分这一先天缺陷, 而DEP这种看似釜底抽薪式的防护措施是否真的可以杜绝溢出攻击呢?答案马上揭晓。
第13章 在内存中躲猫猫:ASLR
程序加载时不再使用固定的基址加载,ASLR技术将溢出时使用的跳板在内存中隐藏了起来,没有了跳板我们如何溢出呢?本章将带领您在黑暗中寻找溢出的出口。
第14章 S.E.H终极防护:SEHOP
SafeSEH的败北,让微软推出一种更为严厉的S.E.H保护机制SEHOP。这里将为您展示这种保护机制的犀利之处。
第15章 重重保护下的堆
当堆溢出变成可能后,微软不能再无视堆中的保护机制了,让我们一览堆中的保护机制,并分析其漏洞。
第3篇 漏洞挖掘技术
第16章 漏洞挖掘技术简介
不论从工程上讲还是从学术上讲,漏洞挖掘都是一个相当前沿的领域。本章将从动态测试和静态审计两方面对漏洞挖掘技术的基础知识进行简单的介绍。
第17章 文件类型漏洞挖掘与Smart Fuzz
文件类型的漏洞层出不穷,持续威胁着互联网的安全。如何系统的测试文件格式,产生精确有效的畸形测试用例用以发掘文件解析器的安全漏洞,并不是一件容易的事情。本章将从理论和实践两个方面向您讲述灰盒测试技术。
第18章 FTP的漏洞挖掘
本章将简述FTP协议,并手把手地带领您完成几个初级的漏洞测试案例,让您亲身体会下真实的漏洞长什么模样。
第19章 E-mail的漏洞挖掘
E-mail系统涉及的安全问题不光只有缓冲区溢出,在本章的挖掘案例中,您会发现除了工具和常用方法外,威力最为强大的武器还是您的大脑。Evil thinking是安全测试中最重要的思维方式之一。
第20章 ActiveX控件的漏洞挖掘
控件类漏洞曾经是大量网马的栖身之地。本章将结合若干个曾经的0 day向您比较系统的介绍这类漏洞的测试、调试的相关工具和方法。
第4篇 操作系统内核安全
第21章 探索ring0
研究内核漏洞,需要首先掌握一些内核基础知识,例如内核驱动程序的开发、编译、运行和调试,内核中重要的数据结构等,本章将为读者开启探索ring0之门,逐步掌握一些内核基础知识。
第22章 内核漏洞利用技术
本章将带领读者从一个简单的内核漏洞程序exploitme.sys的编写开始,展示内核漏洞利用的思路、方法,以及利用程序和Ring0 Shellcode的编写和设计。
第23章 FUZZ驱动程序
掌握了内核漏洞的原理和利用方法,本章将进入内核漏洞挖掘阶段,学习较为高级的内核漏洞挖掘技术,最后实践该漏洞挖掘技术,分析挖掘出内核漏洞。
第24章 内核漏洞案例分析
本章对几种典型的内核漏洞,用几个真实的内核漏洞案例来详细分析,分析漏洞造成的具体原因和细节,并构造漏洞成功利用的方法。
第5篇 漏洞分析案例
第25章 漏洞分析技术概述
本章纵览了漏洞分析与调试的思路,并介绍了一些辅助漏洞调试分析的高级逆向工具。
第26章 RPC入侵:MS06-040 与MS08-067
由于可以做到主动式远程入侵,RPC级别的漏洞被誉为漏洞中的王者,此类漏洞也极其稀有,每一个都有一段曲折的故事。值得一提的是最近的两个RPC系统漏洞竟然出自同一个函数。本章将对这个缝来补去没有修好的函数进行详细分析,让您从攻防两方面深刻理解漏洞的起因和修复策略的重要性。
第27章 MS06-055分析:实战Heap Spray
通过网页“挂马”是近年来攻击者惯用的手法。本章通过分析微软IE浏览器中真实的缓冲区溢出漏洞,告诉您为什么不能随便点击来历不明的URL链接,并在实战中为大家演示Heap Spray技术。
第28章 MS09-032分析:一个“&”引发的血案
一个视频网页的背后可能是一只凶狠的木马,这就是着名的Microsoft DirectShow MPEG-2视频ActiveX控件远程代码执行漏洞。本章将为您分析该漏洞产生的原因及分析技巧。
第29章 Yahoo!Messenger栈溢出漏洞
在波涛汹涌的溢出大潮中Yahoo也没能幸免,作为国外非常流行的Yahoo!Messenger也存在过非常严重的漏洞。本章将重现当时的场景,并分析漏洞产生的原因。
第30章 CVE-2009-0927:PDF中的JS
您可能不会随便运行一个可执行文件,但是您会想到别人发过来的PDF文档中也有可能隐藏着一些东西吗?本章将以PDF文档为例,带您领略文件类型溢出漏洞的风采。
第31章 坝之蚁穴:超长URL溢出漏洞
安全软件不一定安全,即便是这款保护未成年人健康上网的计算机终端过滤软件,也有可能成为黑客攻击的窗口。本章将介绍绿坝软件中一个已经被修复了的安全漏洞。
第32章 暴风影音M3U文件解析漏洞
晚上回家后用暴风影音打开别人发过来的M3U列表文件,在你陶醉于其内容之时,一只精干的小马已悄然在后台运行。想要了解这只小马是如何进入你的电脑的?请阅读本章。
第33章 LNK快捷方式文件漏洞
是否我不去运行任何可疑文件,不去打开陌生的网址就安全了呢?答案是否定。LNK快捷方式漏洞无需打开文件,只要浏览恶意文件,所在文件夹就会中毒,俗称“看一眼就挂”。本章将带您分析这一神奇的漏洞。
Failwest
❺ 如何检查 Android 应用的内存使用情况
解析日志信息
最简单的调查应用内存使用情况的地方就是Dalvik日志信息。可以在logcat(输出信息可以在Device Monitor或者IDE中查看到,例如Eclipse和Android Studio)中找到这些日志信息。每次有垃圾回收发生,logcat会打印出带有下面信息的日志消息:
java
1
D/dalvikvm: <GC_Reason> <Amount_freed>, <Heap_stats>, <External_memory_stats>, <Pause_time>
GC原因
触发垃圾回收执行的原因和垃圾回收的类型。原因主要包括:
GC_CONCURRENT
并发垃圾回收,当堆开始填满时触发来释放内存。
GC_FOR_MALLOC
堆已经满了时应用再去尝试分配内存触发的垃圾回收,这时系统必须暂停应用运行来回收内存。
GC_HPROF_DUMP_HEAP
创建HPROF文件来分析应用时触发的垃圾回收。
GC_EXPLICIT
显式垃圾回收,例如当调用 gc()(应该避免手动调用而是要让垃圾回收器在需要时主动调用)时会触发。
GC_EXTERNAL_ALLOC
这种只会在API 10和更低的版本(新版本内存都只在Dalvik堆中分配)中会有。回收外部分配的内存(例如存储在本地内存或NIO字节缓冲区的像素数据)。
释放数量
执行垃圾回收后内存释放的数量。
堆状态
空闲的百分比和(活动对象的数量)/(总的堆大小)。
外部内存状态
API 10和更低版本中的外部分配的内存(分配的内存大小)/(回收发生时的限制值)。
暂停时间
越大的堆的暂停时间就越长。并发回收暂停时间分为两部分:一部分在回收开始时,另一部分在回收将近结束时。
例如:
Java
1
D/dalvikvm( 9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/K, paused 2ms+2ms
随着这些日志消息的增多,注意堆状态(上面例子中的3571K/9991K)的变化。如果值一直增大并且不会减小下来,那么就可能有内存泄露了。
查看堆的更新
为了得到应用内存的使用类型和时间,可以在Device Monitor中实时查看应用堆的更新:
1.打开Device Monitor。
从<sdk>/tools/路径下加载monitor工具。
2.在Debug Monitor窗口,从左边的进程列表中选择要查看的应用进程。
3.点击进程列表上面的Update Heap。
4.在右侧面板中选择Heap标签页。
Heap视图显示了堆内存使用的基本状况,每次垃圾回收后会更新。要看更新后的状态,点击Gause GC按钮。
图1.Device Monitor工具显示[1] Update Heap和 [2] Cause GC按钮。右边的Heap标签页显示堆的情况。
跟踪内存分配
当要减少内存问题时,应该使用Allocation Tracker来更好的了解内存消耗大户在哪分配。Allocation Tracker不仅在查看内存的具体使用上很有用,也可以分析应用中的关键代码路径,例如滑动。
例如,在应用中滑动列表时跟踪内存分配,可以看到内存分配的动作,包括在哪些线程上分配和哪里进行的分配。这对优化代码路径来减轻工作量和改善UI流畅性都极其有用。
使用Allocation Tracker:
1.打开Device Monitor 。
从<sdk>/tools/路径下加载monitor工具。
2.在DDMS窗口,从左侧面板选择应用进程。
3.在右侧面板中选择Allocation Tracker标签页。
4.点击Start Tracking。
5.执行应用到需要分析的代码路径处。
6.点击Get Allocations来更新分配列表。
列表显示了所有的当前分配和512大小限制的环形缓冲区的情况。点击行可以查看分配的堆栈跟踪信息。堆栈不只显示了分配的对象类型,还显示了属于哪个线程哪个类哪个文件和哪一行。
图2. Device Monitor工具显示了在Allocation Tracker中当前应用的内存分配和堆栈跟踪的情况。
注意:总会有一些分配是来自与 DdmVmInternal 和 allocation tracker本身。
尽管移除掉所有严重影响性能的代码是不必要的(也是不可能的),但是allocation tracker还是可以帮助定位代码中的严重问题。例如,应用可能在每个draw操作上创建新的Paint对象。把对象改成全局变量就是一个很简单的改善性能的修改。
查看总体内存分配
为了进一步的分析,查看应用内存中不同内存类型的分配情况,可以使用下面的 adb 命令:
Java
1
adb shell mpsys meminfo <package_name>
应用当前的内存分配输出列表,单位是千字节。
当查看这些信息时,应当熟悉下面的分配类型:
私有(Clean and Dirty) 内存
进程独占的内存。也就是应用进程销毁时系统可以直接回收的内存容量。通常来说,“private dirty”内存是其最重要的部分,因为只被自己的进程使用。它只在内存中存储,因此不能做分页存储到外存(Android不支持swap)。所有分配的Dalvik堆和本地堆都是“private dirty”内存;Dalvik堆和本地堆中和Zygote进程共享的部分是共享dirty内存。
实际使用内存 (PSS)
这是另一种应用内存使用的计算方式,把跨进程的共享页也计算在内。任何独占的内存页直接计算它的PSS值,而和其它进程共享的页则按照共享的比例计算PSS值。例如,在两个进程间共享的页,计算进每个进程PPS的值是它的一半大小。
PSS计算方式的一个好处是:把所有进程的PSS值加起来就可以确定所有进程总共占用的内存。这意味着用PSS来计算进程的实际内存使用、进程间对比内存使用和总共剩余内存大小是很好的方式。
例如,下面是平板设备中Gmail进程的输出信息。它显示了很多信息,但是具体要讲解的是下面列出的一些关键信息。
注意:实际看到的信息可能和这里的稍有不同,输出的详细信息可能会根据平台版本的不同而不同。
Java
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
** MEMINFO in pid 9953 [com.google.android.gm] **
Pss Pss Shared Private Shared Private Heap Heap Heap
Total Clean Dirty Dirty Clean Clean Size Alloc Free
------ ------ ------ ------ ------ ------ ------ ------ ------
Native Heap 0 0 0 0 0 0 7800 7637(6) 126
Dalvik Heap 5110(3) 0 4136 4988(3) 0 0 9168 8958(6) 210
Dalvik Other 2850 0 2684 2772 0 0
Stack 36 0 8 36 0 0
Cursor 136 0 0 136 0 0
Ashmem 12 0 28 0 0 0
Other dev 380 0 24 376 0 4
.so mmap 5443(5) 1996 2584 2664(5) 5788 1996(5)
.apk mmap 235 32 0 0 1252 32
.ttf mmap 36 12 0 0 88 12
.dex mmap 3019(5) 2148 0 0 8936 2148(5)
Other mmap 107 0 8 8 324 68
Unknown 6994(4) 0 252 6992(4) 0 0
TOTAL 24358(1) 4188 9724 17972(2)16388 4260(2)16968 16595 336
Objects
Views: 426 ViewRootImpl: 3(8)
AppContexts: 6(7) Activities: 2(7)
Assets: 2 AssetManagers: 2
Local Binders: 64 Proxy Binders: 34
Death Recipients: 0
OpenSSL Sockets: 1
SQL
MEMORY_USED: 1739
PAGECACHE_OVERFLOW: 1164 MALLOC_SIZE: 62
通常来说,只需关心Pss Total列和Private Dirty列就可以了。在一些情况下,Private Clean列和Heap Alloc列也会提供很有用的信息。下面是一些应该查看的内存分配类型(行中列出的类型):
Dalvik Heap
应用中Dalvik分配使用的内存。Pss Total包含所有的Zygote分配(如上面PSS定义所描述的,共享跨进程的加权)。Private Dirty是应用堆独占的内存大小,包含了独自分配的部分和应用进程从Zygote复制分裂时被修改的Zygote分配的内存页。
注意:新平台版本有Dalvik Other这一项。Dalvik Heap中的Pss Total和Private Dirty不包括Dalvik的开销,例如即时编译(JIT)和垃圾回收(GC),然而老版本都包含在Dalvik的开销里面。
Heap Alloc是应用中Dalvik堆和本地堆已经分配使用的大小。它的值比Pss Total和Private Dirty大,因为进程是从Zygote中复制分裂出来的,包含了进程共享的分配部分。
.so mmap和.dex mmap
mmap映射的.so(本地) 和.dex(Dalvik)代码使用的内存。Pss Total 包含了跨应用共享的平台代码;Private Clean是应用独享的代码。通常来说,实际映射的内存大小要大一点——这里显示的内存大小是执行了当前操作后应用使用的内存大小。然而,.so mmap 的private dirty比较大,这是由于在加载到最终地址时已经为本地代码分配好了内存空间。
Unknown
无法归类到其它项的内存页。目前,这主要包含大部分的本地分配,就是那些在工具收集数据时由于地址空间布局随机化(Address Space Layout Randomization ,ASLR)不能被计算在内的部分。和Dalvik堆一样, Unknown中的Pss Total把和Zygote共享的部分计算在内,Unknown中的Private Dirty只计算应用独自使用的内存。
TOTAL
进程总使用的实际使用内存(PSS),是上面所有PSS项的总和。它表明了进程总的内存使用量,可以直接用来和其它进程或总的可以内存进行比较。
Private Dirty和Private Clean是进程独自占用的总内存,不会和其它进程共享。当进程销毁时,它们(特别是Private Dirty)占用的内存会重新释放回系统。Dirty内存是已经被修改的内存页,因此必须常驻内存(因为没有swap);Clean内存是已经映射持久文件使用的内存页(例如正在被执行的代码),因此一段时间不使用的话就可以置换出去。
ViewRootImpl
进程中活动的根视图的数量。每个根视图与一个窗口关联,因此可以帮助确定涉及对话框和窗口的内存泄露。
AppContexts和Activities
当前驻留在进程中的Context和Activity对象的数量。可以很快的确认常见的由于静态引用而不能被垃圾回收的泄露的 Activity对象。这些对象通常有很多其它相关联的分配,因此这是追查大的内存泄露的很好办法。
注意:View 和 Drawable 对象也持有所在Activity的引用,因此,持有View 或 Drawable 对象也可能会导致应用Activity泄露。
获取堆转储
堆转储是应用堆中所有对象的快照,以二进制文件HPROF的形式存储。应用堆转储提供了应用堆的整体状态,因此在查看堆更新的同时,可以跟踪可能已经确认的问题。
检索堆转储:
1.打开Device Monitor。
从<sdk>/tools/路径下加载monitor工具。
2.在DDMS窗口,从左侧面板选择应用进程。
3.点击Dump HPROF file,显示见图3。
4.在弹出的窗口中,命名HPROF文件,选择存放位置,然后点击Save。
图3.Device Monitor工具显示了[1] Dump HPROF file按钮。
如果需要能更精确定位问题的堆转储,可以在应用代码中调用mpHprofData()来生成堆转储。
堆转储的格式基本相同,但与Java HPROF文件不完全相同。Android堆转储的主要不同是由于很多的内存分配是在Zygote进程中。但是由于Zygote的内存分配是所有应用进程共享的,这些对分析应用堆没什么关系。
为了分析堆转储,你需要像jhat或Eclipse内存分析工具(MAT)一样的标准工具。当然,第一步需要做的是把HPROF文件从Android的文件格式转换成J2SE HRPOF的文件格式。可以使用<sdk>/platform-tools/路径下的hprof-conv工具来转换。hprof-conv的使用很简单,只要带上两个参数就可以:原始的HPROF文件和转换后的HPROF文件的存放位置。例如:
Java
1
hprof-conv heap-original.hprof heap-converted.hprof
注意:如果使用的是集成在Eclipse中的DDMS,那么就不需要再执行HPROF转换操作——默认已经转换过了。
现在就可以在MAT中加载转换过的HPROF文件了,或者是在可以解析J2SE HPROF格式的其它堆分析工具中加载。
分析应用堆时,应该查找由下导致的内存泄露:
对Activity、Context、View、Drawable的长期引用,以及其它可能持有Activity或Context容器引用的对象
非静态内部类(例如持有Activity实例的Runnable)
不必要的长期持有对象的缓存
使用Eclipse内存分析工具
Eclipse内存分析工具(MAT)是一个可以分析堆转储的工具。它是一个功能相当强大的工具,功能远远超过这篇文档的介绍,这里只是一些入门的介绍。
在MAT中打开类型转换过的HPROF文件,在总览界面会看到一张饼状图,它展示了占用堆的最大对象。在图表下面是几个功能的链接:
Histogram view显示所有类的列表和每个类有多少实例。
正常来说类的实例的数量应该是确定的,可以用这个视图找到额外的类的实例。例如,一个常见的源码泄露就是Activity类有额外的实例,而正确的是在同一时间应该只有一个实例。要找到特定类的实例,在列表顶部的<Regex>域中输入类名查找。
当一个类有太多的实例时,右击选择List objects>with incoming references。在显示的列表中,通过右击选择Path To GC Roots> exclude weak references来确定保留的实例。
Dominator tree是按照保留堆大小来显示的对象列表。
应该注意的是那些保留的部分堆大小粗略等于通过GC logs、heap updates或allocation tracker观察到的泄露大小的对象。
当看到可疑项时,右击选择Path To GC Roots>exclude weak references。打开新的标签页,标签页中列出了可疑泄露的对象的引用。
注意:在靠近饼状图中大块堆的顶部,大部分应用会显示Resources的实例,但这通常只是因为在应用使用了很多res/路径下的资源。
图4.MAT显示了Histogram view和搜索”MainActivity”的结果。
想要获得更多关于MAT的信息,请观看2011年Google I/O大会的演讲–《Android 应用内存管理》(Memory management for Android apps),在大约21:10 的时候有关于MAT的实战演讲。也可以参考文档《Eclipse 内存分析文档》(Eclipse Memory Analyzer documentation)。
对比堆转储
为了查看内存分配的变化,比较不同时间点应用的堆状态是很有用的方法。对比两个堆转储可以使用MAT:
1.按照上面描述得到两个HPROF文件,具体查看获取堆转储章节。
2.在MAT中打开第一个HPROF文件(File>Open Heap Dump)。
3.在Navigation History视图(如果不可见,选择Window>Navigation History),右击Histogram,选择Add to Comp are Basket。
4.打开第二个HRPOF文件,重复步骤2和3。
5.切换到Compare Basket视图,点击Compare the Results(在视图右上角的红色“!”图标)。
触发内存泄露
使用上述描述工具的同时,还应该对应用代码做压力测试来尝试复现内存泄露。一个检查应用潜在内存泄露的方法,就是在检查堆之前先运行一会。泄露会慢慢达到分配堆的大小的上限值。当然,泄露越小,就要运行应用越长的时间来复现。
也可以使用下面的方法来触发内存泄露:
1.在不同Activity状态时,重复做横竖屏切换操作。旋转屏幕可能导致应用泄露 Activity、Context 或 View对象,因为系统会重新创建 Activity,如果应用在其它地方持有这些对象的引用,那么系统就不能回收它们。
2.在不同Activity状态时,做切换应用操作(切换到主屏幕,然后回到应用中)。
提示:也可以使用monkey测试来执行上述步骤。想要获得更多运行 monkey 测试的信息,请查阅 monkeyrunner 文档。
❻ 如何禁用win7的ASLR
一些原来XP下有的,不过不能很好的发挥作用。这些机制包括/GS安全编译选项、SafeSEH、SEHOP,还有最重要的两个ASLR和DEP的结合。
❼ framework3.0.exe是什么意思
是一个新的Windows编程框架 微软今天发布了.NET Framework 3.5第一个SP服务包的最终版。这是一个累积更新,包含很多基于.NET Framework 2.0、3.0和3.5不断生成的新功能,此外还包括.NET Framework 2.0 SP2和.NET Framework 3.0 SP2累积更新,支持x86、x64、IA64三种架构。.NET Framework 3.5 SP1集成了此前发布的三十个相关Hotfix热修复补丁,同时还引入了不少新特性和改进:1.ASP.NET动态数据,它提供了丰富的框架,从而使用户可以快速进行数据驱动的开发,而无需编写代码;ASP.NET AJA 的一项新增功能,对管理浏览器历史记录提供了支持(支持后退按钮)。有关更多信息,请参见ASP.NET和Web开发中的新增功能。2.对公共语言运行时的核心改进包括:改进了.NET Framework本机映像的布局、选择不再对完全受信任的程序集进行强名称验证、提高了应用程序启动性能、改进了生成的代码以缩短端对端应用程序执行时间、选择在ASLR(地址空间布局随机化)模式下运行托管代码(如果操作系统支持)。此外,从网络共享打开的托管应用程序在完全受信任环境下运行时与本机应用程序具有相同的行为。3.提高了Windows Presentation Foundation的性能,包括缩短了启动时间,提高了与位图效果有关的性能。WPF的其他新增功能包括:改善了对业务线应用程序、本机初始屏幕、DirectX 像素着色器的支持,并且新增了WebBrowser控件。4.ClickOnce应用程序发行者可以决定在适当情况下不进行签名和加密,开发人员可以编程方式安装ClickOnce应用程序以显示自定义署名,并且ClickOnce错误对话框支持链接到Web上应用程序特定的支持网站
❽ Google与微软互怼,看看谁的浏览器沙箱更安全
前言
Google安全团队Project Zero曾多次揭露微软产品的安全漏洞,有几次更在微软修补前即公布,惹来微软的不满。双方曾为此隔空交战,微软在10月18号也揭露了Chrome浏览器漏洞,并指责其沙箱安全性不足,修补政策无法有效防止黑客攻击。
下面就让我具体分析一下此次事件,看看微软说的有没有道理。让我先从Chrome开始,看看Chrome是如何阻止一个RCE漏洞的,然后进一步探讨是否有强大的沙箱模式足以使浏览器达到最安全的状态。
通过取证分析,我发现了Chrome所包含的以下漏洞:
1.CVE-2017-5121漏洞表明在Chrome中有RCE漏洞;
2.Chrome缺乏预防RCE漏洞的技术,这意味着从发现漏洞到使用漏洞的时间会很短;
3.在Chrome沙箱内进行的几次安全检查表明,RCE能够绕过同源策略(SOP),让攻击者访问受害者的在线服务(如电子邮件、文档和银行会话)并保存登录凭据;
4.由于Chrome的漏洞处理流程是先向用户公开披露漏洞细节,所以很可能使得漏洞在修复之前被滥用。
发现并利用一个RCE漏洞
要发现漏洞,就要首先找到一个异常现象。通常,我们都会找到内存漏洞,如缓冲区溢出或UAF漏洞来来实现此目的。对浏览器的攻击方法多种多样,包括V8 JavaScript引擎编译、Blink DOM引擎和pdfium PDF渲染器等,其中V8编译是本文的重点。
本文所使用的CVE-2017-5121漏洞就是微软使用基于Azure的漏洞检查工具ExprGen发现的。ExprGen是通过监测Chrome浏览器所使用的V8 JavaScript引擎,从而发现的CVE-2017-5121。
译者注:Google在2014将其V8JavaScript 解析引擎移到Github地址是:https://github.com/v8/v8。****V8是Google发布的开源 JavaScript引擎,采用C++ 编写,在Google的Chrome浏览器中被使用。V8 引擎可以独立运行,也可以用来嵌入到C++应用程序中执行。
识别漏洞
与手动审查代码相比,基于Azure的自动化模糊检测的缺点就是不能很快地分析出漏洞发生的原因。
由于模糊检测技术经常产生大量复杂的代码片段,所以在使用ExprGen检测时,首先要将测试样本的代码进行精简,只留下一些能够识别的代码。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
当使用D8运行此代码时,V8的独立可执行版本由git标签6.1.534.32构建,我们会遇到崩溃:
这段代码的任务就是创建一个奇怪的结构化对象,然后设置一些字段。虽然从理论上讲,这不应该引发任何奇怪的行为,但实际上却出现了一些运行结果。当使用D8运行这段代码运行时,发现V8的独立可执行版本是由git标签6.1.534.32构建,此时会出现一次崩溃(如下图)。
译者注:如果你想了解如何使用D8分析javascript被V8引擎优化,请点此链接。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
由上图可以看出,崩溃发生的地址是0x000002d168004f14,因此我可以断定该崩溃是不会发生在静态模块中的。因此,它必须是由V8的just-in-time(JIT)编译器动态生成的。还能看到,崩溃发生是因为rax寄存器是零。
乍一看,这看起来像空引用异常(null dereference bug),如果是这样的话就没有什么可讲的了,因为这些异常通常不是可利用的,因为目前的操作系统会禁止零虚拟地址(zero virtual address)的映射。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
我可以从上图的代码中发现两个有用的线索:
首先,可以注意到崩溃发生在一个函数调用之前,该函数看起来像一个JavaScript函数调度器存根,这主要是由于v8::internal::Builtin_FunctionPrototypeToString的地址被加载到该调用之前的一个寄存器中。看看位于0x000002d167e84500的函数代码,我发现地址0x000002d167e8455f确实包含一个调用rbx指令,这似乎证实了我的怀疑。
调用Builtin_FunctionPrototypeToString很有趣,因为这是Object.toString方法的实现。这似乎表明崩溃发生在func0 Javascript函数的JIT编译器中。
其次,在崩溃时寄存器rax中包含的零值是从内存中加载的。这个过程看起来像是原本应该被加载的值被传递给作为参数的toString函数调用,并且是从[rdi + 0x18]加载的,以下就是内存加载的部分代码。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
以上代码并没有包含什么有价值的信息,因为大多数值都是指针。但是,分析指针的来源却很有用,因为它可以帮助我弄清楚为什么这个值一开始就为零。使用WinDbg最新公布的“时间旅程调试(TTD)” 功能,我可以在该位置上放置一个内存写入断点(baw 8 0000025e ' a6845dd0),然后在函数的起始处放置一个执行断点,最后重新反过来进行跟踪(g -)。
有趣的是,放置的内存写入断点并不会被触发,这意味着这个内存数据不会在这个函数中被初始化,或者至少在使用之前不会被初始化。但如果我对测试样本进行一些处理,例如把o.b.bc.bca.bcab = 0;替换成o.b.bc.bca.bcab = 0xbadc0de;,然后就可以发现崩溃值源自于内存区域的变化:
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
由上图可以看到, 0xbadc0de常数值最终出现在内存区域中。尽管这并没有证明什么,但却似乎表明,这个内存区域被jit编译的函数使用过,用来存储局部变量,因为开始处的代码看起来像是前面被传递给Object.toString作为参数的加载值。
结合TTD确认该内存槽未被该功能初始化的事实,可能的解释是JIT编译器无法发出将初始化表示用于访问o.b.ba.bab字段的对象成员的指针代码。
为了证实我的推断,我可以用-trace-turbo和-trace-turbo-graph参数在D8中运行测试样本。这样,D8就会输出有关TurboFan,V8的JIT编译器如何构建和优化相关代码的信息。Javascript 引擎 V8采用的是新的引擎:TurboFan 和 Ignition,其中 Turbofan 是新的优化编译器,而 Ignition 则是新的解释器。
TurboFan的工作原理是将各个阶段的优化信息都转化成对象映射图,如下图所示。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
可以看出优化器将func0嵌入到无限循环中,然后拉出第一个循环进行迭代。这些信息有助于了解这些功能块之间如何相互关联。然而,用映射图进行表示的缺点就是无法表示对应于加载函数调用参数的节点,以及局部变量的初始化。
幸运的是,我们可以使用turbolizer来显示出这些内容。关注第二个Object.toString调用,我可以看到参数的来源,以及它被分配和初始化的位置:
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
在优化流程的阶段,代码看起来完全合理:
1.分配存储块以存储局部对象o.b.ba(节点235),并且其字段baa和bab被初始化;
2.分配存储块以存储局部对象o.b(节点259),并且其字段都被初始化,其中ba专门用对前一个o.b.ba分配的引用来初始化;
3.分配存储块以存储局部对象o(节点303),并且其字段都被初始化;
4.局部对象o的字段b被具有对象o.b(节点185)的引用覆盖;
5.局部对象字段o.b.ba.bab被加载(节点199,209和212);
6.调用Object.toString方法,将o.b.ba.bab作为第一个参数传递。
不过,优化过程中编译的代码不应该显示未初始化的局部变量行为,所以我可以假设这chrome漏洞发生的根本原因。话虽如此,这只是我的一个假设。查看分别被加载到o.b.ba和o.b.ba.bab的节点209和212,它们被用作函数调用参数,如下图,我可以在偏移量+ 24和+ 32处看到被反汇编过的崩溃代码。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
0x17和0x1f分别为23和31,考虑到V8标签的值可以区分实际对象与内联整数(SMI),可以进行这样的推测:如果一个表示JavaScript变量的值具有最低有效位设置,则被视为指向对象的指针,否则就是SMI。因此,在取消引用(dereferencing)之前,可以使用V8代码进行优化,减去一个JavaScript对象的偏移量。
不过到目前我还是没有找出chrome漏洞的原因,所以我会继续进行优化以找到原因。之后我进行了逃逸分析(Escape Analysis) ,分析试图如下所示。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
可以看出,有两个显着的不同:
1.代码不需要从o加载到o.b,被优化后直接引用o.b,我想可能是因为该字段的值从未更改过;
2.代码不再初始化o.b.ba,从上图中可以看出,turbolizer输出了节点264,这意味着它不再是实时的,因此不会被嵌入到最终的代码中。
此时,查看所有的活动节点似乎都确认这个字段不会再被初始化了。不过为了保险起见,我还是在这个带有–no-turbo-escape标志的测试样本上运行d8,以跳过此优化阶段。结果我发现d8不再崩溃,所以可以确定这就是漏洞的真正原因。其实, Google已在v8 6.1中完全禁用了逃逸分析阶段,只有在v8 6.2中才会发生逃逸分析。
现在我已经掌握了该漏洞的所有信息,不过为了深度验证此漏洞,我还要想办法利用它,看看它是不是一个攻击力很大的漏洞,不过这完全取决于我控制未初始化的内存插槽的能力。
获取泄漏信息
此时,利用漏洞的最简单的方法是对样本进行简单地处理。例如,可以从未初始化的指针中更改正在加载的字段类型,看看会出现什么反应:
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
其结果是,该字段现在直接被加载为一个FLOAT 数据类型,而不是一个对象指针或SMI:
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
同样,我可以尝试在对象中添加更多字段:
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
运行以上的代码段,可以得到以下崩溃:
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
这很有趣,因为它看起来像是将字段添加到经过对象修改的偏移量中,其中该偏移量的位置位于被加载的对象字段中。如果你感兴趣,可以做个数学运算,你会看到(0x67 – 0x1f)/ 8 = 9,这恰好是我从o.b.ba.bab中添加的字段数量。这同样适用于从rbx加载的新偏移量。
经过对测试样本进行更多的操作后,我可以确认,即使这些字段没有被初始化,我还是能对未初始化的指针加载的偏移量进行控制。现在,就让我检测一下,看看是否可以将任意的数据放到这个内存区域中发生反应。使用0xbadc0de进行的早期测试似乎肯定了我的检测,不过每个测试样本的每次运行所检测出的偏移量都不一样。通常情况下,我会利用喷洒数值(spray value)的方式来解决这些问题。其原理是这样的:如果我不能准确地将目标锁定到给定的位置,那我就可以让目标范围扩大。在实践中,我经常使用内嵌数组(inline array)来扩大数值范围。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
发生的故障转储(crash mp)如下所示:
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
可以看出,崩溃与以前基本相同,但如果我查看来自内存的未初始化数据,你会发现如下的情况。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
在r11的偏移位置处,我可以看到一大块由任意脚本控制的值。将这个发现与之前的偏移量相结合进行分析,我可以得出更靠谱的结论。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
由上图可以看出,我取消了任意地址的float值:
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
当然,这是非常强大的,因为它会立即导致任意读取原语。但不幸的是,没有初始信息泄漏的任意读取原语在实践中并不是很有用的,因为我需要知道要读取哪些地址才能使用它。
变量v可以替换成任何我想要的东西,比如,我可以用一个对象替换它,然后读取它的内部字段。再比如,我可以使用自定义的回调来替换对Object.toString()的调用,并将V替换为DataView对象,从而读取该对象的备份存储地址,这就为我提供了一种找到完全由脚本控制的数据的方法。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
以上就是返回的代码(以ASLR为模型):
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
使用WinDbg,就可以验证这是我的缓冲区的后备存储器。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
由于这是一个非常强大的原语,我可以使用它来泄漏任何来自对象的字段,以及任何JavaScript对象的地址,因为这些对象有时会存储为其他对象中的字段。
构建任意的读/写原语
能够在已知地址处放置任意数据,就意味着我可以构建一个更强大的原语,因为此时我已经具备了创建任意JavaScript对象的能力。只需改变从float读取到的对象的字段类型,我就可以从内存中的任何地方读取对象指针,比如已知地址的缓冲区。我可以使用WinDbg在已知的地址(上面发现的原语)中使用以下命令来进行测试:
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
这将在我的任意对象指针的加载位置放置一个表示整数0xbadc0de的SMI,由于我没有设置最低有效位,它将被V8解释为内联整数:
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
正常情况下,V8会打印以下输出:
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
鉴于此,我就可以创建任意对象,比如,我可以通过创建假的DataView和ArrayBuffer对象来组合一个我使用起来很方便的任意读/写原语。现在,我会再次使用WinDbg将我的假对象数据放在已知位置。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
然后我会用以下JavaScript进行测试:
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
如预期的那样,调用DataView.prototype.setUint32会触发崩溃,因为调用会尝试将0xdeadcafe值写入0x00000badbeefc0de地址。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
可以看出,数据写入或读取的地址被控制了,该问题只是修改通过WinDbg填充的obj.arraybuffer.backing_store插槽所出现的问题之一。因为在实际的漏洞中,内存将成为真正的ArrayBuffer对象的后备存储器的一部分,要实现这点很容易,例如,写入如下所示的原语。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
这样,我就可以在JavaScript的Chrome渲染程序中可准确地读写任意内存位置。
实现任意代码执行
只要有任意读/写原语,就可以很容易地在Chrome渲染程序中实现代码执行。由于V8会将其JIT代码页分配给读写执行(RWX)权限,这意味着可以通过定位一个JIT代码页,然后覆盖该页面,最后通过调用来完成代码执行。在实际操作过程中,可以通过使用我的信息泄漏来定位JavaScript函数对象的地址并读取其函数entrypoint字段来实现。一旦我将代码放在了入口点,就可以调用JavaScript函数来执行代码。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
值得注意的是,即使V8没有使用RWX页面,由于缺乏对控制流程的完整性检查,仍然很容易触发返向导向编程(ROP)链的执行。如果发生这种情况,可以通过重写JavaScript函数对象的entrypoint字段来指向所需的gadget,然后进行函数调用。
不过,这些技术都不能直接用于具有CFG和ACG功能的Microsoft Edge。在Windows 10 Creators Update中引入的ACG会执行严格的数据执行保护(DEP),并将JIT编译器移动到外部进程。这就形成了一个强大的防御,即攻击者在不破坏JIT进程的情况下,是不能重写可执行代码的,这就需要发现和开发其它的漏洞。
其次,CFG保证了间接调用站点只能跳转到某一组函数,这意味着该函授不能用于直接启动ROP执行。另外, win10 creators update还引入了CFG导出抑制,通过将大部分导出的函数从有效的目标集合中删除,从而大大减少了有效的CFG间接调用目标集,所有这些缓解措施都使得黑客很难利用Microsoft Edge中的RCE漏洞。
RCE漏洞的危险
Chrome采用多进程模式,涉及到多种流程类型,比如浏览器进程,GPU进程和渲染器进程。
每个渲染器都会负责解析和解释对应网页的的HTML,JavaScript等。沙箱模型使得这些进程只能访问其需要的功能。因此,我无法通过渲染器中对受害者的系统进行攻击。
如此一来,我就要考虑攻击者有没有可能使用了其它的漏洞完成攻击。虽然大多数选项卡的进程中都是进行单独隔离的,但还是有些特殊情况,例如,如果在bing.com上使用JavaScript开发者控制台(可以通过按F12打开该控制台)来运行window.open('https://microsoft.com'),则会打开一个新的选项卡,但新的选项卡通常会与原始标签的进程完全相同。这可以通过使用Chrome的内部任务管理器来看到,你可以通过按Shift + Esc来打开它。
Google与微软互怼,看看谁的浏览器沙箱更安全?
Google与微软互怼,看看谁的浏览器沙箱更安全?
这是一个有趣的观察,因为它表明渲染器进程没有被锁定到任何一个来源。这意味着在渲染器进程中实现任意代码执行就可以使攻击者访问其他来源的进程。虽然攻击者以这种方式绕过同源策略(SOP)的可能性并不大,但如果一旦发生,则后果不堪设想:
1.攻击者可以通过劫持PasswordAutofillAgent界面从任何网站窃取用户保存的密码;
2.攻击者可以将任意JavaScript注入任何页面,例如通过劫持 blink::ClassicScript::RunScript 的方法;
3.攻击者可以在用户没有注意的情况下导航到后台的任何网站,例如,通过创建隐藏的弹出式窗口。因为许多用户交互检查是发生在渲染器进程中的,无法让浏览器进行进程验证。这样,类似ChromeContentRendererClient:AllowPopup的进程就会被劫持。这样在不需要用户交互的情况下, 攻击者就可以隐藏新的窗口。他们还可以在关闭的时候继续打开新的弹出窗口,例如,通过连接到onbeforeunload窗口事件。
这种攻击更好地研究并实施了渲染器和浏览器进程如何相互通信并直接模拟相关消息,但这表明这种攻击可以在有限的努力下实现。虽然双重身份验证的民主化减轻了密码盗窃的危险,但是由于可以让攻击者在已经登录的网站上欺骗用户的身份,所以不可认为双重认证就是绝对可靠的。
这表明只要在渲染器和浏览器进程的通信中做点文章,即使用户采用了双因素身份验证,攻击者还是能够达到盗取账号的目的的。
总结
客观地讲,Google与微软互怼的结果,会让普通的用户受益,因为每个浏览器都有其长板和短板,互相竞争的结果迫使它们不得不努力改善自己以吸引用户。就Microsoft Edge而言,目前它正在继续改进隔离技术,并使得任意代码执行难以实现。就Google而言,Google正在开发一个网站隔离功能,一旦该功能实现,Chrome就可以通过保证任何给定的渲染器进程只能与单一来源进行交互,这样Chrome就能轻松应对RCE攻击。
❾ 如何从零开始写一个简单的操作系统
早先写过一个玩具内核,现在正做操作系统课助教,带一伙学弟学妹做这个事情。 假定题主对操作系统有一定的认识(被丢去裸考期末考试不会挂科)。 总体路线图大约是这样的: *以下内容全是干货,试图在不干预题主自己的设计的条件下尽可能指出所有的大坑,此方案不能代替看书/读论文/上课/看手册等* 第一阶段:早期规划 1. 搞清楚自己打算写一个内核干啥:试着设计?练习实现?拿来实用的话打算跑什么呢?打不打算跨平台?打算跨哪些平台,兼容到什么程度? 2. interface大概会长什么样?给用户空间提供哪些服务?(并不一定要和现有系统兼容或者怎么样) 3. 想怎么样boot?兼容一个现有bootloader还是自己写一个?内核被load的时候是什么格式? 第二阶段:方案设计 4. 选个架构吧,推荐IA32或者ARMv7A之类的 5. 找到各种手册翻看一下,脑内构思一下内核里各种机制该用什么方案实现 6. 选个目标设备吧,qemu可以玩玩但是内核都写了,还是上个设备跑一跑比较好。(如果你打算在树莓派上做的话下一步你会比较郁闷) 7. 这个设备的启动流程怎么样,和之前的想法有没有冲突? 8. 找到各种手册看一下,之前想好的实现方案有没有坑?时钟、中断、DMA之类的,大概怎么搞,心里要有数了。 9. 想不想要JTAG之类的调试方案?有没有?方不方便? 10. 提前组织一下模块划分、代码结构、编译管理方案等。 第三阶段:初步实施 11. 选好之后就把设备买下吧,需要的SD卡啦电源啦都买下,按照noobs' kit之类的东西试试好不好用 12. 准备工具链。在linux上你需要gcc和binutils。libgcc要不要加?不加的话有什么坑?(CortexA9没有硬件整数除法我说的就是你)怎么处理? 13. 编写字符输出驱动,不管是UART还是IA32的默认控制台或者是什么的。 14. 编写Hello world并作为最简单的内核或者bootloader运行。 15. (如果自己写bootloader)读启动介质的驱动和你想load的内核格式的支持代码应该写出来了。内核load到哪里去?内核想要load到非常奇怪的地址(比如设备区或者和bootloader重叠)怎么办? 16. 平台初始化要做一做了吧?页表准备一下该开MMU了吧?说道MMU就要说缓存,目标架构上缓存需要内核做哪些维护?如何启用?设备区怎么处理?(MIPS没有硬件table walker这种事情也要在这里处理掉) 17. 要不要跳虚拟地址?虚拟地址空间怎么划分? 第四阶段:各种内核组件 18. 一套完整的线性映射能不能容纳?不能的话怎么办?类似vmalloc和ioremap的机制,要实现的话需要提前规划好。 19. 物理内存怎么管理?连续页的分配和回收使用怎样的算法? 20. 任意大小内存块的分配和释放要怎么处理?有没有什么会要求非常大块的对齐(ARM的一级页表你别跑),怎么办? 21. 虚拟地址空间怎么管理?用户空间的和内核自己的虚拟地址空间管理方案可不一样的。 22. 中断和出错该怎么处理?向量表怎么搞?中断路由怎么设置? 23. 系统调用使用怎样的格式?中断信息获取之类的杂务该怎么做? 24. 上下文保存和恢复应该怎么做?保存哪些内容? 25. 各种驱动程序怎样部署和运行?静态携带还是动态注册?有没有打算做内核模块机制?怎么做?驱动的特权级要不要低于内核?怎么实现?驱动要不要参与未来的调度?和用户空间比有什么特别的? 26. 进程和线程打算怎样实现?依靠用户空间的库来调度还是像linux这样做线程和线程组?进程描述符长什么样? 27. 时钟怎么用?时钟比较器是共享的还是独享的? 28. 调度算法是怎样的?有没有什么好处坏处? 29. 自旋锁该怎么实现?有哪些使用要求? 30. 内核提供哪些同步机制?怎么实现? 31. 超过一个CPU的话,其他核心怎样唤醒?唤醒之后哪些初始化需要另做? 32. 各种系统调用内部该如何实现? 第五阶段:和用户态的配合 33. 怎样把提供的系统调用包成一个C库一类的东西? 34. 做哪些文件系统支持?内核要不要导出虚拟文件系统?控制台输入输出算不算文件? 第六阶段:可选内核组件 35. 管道、共享内存等IPC方案? 36. 动态挂载和卸载文件系统? 37. 前面提到过的内核模块? 38. kexec和kmp一类的机制? 39. ASLR?运行禁止?其他一些被动安全机制? 40. 随机数生成器? 41. 安全内存?处理器的加密解密部件? 42. 缺页和换页? 43. 区分一下用户?组?密码?shadow? 44. 文件权限?SUID/SGID? 45. 用户态的init差不多应该负担一些责任了? 46. 管理一下电源和频率?idle的时候做点节能? 47. 用文件/文件系统的方式和内核做一些交互? 48. 网络?路由?名称服务?防火墙? 49. 动态的设备管理?热插拔? 50. (我想不出更多了)来点图形界面?