---
title: 'FILE STRUCTURE'
tags: file_struct, writeup
---
[toc]
*Bài này mình việc lại kiến thức học được theo kiểu mình hiểu nhằm mục đích ôn tập và lưu trữ*
## **DEFINATION**
FILE là một struct được định nghĩa trong `standard IO library` [*](https://code.woboq.org/userspace/glibc/libio/bits/types/struct_FILE.h.html) của linux, các FILE được liên kết với nhau trong một chain lưu tại biến `_IO_list_all`.
Size của FILE ở 64bit là 216 bytes còn ở 32bit là 148 bytes.
```
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
};
```
Có 3 FILE được định nghĩa sẵn khi bắt đầu chương trình là:
* _IO_2_1_stderr_
* _IO_2_1_stdout_
* _IO_2_1_stdin_
3 FILE nằm này trên binary và trỏ tới structure thực sự nằm trên `libc`
FILE được bọc trong một struct khác là `_IO_FILE_plus` cùng với ptr `vtable` (tất cả các FILE đều sài chung một vtable).
`vtable` ở 64bit nằm ở offset 0xD8, .
```
struct _IO_FILE_plus
{
_IO_FILE file;
IO_jump_t *vtable;
}
```
`vtable` là ptr kiểu `IO_jump_t`, chứa một dãy các function sẽ được call vào từng lúc trong lúc xử lý file (đọc, ghi, đóng, mở), nếu như có thể ghi đè `vtable` có thể control được luồng thực thi của chương trình.
```
void * funcs[] = {
1 NULL, // "extra word"
2 NULL, // DUMMY
3 exit, // finish
4 NULL, // overflow
5 NULL, // underflow
6 NULL, // uflow
7 NULL, // pbackfail
8 NULL, // xsputn #printf
9 NULL, // xsgetn
10 NULL, // seekoff
11 NULL, // seekpos
12 NULL, // setbuf
13 NULL, // sync
14 NULL, // target location
15 NULL, // read
16 NULL, // write
17 NULL, // seek
18 pwn, // close *
19 NULL, // stat
20 NULL, // showmanyc
21 NULL, // imbue
};
```
[7] `_IO_XSPUTN`: ptr được thực thi khi call các hàm ghi(write, puts, printf,..).
[8] `_IO_XSGETN`: ptr được thực thi khi call các hàm đọc(read, gets, scanf,...).
FILE structure được lưu trữ trên heap (các FILE structure ngoài in, out, err).
các bước OPEN FILE:
1. Malloc FILE structure
2. Gán vtable vào FILE structure
3. Khởi tạo FILE structure
4. Liên kết FILE structure vào `_IO_list_all`
5. Call system khởi tạo file.
Các bước CLOSE FILE:
1. Unlink FILE structure ra khỏi `_IO_list_all`
2. Call system đóng file.
3. `_IO_FINISH` trong vtable được thực thi.
## **HOW TO EXPLOIT**
Để khai thác FILE structure chúng ta cần ghi đè được vào vtable của FILE structure.
Thay các function cần được thực thi vào chỗ các các ptr tùy theo mục đích, cái này mình đã thử libc version 2.23, 2.21 vì `vtable` được lưu ở non-writable libc segment.
Còn một cách khác là fake một cái vtable rồi ghi đè địa chỉ của nó vào `_IO_FILE_plus`, ở các version về sau thì sẽ có các kiểm tra để chống fake vtable.