ghkdtlwns987
_IO_FILE_vtable 1 본문
이번엔 _IO_FILE_vtable 에 대해 다뤄보고자 한다.
_IO_FILE 이라 하면 파일 포인터(fp) 가 생각나는게 일반적이다.
하지만 _IO_FILE 은 그보다 더 많은 정보를 포함하고 있다.
예를 들자면 read,write,fread,write... 와 같은 함수를 사용하면 내부적으로 _IO_FILE 구조체를 참고하게 되는 것이다.
_IO_FILE
struct _IO_FILE
{
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
/* The following pointers correspond to the C++ streambuf protocol. */
char *_IO_read_ptr; /* Current read pointer */
char *_IO_read_end; /* End of get area. */
char *_IO_read_base; /* Start of putback+get area. */
char *_IO_write_base; /* Start of put area. */
char *_IO_write_ptr; /* Current put pointer. */
char *_IO_write_end; /* End of put area. */
char *_IO_buf_base; /* Start of reserve area. */
char *_IO_buf_end; /* End of reserve area. */
/* The following fields are used to support backing up and undo. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base; /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno;
int _flags2;
__off_t _old_offset; /* This used to be _offset but it's too small. */
/* 1+column number of pbase(); 0 is unknown. */
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];
_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};
-
_flags
-
파일에 대한 읽기/쓰기/추가 권한을 의미한다. 0xfbad0000가 매직 값이며 하위 2바이트는 여러 비트 플래그들입니다. 각각의 의미에 대해서는 잠시 후에 다루겠다.
-
-
_IO_read_ptr
-
파일 읽기 버퍼에 대한 포인터이다.
-
-
_IO_read_end
-
파일 읽기 버퍼 주소의 끝을 가리키는 포인터이다.
-
-
_IO_read_base
-
파일 읽기 버퍼 주소의 시작을 가리키는 포인터이다
-
-
_IO_write_base
-
파일 쓰기 버퍼 주소의 시작을 가리키는 포인터이다
-
-
_IO_write_ptr
-
쓰기 버퍼에 대한 포인터이다.
-
-
_IO_write_end
-
파일 쓰기 버퍼 주소의 끝을 가리키는 포인터이다.
-
-
_chain
-
프로세스의 _IO_FILE 구조체는 _chain 필드를 통해 링크드 리스트를 만든다. 링크드 리스트의 헤더는 라이브러리의 전역 변수인 _IO_list_all에 저장된다.
-
-
_fileno
-
파일 디스크립터의 값이다.
-
+ 예를 들자면 다음과 같을 것이다.
- Read buffers
- _IO_read_ptr
- _IO_read_end
- _IO_read_base
- Write buffers
- _IO_write_ptr
- _IO_write_end
- _IO_write_base
- Reserve buffers
- _IO_buf_base
- _IO_buf_end
위의 접은 글에 있는 내용은 드림핵에 나와 있는 내용이다.
난 여기서 추가로 공부했던 내용도 추가로 정리해 볼 예정이다.
먼저, _IO_write_base, _IO_write_ptr 에 대해 설명해 보자면 _IO_write_base < _IO_write_ptr 이 된다면
_IO_overflow() 함수를 호출하게 되는데, 이는 잠시 후에 설명하도록 하겠다. (너무 길어지면 다음글에 정리)
우선은 flag 에 대해 설명해보고자 한다.
#define _IO_MAGIC 0xFBAD0000 /* Magic number */
#define _IO_MAGIC_MASK 0xFFFF0000
#define _IO_USER_BUF 0x0001 /* Don't deallocate buffer on close. */
#define _IO_UNBUFFERED 0x0002
#define _IO_NO_READS 0x0004 /* Reading not allowed. */
#define _IO_NO_WRITES 0x0008 /* Writing not allowed. */
#define _IO_EOF_SEEN 0x0010
#define _IO_ERR_SEEN 0x0020
#define _IO_DELETE_DONT_CLOSE 0x0040 /* Don't call close(_fileno) on close. */
#define _IO_LINKED 0x0080 /* In the list of all open files. */
#define _IO_IN_BACKUP 0x0100
#define _IO_LINE_BUF 0x0200
#define _IO_TIED_PUT_GET 0x0400 /* Put and get pointer move in unison. */
#define _IO_CURRENTLY_PUTTING 0x0800
#define _IO_IS_APPENDING 0x1000
#define _IO_IS_FILEBUF 0x2000
/* 0x4000 No longer used, reserved for compat. */
#define _IO_USER_LOCK 0x8000
다음은 flag bit 이다. 만약 flag 가 0xfbad2488 라 한다면 _IO_MAGIC, _IO_IS_FILIEBUF, _IO_TIED_PUT_GET, _IO_LINKED, _IO_NO_WRITES 가 설정되어 있다고 볼 수 있다.
설명할게 많기 떄문에 우선은 여기까지만 설명하고 넘어가겠다.
다음으로는 _IO_FILE_vtable 에 대해서 알아보도록 하자.
이는 _IO_FILE_plus 라고도 불린다. 즉, _IO_FILE_plus 는 vtable을 가리킨다라고 생각하면 된다.
stdin, stdout, stderr 도 이 구조체를 사용하고, 모든 파일 관련된 작업들은 이 _IO_FILE_plus 를 사용한다.
struct _IO_FILE_plus
{
_IO_FILE file;
const struct _IO_jump_t *vtable;
};
(디버깅을 할 때는 _IO_file_jumps 라고 한다. 실제 명칭도 그렇다.)
const struct _IO_jump_t _IO_file_jumps libio_vtable =
{
JUMP_INIT_DUMMY,
JUMP_INIT(finish, _IO_file_finish),
JUMP_INIT(overflow, _IO_file_overflow),
JUMP_INIT(underflow, _IO_file_underflow),
JUMP_INIT(uflow, _IO_default_uflow),
JUMP_INIT(pbackfail, _IO_default_pbackfail),
JUMP_INIT(xsputn, _IO_file_xsputn),
JUMP_INIT(xsgetn, _IO_file_xsgetn),
JUMP_INIT(seekoff, _IO_new_file_seekoff),
JUMP_INIT(seekpos, _IO_default_seekpos),
JUMP_INIT(setbuf, _IO_new_file_setbuf),
JUMP_INIT(sync, _IO_new_file_sync),
JUMP_INIT(doallocate, _IO_file_doallocate),
JUMP_INIT(read, _IO_file_read),
JUMP_INIT(write, _IO_new_file_write),
JUMP_INIT(seek, _IO_file_seek),
JUMP_INIT(close, _IO_file_close),
JUMP_INIT(stat, _IO_file_stat),
JUMP_INIT(showmanyc, _IO_default_showmanyc),
JUMP_INIT(imbue, _IO_default_imbue)
};
다음은 _IO_FILE_vtable 이다. _IO_FILE_vtable 이라 함은 _IO_FILE 에서 내부적으로 호출하는 table 이라 할 수 있다.
만약 read() 가 실행이 된다면 vtable은 read 를 가리킬 것이고, fclose() 함수가 호출이 되면 close() 가 호출 될 것이다.
이는 직접 디버깅을 통해 보여주겠다.
다음 그림은 read() 함수가 실행되었을 때의 파일 포인터이다.
vtable 은 빨간색으로 체크 해 놓은곳에 존재한다.
다음을 보면 _IO_file_jumps 가 있고, 특정 주소가 들어가 있다. 이를 확인해보자.
다음과 같이 file_finish, file_overflow... 을 가리키는 주소가 들어가 있다.
그림으로 표현하자면 다음과 같다.
이번 글에서는 _IO_FILE 구조체, _IO_FILE_Plus 구조체, file_jumps 를 공부해 봤다.
다음글에서는 _IO_FILE_vtable 을 가지고 어떻게 Exploit 하는지 알아보도록 하겠다.
'시스템' 카테고리의 다른 글
FSOB(_IO_flush_all_lockp ) (0) | 2020.10.10 |
---|---|
flose() 분석 (0) | 2020.10.10 |
FSOB(File Stream Oriented Programming) 1 (0) | 2020.10.10 |
_IO_FILE_vtable_check (0) | 2020.10.10 |
_IO_FILE_vtable 2 (0) | 2020.10.10 |