Exploit writing tutorial part1 : Stack Based Overflows
Pwnable

Exploit writing tutorial part1 : Stack Based Overflows

728x90

 

2009717일에 발표된 Easy RM to MP3 Converter에 존재하는 취약점을 이용해 실제 exploit을 작성해본다. Corelan이 작성한 Exploit Writing tutorial에 그 기반을 두며 해당 문서에서는 perl을 사용하여 exploit을 작성하지만 나의 경우에는 python을 사용할 것이다. 해당 취약점을 사용하기 위해 windows xp professional vmware에 올려 가상 환경을 구축하였다.

먼저 환경을 구축해준다. python을 사용할 것이기 떄문에 xp에서 구동할 수 있는 버전이 필요 했고 python 3.4.1버전이 xp에서 구동되는 것을 확인하고 공식 홈페이지에서 다운로드 받고 설치하였다. 또한 취약점이 존재하는 Easy RM to MP3를 버전을 확인하고 구글링을 통해 같은 버전을 다운로드 후 설치 하였다.

 

      

python 설치

 

또한 exploit을 작성하기 위하여 디버깅 툴이 필요한데 Windbg를 사용할 것이다. 이것 또한 환경구축을 해주어야 한다. Microsoft공식 홈페이지에 가면 Windows10 이전 OS에 대한 WinSDK를 사용을 위한 링크가 있다. 가장 오래된 버전인 Windows 7 Windows SDK .NET Framework 4windows xp도 지원한다고 나와있으므로 해당 버전을 설치해준다.

Windows SDK  설치 페이지

 

설치가 잘 진행되면 좋겠지만 아래와 같은 오류가 나면서 설치가 진행되지 않는다.

SDK 설치 오류

 

대략적인 내용은 .NET Framework 2.0이 필요하다는 내용이므로 구글링을 통해 해당 프로그램을 설치해준다.

이후 windbgpostmortem debugger로 설정해주기 위해 아래와 같은 경로에서 명령어를 입력해준다.

postmortem debugger  등록

 

여기까지 환경 구축이 완료 되었다.  이제부터 구축하 환경을 바탕으로 Easy RM to MP3 converter에 대한 exploit을 작성할 것이다.

 

 

 먼저 파이썬 스크립트를 통해 악의적인 .m3u 파일을 생성해준다. 생성한 코드는 아래와 같다.

genCrach.py

 

위와 같은 코드를 실행시켜 Crash.m3u 파일을 생성시키고 해당 파일을 Easy RM to MP3 converter에 로드 시킨다. \x41 값을 10000개 주입 시켜 주었을 때 오류가 발생 하지만 크래쉬는 발생하지 않는다.

버그 발생

파일 경로를 A가 덮어 쓴 것으로 보아 버퍼 오버 플로우가 발생한 것을 예상할 수 있다. 하지만 내가 원하는 것은 crash가 발생하는 것 이므로  GenCrash.py파일에서 \x41값을 30000개로 설정하여 다시 Easy RM to MP3 converter에 로드시킨다.

A30000개를 주입시켜 줄 경우 crash가 발생하며 앞서 windbg postmortem debugger로 설정해주었기 때문에 자동적으로 Windbg가 로드 된다.

crash 발생

앞선 사실을 바탕으로 10000개 이상 30000개 이하의 A를 프로그램에 주입해주어야 BOF가 발생하는 것을 유추 할 수 있다. EIP를 정확하게 덮어 쓰기 위해 정확하게 얼마만큼의 A를 입력해 주어야 할지 추정을 해주어야 한다. 점점 범위를 줄이면서 유추하는 방법도 있겠지만 시간을 단축 시키고 편리성을 위해서 Metasploit에서 재공하는 pattern_creat.rb 도구를 사용하여 EIP offset을 유추 할 것이다.  Pattern_creat.rb 도구는 유일한 패턴을 가진 문자열을 생성시켜 주므로 정확한 버퍼의 크키를 알아내는데 도움을 준다. Pattern_creat.rb파일을 사용하기 위하여 kali linux에 포함된 metasploit을 사용할 것이다.

Pattern_create.rb파일은 기존 Exploit writing tutorial 문서에 적힌 경로와 다르게 존재하며 Kali linux 2020.3버전을 기준으로 /usr/share/metasploit-framework/tools/exploit 경로에 존재 한다. 또한 사용법 역시 ./pattern_create.rb -l 5000 과 같은 방식으로 -l 옵션을 주어야 한다.

 현재 패턴을 15000개 이상 생성해 보아야 offset을 계산할 수 있기 때문에 범위를 조금 줄여서 BOF가 발생하는 지점이 A25000개에서 30000사이임을 확인하고 5000자 길이의 패턴을 생성해 줄 것이다.

 

