1. PEDA ?

Python Exploit Development Assistance for GDB 의 약자로써, 일반 GDB보다 바이너리 Exploit을 편리하게 할 수 있도록 다양한 옵션과 기능이 추가되어 만들어진 툴입니다. CTF대회같은 경우 시간절약이 중요하기 때문에 많이들 사용하시는 거 같습니다. 

저도 사용해보니 일단 알록달록해지는 UI와 디버깅 진행 할때마다 눈에 잘들어오는 stack 및 레지스트리 값 변화 등 보통의 gdb에 비해

아주아주 편리했습니다.


PEDA를 설치해본 결과 설치방법은 아래 링크가 가장 잘 설명이 되어있는 것 같습니다. 

설치 관련 블로그 링크 : https://hexa-unist.github.io/2015/02/25/PEDA-Introduction-Installation/



2. PEDA 기본 기능

모든 기능과 옵션을 본 글에서 다루기에는 어려움이 있어서... 상세한 내용은 2012년 BlackHat 발표자료를 첨부하였으니 살펴보시면 됩니다.


BH_US_12_Le_Linux_Interactive_Exploit_Development_with_GDB_and_P


2-1) pdisas

gdb에서 disas 혹은 disassemble 로 사용했던 디스어셈블 기능의 확장판이라고 보시면 됩니다.

pdisas로 디스어셈블을 하게 되면 알록달록하게 하이라이팅 되어 비교적 가독성이 뛰어난 어셈블코드를 볼 수 있습니다.


아래 캡쳐를 보시면 확연히 비교가 됩니다.


disas func로 디스어셈블



pdisas func로 디스어셈블


2-2) stack 및 레지스트리 값 변화 확인

위 기능은 특별한 옵션을 주거나 명령을 통해 확인하는 것이 아니라, 브레이크 포인트를 걸고 디버깅을 하는 과정에서 바로 기능이 적용됩니다.



브레이크포인트를 걸고 실행을 하여 해당 위치에서 멈춘 화면입니다.

맨 위에는 각 레지스트리의 값과 해당 메모리에 어떤 값이 위치하고 있는지 해석도 나오고 있으며, 바로 아래에는 현재 브레이크 포인트가 어디에 멈추어져있는지(EIP 값이 얼마인지)를 나타내는 부분이 있고, 맨 아래에는 stack의 값 또한 바로 보여주고 있습니다.


2-3) find 명령어

find 명령어를 사용하여 특정 스트링을 검색 할 수 있습니다.

현재 프로그램에서 입력하는 곳에 "aaa"문자열을 입력한 상태였고, find명려어로 aaa를 서치한 결과입니다.



aaa라는 문자열이 heap과 stack에서 어디에 위치하고 있는지 표시해주고 있습니다.


2-4) 쉘코드 생성하기

BOF공격을 하기 위해 쉘코드를 찾으려고 여러 블로그를 뒤져보곤했는데, PEDA에선 각종 쉘코드를 제너레이트 해주는 기능이 있었습니다.

먼저 shellcode generate라고 입력하면 생성할 수 있는 shellcode의 종류를 보여줍니다.

위 캡쳐 화면에서 볼 수 있듯이 현재로써는 x86 쉘코드 밖에 지원이 되지 않는 것 같습니다.


직접 제너레이트 한 결과는 아래와 같습니다.



따로 쉘코드를 작성하거나, 블로그를 뒤져 찾아보지 않아도 되니 급할 때는 유용하게 사용 할 수 있을 것 같네요.



3) PEDA를 이용한 pwnable.kr bof문제 풀어보기


3-1) 문제 확인




문제 화면입니다.


Nana told me that buffer overflow is one of the most common software vulnerability. 

Is that true?


나나가 나에게 버퍼오버플로우가 가장 일반적인 소프트웨어 취약점이라고 말했는데 이거 실화냐? 라고 묻고있네요.

그리고 Download 링크가 두개가 있습니다. 하나는 c소스 파일이고 다른 하나는 c소스파일을 컴파일하여 생성된 바이너리인 것 같습니다.

wget으로 다 다운받아줍니다.


그리고 pwnable.kr 9000으로 돌리라고 하네요.


3-2) c소스파일 분석




메인함수에는 별 로직이 없네요.

func라는 함수에 헥사 값 0xdeadbeef라는 값을 전달하고 종료하고 있습니다.

bof를 유도 하는 로직은 func에 있는 듯 합니다.


func함수를 살펴보면 리턴 값은 없고, int형의 key라는 파라미터를 받고 있습니다. 

이 key값에는 메인함수에서 하드코드로 박혀있는 0xdeadbeef값이 전달이 되겠네요.


func함수의 바로 첫 라인에서는 overflowme라고 대놓고 선언되어있는 지역변수 char배열 32byte짜리 변수가 보입니다.

그리곤 overflow me : 라는 문자열을 출력하고 입력받은 값을 overflowme에 넣어주고 있습니다.

단순 gets함수로 받고 있기 때문에, 또 앞부분에서 size검사 부분이 없기 때문에 bof를 시킬 수 있는 포인트가 되며 

