System Hacking/Buffer Overflow

[Buffer Overflow] Return Address Overwrite 실습 - (2)

jir4vvit 2020. 9. 8. 15:16

참고 : dreamhack.io
환경 : ubuntu 16.04.7

 

[Buffer Overflow] Return Address Overwrite 실습 - (1-2)

jiravvit.tistory.com/entry/Buffer-Overflow-Return-Address-Overwrite-%EC%8B%A4%EC%8A%B5-1-2

 

[Buffer Overflow] Return Address Overwrite 실습 - (1-2)

참고 : dreamhack.io 환경 : ubuntu 16.04.7 jiravvit.tistory.com/entry/Buffer-Overflow-Return-Address-Overwrite-%EC%8B%A4%EC%8A%B5-1 [Buffer Overflow] Return Address Overwrite 실습 - (1) 참고 : dreamh..

jiravvit.tistory.com

 

buf에 내가 원하는 행동(쉘 획득)을 실행시키는 쉘 코드를 넣고 RET에 buf가 시작되는 주소로 설정해 공격이 되는지 실습을 진행하도록 하자.


 

계속 동일한 코드이다.

버퍼 오버플로우를 실습할 example1.c이다.

example1.c

표시한 strcpy에서 버퍼오버플로우 취약점이 발생하고 있다.

 


buf에 우리가 원하는 행동 즉, 쉘 획득을 하는 쉘코드를 넣어야한다.

여기서 쉘코드가 무엇인지부터 알아보자. 

 

쉘은 커맨드 라인의 명령어, 혹은 스크립트를 받아 서버에서 그에 맞는 기능을 실행해주는 프로그램이다.

 

쉘을 실행하는 이유는, root 권한을 얻기 위해 권한을 상승시키거나 본래의 프로그램이 의도치 않은 행위를 하기 위해서 이다. 이 프로그램에서 쉘을 실행하게 되면 해당 바이너리 권한의 쉘을 획득하여 임의의 명령어를 실행할 수 있게 된다.

 

한 마디로, 공격자 마음대로 서버를 조종할 수 있게 된다는 뜻이다.

 

 

공격자가 /bin/sh 혹은 쉘 바이너리를 실행하는 기계어코드를 실행한다면, 쉘에서 제공하는 여러 명령어들을 실행할 수 있게 된다.

 

해당 쉘코드는 직접 만들 수도 있지만, 구글에서 쉽게 찾을 수 있다.

 

우리는 아래의 쉘 코드를 사용하도록 하자.

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xb0\x0b\xcd\x80

아래는 vuln 함수의 구조이다.

vuln 함수

buf에 strcpy 함수를 통해 복사된 문자열이 쌓인다. 저기다가 우리가 준비한 쉘 코드를 넣고 추가로 더미값을 넣어준다. 

 

RET를 건드리기 전까지 더미값을 넣어주고 최종적으로 RET에는 buf의 시작주소를 넣어주면 우리가 준비한 쉘코드가 실행되어 쉘을 획득할 수 있지 않을까??? 

 

기대할 수 있다. ㅎㅎ

 

위의 말을 아래 그림처럼 그려볼 수 있겠다.

메모리

이를 위해 페이로드를 작성해보자. dummy 값은 그냥 간단하게 "A"로 잡자.

 


입력값으로 "aaaabbbbccccddddeeeeffffgggghhhh"를 주었다.

 

vuln 함수 안에서 strcpy 함수를 실행시키고 esp를 확인해보았다.

메모리 주소 0xffffd00c에 위치한 buf에 내가 입력한 문자열이 복사된 것을 확인하였다.

 

우리 컴퓨터는 리틀엔디안을 기본원칙으로 하기 때문에 저기서 메모리 주소를 반대로 적어야 한다. 

 

 

 

 

결론적으로 아래의 문자를 argv[1]로 입력해줘야 한다. 

"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xb0\x0b\xcd\x80" + "A"*13 + "\x0c\xd0\xff\xff"​

 


argv[1]로 입력해주었지만... 세그멘테이션 오류가 뜬다... 쉘을 획득하지 못하고 프로그램이 종료되었다.

 

왜그럴까..?

 

왜냐하면 스택의 쉘 코드의 주소가 바뀌었기 때문이다.

 

 

아래코드를 실행시켜보겠다.

// binary.c
#include <stdio.h>

int main(int argc, char *argv[1]){

  printf("argv[0] : %s\n", argv[0]);
  
}

그냥 실행시켰을 때 argv[0]에 상대경로로 저장하고, gdb는 argv[0]에 절대경로로 저장한다.

우리는 gdb에서 열심히 스택 주소값을 살펴보았다 ㅋㅋ

 

때문에 스택 주소에 약간의 오차가 생기게 된다.

 

 

 

 

 

 

이를 어떻게 해결하면 좋을까..?

다음 포스팅에서 알아보자.