Shahriyar Nasirov Research Assistant ORKESTRA, Instituto Vasco de Competitividad
Bypassing MS Windows Memory Protections Shahriyar Jalayeri [email protected] 1 st Iranian...
-
Upload
jared-carpenter -
Category
Documents
-
view
217 -
download
2
Transcript of Bypassing MS Windows Memory Protections Shahriyar Jalayeri [email protected] 1 st Iranian...
Bypassing MS Windows Memory Protections
Shahriyar [email protected]
1st Iranian Confrence on Cybespace Security Incidents and Vulnerabilities
Who am I?
• Security researcher since 2005• Senior Member of Snoop Security Researching
community• Writer and Technical Editor of Snoop Magazine ( First
Persian Technical Information Security Magazine )• University student
What is this talk about?
• Overview of Softwares Security Flaws• Deep looking at OS protection mechanismes• Explaining ways to bypass some of OS PM
Security Flaws
• Stack Based Buffer Overflow• Heap Based Buffer Owerflow• Format String• etc
Stack Based Buffer Overflow
• an old story – Programer Copy Buffer entry into stack without
bound checking– Stack corrupted and FramePointer+Saved Return
Address overwritten– The BAD ret Instruction
Stack Based Buffer Overflow ( Cont. )
– Stack.c
#include <stdio.h>Int main( int argc, char **argv){
char buff[100];strcpy(buff,argv[1]);printf(“Hello , %s!\n”,buff);return 0;
}
Overflow occured here
Stack Based Buffer Overflow ( Cont. )
Args--------------------
--Saved Ret
----------------------
Saved FP--------------------
--BUFFER
Stac
k La
yout
0xHighMemAddr0xLowStackAddr
Args--------------------
--Saved Ret
----------------------
Saved FP--------------------
--BUFFER
0xLowMemAddr0xHighStackAddr
AAAAAAAAAAAA
Overflow
Stack Based Buffer Overflow ( Cont. )
– The BAD ret instruction ( and also leave :D ) 004012DC |. 83C4 10 ADD ESP,10004012DF |. C9 LEAVE004012E0 \. C3 RETN
Args--------------------
--Saved Ret
----------------------
Saved FP--------------------
--BUFFER
EIP
Boom
AAAAAAAAAAAA
Overflow
Heap Overflow
– Heap Structure • LIST_ENTRY Structure ( WinNT.h )
• FreeList array– Pointer to free heap blocks
typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink;} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;
Heap Overflow ( cont. )
– Heap.c
HANDLE h = HeapCreate(0, 0, 0);DWORD vulner(LPVOID str) {
LPVOID mem = HeapAlloc(h, 0, 128);// <..>strcpy(mem, str);// <..>LPVOID mem2 = HeapAlloc(h, 0, 128);// <..>return 0;
}
Overflow
Affected Memory
Heap Overflow ( cont. )
– Freeing Scenario and Pointers ( without Safeunlinking )
BOOLEAN RemoveEntryList(IN PLIST_ENTRY Entry){ PLIST_ENTRY Blink; PLIST_ENTRY Flink; Flink = Entry->Flink; // what Blink = Entry->Blink; // where Blink->Flink = Flink; // *(where) = what Flink->Blink = Blink; // *(what+4) = where return (BOOLEAN)(Flink == Blink);}
Heap Overflow ( Cont. )
– Freeing Scenario and Pointers ( without Safeunlinking )
• Disass...
– Exploitation Scenario
mov dword ptr [ecx],eax mov dword ptr [eax+4],ecxEAX - Flink ECX - Blink
ECX = Function PointerEAX = Instruction which transfer execution to shellcode
Heap Overflow ( Cont. )
– Function pointers which can overwrite during unlinking ( ECX )• Unhandled Exception Filter• Vector Exception Handling ( VEH )• PEB Pointers• TEB Pointers• Your own pointer !
Format String
– Using format specified functions in wrong way• Printf(buffer)
– We are able to overwrite arbitrary address• Mentioned pointers can be good target• Saved Return Address !!!
Memory Protections
• Protections against buffer overflow– Guard Stack ( a.k.a /GS )– Data Execution Prevention ( a.k.a DEP or
/NXCOMPAT )– Safe SEH Table ( a.k.a /SafeSEH )– SEH Overwrite Protection ( a.k.a SEHOP )– Address Space Layout Randomization ( a.k.a ASLR
or /DYNAMICBASE )
Guard Stack ( /GS ) Protection
– Compiler Insert Cookie after Function Stack Frame– There is also a copy of cookie in .data section– Before function return cookie check with .data
saved cookie– If dose not match , Ret instruction never execute– In overflow situation we have to overwrite cookie
befor reaching “Saved Return Address”– Now what ?
Guard Stack ( /GS ) Protection ( cont. )• Memory Layout
Parameters
Return Address
Frame Pointer
Locals
Parameters
Return Address
Frame Pointer
Exception Handler Frame
Locals
Parameters
Return Address
Frame Pointer
Exception Handler Frame
Locals
Safe Parameters
CookieCookie
(1)
(2)
(3)
(1) Without Cookie(2) MSVC++ 2003(3) MSVC++ 2005
Guard Stack ( /GS ) Protection ( cont. )
– Q : What is Safe Parameters ?– A : Function pointer overwrite prevention trick
– Prevention is better than cure :D
Para
met
ers
Retu
rn A
ddre
ss
Fram
e Poin
ter
Exce
ption
Handle
r Fra
me
Loca
lsSa
fe
Para
met
ers
Cook
ie
#include <windows.h>int main(int argc, char *argv[]){ HMODULE Lib=NULL; unsigned int FuncAddress = 0; int err = 0; Lib = LoadLibrary("msvcrt.dll"); FuncAddress = GetProcAddress(Lib,"printf"); err = DoStuff(argv[1],FuncAddress); return 0;}int DoStuff(char *buf, FARPROC fnk){ char buffer[20]=""; strcpy(buffer,buf); (fnk)(buffer); __asm add esp,4 return 0;}
Guard Stack ( /GS ) Protection ( cont. )
– When /GS dose not protect your Code ?• The optimization (O) option is not enabled• The function does not contain a stack buffer• The function is marked with naked in C++• The function has a variable argument list• The function begins with inline assembly code• The compiler determines that the function’s variables
are used only in ways that are less likely to be exploitable
Guard Stack ( /GS ) Protection ( cont. )
– Implementation• ___security_init_cookie()• Protected function prologue changes• Protected function epilogue changes• __security_check_cookie()• ___report_gsfailure()
Guard Stack ( /GS ) Protection Reversing in Action
Just trigger IDA
•/G
S Reversing–
___security_init_cookie()
Security Init Cookievoid __cdecl __security_init_cookie(void){
UINT_PTR cookie; if (__security_cookie != DEFAULT_SECURITY_COOKIE && (__security_cookie & 0xFFFF0000) != 0 ){ __security_cookie_complement = ~__security_cookie; return; }
GetSystemTimeAsFileTime(&systime.ft_struct);cookie = systime.ft_struct.dwLowDateTime;
cookie ^= systime.ft_struct.dwHighDateTime; cookie ^= GetCurrentProcessId(); cookie ^= GetCurrentThreadId(); cookie ^= GetTickCount(); QueryPerformanceCounter(&perfctr);
cookie ^= perfctr.LowPart; cookie ^= perfctr.HighPart;
if (cookie == DEFAULT_SECURITY_COOKIE){ cookie = DEFAULT_SECURITY_COOKIE + 1; }
else if ((cookie & 0xFFFF0000) == 0){ cookie |= cookie << 16; }
__security_cookie = cookie; __security_cookie_complement = ~cookie;}
UINT_PTR cookie_temp_storage,cookie_global;cookie_temp_storage = 0xCCCCCCCC;cookie_temp_storage = __security_cookie;// cookie_temp_storage = cookie_temp_storage ^ EBP;// cookie_global = cookie_temp_storage;__asm {
xor cookie_temp_storage, ebpmov dword prt [ebp-4],cookie_temp_storage
}
•/G
S Reversing–
Protected function prologue changesPrologue
cookie_temp_storage = cookie_global;// cookie_temp_storage = cookie_temp_storage ^ EBP;__asm{
xor cookie_temp_storage, ebp}__security_check_cookie();
•/G
S Reversing–
Protected function eplilogue changesEpilogue
void __security_check_cookie(){if ( cookie_temp_storage == __security_cookie )
return;__report_gsfailure();
}
•/G
S Reversing–
__security_check_cookie()Memory Protections
void __report_gsfailure(){// rise an fake exception // saving the contex record codes skiped :D GS_ContextRecord.ContextFlags = CONTEXT_CONTROL; GS_ExceptionRecord.ExceptionAddress = (PVOID)(ULONG_PTR)GS_ContextRecord.Eip;
GS_ExceptionRecord.ExceptionCode = STATUS_STACK_BUFFER_OVERRUN; GS_ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
cookie[0] = __security_cookie; cookie[1] = __security_cookie_complement;
if ( IsDebuggerPresent() )_CRT_DEBUGGER_HOOK(_CRT_DEBUGGER_GSFAILURE);
SetUnhandledExceptionFilter(NULL); UnhandledExceptionFilter((EXCEPTION_POINTERS *)&GS_ExceptionPointers);
TerminateProcess(GetCurrentProcess(), STATUS_STACK_BUFFER_OVERRUN);}
•/G
S Reversing–
___report_gsfailure()Report Gs Failure
– Puting shellcode into buffer– Overwrite EXCEPTION_REGISTRATION• Next = jump to shellcode• Handler = call [ebp+30] or pop,pop,ret or ...
– Causing an exception before coockie check– BOOOOM!!!
Defeating /Gs Scenario
– When exception occured os call _except_handler() function– The location of handler function is store into stack by
EXCEPTION_REGISTRATION structure ( E_R )
– Os find address of first regsiter E_R by accessing to fisrt 4 byte of thread TEB
– OS access to TEB through fs register– Fs[0] alwayes point to first installed E_R in TEB
Exception Handling Overview
typedef struct EXCEPTION_REGISTRATION{EXCEPTION_REGISTRATION *next;PEXCETION_HANDLER *handler;
}EXCEPTION_REGISTRATION, *PEXCEPTION_REGISTRATION;
– There is chain of E_R structures in stack– If one hanlder faild to handle exception , chain
traversealed to find a proper handler
Exception Handling Overview ( cont. )
– We can control value of both next and handler elements of a registerd E_R
– Overwiting handle with shellcode address and cusing an exception ,then boom ??? No !!!• There is some problems
– If handler address is in stack , handler never execute– If handler address is in heap , handler execute
» Finding writeable heap address in stack overflow situation is usualy impossible • Now what ?
Abusing registered E_R
– Rules are implemnted just for handler, we still have control over next pointer
– Secund parameter of _except_handler() function which is EstablisherFrame point to curent EXCEPTION_REGISTRATION frame
– We can access to this address by poping off two value from stack and then returning to it : pop,pop,ret
– There is also other instructions which work same as pop,pop,ret sequence, such as : • Call dword ptr[ebp+30]• Jmp dword ptr [esp+8]
Abusing registered E_R ( cont. )
– Our attack scenario :– Puting shellcode into buffer– Overwriting handler with pop,pop,ret instructions– Overwriting next with jump to the buffer– Cuasing an exception– Boom !!!
– But there is another problem : /SafeSEH
Abusing registered E_R ( cont. )
– Create a table of safe handlers– Compare each handler value with table values– If handler value is in safe table , handler excecute– If not , go to treminate process with
STATUS_STACK_BUFFER_OVERRUN flag
/SafeSEH Protection
– If program doesnt compile with /SafeSEH every handlers are valid and execute
– If handler address is in module which doesnt handle with /SafeSEH , handler execute
– If handler address is outside of loaded module, handler execute
/SafeSEH Protection Weaknesses
Bypassing /GS , /SafeSEH attack scenario
Target : Vista SP1 EN XP SP3 EN
NOP
Shellcode
Return Address
0x41414141
Jmp to Jmp 0xbuffer
Handler
Jump to Bufferinstructions
Adress of Pop,Pop,Ret
orCall dword ptr [ebp+30]
instruction
Bypassing /GS , /SafeSEH Protection inAction
Just trigger debuuger
– In this case we can use 0x00 in data– If can’t ?• Find address for pop,pop,ret which dosen’t contain
0x00• Put shellcode after overwrited E_R• Overwrite next with jmp forward to shellcode• Boom!
/GS Null Byte problem
– Data Execution Prevention (DEP) is a system-level memory protection feature that is built into the operating system
– DEP enables the system to mark one or more pages of memory as non-executable
– DEP prevents code from being run from data pages such as the default heap, stacks, and memory pools
– If an application attempts to run code from a data page that is protected, a memory access violation exception occurs
– if the exception is not handled, the calling process is terminated
Data Execution Prevention
– Hardware-enforced DEP enables the NX bit on compatible CPUs, through the automatic use of PAE kernel in 32-bit Windows
– The NX bit ( XD/EVP), which stands for No eXecute, is a technology used in CPUs to segregate areas of memory for use by either storage of processor instructions or for storage of data
– Physical Address Extension (PAE) is a feature of x86 and x86-64 processors that enable the use of more than 4 gigabytes[1] of physical memory to be used in 32-bit systems
– In traditional 32-bit protected mode, x86 processors use a two-level page translation scheme, where the control register CR3 points to a single 4 KB long page directory, which is divided into 1024 × 4 byte entries
– The NX bit flag in the page directory, in bit 63, to mark pages as "No eXecute"
– Similat technologies : W^X , PAX , Exec Shield
Data Execution Prevention ( Implementation )
– Software DEP, while unrelated to the NX bit, is what Microsoft calls their enforcement of "Safe Structured Exception Handling“
– Software DEP/SafeSEH simply checks when an exception is thrown to make sure that the exception is registered in a function table for the application
– requires the program to be built with it
Data Execution Prevention ( Implementation Cont. )
– OptIn: 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
– OptOut: 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.
– 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.
– AlwaysOff: This setting does not provide any DEP coverage for any part of the system, regardless of hardware DEP support.
Data Execution Prevention (Configuration )
– The very easy way• Using newly added DEP related API
– SetProcessDEPPolicy Fucntion
– Thr easy way:• Filling buffer with shellcode • Calling NtSetInformationProcess with Desire parameters to disable
DEP for Current Process• Jumping into buffer ( jmp esp)
– The hard way :• Filling buffer with shellcode • Making a page RWX by calling VirtualAlloc function• Copying Shellcode to RWX memry region through calling memcpy• Jumping to RWX memory region
Bypassing DEP Scenario
– We can change DEP policy for spesific process at run-time.
– We will use SetProcessDEPPolicy with desire parameters
• setting dwFlags to 0 disables DEP for the process
– Jump back to shellcode
The very easy way
BOOL WINAPI SetProcessDEPPolicy( DWORD dwFlags );
Finall attack scenarioThe very easy way Target : XP SP3 EN
NOP
Shellcode
Return AddressSetProcessDEPPolicy
Shellcodeaddr
0x00000000
Bypassing DEP Protection ( very easy way ) in
ActionJust trigger debugger
– We can change DEP policy for spesific process at run-time.– LdrpCheckNXCompatibility determine whether or not NX support should
be enabled for the process– As a result of these checks, NX support is either enabled or disabled
through a new PROCESSINFOCLASS named ProcessExecuteFlags (0x22).– When we calling NtSetInformationProcess 4 byte bit-mask parameter
push to the buffer as parameter for MmSetExecuteOptions– MmSetExecuteOptions perform appropriate operation to set the
executio flag– Parameters which we can pass to NtSetInformationProcess are :
• MEM_EXECUTE_OPTION_ENABLE ( 0x1 )• MEM_EXECUTE_OPTION_DISABLE (0x2 )
– So ,all we have to do is calling NtSetInformationProcess with mentioned parameters for current process at the overflow time
The easy way
• Take a quick look at NtSetInformationProcess :
• We can find NtSetInformationProcess Calling with desire parameters in a few dlls , such as : ntdll.dll , acgenral.dll , ....
• In exploit code i use ntdll instruction sequence becaus :– is more interesting than direct call in acgenrall.dll ....– Maybe our program dosnt load acgenral.dll...
• For acgenral.dll call ,Just search this sequence of byte in selected dll by msfpescan:– Msfpescan –r "\x6A\x04\x8D\x45\x08\x50\x6A\x22\x6A\xFF“
The easy way ( cont. )
NtSetInformationProcess(NtCurrentProcess(), // (HANDLE)-1ProcessExecuteFlags, // 0x22&ExecuteFlags, // ptr to 0x2sizeof(ExecuteFlags)); // 0x4
push 4;lea eax, [ebp+arg_0];push eax;push 22h;push 0FFFFFFFFh
• IDA View :D
The easy way ( cont. )
Finall attack scenarioThe easy way Target : XP SP3 EN
NOP
Shellcode
Return AddressNtSetInformationProcess
Some Pad
NtSetInfoReturn Address Jump to Buffer
Bypassing DEP Protection ( easy way ) inAction
Just trigger debugger
– calling VirtualAlloc function as return address and allocate commited memory with RWX protection mode
– set flAllocationType to MEM_COMMIT– And flProtect to PAGE_EXECUTE_READWRITE
The Hard way
LPVOID WINAPI VirtualAlloc( __in LPVOID lpAddress, __in SIZE_T dwSize, __in DWORD flAllocationType, __in DWORD flProtect );
– After VirtualAlloc returned , we call memcpy and copy shellcode into allocated RWX memory region
– set dest to Allocated unit by VirtualAlloc– And scr to shellcode address in buffer– Trick : You can also call VirtualProtect to make
shellcode location executable ( no memcpy needed )
The Hard way ( cont. )
void *memcpy( void *dest, const void *src, size_t count );
– VirtualAlloc function has __cdecl calling convention
– So ,Calling function pops it’s the arguments from the stack
– What we have to do if we want to call another function which has calling convention that not clear stack after call ?
– We can use pop,ret instruction
The Hard way ( cont. )
Pop regPop regPop regret
N time
N = function arguments count
Finall attack scenarioThe hard wayTarget : XP SP3 EN
Shellcode
VirtualAlloc
Memcpy
Mem Addr
Shellcode Size
MEM_COMMIT
PAGE_EXECUTE_READWRITE
Mem Addr
Shellcode Addr
Mem Addr
Shellcode Size
Saved Return Address
Bypassing DEP Protection ( hard way ) inAction
Just trigger debuuger
– In this case we can use 0x00 in data– If can’t ?• Use swquence of functions which dosent need 0x00 in
arguments• Use NtSetInformationProcess method which dosnt
need any null byte
DEP Null Byte problem
– In Windows Vista, NX cannot be disabled once turned on for a process
– now?• If can use null byte , VirtualAlloc+memcpy or
VritualProtect functions are handy ! ( without ASLR , in browser exploitation also with ASLR )• If cant , i dont know the asnwer ...
DEP Vista problem
– ASLR randomizes the location of images (PE files mapped into memory), heaps, stacks,the PEB and TEBs
– When a new address is being selected as an image base for an executable, a random delta value
– is added to or subtracted from the ImageBase value in the executable's PE header
– This delta value is calculated by taking a random 8-bit value from the RDTSC counter and multiplying it by 64KB
Address Space Layout Randomazation
– Heap Randmoazation• 5-bit random value is generated• multiplied by 64K• This value used as an offset from the base address
returned by the NtAllocateVirtualMemory
Address Space Layout Randomazation ( cont. )
– Stack Randmoazation• base of the stack is chosen randomly• offset into the initial page where the stack starts getting
used is also chosen at random
Address Space Layout Randomazation ( cont. )
– Heap Spray• Allocating larg amount of heap blocks• Filling Heap Blocks withNop and Shellcode• Use randomly address base on allocated units base
address and 64kb alignment• Filling buffer with return address • JavaScript !!!• Browser dependent limitation ( or every progarm which
allow us to make big block of heaps)
Bypassing ASLR Scenario
Memory Protections
DemoHeapSpray Technique
– IE disallow address which contain non-ascii bytes– Address most be taken base on heap blocks count– Using ascii sequnce address are highly recommend– Address such as : 0x05050505 , 0x0d0d0d0d ,
0x0a0a0a0a– You can also use Heap-Feng-Shui method instead
of HeapSpray
Heap Spray notes
Bypassing ASLR Protection inAction
Just trigger debugger
– FinalExceptionHandler function in NTDLL.DLL is registered as the first exception handler in all theads
– As additional exception handlers are registered, they form a linked list with the last record always pointing to FinalExceptionHandler
– The exception dispatcher walks this linked list and verifies that the last record still points to that Function
– If an attacker overwrites the Next field of an exception handler record, the validation loop will not reach the last record and the SEH chain corruption will be detected
SEH Overwrite Protection ( SEHOP )
– Skape offer ( current implementation is abit diff )
SEHOP ( Implementation )
CurrentRecord = fs:[0];ChainCorrupt = TRUE;while (CurrentRecord != 0xffffffff) {
if (IsInvalidAddress(CurrentRecord->Next))break;
if (CurrentRecord->Next == ValidationFrame) {ChainCorrupt = FALSE;break;
}CurrentRecord = CurrentRecord->Next;
}if (ChainCorrupt == TRUE)
ReportExploitationAttempt();
– Exist theory• One potential way to bypass this protection is to point
the overwritten Next pointer to a fake SEH record that points to the FinalExceptionHandler function. However, the ASLR implementation inVista randomizes the address of the function and makes it impossible to for an attacker to terminate the SEH chain unless they have a way to bypass ASLR
– My theory
SEHOP bypassing theories
– /Gs , /SafeSEH– /Gs , /SafeSEH , DEP– ASLR , DEP– /Gs , /SafeSEH , ASLR , DEP
Combined Protections Bypassing Scenarios
Bypassing Combined Protection inAction
Just trigger debugger
Question ?
Thank you for attending