ssongk
ssongk
ssongk
전체 방문자
오늘
어제

공지사항

  • resources
  • 분류 전체보기 (627)
    • CTF (24)
    • background (79)
      • fuzzing (5)
      • linux (29)
      • linux kernel (15)
      • windows (2)
      • web assembly (1)
      • embedded (0)
      • web (13)
      • crypto (9)
      • mobile (1)
      • AI (1)
      • etc.. (3)
    • write-up(pwn) (171)
      • dreamhack (102)
      • pwn.college (4)
      • pwnable.xyz (51)
      • pwnable.tw (3)
      • pwnable.kr (5)
      • G04T (6)
    • write-up(rev) (32)
      • dreamhack (24)
      • reversing.kr (8)
    • write-up(web) (195)
      • dreamhack (63)
      • LOS (40)
      • webhacking.kr (69)
      • websec.fr (3)
      • wargame.kr (6)
      • webgoat (1)
      • G04T (7)
      • suninatas (6)
    • write-up(crypto) (19)
      • dreamhack (16)
      • G04T (1)
      • suninatas (2)
    • write-up(forensic) (53)
      • dreamhack (5)
      • ctf-d (47)
      • suninatas (1)
    • write-up(misc) (14)
      • dreamhack (13)
      • suninatas (1)
    • development (31)
      • Linux (14)
      • Java (13)
      • Python (1)
      • C (2)
      • TroubleShooting (1)
    • 자격증 (8)
    • 이산수학 (1)
    • 정보보안 (0)
hELLO · Designed By 정상우.
ssongk

ssongk

background/linux

FSOP(File Stream Oriented Programming)

2024. 4. 29. 15:01

Source code (bootlin)

_IO_FILE_plus & _IO_FILE_complete_plus

struct _IO_FILE_plus
{
  FILE file;
  const struct _IO_jump_t *vtable;
};

#ifdef _IO_USE_OLD_IO_FILE
/* This structure is used by the compatibility code as if it were an
   _IO_FILE_plus, but has enough space to initialize the _mode argument
   of an _IO_FILE_complete.  */
struct _IO_FILE_complete_plus
{
  struct _IO_FILE_complete file;
  const struct _IO_jump_t *vtable;
};
#endif

_IO_FILE & _IO_FILE_complete

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
};

struct _IO_FILE_complete
{
  struct _IO_FILE _file;
#endif
  __off64_t _offset;
  /* Wide character stream stuff.  */
  struct _IO_codecvt *_codecvt;
  struct _IO_wide_data *_wide_data;
  struct _IO_FILE *_freeres_list;
  void *_freeres_buf;
  size_t __pad5;
  int _mode;
  /* Make sure we don't get into trouble again.  */
  char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
};

_flags

#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

_IO_jump_t

struct _IO_jump_t {
    JUMP_FIELD(size_t, __dummy);
    JUMP_FIELD(size_t, __dummy2);
    JUMP_FIELD(_IO_finish_t, __finish);
    JUMP_FIELD(_IO_overflow_t, __overflow);
    JUMP_FIELD(_IO_underflow_t, __underflow);
    JUMP_FIELD(_IO_underflow_t, __uflow);
    JUMP_FIELD(_IO_pbackfail_t, __pbackfail);
    /* showmany */
    JUMP_FIELD(_IO_xsputn_t, __xsputn);
    JUMP_FIELD(_IO_xsgetn_t, __xsgetn);
    JUMP_FIELD(_IO_seekoff_t, __seekoff);
    JUMP_FIELD(_IO_seekpos_t, __seekpos);
    JUMP_FIELD(_IO_setbuf_t, __setbuf);
    JUMP_FIELD(_IO_sync_t, __sync);
    JUMP_FIELD(_IO_doallocate_t, __doallocate);
    JUMP_FIELD(_IO_read_t, __read);
    JUMP_FIELD(_IO_write_t, __write);
    JUMP_FIELD(_IO_seek_t, __seek);
    JUMP_FIELD(_IO_close_t, __close);
    JUMP_FIELD(_IO_stat_t, __stat);
    JUMP_FIELD(_IO_showmanyc_t, __showmanyc);
    JUMP_FIELD(_IO_imbue_t, __imbue);
#if 0
    get_column;
    set_column;
#endif
};

