write-up/pwnable

[ftz] level 16: about to cause mass

여니두 2019. 8. 24.

16_함수 포인터 변조(1)

 

앞의 단순한 변수형의 포인터보다 더 어려운 함수 포인터와 관련된 문제이다.

함수의 시작 번지를 가지고 있는 포인터의 주소값다른 함수의 주소값으로 바꾸면,

다른 함수가 실행되는 공격도 가능하다는 것이 핵심.

 

- void (*call)() 타입의 call 함수 포인터를 printit의 주소로 선언, 초기화.

- buf 크기 20byte

- 입력값은 48byte까지 받을 수 있다

- call() 함수 포인터 호출 > printit이 실행될 것

 

>> call 함수 포인터가 가리키는 함수의 주소를

shell() 함수의 주소로 바꾼다면 shell() 함수를 실행할 수 있을 것

 

- 함수 흐름을 바꾸는 기법에서 더 나아가면

RTL(Return To Libc), GOT(Global Offset Table) 같이 공유 라이브러리나 바이너리에 내장된 글로벌 옵셋 테이블에 있는 함수로 흐름을 바꿔 배시셸을 실행할 수 있다.

: 고급 BOF 공격

 

√ gdb로 소스코드 분석

 

* disas main

- main+3> stack에 공간 56byte 확보

- ebp-16에 0x8048500 대입

: void (*call)() = printit;

- >> fgets(ebp-56, 0x30, 0x80496e8)

= fgets(buf, 48, stdin)

- ebp-16에 있는 내용(함수) 호출

: call()

 

buf 배열 시작주소에서 44byte 떨어진 곳에 call 함수 포인터와 crap 변수가 있음.

 

buf[20]
dummy

*call()

(0x08048500)

crap
dummy
SFP
RET

* disas printit

printit() 함수의 시작 주소가 0x08048500임을 확인하였다.

 

* disas shell

shell() 함수의 주소: 0x080484d0

 

 

√ 공격

BOF 시켜 *call() 함수 포인터에 초기화돼있는 printit() 함수의 주소를 shell() 함수의 주소로 바꾸자.

 

NOP[40] + 0x080484d0

 

Level 17 Password = king poetic

 

** AT&T 문법 VS Intel 문법

- gdb의 디폴트 문법: AT&T 어셈블리 문법

- AT&T 문법: 명령어 SRC DEST

- Intel 문법: 명령어 DEST SRC

 

 

** 환경변수 이용한 BOF

fgets(buf, 48, stdin)은 48byte까지만 입력받는 BOF 방어 코드 때문에 RET을 변조할 수 없지만,

다행히 오버플로우시킬 수 있는 범위 안에

*call() 함수 포인터에서 호출하는 주소는 변조할 수 있으므로 이를 BOF 시켜보자.

 

방법1) 환경변수에 셸코드를 올리고, 환경변수 주소를 call 포인터 변수에 덮어쓰기

- 환경변수 SHELL에 셸코드 올리기

getenv.c

 

방법2) buf 배열에 셸코드를 넣고, buf 배열의 주소를 *call() 함수 포인터에 덮어쓰기

 

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

[ftz] level 18: why did you do it  (0) 2019.08.27
[ftz] level 17: king poetic  (0) 2019.08.26
[ftz] level 15: guess what  (0) 2019.08.24
[ftz] level 14: what that nigga want?  (0) 2019.08.23
[ftz] level 13: have no clue  (0) 2019.08.23

댓글