본문 바로가기

Hacking & Security/Exploit

Return to Shellcode

Return to Shellcode


- Return to Shellcode 란 , 이름 그대로 프레임의 Return address 영역을 Shellcode가 위치한 주소로 변경시켜
 프로그램의 흐름을 의도적
으로 조작하여 shellcode를 호출하는 방식이다.



Return to Shellcode 이해하기


- Return to Shellcode를 이해하기 위해서는 Assembly Instruction 중 CALL 과 RET에 대한 이해가 요구된다.


CALL Instruction : Return Address ( CALL 명령어 다음으로 실행할 명령어의 위치 ( 주소 ) ) 를 Stack에 저장후 , 피연산자의 주소로 이동 


RET Instruction : POP Instruction을 통하여 ESP 레지스터가 가리키는 Stack 영역에 저장된 값을 EIP에 저장후 , 해당 주소로 이동한다.


즉 , Stack 영역에 저장된 Return address 값을 변경할 수 있다면 , 우리는 프로그램의 흐름을 변경할 수 있다.



CALL & RET 명령어 이해하기.


- 다음의 예시와 같은 코드를 통하여 CALL , RET 명령어에 대한 이해를 돕자.



main() 에서 vuln() 을 호출하는 단순 코드이며 , vuln()은 아무 역할도 하지 않는다.



해당 소스를 위의 적어놓은 컴파일 옵션을 통하여 컴파일 후 ,


위와 같이 BreakPoint를 설정한다.


위의 Call Instruction의 흐름은 아래의 사진을 보며 이해해보자.



Call Instruction


Call Instruction의 동작.


- vuln() 함수 호출전 , ESP(RSP) Register가 가리키는 Stack의 위치는 0x7fffffffddb0 이며 , 
   해당 영역에 저장되어 있는 값은  0x0000555555554620 이다.


- vuln() 함수 호출 후 , ESP(RSP) Register가 가리키는 Stack의 위치는 0x7fffffffdda8 이며 , 

   해당 영역에 저장되어 있는 값은 0x000055555555460f 이다.


- 즉 , CALL 명령어에 의해 Stack에 호출된 함수가 종료된 후에 이동할 주소 (Return address ) 값을 저장함을 확인 할 수 있다.



RET instruction


RET instruction의 동작.


위와 같은 개념을 이용하여 레지스터의 흐름을 살펴보면 RET의 동작의 흐름을 이해할 수 있다.


이제 해당 기법을 이용하여 직접 문제에 적용시켜 보자.



compile option : gcc -z execstack -fno-stack-protector -o test test.c


예제 소스이다.


소스를 분석해보자.


- main함수는 vuln함수를 호출한다.

- vuln함수에는 길이 50의 buf가 있으며 , read 함수를 통하여 buf에 100byte 길이까지 입력을 받는다.


여기 취약점이 존재한다.


buf의 크기는 50byte인데 , 우리가 입력할 수 있는 길이는 100byte로 Stack Overflow가 발생한다.



그럼 이제 Exploit 위해 필요한 정보들을 긁어모으자!



Stack Overflow의 흐름을 정확히 파악하기 위해 다음과 같이 BreakPoint를 설정한다.


vuln+0 : vuln()의 첫번째 명령어


vuln+49 : vuln()내에서 read()함수 호출부분


vuln+56 : vuln()의 ret 명령어


이제 Return address를 확인하여 보자.



위와 같이 gdb를 통하여 Return address를 확인 할 수 있다.


Return address는 함수를 호출 후 돌아갈 주소가 저장되어 있음을 기억하자.


RSP 레지스터가 가지고 있는 stack 최상위 메모리는 0x7fffffffdda8 이며 , 해당 메모리에 vuln() 함수 종료 후


돌아갈 코드영역의 주소값 0x5555555546d1이 저장되어 있다.


Return address의 주소는 구하였으니 이제 취약점을 공략하기 위한 요소인 buf의 시작주소를 구하자.



이번 예제에서는 본문 소스에서 %p , buf 를 통하여 프로그램 구동시 buf의 시작주소를 프린트하도록 설계해놓았다.


이렇게 Exploit을 위한 준비요소는 모두 준비되었다.


Return address : 0x7ffffffffdda8


buffer의 시작 주소 : 0x7ffffffffdd60


이 둘 사이의 위치를 구하여 보면 10진수 값으로 72byte임을 확인할 수 있다.


위 정보의 의미는 , 사용자 입력값으로 문자를 72개 이상 입력하면 , Return address를 덮어쓸 수 있다는 의미이다.


이 정보들을 토대로 Exploit code를 작성한다.



그리고 해당 코드를 실행시키면 쉘을 획득할 수 있다.

'Hacking & Security > Exploit' 카테고리의 다른 글

diff 32bit vs 64bit  (0) 2019.11.20
Return To Libc ( RTL )  (0) 2018.12.29
Basic of pwnable  (0) 2018.12.27
BOF 기초문서  (0) 2018.11.03