_IO_file_jumps

  [IO_FILE_JUMPS] = {
    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_wfile_jumps

  [IO_WFILE_JUMPS] = {
    JUMP_INIT_DUMMY,
    JUMP_INIT (finish, _IO_new_file_finish),
    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wfile_overflow),
    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wfile_underflow),
    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
    JUMP_INIT (xsputn, _IO_wfile_xsputn),
    JUMP_INIT (xsgetn, _IO_file_xsgetn),
    JUMP_INIT (seekoff, _IO_wfile_seekoff),
    JUMP_INIT (seekpos, _IO_default_seekpos),
    JUMP_INIT (setbuf, _IO_new_file_setbuf),
    JUMP_INIT (sync, (_IO_sync_t) _IO_wfile_sync),
    JUMP_INIT (doallocate, _IO_wfile_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)
  },

 


AAR - write() ing to Arbitrary Memory

  • _flags = 0xfbad0800
  • _IO_read_end = _IO_write_base
  • _IO_write_base = target address to write
  • _IO_write_ptr = target address + length
  • _fileno = stdout(1)
  • call fwrite, fputs ...

 

AAW - read() ing to Arbitrary Memory

  • _flags = 0xfbad2488
  • _IO_read_ptr = read_end
  • _IO_ buf_base = target address to read
  • _IO_ buf_end = target address + length
  • _IO_ buf_end - _IO_ buf_base >= number of bytes to read
  • _fileno = stdin(0)
  • call fread, fgets ...

 

vtable overwrite

  • _IO_FILE_plus.vtable = fake_vtable
  • _lock = address_ptr (writable && has NULL value) 
  • but, morden glibc versions validate vtable function

 

validate vtable bypass (_IO_wfile_overflow)

  • _IO_FILE_plus.wide_data = fake_vtable
  • _IO_FILE_plus.vtable = _IO_wfile_overflow - call offset
  • _IO_wfile_overflow -> _IO_wdoallocbuf -> call rax (rax is fake_vtable)
// _IO_wdoallocbuf+36
mov rax, qword ptr [rax+0xe0]
call qword ptr [rax+0x68] // call any function

 


info leak (fclose)

  • _flags = 0xfbad0840 (
  • _IO_read_end = _IO_write_base
  • _IO_write_base = target address to write
  • _IO_write_ptr = target address + length
  • _fileno = stdout(1)
  • call fclose

 

info leak (stdin/stdout)

  • _flags = 0xfbad1800
  • _IO_read_ptr = 0x0
  • _IO_read_end = 0x0
  • _IO_read_base = 0x0
  • _IO_write_base = 0x0
  • _IO_write_ptr = the first byte is 0x00
  • call fgets ... / fflush, fputs ...

 

 


 

https://ssongkit.tistory.com/271

 

[glibc-2.27] _IO_FILE & fopen

드림핵 강의를 보고 glibc-2.27을 분석한 글 입니다. (틀린 내용이 있을 수 있습니다) 먼저, 드림핵에서 소개하는 예제 코드는 다음과 같다. // Name: iofile.c // Compile: gcc -o iofile iofile.c #include #include #inc

ssongkit.tistory.com

https://pwn.college/software-exploitation/file-struct-exploits

 

pwn.college

Apply various FILE struct exploits to obtain a leak, then hijack hijack control flow. Start Practice

pwn.college

https://pwnable-study.tistory.com/43

 

stdout 으로 libc leak

이번엔 stdout 으로 libc 를 leak 하는 방법에 대해 알아보겠다. stdout 으로 leak 하기 위해선 stdout 구조체에 값을 입력할 수 있어야 한다. 1. stdout 이란? stdout 은 '표준 출력 스트림' 이다. printf 나, puts

pwnable-study.tistory.com

 

'background > linux' 카테고리의 다른 글

[pwn.college] Format String Bug  (0) 2024.05.06
[pwn.college] Return Oriented Programming  (1) 2024.05.02
[how2heap] Tcache Poisoning (glibc 2.31/2.35)  (0) 2024.04.10
[how2heap] House of Botcake (glibc 2.31)  (0) 2024.03.18
[how2heap] Fastbin dup into stack (glibc 2.35)  (1) 2024.03.11
    'background/linux' 카테고리의 다른 글
    • [pwn.college] Format String Bug
    • [pwn.college] Return Oriented Programming
    • [how2heap] Tcache Poisoning (glibc 2.31/2.35)
    • [how2heap] House of Botcake (glibc 2.31)
    ssongk
    ssongk
    벌레 사냥꾼이 되고 싶어요

    티스토리툴바