Pattern_create.rb 를 이용해 패턴 생성

 

해당 패턴을 복사하여 앞서 만든 genCrash.py파일에 추가해준다.

 

수정된 genCrash.py

 

새롭게 수정된 crash.m3u 파일을 Easy RM to mp3 converter에 로드시키면 크래쉬가 발생하며 Windbg가 자동적으로 실행된다. 여기서 주목할 값은 EIP상에 어떤 값들이 덮어쓰여 졌는지 확인해야한다.

 

 

위 사진에서 확인 할 수 있듯이 EIP값이 42396942로 덮여 쓰여진 것을 알 수 있다. 해당 값을 metaspoloit에 내장되어있는 pattern_offset.rb를 통해 정확한 offset을 계산 할 수 있다. 해당 도구는 앞선 pattern_create.rb와 같은 경로에 위치하며 사용법은 ./pattern_offset.rb -q 0x42396942 -l 5000   같은 형식으로 사용한다. 덮여 쓰여진 16진수 값과 초기 생성했던 문자열의 길이를 인자로 전달해주면 정확한 offset을 계산할 수 있다. 해당 명령을 실행 시켜주면 정확한 offset을 계산해준다.

 

Pattern.offset  사용해  offset  계산

 

정확한 offset1047임이 확인이 되었다. 따라서 25000 + 1047 = 26047임이므로 스택의 구조를 대략적으로 유추할 수 있다.

stack 구조

 

 

위와 같은 내용을 확인하기 위해서 genCrash.py파일을 조금 수정해 준다. 먼저 junk 값을 26047개 만큼 넣어주고 거기에 더해 딱 4바이트 만큼의 임의의 문자열을 추가해 디버거 상애 내가 조작한 값이 EIP상에 잘 덮어 쓰여 졌는지 확인할겄이다. 수정된 코드는 아래와 같다.

수정된  genCrash.py

 

새롭게 수정된 Crash.m3u 파일을 Easy Rm to mp3 converter에 로드 시킨후 windbg에 나타나는 EIP 값을 확인해보면 B의 아스키 값인 42424242가 입력 되어있는 것을 알 수 있다.

windbg 확인

 

여기까지 EIP를 조작할 수 있고 실제 offset까지 확인 하였으므로 어디에 쉘코드를 넣을지, 또한 EIP를 조작하여 쉘코드가 있는 곳에 점프 할 수 있는지에 대한 확인이 필요하다.

 

 

먼저 쉘코드가 들어갈 자리를 확인 해야한다. 따라서 EIP까지를 덮어쓴 이후 쉘코드에 해당하는 부분을 genCrash.py에 추가해준다.

쉘코드 공간을 추가한  genCrash.py

 

해당 crash.m3u를 로드시킨 후 windbg에서 커맨드 라인에 d esp를 입력하면 esp에 들어있는 데이터를 확인 할 수 있다.

ESP 의 상태

 

ESP35 36 37로 시작하는 것으로 보아 앞서 쉘코드 공간에 넣어준 1234(0x31,0x32,0x33,0x34)값이 없는 것을 확인 할 수 있다. 사라진 4바이트 값은 saved ebp라고 한다. 따라서 4바이트 만큼의 더미 값이 필요하다. 결과적으로 공격코드의 구성은 아래와 같다.

 

26,047개의 문자열 + “ESP” + “4Byte Dummy” + Shellcode

 

 

결과적으로 수정된 코드는 아래와 같다.

수정된  genCrash.py

 

 

하지만 해당 Crash.m3u파일을 로드해 esp를 확인 해보면 알 수 없는 null값만 존재하고 내가 의도 한 값들은 들어있지 않다.

esp 상태

 

 

이러한 문제가 발생하는 이유는 EIP에 들어가는 값에 00이 존재하므로 Null terminate되어 정상적으로 작동할 수가 없다. 이렇듯 특정 메모리 주소로 직접 점프하는 방식은 좋은 형태의 공격방법이 될 수 없다. 따라서 다른 방법을 사용해야 한다.

결론적으로, 앞서 의도한 것처럼 0x000ff730 과 같이 직접적인 메모리로 EIP를 덮어쓸 수는 없다. 대신에, 어플리케이션이 우리가 제작한 코드로 점프하게 만들도록 하는 방법이 있다. 이상적으로 우리는 레지스터(혹은 레지스터에 대한 offset)을 참조할 수 있어야 하며(현재의 경우 ESP), 그 레지스터로 점프하는 함수를 찾아야 한다. 그런 다음, 우리는 그 함수의 주소로 EIP를 덮어쓸 수 있을 것이다.