주석으로도 smash me! 라고 외치고 있는 것을 볼 수 있습니다.


아래 부분에서는 key 값이 0xcafebabe를 가지고 있는지 검사한 후 값이 일치하면 쉘을 넘겨 주고 있습니다.

위의 소스코드를 분석한 내용을 토대로 보면, func함수가 호출 되었을 때 stack의 모습을 예상해 볼 수 있습니다.





3-3) PEDA를 이용한 분석




main함수를 디스어셈블한 화면입니다. 함수 콜 직전에 0x0000063라인을 보면 mov로 esp에 함수 인자값을 대입하고 있는데,

간단히 push를 실행한 것과 동일하다고 보시면 되겠습니다.

그럼 func함수 호출부분에 브레이크 포인터를 걸고 실행하여 위의 내용이 맞는지 호출 전 스택의 상황을 살펴보도록 하겠습니다.



우리가 예상 한 것처럼 스택의 최상단에 func함수의 인자로 넣어준 0xdeadbeef가 위치하는 것을 확인할 수 있습니다.





si 명령을 통해 func함수 호출 직 후의 화면입니다. 함수 call을 하면서 다음 실행 명령 주소를 stack에 push한 것을 볼 수 있습니다.




func함수를 디스어셈블 한 화면입니다. 스택프레임 구성을 위해 ebp를 푸쉬하고있고, 지역변수인 overflowme[32]를 스택에 올리기위해 esp를 0x48 만큼 빼주고 있습니다. 정확히 32byte가 아니고, 0x48만큼인 이유는 컴파일러마다 약간의 사이즈 차이가 있기 때문이라고 하네요.


여기까지 분석한 스택의 상황을 그림으로 살펴보면 아래 처럼 되겠습니다.


더미가 overflowme[32]변수의 위에 위치할 지, 아래에 위치할 지 혹은 위 아래 나뉘어서 위치하고 있을 지는 직접 메모리를 들여다 보지 않아서 모르나, 둘이 합쳐 72byte(0x48)임은 어셈코드에서 알 수 있었고, 이에 따라 러프하게 개념적으로 위처럼 그려볼 수 있습니다. 

따라서 덮어써야할 내용은 

최소 44바이트(32byte + 4byte + 4byte + 0xcafebabe(4byte)) 부터 84byte(72byte + 4byte + 4byte + oxcafebabe(4byte))가 됩니다.

정확히 몇 바이트인지는 더 분석을 해봐야하겠네요.


입력값은 aaaaaaaa을 넣은 후 func+40에서 브레이크 포인트를 잡은 후 확인을 해보도록 하겠습니다.



esp(0xffffd1d0)에는 우리가 입력한 aaaaaaaa를 저장하고 있는 스택 내 overflowme[32]변수의 주소(0xffffd1ec)를 가르키고 있는 것을 볼 수 있습니다.



2-3) 에서 알아봤던 find명령어를 이용하여 aaaaaaaa가 위치한 스택 내 주소를 찾고, 0xdeadbeef가 위치한 스택 내 주소를 찾았습니다.

0xdeadbeef가 헥사값이라서 검색이 안될줄 알았는데 검색이 되어서 놀랐네요;

여하튼! 나온 주소 값의 차이는 0xffffd220 - 0xffffd1ec = 0x34(52) 임을 확인했습니다. 이 결과를 가지고 스택을 다시 그려보면

overflowme변수 위 아래에 더미가 껴있는 아래와 같은 형태로 그릴 수 있겠습니다.



3-4) exploit

결과부터 말씀드리면 exploit에 성공한 코드는 아래와 같습니다.


(python -c 'print "A"*52+"\xbe\xba\xfe\xca"';cat)|nc pwnable.kr 9000



먼저, python -c 'print "A"*52+"\xbe\xba\xfe\xca" 이 부분은 우리가 위에서 계산한 52바이트를 A라는 문자로 덮어버린 후

조작해야 할 헥사값 0xcafebabe로 만드는 문자열을 만드는 파이썬 구문입니다.

\xbe\xba\xfe\xca 처럼 역 순으로 문자열을 만든 이유는 엔디언 방식이 다르기 때문이고, 괄호와 세미콜론 + cat의 의미는

바이너리 실행 후 입력 값을 받는 형태를 맞춰주기 위함 입니다.

마지막으로 파이프로 연결한 후 문제에서 제시한 서버와 포트에 nc를 이용하여 전달하였습니다.



3-5) 결과



쉘이 실행 되었고 플래그값을 읽을 수 있음을 확인하였습니다 :)

'Study > Pwnable' 카테고리의 다른 글

[HITCON Training] lab4 / return to library  (0) 2017.11.29
[HITCON Training] lab2 / shellcraft  (0) 2017.11.28
NX(No eXcutable) / ROP  (1) 2017.09.29
pwnable.kr / input / pwntools  (0) 2017.08.01
pwnable.kr passcode  (5) 2017.07.31
PEDA / pwnable.kr bof문제  (0) 2017.07.12

+ Recent posts