[ftz] level 16: about to cause mass
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에 셸코드 올리기
방법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 |
댓글