Defeating Microsoft Windows XP SP2 Heap protection and DEP bypass
Computing/Windows 2009. 1. 21. 16:47이 논문은 Execution Protection(실행 보호) 와 힙, 그리고 힙 오버플로우(heap overflow)에대하여 설명한다...
번역하다보니...결국 지네 재품설명같은데....뭐 그래서 뒤쪽은 번역하지도 않았다.;
이것또한 논문에 필요한 자료같아서 번역하였지만 ...그닥;;
Memory protection
메모리 보호
Buffer overrun attacks are among the most common mechanisms, or vectors, for intrusion into computers.
버퍼 오버런 어택은 컴퓨터 안에서 가장 일반적인 구성, 백터, 관섭 에 둘러싸여져 있다.
In this type of exploit, the attacker sends a long string to an input stream or control – longer than the memory buffer allocated to hold it.
이 익스플로잇 형식 안에서 공격자는 긴 문자열을 제어또는 흐름을 입력하기위해 전송할수 있다. - 메모리 버퍼보다 긴 문자열
The long string injects code into the system, which is executed, launching a virus or worm.
긴 문자열은 시스템안에 코드를 입력하고 어느것인가를 실행시킨다.(바이러스,웜등..)
Windows XP Service Pack 2 uses two general categories of protection measures to inhibit buffer-overrun attacks.
윈도우 xp sp2는 버퍼 오버런 공격을 막기 위해 2가지 일반적인 선택을 사용한다.
On CPUs that support it, the operating system can turn on the execution protection bit for virtual memory pages that are supposed to hold only data.
이것을 지원하는 CPU에, 운영체제는 유일한 데이터를 유지하기위한 가상 메모리 페이지를 위해 실행보호비트를 실행할수 있다.
On all CPUs, the operating system is now more careful to reduce both stack and heap buffer overruns, using "sandboxing" techniques.
모든 CPU들은 sandboxing 기술을 사용하면서, 운영체제는 지금 스택과 힙버퍼 오버런을 축소키기 위해 힘쓰고 있다.
Execution Protection (NX)
실행 보호
On the 64-bit AMD K8 and Intel Itanium processor families, the CPU hardware can mark memory with an attribute that indicates that code should not be executed from that memory.
64비트 AMD K8이나 인텔 프로세서군에서 CPU하드웨어는 코드로부터 실행할수 없는 매모리를 가르치는 속성을 메모리와 함께 마크할 수 있다.
This execution protection (NX) feature functions on a per-virtual memory page basis, most often changing a bit in the page table entry to mark the memory page.
이 가상 메모리 페이지의 기초안의 실행 보호특징 함수,메모리페이지를 마크하기위해 페이지 테이블로 진입하는 가장 자주 바뀌는 비트.
On these processors, Windows XP Service Pack 2 uses the execution protection feature to prevent the execution of code from data pages.
이 프로세서들안에서 윈도우즈 xp sp2 는 실행보호 특징을 데이터 페이지로부터 코드를 막기위해 사용된다.
When an attempt is made to run code from a marked data page, the processor hardware raises an exception immediately and prevents the code from executing.
마크된 데이터 페이지로부터 코드가 실행되는 것을 위한 시도가 될 때, 프로세서 하드웨어는 즉시 예외로 올려지고 실행으로부터 코드는 보호된다.
This prevents attackers from overrunning a data buffer with code and then executing the code; it would have stopped the Blaster worm dead in its tracks.
이 것은 공격자의 실행 되는 코드와 데이터 버퍼 오버런으로부터 막을수 있다. : 이것은 블라스터웜을 멈출수 있다.
Although the support for this feature is currently limited to 64-bit processors, Microsoft expects future 32-bit and 64-bit processors to provide execution protection.
또한 이 특징은 64비트 프로세서의 현재 한계를 위해 지원한다. 마이크로 소프트는 미래의 32/64비트 프로세서가 실행보호를 지원할거라고 예상한다.
Sandboxing
To help control this type of attack on existing 32-bit processors, Service Pack 2 adds software checks to the two types of memory storage used by native code: the stack, and the heap.
32비트 프로세서상에서 존재하는 공격의 종류는 도움을 제어할 수 있다. sp2는 소프트웨어 체크가 원래 코드에 의해 메모리 저장공간의 두가지에 사용되는 것이 추가된다.
The stack is used for temporary local variables with short lifetimes; stack space is automatically allocated when a function is called and released when the function exits.
스텍은 짧은 라이프타임과 임시 로컬 변수를 위해 사용된다.
The heap is used by programs to dynamically allocate and free memory blocks that may have longer lifetimes.
힙은 동적 할당과 긴 지속시간을 가진 빈 메모리 블록을 위해 프로그램에 의해 사용된다.
The protection added to these two kinds of memory structures is called sandboxing.
보호는 sandboxing이라고 불리는 이 두가지 종류의 메모리 구조가 추가되었다.
To protect the stack, all binaries in the system have been recompiled using an option that enables stack buffer security checks.
스텍을 보호하는 것, 시스템 안에서 모든 이진수는 스텍 버퍼 보호 검사가 가능한 옵션이 사용되어 수집되었다. .
A few instructions added to the calling and return sequences for functions allow the runtime libraries to catch most stack buffer overruns.
몇몇 명령들은 호출하고, 스텍 버퍼 오버런을 잡아내고 런타임 라이브러리가 허용된함수를 위한 수열 리턴이 추가되었다.
This is a case where a little paranoia goes a long way.
이것은 어디로 작은 paranoia 가는 경우이다. (?)
In addition, "cookies" have been added to the heap.
추가로, 쿠키는 힙에 추가되어졌다.
These are special markers at the beginning and ends of allocated buffers, which the runtime libraries check as memory blocks are allocated and freed.
버퍼 할당의 시작과 끝에 특수한 마커들이 있다. 자유로워지고 할당된 메모리 블록으로써 런타임 라이브러리.
If the cookies are found to be missing or inconsistent, the runtime libraries know that a heap buffer overrun has occurred, and raise a software exception.
만약 쿠키들이 일지하지 않거나 사라졌다면, 런타임 라이브러리는 힙 버퍼 오버런이 발생된것과 소프트웨어가 실행된 것을 알 것이다.
- from Microsoft.com
Heap Design
Heap is a reserved address space region at least one page large from which the heap manager can dynamically allocate memory in smaller pieces.
힙은 힙 메니져가 동적으로 작은 영역에 메모리를 할당할수있는것으로부터 큰 하나의 페이지를 가장 보류한 주소 공간 영역이다.
The heap manager is represented by a set of function for memory allocation/freeing which are localised in two places: ntdll.dll and ntoskrnl.exe.
힙 메니져는 두 ntdll.dll and ntoskrnl.exe의 두 곳에서 국한 시키는 메모리 할당/해제에 대한 기능의 집합이다.
Every process at creation time is granted with a default heap, which is 1MB large (by default) and grows automatically as need arise.
만들어지는 시간에서의 모든 프로세스는 디폴트 힙과 함께 수령된다.
The default heap is used not only by the win32 apps, but also by many runtime library functions which need temporary memory blocks.
이 디폴트 힙은 win32 app에 의해 사용되고 또한 많은 임시 메모리 블록이 필요한 런타임 라이브러리 함수로써 사용된다.
A process may create and destroy additional private heaps by calling HeapCreate()/HeapDestroy().
프로세스는 HeapCreate()/HeapDestroy()를 호출하는것에 의해 부가적인 개인 힙을 만들거나 파괴할수 있다.
Use of the private heaps` memories is established by calling HeapAlloc() and HeapFree().
개인 힙의 사용은 HeapAlloc() and HeapFree()에 의해 수행되어진다.
[*] More detailed information about the heap management functions is provided in the Win32 API documentation.
그 힙 메니져의 기능에 대한 더 상세항 정보는 win32 api문서에서 나와있다.
Memory in heaps is allocated by chunks called 'allocation units' or 'indexes' which are 8-byte large.
메모리는 큰 8바이트 인덱스나 할당 유닛으로 불린 chunks에 의해 할당 된다.
Therefore, allocation sizes have a natural 8-byte granularity.
그러므로, 할당 사이즈는 자연스런 8바이트들로 이루어 져있다.
For example if an application needs a 24-byte block the number of allocation units it gets 3 allocation units.
예로, 만약 어플리케이션에서 24바이트 블록에 해당하는 공간이 필요하면 이것은 3배 단위의 수를 가집니다.
In order to manage memory for every block a special header is created, which also has a size divisible by 8 (fig. 1, 2).
모든 블록 특수 해더는 만들어지기위해 메모리가 관리된다. 이것은 도한 8로 나눈 사이즈를 가지고있다.
Therefore a true memory allocation size is a total of the requested memory size, rounded up towards a nearest value divisible by 8 and the size of the header.
그러므로, 실제 메모리 할당 사이즈는 요청된 메모리 사이즈의 모든 크기이다. 이 해더의 사이즈 8과 그 크기에 의해 나눌수 있는 가장 가까운 수로 반올림 합니다.
SizeSegmentIndexPrevious SizeUnusedFlagsTag Index
Fig.1. Busy block header.
FlinkBlinkSizeSegmentIndexPrevious SizeUnusedFlagsTag Index
Fig.2. Free block header.
Where:
Size - memory block size (real block size with header / 8);
Previous Size - previous block size (real block size with header / 8);
Segment Index - segment index in which the memory block resides;
Flags - flags:
- 0x01 - HEAP_ENTRY_BUSY
- 0x02 - HEAP_ENTRY_EXTRA_PRESENT
- 0x04 - HEAP_ENTRY_FILL_PATTERN
- 0x08 - HEAP_ENTRY_VIRTUAL_ALLOC
- 0x10 - HEAP_ENTRY_LAST_ENTRY
- 0x20 - HEAP_ENTRY_SETTABLE_FLAG1
- 0x40 - HEAP_ENTRY_SETTABLE_FLAG2
- 0x80 - HEAP_ENTRY_SETTABLE_FLAG3
Unused - amount of free bytes (amount of additional bytes);
Tag Index - tag index;
Flink - pointer to the next free block;
Blink - pointer to the previous free block.
The specification of the allocation size in allocation units is important for the free block list management.
할당 유닛에 있는 할당 사이즈 명세는 자유 블록 리스트 관리를 위해 중요합니다.
Those free block lists are sorted by size and the information about them is stored in an array of 128 doubly-linked-lists inside the heap header (fig. 3, 4).
이것들은 리스트 크기와 힙 해더의 128 이중연결 리스트 배열안에서 저장된것에 대한 사이즈와 정보에 의해 블록 리스트는 자유로워 진다.
Free blocks in the size diapasone from 2 to 127 units are stored in lists corresponding to their size (index).
사이즈안의 자유 블록은 2~127의 유닛은 그 사이즈에 대응하는 리스트로에서 저장된 것으로 부터 diapasone되었다.(?)
For example, all free blocks with the size of 24 units are stored in a list with index 24, i.e. in Freelist[24].
예를 들면, 모든 자유 블록은 24유닛의 사이즈와 함께 index24 같이 리스트에 저장된다. I.e. in freelist
The list with index 1 (Freelist[1]) is unused, because blocks of 8 bytes can`t exist and the list with index 0 is used to store blocks larger than 127 allocation units (bigger than 1016 bytes).
인덱스 1과 함께 리스트는 사용되지 않는다. 왜냐하면 8바이트의 블록은 존재할수 없고 인덱스 0과 함께 리스트는 127할당 유닛보다 큰 블럭을 저장을 위해 사ㄴ용된다.
Free list 1Free list 0Free list 2...Free list 127Lookaside list 0Lookaside list 1Lookaside list 2...Lookaside list 127Free EntryFree EntryFree EntryFree EntryNULLHeap headerFree Entry......
Fig. 3.
If, during the heap allocation, the HEAP_NO_SERIALIZE flag was unset but the HEAP_GROWABLE flag was set (which is actually the default), then in order to speed up allocation of the small blocks (under 1016 bytes) 128 additional singly-linked lookaside lists (fig. 3, 4) are created in the heap.
만약 힙 할당하는 동안, heap_no_serialize 플래그는 unset되지만 heap_growable 플래그는 설정(사실 기본설정이다)된다. 그리고 부가적인 싱글 링크 lookaside lists는 작은 블럭의 할당 속도를 높이기 위해 힙 안에서 생성된다.
Initially lookaside lists are empty and grow only as the memory is freed. In this case during allocation or freeing these lookaside lists are checked for suitable blocks before the Freelists.
초기의 lookaside lists는 비어있고, 메모리을 해제해주는것에 따라 성장합니다. 이 경우에 할당 및 해제 하는 동안 이 lookaside lists 는 freelists 전에 적당한 블록을 위해 검사합니다.
The heap allocation routines automatically tune the amount of the free blocks to store in the lookaside lists, depending on the allocation frequency for certain block sizes.
힙 할당 루틴은 자동으로 lookaside list안에 저장하기 위해 블록의 양을 조절하고 할당한다. 이것은 확실한 블록 사이즈를 위해 종종 할당되는것에 달렸다.
The more often memory of certain size is allocated -- the more can be stored in the respective lists, and vice versa -- underused lists are trimmed and the pages are freed to the system.
확실한 메모리 크기는 더 자주 할당되었다. 시스템에게 페이지가 해제 되고, underused lists 는 없어진다.
Because the main goal of the heap is to store small memory blocks this scheme results in relatively quick memory allocation/freeing.
힙의 주 목적이 작은 메모리 블록을 저장하는것을 위함 이기 때문에 이 계획은 결과는 상대적으로 빠른 메모리 할당및 해제이다.
Flink (Next block)Blink (Prev Block)Free list NFlinkBlink...Free entryFlinkBlinkLast Free entry
doubly-linked freelist
FlinkFlinkNULLFree entryFree entryFlink (Next block)Lookaside list N
singly-linked lookaside list
Fig. 4.
Heap Overflow
Let`s take a look at this pretty simple example of a vulnerable function:
이 취약한 함수의 예를 보도록 하자.
HANDLE h = HeapCreate(0, 0, 0); // default flags
DWORD vulner(LPVOID str)
�
LPVOID mem = HeapAlloc(h, 0, 128);
// <..>
strcpy(mem, str);
// <..>
return 0;
�
As we can see here the vulner() function copies data from a string pointed by str to an allocated memory block pointed at by buf, without a bound check.
여기서 str에의해 메모리 블록 할당을 버퍼에서 bound 검사 없이 하기 위해 문자열 가르친 것으로부터 vulner()함수가 데이터를 복사한것을 볼수있다.
A string larger than 127 bytes passed to it will thereby overwrite the data coincidental to this memory block (Which is, actually, a header of the following memory block).
문자열은 이것을 통과한 127바이트보다 더 크다. 이것으로 데이터 덮어쓰기가 이 메모리 블록에서 동시에 일어날것이다.
The heap overflow exploitation scenario usually proceeds on like this:
이처럼 힘 오버플로우 이용 시나리오에 일반적으로 진행된다.
If during the buffer overflow the neighboring block exists, and is free, then the Flink and Blink pointers are replaced (Fig. 5).
만약 버퍼 오버플로우에 가까운 블록이 존제하는 중이라면, 그리고 자유롭다면, Flink and Blink포인터들은 제자리로 돌아간다.
At the precise moment of the removal of this free block from the doubly-linked freelist a write to an arbitrary memory location happens:
이 이중 연결 프리리스트에서 나온 자유블럭의 이동하는 정확한 순간에 임의의 메모리 위치에 쓰기가 일어난다.
mov dword ptr [ecx],eax
mov dword ptr [eax+4],ecx
EAX - Flink
ECX - Blink
For example, the Blink pointer could be replaced by the unhandled exception filter address (UEF -- UnhandledExceptionFilter), and Flink, accordingly, by the address of the instruction which will transfer ther execution to the shellcode.
예를 들면 Blink 포인터는 필터 주소를 제외한 언핸들에 의해 재 배치 됤수있다. 그리고 flink는 그에 맞게 쉐코드에 실행을 전솔할 명령어의 주소에 의해.
[*] More detailed information about the heap overflows is provided in the “Windows Heap Overflows” whitepaper (by David Litchfield, BlackHat 2004).
힙 오버플로우에 대해 더 자세한 정보를 원하면 windows heap overflows를 참조하라.
BlinkFlinkBlock_headerbufferBlock_headerOverflowdirection
Fig. 5.
In Windows XP SP2 the allocation algorithm was changed -- now before the removal of a free block from the freelist, a pointer sanity check is performed with regard to the previous and next block addresses (safe unlinking, fig. 6.):
윈도우 xp sp2에서 할당 알고리즘은 바뀌었다. -- 지금 freelist로부터 프리블럭이동 전에, 이 정상적인 검사 포인터는 전과 다음 주소를 주의하여 실행된다.
BlinkFlinkBlinkFlinkBlinkFlinkAllocateFree entry 1Free entry 2Free entry 3
Fig. 6. Safe unlinking.
1. Free_entry2 -> Flink -> Blink == Free_entry2 -> Blink -> Flink
2. Free_entry2 -> Blink -> Flink == Free_entry2
7C92AE22 mov edx,dword ptr [ecx]
7C92AE24 cmp edx,dword ptr [eax+4]
7C92AE27 jne 7C927FC0
7C92AE2D cmp edx,esi
7C92AE2F jne 7C927FC0
7C92AE35 mov dword ptr [ecx],eax
7C92AE37 mov dword ptr [eax+4],ecx
Then that block gets deleted from the list.
이때 리스트로부터 저 블록은 지워졌다.
The memory header block was changed, besides other things (fig. 7.).
메모리 해더 블럭은 바뀌었다. 다른 것들 근처에서.
A new one-byte-large 'cookie' field was introduced, which holds a unique precomputed token -- undoubtely designed to ensure header consistency.
새로운 one-byte-large 쿠키 필드는 소개되었다. 이것은 계산된 토큰을 가지고 있다. -- 확실히 해더의 일관성을 책임진다.
This value is calculated from the header address and a pseudorandom number generated during the heap creation:
이 값은 해더 주소와 의사 난수 숫자 생성기에 의해 힙에서 만들어지는동안 계산되었다.
(&Block_header >> 3) xor (&(Heap_header + 0x04))
The consistency of this token is checked only during the allocation of a free memory block and only after its deletion from the free list.
이 토큰의 일관성은 오직 프리 메모리 블록 할당과 프리 리스트에서 이것을 삭제하는 동안 검사되었다.
FlinkBlinkSizeCookiePrevious SizeUnusedFlagsSegmentIndex
Fig. 7.
If at least one of these checks fails the heap is considered destroyed and an exception follows.
만약 이것들중 작은 하나가 검사에 실패하면 힙은 판단 끝에 제거되고 흐름에서 제외된다.
The first weak spot -- the fact that the cookie gets checked at all only during free block allocation and hence there is no checks upon block freeing.
첫 번재 약한 부분-- 그 쿠키가 자유블럭 배당하는동안 검사하게되고, 이 때문에 블록 할당조차 검사되지 않는다.
However in this situation there is nothing you can do except changing the block size and place it into an arbitrary freelist.
어째꺼나 이 상황에서 너가 블록 사이즈를 바꾸는것을 제외하고 할수있는것이 없다. 그리고 임의의 프리 리스트안에서 놓을수도 없다.
And the second weak spot – the manipulation of the lookaside lists doesn`t assume any header sanity checking, there isn`t even a simple cookie check there.
그리고 두 번째 약한 부분 - lookaside lists의 다루는 것은 어느 해더의 온전한 검사도 취할수 없다. 간단한 쿠키 체크 조차도 없다.
Which, theoretically, results in possibility to overwrite up to 1016 bytes in an arbitrary memory location.
이론적으론, 1016바이트를 임의의 메모리 위치에 덮어 쓰는것이 가능하다는 결론이다.
The exploitation scenario could proceed as follows:
그 실행 시나리오는 다음과같은 과정을 가질수 있다.
if, during the overflow the concidental memory block is free and is residing in the lookaside list, then it becomes possible to replace the Flink pointer with an arbitrary value.
오버플로우 동안 concidental 메모리 블록은 자유롭고 lookaside list안에서 존재하고있다. 그때 이것은 Flink 포인터는 임의의 값과 함께 재 배치 가능성을 가질수 있다.
Then, if the memory allocation of this block happens, the replaced Flink pointer will be copied into the header of the lookaside list and during the next allocation HeapAlloc() will return this fake pointer.
그때 만약 이블럭의 메모리 할당이 일어나면, 재배치된 flink 포인터는 lookaside list의 해더에서 복사될것이다. 그리고 다음 heapalloc() 할당은 이 가짜 포인터로 리턴될것이다.
The prerequisite for successful exploitation is existence of a free block in lookaside list which neighbors with the buffer we overflow.
성공의 필수 개발은 우리가 덮어쓴 버퍼를 가진 근처 lookaside list 안의 자유블럭의 존재이다.
This technique was successfully tested by MaxPatrol team in trying to exploit the heap buffer overflow vulnerability in the Microsoft Windows winhlp32.exe application using the advisory published by the xfocus team:
이 기술은 성공적으로 xfocus team이 권고 발표에 사용된 MS사의 윈도우즈 winhlp32.exe 어플리케이션이 Maxpatrol team의 힙 버퍼 오버플로우 취약점 이용을 위한 시도중에 테스트 되었다.
HTTP://WWW.XFOCUS.NET/FLASHSKY/ICOEXP/INDEX.HTML
The effect of a successful attack:
1) Arbitrary memory region write access (smaller or equal to 1016 bytes).
2) Arbitrary code execution (appendix A).
3) DEP bypass. (DEP is Data Execution Prevention) (appendix B).
Disclosure timeline
10/09/2004 The possibility to work around the Heap protection mechanism was discovered by MaxPatrol security scanner research team in course of advanced vulnerabilities analysis
힙 보호 메카니즘 주위에 작업하는 가능성은 Maxpatrol security scannerresearch team에게 개선된 취약점 분석 진행에서 발견되었다.
12/21/2004 Initial vendor notification
12/22/2004 Initial vendor response
12/22/2004 PoC code was sent to Microsoft.
Solution
One might employ restriction of lookaside list creation, governed by a special global flag, as a temporary security measure.
특별한 글로벌 플래그에의해 좌우 되면서 lookaside 리스트 제작의 제한이 생길지도 모른다.
Actually a simple program for this purpose was already created by MaxPatrol research team and is available for free download from:
실제로, 이 목적을위한 간단한 프로그램은 이미 MaxPatrol 연구 팀에 의해 만들어 졌고 무료 다운로드가 아래사이트에서 가능하다.
HTTP://WWW.MAXPATROL.COM/PTMSHORP.ASP
During the first execution this program shows the list of applications which already have this flag set.
이 프로그램이 첫 번재로 실행하는 동안 이미 플래그셋을 한 어플리케이션의 리스트를 본다.
In order to activate the global flag, which would disable use of the lookaside lists, one needs to add the name of the executable file and then, optionally, close the application (PTmsHORP).
글로벌 플래그가 활성화 되기 위해, 어느 lookaside list의 사용은 중지될 수 있고, 실행파일이름의 추가가 필요하고,선택적으로 어플리케이션을 닫을수있다.
Warning: this flag, while enabled, may decrease the application performance.
경고 : 사용하는 동안, 어플리케이션 실행은 줄어들것이다.