Studying Security

_IO_FILE vtable 본문

개념 정리/_IO_FILE

_IO_FILE vtable

J4guar 2022. 5. 13. 01:08
728x90
반응형

vtable overwrite (glibc < 2.24)

만약 vtable을 overwrite할 수 있는 조건이라면 해당 vtable에 조작된 vtable을 overwrite함으로써

원하는 동작을 수행하도록 할 수 있습니다.

 

그러나 IO_validate_vtable 함수가 생겨나면서 더 이상 vtable overwrite 기법으로 공격할 수 없습니다.

Bypass IO_validate_vtable (glibc < 2.29)

전달된 파일 포인터의 vtable 주소를 참조하기 때문에 이 점을 이용합니다.

vtable을 참조하는 과정을 확인해봅시다.

IO_validate_vtable

vtable pointer가 __libc_IO_vtables section에 할당됩니다.

해당 섹션의 시작과 끝 주소의 차이로 섹션의 크기를 알아냅니다.

호출하려는 vtable의 주소가 섹션의 크기를 벗어나는 값이라면 _IO_vtable_check함수를 호출해 에러를 발생시킵니다.

 

따라서 해당 검사를 우회하기 위해서는 __libc_IO_vtables 섹션에 존재하는 함수들 중 공격에 사용될 수 있는 함수를 찾아야 합니다.

 

using _IO_str_overflow

<_IO_str_overflow>

_IO_str_overflow 함수를 보면 파일 포인터 내에서 _s._allocate_buffer라는 이름의 함수 포인터를 호출합니다.

그리고 인자로 new_size를 전달받았음을 확인할 수 있습니다.

new_size 변수가 어떻게 설정되는지 보면 함수 포인터 내의 _IO_buf_end와 _IO_buf_base를 이용하여

new_size = 2 * ((fp)->_IO_buf_end - (fp)->_IO_buf_base) + 100 으로 설정됩니다.

#define _IO_blen(fp) ((fp)->_IO_buf_end - (fp)->_IO_buf_base)

따라서 파일의 구조체를 overwrite할 수 있는 상황이라면 new_size 변수를 조작할 수 있습니다.

 

함수 포인터를 호출하기 위한 조건

함수 포인터를 호출하기 위해서는 조건문을 통과해야 합니다.

해당 조건문 또한 _IO_FILE 구조체 변수인 _IO_write_ptr과 _IO_write_base 변수들의 연산 값을 사용합니다.

비교 구문에서 사용되는 flush_only 변수는 기본값이 0이며, 결과적으로 pos >= _IO_blen(fp) 입니다.

따라서 _IO_write_base를 0으로 초기화하면 _IO_write_ptr 값이 곧 pos 변수의 값이 되므로 쉽게 해당 비교 구문을 통과하고 함수 포인터를 호출할 수 있습니다.

 

using _IO_str_finish

<_IO_str_finish>

_IO_str_finish의 경우도 fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF)의 조건문을 통과한다면

_s._free_buffer라는 함수 포인터를 호출할 수 있습니다.

인자로 fp->_IO_buf_base 변수가 전달되며 이를 조작할 수 있다면 원하는 함수를 호출할 수 있습니다.

 

Reference

 

 

반응형

'개념 정리 > _IO_FILE' 카테고리의 다른 글

_IO_FILE Arbitrary Address Write  (0) 2022.05.12
_IO_FILE Arbitrary Address Read  (0) 2022.05.12
_IO_FILE  (0) 2022.05.11
Comments