10.06
Hi fellas
This is again Snake with his poor English
. when m08-67 vulnerability exploited successfully by metasploit guys , i got experience on dep .now i think it is good time ( i know it is a little late
) to public my information about this protection. in this post i try to explain some things that i found about dep internals and NtSetInformationProcess function.
Paging,Page Table,Page Directory
in IA-32 arch architect and Memory Virtualazation , CPU and OS are using mechanism called paging.they use paging for mapping linear address space to physical memory . linear address space is CPU addressable space and physical memory is physically connected memory , like RAM or ROM.and mapping is mechanism that translate an address in Virtual memory or Linear Address space to its equal in physical memory. with out paging and Virtualazation , CPU translate an address directly to Physical memory. but in Memory Virtualazation , whole address space divided into short fix size blocks called Page.pages can present in different size , but usually are 4 kb in IA-32 . Page-Directory is 32 bit array of pointers to Page-Tables . and Page Table is 32 bit array that contain address of each page in physical memory. now CPU for mapping an address from Linear Address Space to Physical memory go to desire Page-Directory and find exact Page-Table.then it find correct address from Page and … . figure.1 show this mechanism in better way :
bellow you can see Page-Directory and Page-Table arrays :
PD and PT bits are not in important for us , just an imagination of what they are and what they do . by setting Present bit whole array use for storing address and other bits overwritten by addresses
.in this type of IA-32 paging mechanism, a OS can support and address only 2^32 bits , form 0 to FFFFFFFF. in other word you can have only 4 gig memory for each process . Intel introduced Page Address Extension ( PAE ) for obviating this limits.by using PAE supported CPUs OS can have 2^36 bit address space and it mean 64 gig memory for each process ! for using this advantage Intel changed Page-Table and Page-Directory to 64 bit array. above figure show changed PD and PT :
PAE moreover 64 gig address space, introduced new bit in Page-Table called NX bit ( Execute Disable , Non-Execute ) .this bit is new protection mechanism in paging related protections such as setting privilege ( R\W ) for Pages . with NX we can mark a page as non executable . there is many Pages that are use only for holding Data and they are executable so . why let them executable ? so by setting this bit OS separate Page for holding Executable Data and Non-Executable data. by this mechanism data related spaces such as Stack,Heap and data section became non-executable and this is Game Over for Exploits that run shellcode from stack or other data sections.
Linux Kernel NX Patch
lets take look at one of first linux Kernel NX patch for better understanding of this protection. at the first we have :
movl %eax,%cr4 btl $5, %eax # check if PAE is enabled jnc 6f /* Check if extended functions are implemented */ movl $0x80000000, %eax cpuid cmpl $0x80000000, %eax jbe 6f mov $0x80000001, %eax cpuid /* Execute Disable bit supported? */ btl $20, %edx jnc 6f
cr4 control register loaded into eax , fifth bit of CR4 contain a sign for supporting PAE tech . if it presented we have PAE if not no PAE. BT instruction used for bit testing and CF will receive its result. after that we use CPUID:80000001 instruction for NX bit checking. 20 bit of edx will recive the result and like PAE checking we have bt instruction again.i skip some functions that are written for mapping kernel address space to physical memory .after that we have function for catching NX in Page-Table :
static void __init set_nx(void)
{
unsigned int v[4], l, h;
if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
if ((v[3] & (1 << 20)) && !disable_nx) {
rdmsr(MSR_EFER, l, h);
l |= EFER_NX;
wrmsr(MSR_EFER, l, h);
use_nx = 1;
__supported_pte_mask |= _PAGE_NX;
}
}
}
then Kernel setup Page-Table by paging_init() function and set NX bit in pages ( if it is compatible ) :
void __init paging_init(void)
{
#ifdef CONFIG_X86_PAE
set_nx();
if (use_nx)
printk("NX (Execute Disable) protection: active\n");
else
printk("NX (Execute Disable) protection: not present!\n");
#endif
pagetable_init();
[...]
now all the Pages are setuped with NX bit enable . for alocating executable Pages Kernel use vmalloc_exec() function :
void *vmalloc_exec(unsigned long size)
{
return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC);
}
Exploitation Limits After NX
as you can see , NX snatch us permission of executing code from data marked pages. so if we want to exploit a vulnerability by jumping into data preserve page with NX enable , we got Access Violation Exception ( actually a Page Fault ). now Heap , Stack and Data sections are non-executable .the only Executable memory is Code or text section , but it is write protected !
Windows and NX Bit
windows memory management system also take advantage of NX bit to defeat Stack/Heap/Date base buffer overflow exploits. windows intruduce this protection in the term of Hardware Enforce Data Execution Prevention or just DEP in brevity. if CPU dosnt suppurt NX bit , there is very limit version of DEP , called Software DEP. it is not like Linux patch non-exportability emulation and just ensure that SEH Handler is located in executable Page ( not Stack or Heap ). DEP is configurable also and you can disable it from boot.ini or boot management in Vista . there is copy-pasted text of boot configuration from Wikipedia
.
The Boot.ini file settings are as /noexecute=policy_level, where policy_level is defined as one of the following values:
OptIn
This setting is the default configuration for Windows XP. On systems with processors that can implement hardware-enforced DEP, DEP is enabled by default for limited system binaries and programs that “opt in”. With this option, only Windows system binaries are covered by DEP by default and cannot be disabled without changing the policy to “AlwaysOff”. This is also the default in Windows Vista; however in 64-bit Vista 64-bit applications are always opted in. [8]
OptOut
This setting is the default configuration for Windows 2003 SP1. DEP is enabled by default for all processes. A list of specific programs that should not have DEP applied can be entered using the System dialog box in Control Panel. Network administrators can use the Application Compatibility Toolkit to “opt out” one or more programs from DEP protection. System compatibility fixes, or shims, for DEP do take effect. Also note that Windows silently disables DEP for certain executables, such as those packaged with ASPack. [9]
AlwaysOn
This setting provides full DEP coverage for the whole system. All processes always run with DEP applied. The exceptions list to exempt specific programs from DEP protection is not available. System compatibility fixes for DEP do not take effect. Programs that have been opted out by using the Application Compatibility Toolkit run with DEP applied.
AlwaysOff
This setting does not provide any DEP coverage for any part of the system, regardless of hardware DEP support.
DLLs And DEP Compatibly
there is also a mechanism for detecting DEP incompatible binaries .at binary loading stage , OS call a LdrpCheckNXCompatibility() function. LdrpCheckNXCompatibility() make some experiences on binary to known DEP compatibility/ incompatibility. for example by if there is sections like .aspack , .sforce or any other signature base sections of packers , the binary is DEP incompatible.if binary is listed in HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNt\CurrentVersion\Image File Execution Option\DllNXOptions registery key it is also incompatible , this key is list of DEP incompatible PEs . if binary have IMAGE_DLL_CHARACTERISTICS_NX_COMPAT set in DllCharacteristics field of its optional header its DEP compatible ( by 0×0100 value ) . this filed will set if binary is linked with /NXCOMPAT linker option.what happen if a dll wasn’t DEP compatible ? in this situation LdrpCheckNXCompatibility() disable DEP for that specific incompatible process at runtime. but how ?
Disabling DEP at Runtime
LdrpCheckNXCompatibility() function use NtSetInformationProcess function to disable DEP for a specific process .there is NteSetInformationProcess function prototype :
NTSYSAPI NTSTATUS NTAPI NtSetInformationProcess( IN HANDLE ProcessHandle, IN PROCESS_INFORMATION_CLASS ProcessInformationClass, IN PVOID ProcessInformation, IN ULONG ProcessInformationLength );
for setting specific characteristic of a process , Nt SetInformationProcess() use ProcessInformationClass structure .see this structure in above :
typedef enum _PROCESSINFOCLASS {
ProcessBasicInformation,
ProcessQuotaLimits,
ProcessIoCounters,
ProcessVmCounters,
ProcessTimes,
ProcessBasePriority,
ProcessRaisePriority,
ProcessDebugPort,
ProcessExceptionPort,
ProcessAccessToken,
ProcessLdtInformation,
ProcessLdtSize,
ProcessDefaultHardErrorMode,
ProcessIoPortHandlers, // Note: this is kernel mode only
ProcessPooledUsageAndLimits,
ProcessWorkingSetWatch,
ProcessUserModeIOPL,
ProcessEnableAlignmentFaultFixup,
ProcessPriorityClass,
ProcessWx86Information,
ProcessHandleCount,
ProcessAffinityMask,
ProcessPriorityBoost,
ProcessDeviceMap,
ProcessSessionInformation,
ProcessForegroundInformation,
ProcessWow64Information,
ProcessImageFileName,
ProcessLUIDDeviceMapsEnabled,
ProcessBreakOnTermination,
ProcessDebugObjectHandle,
ProcessDebugFlags,
ProcessHandleTracing,
ProcessIoPriority,
ProcessExecuteFlags,
ProcessResourceManagement,
ProcessCookie,
ProcessImageInformation,
MaxProcessInfoClass
} PROCESSINFOCLASS;
each entry in ProcessInformationClass point to the specific variable . for example ProcessBasicInformation point to structure named PROCESS_BASIC_INFORMATION and defined in NTDDK.H .
typedef struct _PROCESS_BASIC_INFORMATION {
NTSTATUS ExitStatus;
PPEB PebBaseAddress;
ULONG_PTR AffinityMask;
KPRIORITY BasePriority;
ULONG_PTR UniqueProcessId;
ULONG_PTR InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION;
typedef PROCESS_BASIC_INFORMATION *PPROCESS_BASIC_INFORMATION;
now we can set information of this structure for our selected process by calling NtSetInformationProcess like ( i don’t know coding like this is valid or not ,because i doesn’t find any public example of using NteSet… ):
PROCESS_BASIC_INFORMATION P_B_I; P_B_I.ExitStatus = 0; P_B_I.PebBaseAddress = 0x7FFDF000; P_B_I.InheritedFromUniqueProcessId = 666; [...] NtSetInformationProcess(-1, ProcessBasicInformation, &P_B_I, 0x018);
as you can see , first argument is process handle with PROCESS_SET_INFORMATION access and -1 id defined by windows for current process. second argument is entry of ProcessInformationClass structure that we want to set , in this case is ProcessBasicInformation . third argument is pointer to modified/seted structure same as a second argument.and finally forth argument is size of second/third argument structure.for each entry of ProcessInformationClass in the NtSetInformationProcess is switch-case block for setting desire informations. for example for setting ProcessAffinityMask :
NTSTATUS WINAPI NtSetInformationProcess(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
IN PVOID ProcessInformation,
IN ULONG ProcessInformationLength)
{
NTSTATUS ret = STATUS_SUCCESS;
switch (ProcessInformationClass)
{
[...]
ProcessAffinityMask:
if (ProcessInformationLength != sizeof(DWORD_PTR)) return STATUS_INVALID_PARAMETER;
if (*(PDWORD_PTR)ProcessInformation & ~(((DWORD_PTR)1 << NtCurrentTeb()->Peb->NumberOfProcessors) - 1))
return STATUS_INVALID_PARAMETER;
SERVER_START_REQ( set_process_info )
{
req->handle = wine_server_obj_handle( ProcessHandle );
req->affinity = *(PDWORD_PTR)ProcessInformation;
req->mask = SET_PROCESS_INFO_AFFINITY;
ret = win_server_call( req );
}
SERVER_END_REQ;
break;
[...]
for us there is only one important entry in ProcessInformationClass structure and that is ProcessExecuteFlags. by using this entry in NtSetInfromationProcess() we can Enable/Disable DEP for specific process. DEP setting for a procees is defined in KEXECUTE_OPTIONS field of KPROCESS structure :
DISPATCHER_HEADER Header /* 000 */
LIST_ENTRY ProfileListHead; /* 010 */
PHYSICAL_ADDRESS DirectoryTableBase; /* 018 */
KGDTENTRY LdtDescriptor; /* 020 */
KIDTENTRY Int21Descriptor; /* 028 */
USHORT IopmOffset; /* 030 */
UCHAR Iopl; /* 032 */
UCHAR Unused; /* 033 */
ULONG ActiveProcessors; /* 034 */
ULONG KernelTime; /* 038 */
ULONG UserTime; /* 03C */
LIST_ENTRY ReadyListHead; /* 040 */
SINGLE_LIST_ENTRY SwapListEntry; /* 048 */
PVOID VdmTrapcHandler /* 04C */
LIST_ENTRY ThreadListHead; /* 050 */
KSPIN_LOCK ProcessLock; /* 058 */
KAFFINITY Affinity; /* 05C */
union {
struct {
ULONG AutoAlignment:1; /* 060.0 */
ULONG DisableBoost:1; /* 060.1 */
ULONG DisableQuantum:1; /* 060.2 */
ULONG ReservedFlags:29; /* 060.3 */
};
ULONG ProcessFlags; /* 060 */
};
CHAR BasePriority; /* 064 */
CHAR QuantumReset; /* 065 */
UCHAR State; /* 066 */
UCHAR ThreadSeed; /* 067 */
UCHAR PowerState; /* 068 */
UCHAR IdealNode; /* 069 */
UCHAR Visited; /* 06A */
KEXECUTE_OPTIONS Flags; /* 06B */
ULONG StackCount; /* 06C */
LIST_ENTRY ProcessListEntry; /* 070 */
KEXECUTE_OPTIONS contain 7 flag . 4 flag is used for DEP setting :
UCHAR ExecuteDisable:1; UCHAR ExecuteEnable:1; UCHAR DisableThunkEmulation:1; UCHAR Permanent:1; UCHAR ExecuteDispatchEnable:1; UCHAR ImageDispatchEnable:1; UCHAR Spare:2;
if DEP is Enable ExecuteDisable bit set by 1 . if DEP is Disable ExecuteEnable option will set . if dep is configured as OptOut both ExecuteEnable and ExecuteDisable flags set to 1 and DEP is aslo Enable . there is one another important flag , Permanent ! in windows Vista/2008/7 Microsoft take advantage of this bit to create a second layer protection against disabling DEP at runtime. in Visat/2008/7 when a program loaded for fist time this bit will set , if compatible , DEP enable and if not disable dep and set Permanent flag so. if Permanent falg set for process we cannot change DEP policy at runtime . but in prior to Vista we can change dep setting at runtime by calling NtSetInformationProcess() . this macros are defined for changing DEP policy :
#define ProcessExecuteFlags 0x22 #define MEM_EXECUTE_OPTION_DISABLE 0x01 #define MEM_EXECUTE_OPTION_ENABLE 0x02 #define MEM_EXECUTE_OPTION_PERMANENT 0x08
we are familiar with ProcessExecuteFlag as before , it is a part of ProcessInformationClass . by using MEM_EXECUTE_OPTION_DISABLE DEP enable for a process and MEM_EXECUTE_OPTION_ENABLE will disable it.lets take look at this pseudo code and see how NtSetInformationProcess() disable DEP thru this flags :
[...]
case ProcessExecuteFlags:
if (ProcessInformationLength != sizeof(ULONG))
return STATUS_INVALID_PARAMETER;
else if (execute_flags & MEM_EXECUTE_OPTION_PERMANENT)
return STATUS_ACCESS_DENIED;
else
{
BOOL enable;
switch (*(ULONG *)ProcessInformation & (MEM_EXECUTE_OPTION_ENABLE|MEM_EXECUTE_OPTION_DISABLE))
{
case MEM_EXECUTE_OPTION_ENABLE:
enable = TRUE;
break;
case MEM_EXECUTE_OPTION_DISABLE:
enable = FALSE;
break;
default:
return STATUS_INVALID_PARAMETER;
}
execute_flags = *(ULONG *)ProcessInformation;
[...]
now with this informations , we know calling NtSetInformationProcess() with this arguments , disable DEP for current process :
NtSetInformationProcess(-1, ProcessExecuteFlags, MEM_EXECUTE_OPTION_ENABLE, 0x4 )
this call will set MEM_EXECUTE_OPTION_ENABLE option for ProcessExecuteFlags and therefore DEP will disable . but the question is how calling NtSetInformationProcess with this arguments ? as i said before , widows Operating System use LdrpCheckNXCompatibility() to check NX compatibility and if a process is not compatible it will disable DEP for that process at runtime. so this is the answer , we can use “code reuse” technique and changing program execution flow to a part of LdrpCheckNXCompatibility() that call NtSetInformationProcess() with desire options.lets take look at its code ( in ntdll.dll ) :
loc_7C936831: push 4 lea eax, [ebp+var_4] push eax push 22h push 0FFFFFFFFh call ZwSetInformationProcess jmp loc_7C91CD6D ; END OF FUNCTION CHUNK FOR sub_7C91CD11
for using this section of code you have to jump in upper section and execute thru it till reach this section. i suggest you to read Skape paper about this technique and using ntdll.dll call to SetInformationProcess.there is another dll that call NtSetInformationProcess with DEP disable arguments , it is acgenral.dll :
loc_6F8917C2: push 4 lea eax, [ebp+arg_0] push eax push 22h push 0FFFFFFFFh mov [ebp+arg_0], 2 call ds:NtSetInformationProcess
metasploit use this dll and codes to disable DEP for ms08-67 vulnerability exploit code.you cannot ever jump to this dll , because it most loaded into process address space and it is not communal DLL .but attention if you use LdrpCheckNXCompatibility() (ntdll ) or avgenrall.dll for disabling DEP Set EBP to a writable address . because, as you can see both ntdll and acgenrall calls, use ebp and stack for storing one of NtSetInformationProcess() arguments . as you know at end of function and before RET instruction get execute we have pop ebp ( or simply leave ) instruction and if you corrupt stack of vulnerable function by junk date , you will change ebp value to a unknown address. and calling to NtSetInformationProcess() will fail .
have nice exploitation;) .
Reference :
- React OS – reactos.org
- Skape, Bypassing Windows Hardware-enforced Data Execution Prevention - www.uninformed.org
- WineHQ - www.winehq.org
- Data Execution Prevention – wikipedia.org
- Intel Manual – intel.com
- ms08-67 Vulnerability Exploit Code – metasploit.com
No Comment.
Add Your Comment