우리는 ESP 가 가리키는 곳에 정확히 우리의 쉘코드를 삽입할 수 있었다. (엄밀히 말하자면, ESP 가 쉘코드의 시작 부분을 직접적으로 가리키게 했다.) ESP의 주소로 EIP 를 덮어쓰는 이유는 프로그램이 ESP 로 점프해 쉘코드를 실행하기를 원하기 때문이다.

ESP 로 점프하는 것은 윈도우 어플리케이션에선 아주 흔한 일이다. 사실 윈도우 어플리케이션은 자체적으로 명령어 코드를 가지는 하나 이상의 dll을 가져와 사용한다. 그리고 이 dll에 의해 사용되는 주소들은 정적이다. 40. 만약 우리가 ESP 로 점프하는 명령을 가진 dll을 발견할 수 있다면, 그리하여 우리가 해당 dll에 있는 그 명령의 주소로 EIP 를 덮어쓸 수 있다면 쉘코드 실행이라는 소기의 목적을 달성할 수 있을것이다.

해당 가정을 확인 하기 위해 windbg를 실행 시킨후 Easy RM to MP3 converter attach시킨다.

타겟 프로그램  attach

 

커맨드라인에 a를 입력해 어셈블모드로 전환 시킨후 jmp esp를 입력해 현재 주소 값에 jmp esp를 등록한다. 그리고 a를 다시 입력해 어셈블모드를 종료 시킨후 현재 주소 값을 u 7c90120e를 입력해 주면 아까 내가 입력한 jmp esp 부분이 디스어셈블 되어 나타난다.

 jmp esp  디스어셈블

 

여기서 발견할 수 있는 점은 jmp esp opcode ffe4라는 것이다. 따라서 이제 나는 로딩된 dll중에서 이 opcode를 찾아내야 한다. OS에서 제공하는 dll의 경우 OS에 따라 작동하지 않을 수 있으므로 해당 어플리케이션의 dll에서 찾는 것이 이상적이다. 이번 경우 MSRMCcodec02.dll에서 해당 opcode를 찾도록 할 것이다. 해당 dll이 로드되는 주소는 018f0000 01dbd000이다.

MSRMCcodec02.dll 의 로드 주소

 

Windbg에서 s 018f0000(시작) l(L) 01dbd000() ff e4를 입력해주면 해당 범위내에서 ff e4를 가진 주소를 찾아준다.

ff e4를 가진 주소검색 결과

 

여기서 사용할 주소를 선정할 때 00(Null)이 있는 값들은 피하는 것이 좋다 Null이 리틀에디안 방식으로 마지막에 해당하면 상관없지만 해당 경우는 특수한 경우이기 때문이다.

01afd3db라는 값을 사용하기로 하자. 사용에 앞서 해당 주소를 어셈블 해 실제로 jmp esp가 존재하는지 확인해보자.

01afd3db 어셈블 결과

 

Jmp esp가 존재하는 것을 정확하게 확인 할 수 있다.

결과적으로 eip부분에 방금 찾은 값을 넣어주고 쉘코드에 NOPcc로 브레이크 포인트를 걸어주면 해당 공격이 정상적으로 진행된는 것을 확인 할 수 있을 것이다. 따라서 수정된 genCrash.py코드는 다음과 같다.

수정된  genCrash.py

 

해당 crash.m3u를 로드해 디버거에서 확인해보면 esp에 내가 원하는대로 쉘코드가 올라간 것을 확인 할 수 있다.

esp 상태

 

 

결과적으로 이제 쉘코드에 NOP가 아닌 실제 공격이 가능한 쉘코드를 삽입해주면 공격이 완성될 것이다. 쉘코드는 계산기를 띄우는 것을 사용할 것이다.

 

완성된 exploit 코드

실제 쉘코드를 넣기전에 \x0025개정도 넣어줘야 정상적으로 계산기를 띄울수 있는데 정확한 이유를 모르겠다.

성공적으로 계산기를 띄울 수 있었다.

 

 

 

 


https://www.corelan.be/index.php/2009/07/19/exploit-writing-tutorial-part-1-stack-based-overflows/

eine.tistory.com/entry/%EC%BD%94%EC%96%B4%EB%A0%8C-%ED%8A%9C%ED%86%A0%EB%A6%AC%EC%96%BC-Part1?category=842684

728x90

'Pwnable' 카테고리의 다른 글

CVE-2017-11882 분석  (8) 2021.05.14
Exploit writing tutorial part2 : how to jmp shellcode  (0) 2021.02.21
Exploit writing tutorial part3 : SEH base exploit  (0) 2021.02.14