write-up/pwnable

[ftz] level 12: it is like this

여니두 2019. 8. 21.

12_버퍼 오버플로우

 

√ BOF 관련 개념

1. 버퍼

: 변수에 데이터를 저장하기 위해 확보된 임시 메모리 공간

- 지역변수는 순서대로 변수의 크기에 해당하는 간격을 두고 스택에 쌓임

 

2. main() 함수는 스택 프레임이 구성되면서 지역변수, 스택프레임 포인터(이전 함수 베이스 포인터[EBP]) SFP, 인자수, 인자값, 환경변수의 선형 순서로 스택에 배치됨.

 

3. BOF: 입력값의 크기가 버퍼의 크기보다 큰지 경계 검사를 하지 않은 경우, 메모리에 확보된 버퍼의 크기를 초과해서 데이터가 저장되면서 버퍼 주변 공간(RET 등)까지 덮어씌워지는 이상 현상

- 취약점이 있는 소스코드를 보면 입력받은 값에 대한 길이가 할당된 버퍼 크기를 넘지 않는지 경계 검사를 하지 않는 것이 취약점의 핵심

 

* 취약한 소스코드 예제

함수마다 함수 스택 프레임이 구성된다.

- 현재의 함수를 호출한 함수의 SFP와 RET 및 인자값 등을 먼저 저장

- 그 후 지역변수가 쌓임

(stack에서 POP할 내용이 나중에 있어야 하는 stack 기본 개념과 관련)

 

int a 4
char *ptr 4
char str[256] 256
SFP 4
RET 4
argc 4(인자수)
argv 4(인자값)
env 4(환경변수)

버퍼 오버플로우

- 사용자의 입력에 대한 문자열 길이를 검사하지 않는다면

str 배열에 256byte 이상의 문자열을 입력하면 str 배열은 물론 ptr, a 변수, SFP, RET까지 덮어써서 변수 값 변조는 물론 RET까지 변조할 수 있게 된다.

(메모리 주소에 정상적인 실행 코드가 없다면 Segmentation Fault 에러)

 

>> RET을 덮어쓸 때는 반드시 우리가 의도한 실행코드가 위치한 정확한 주소로 덮어써야 한다.

- 로컬 공격) 셸 실행 코드

- 원격 공격) 포트를 바인딩하는 코드에서 파일을 내려받거나, 원격 서버에서 공격자 쪽으로 역으로 연결하는 리버스커넥션 등의 코드

 

 

√ 문제 분석

%s 포맷스트링이 정확히 입력돼있어서 포맷스트링 취약점은 존재하지 않는다.

 

str 배열과 RET 간의 간격을 정확히 알아야 정확한 위치에 값을 덮어쓸 수 있을 것이다.

디버깅하여 알아보자.

 

√ gdb로 소스코드 분석

 

procedure prelude 과정

함수 프롤로그 부분

main+3> sub esp, 0x108

: stack에 264byte만큼 공간을 줌

str[256]+dummy[8] = 264

 

*** dummy 공간 이유: 컴파일 시 CPU가 처리하기 편한 공간이 할당되기 때문

 

>> setreuid(3093, 3093)

>> printf("문장을~ ")

 

>> gets(ebp-264)

= gets(str)

 

>> printf("%s\n", ebp-264)

printf("%s\n", str)

 

.

.

.

- printf()에 bp를 걸고 문자열을 입력한 후 메모리 구조를 확인해보았다.

- str 배열 시작 주소: 0xbffff0d0

- SFP: 0xbffff1d8

- RET: 0xbffff1dc

 

str[256]
dummy[8]
SFP[4]
RET[4]

 

√ 공격

 

* NOP(No OPeration)

: 썰매. 아무것도 하지 않는 어셈블리 명령

- 셸코드의 시작 주소를 부정확하게 확인하더라도 NOP 개수만큼의 오차 범위 안의 주소로 RET을 덮어쓸 수 있다면 공격 성공 가능

 

str[200] + SHELL CODE[24] + str[32] + dummy[8] + SFP[4] + str 주소

 

>> NOP[240] + SHELL CODE[24] + NOP[8] + str 주소(0xbffff0d0)

 

.

.

.

 

스택 메모리 주소 값이 계속 바뀌는 것 같아서 환경변수에 셸코드를 넣어 공격하기로 했다.

 

- 환경변수에 셸코드 담기

 

- 환경변수 주소 값을 print하는 getenv.c 작성

 

SHELLCODE 주소: 0xbffffafb

 

페이로드: NOP[268] + SHELLCODE 주소[4]

 

./attackme [페이로드]

이렇게 했더니 쉘이 잘 따지지 않아, 위와 같은 방식으로 했더니 잘 따졌다.

웬만하면 파이프로 인자를 전달해야겠다.

 

Level 13 Password = have no clue

'write-up > pwnable' 카테고리의 다른 글

[ftz] level 14: what that nigga want?  (0) 2019.08.23
[ftz] level 13: have no clue  (0) 2019.08.23
[ftz] level 11: what!@#$?  (0) 2019.08.21
[ftz] level 10: interesting to hack!  (0) 2019.08.18
[ftz] level 9: apple  (0) 2019.08.17

댓글