지옥방 3주차 과제 라젠카 뿌시기(Return to Shellcode)
Return to Shellcode
Return address 영역에 Shellcode가 저장된 주소로 변경해, Shellcode를 호출하는 방식(달고나 문서에서 봤던 방법!!)
call 명령어 call 명령어 다음 명령어의 주소 값(return address)을 stack에 push하고, 피연산자로 주어진 주소로 이동한다.
ret 명령어 ESP(RSP)가 가리키고 있는 주소에 있는 값, 즉 call이 push 해놓았던 return address를 EIP(RIP)에 저장한 후, 그 주소로 이동
이 두 명령어가 실행될 때, 생성되고 사용되는 return address 값을 공격자가 바꿀 수 있다면, 프로그램의 흐름을 변경할 수 있다!!!개멋있다.
line 4에 있는 명령어 call의 주소 값인 0x4004e6에 break point 1을 설정한다.
line 1에 있는 vuln() 함수의 첫번째 명령어의 주소 값인 0x4004d6에 break point 2를 설정한다.
line5에 있는 ret 명령어에 break point 3를 설정한다.
break point 1, 즉 vuln() 함수가 호출되기 전 RSP(ESP)가 가리키는 stack의 위치는 0x7fffffffe4b0, 해당 영역에 저장되어 있는 값은 0x4004f0이다.
break point 2, 즉 vuln() 함수가 호출된 바로 후! RSP(ESP) 레지스터가 가리키는 stack의 위치는 0x7fffffffe4a8, 해당 영역에 저장되어 있는 값은 0x4004eb다. stack의 위치는 8만큼 밑으로 내려온걸 볼 수 있다.(ESP였을 경우 4만큼!). 저장되어 있는 값인 0x4004eb는 vuln() 함수가 종료되고 돌아갈 return address 이므로 main() 함수에서 call 명령어 다음으로 수행될 명령어의 주소다!
break point3, vuln() 함수에서 ret 이전 RSP(ESP) 레지스터가 가리키는 stack의 위치는 0x7fffffffe4a8이며, 해당 영역에 저장되어 있는 값은 0x4004eb(call 명령어를 수행하고 나서 수행해야 하는 nop 명령어의 주소)이다.
RET 명령어가 실행된 후 RSP(ESP)가 가리키는 stack의 위치는 0x7fffffffe4b0이며, 해당 영역에 저장되어 있는 값은 0x4004f0이다.
==> RET 명령어에 의해 Stack에 저장되어 있던 주소값을 RIP 레지스터에 저장하여 해당 주소(여기서는 call 명령어 바로 다음 명령어의 주소)로 이동하게 되었다. 여기서 공격자가 이 RIP에 저장되는 return address를 변경할 수 있다면, 어마무시한 공격 가능
Return address 영역의 첫 주소값인 0x7fffffffe488에 저장되어 있던 return address를 set 뭐시기가 바꾸고 있다.
원래의 return address인 0x4004eb를 0x4004d6으로 set을 이용해 바꾸었다.
이 상태로 break point 3(ret 명령 직전)에서 다음 명령인 ret을 수행하게 되면 RIP에는 공격자가 바꿔놓은 return address가 들어가게 되고 만약 이 주소 값이 쉘코드의 주소 값이였다면 큰일난다!
Permissions in memory 한국어로는 메모리 권한ㅎㅎ
메모리 영역은 다음 3가지 권한들이 설정되어있다.
- read(r) 메모리 영역의 값을 읽을 수 있는 권한
- write(w) 메모리 영역에 값을 저장할 수 있는 권한
- excute(x) 메모리 영역에서 코드를 실행할 수 있는 권한
GCC는 기본적으로 DEP(데이터 실행 방지)가 적용되므로 코드가 저장된 영역에만 실행권한(excute)이 설정되며, 데이터가 저장되는 영역에는 실행권한 X
Shellcode(공격 코드)를 실행하기 위해서는 Shellcode가 저장된 영역에는 excute 권한이 있어야한다!
뭔지는 잘 몰라도 DEP가 켜져 있을때는 다들 읽기 권한(r)은 있는거 같은데 가장 중요한 excute(x) 권한이 보이지 않는다.
다들 막 r--p나 rw-p는 있는뒈,,
아까와 달리 DEP가 비활성화 되었을때는 딱 봐도 주어진 권한들이 rwxp 처럼 꽉꽉 차있다!!
이처럼 DEP를 해제하기 위해서는 GCC 옵션으로 "-z execstack"을 추가하면 된당.
이로써 데이터 저장 영역에도 excute 권한이 생겼고, 이는 Stack에 저장된 Shellcode를 실행할 수 있음을 의미한다.
Proof of concept
main() 함수는 vuln()함수를 호출한다. 호출된 vuln() 함수는 read() 함수를 이용해 100개의 문자를 입력받는다. 으이!? 메모리에 할당한 buf의 크기는 50 byte 인디?? 이래서~ Stack Overflow가 발생한다!
(그 와중에, %p는 주소 출력할때 쓰는 친구인가봐여)
위 그림에 엄청난 수작업으로 표시해둔 1,2,3 번에 한 번씩 브레이크 포인트를 잡아준다.
각각 vuln() 함수의 첫번째 명령어, read() 함수 호출, vuln() 함수의 ret 명령어 부분이다.
Break point 1에서 멈췄다! 함수가 호출되고 함수의 첫번째 명령이 수행되기 바로 전의 상황이다.
RSP(ESP) 레지스터가 가리키고 있는 최상위 stack 메모리는 0x7fffffffe448으로 return address가 저장되어 있다
buf 변수의 위치는 0x7fffffffe400임을 알 수 있당
Break point 2, 즉 read() 함수 호출 직전 멈춰있다. buf 변수의 시작 주소 값은 return address와 72바이트 떨어져있다.(위에서 두 주소 값을 뺀 결과가 72임을 확인!!)
ni로 break point2 에서 명령문 하나를 더 진행한다. 이는 read() 함수의 수행을 의미한다.
이때 72개 이상의 문자를 입력하면 read() 함수의 수행 결과 return address를 조작할 수 있다.
Break point 3, ret 명령 수행 직전!
return address가 저장되어 있던 0x7fffffffe448에 원래의 return address가 아니라 0x4a4a4a4a4a4a4a4a(JJJJJJJJ)가 저장되어 있다.
이로써 read() 함수의 수행 결과 return address를 조작했음을 알 수 있다.
Exploit 공.격.
위에서 학습한 내용으로 Exploit code를 분석해보장
일단 파이썬 코드네요!? 흐음
뭐,, exploit에 쉘코드 넣고 이걸 p.send(exploit) 로 stack 에 넣고 실행하는 이런 느낌...?
완벽한 이해를 할 수 있을때 업데이트,, 아마도 3개월 정도 후ㅎㅎ
댓글
이 글 공유하기
다른 글
-
지옥방 포너블 3주차 과제 모음!
지옥방 포너블 3주차 과제 모음!
2020.04.24 -
지옥방 3주차 과제 라젠카 뿌시기(NX Bit)
지옥방 3주차 과제 라젠카 뿌시기(NX Bit)
2020.04.24 -
지옥방 3주차 과제 달고나 문서 뿌시기!
지옥방 3주차 과제 달고나 문서 뿌시기!
2020.04.23 -
지옥방 3주차 과제 DreamHack-System Exploitation Fundamental
지옥방 3주차 과제 DreamHack-System Exploitation Fundamental
2020.04.21