what is IO_validate_vtable & _IO_vtable_check & _IO_*_jumps

우리가 흔히 생각할 수 있는 공격 중 하나가 FSOP에서 vtable을 덮는 공격인 vtable overwrite 공격이 있다 그런데 과연 glibc 에서 이런 공격을 방치할까? 당연히 보안적인 대책을 만들었다.

IO_validate_vtable → glibc 2.24부터 처음 적용됐어요. → glibc 2.27에서 호환성/안정성 보완

libc.2-27.so 을 기준으로 설명한다.

C
# define _IO_JUMPS_FUNC(THIS) \
  (IO_validate_vtable                                                   \
   (*(struct _IO_jump_t **) ((void *) &_IO_JUMPS_FILE_plus (THIS)	\
			     + (THIS)->_vtable_offset)))

다음과 같이 vtable을 참조할때 IO_validate_vtable 함수를 부르면서

C
&_IO_JUMPS_FILE_plus (THIS) + (THIS)->_vtable_offset)))

다음과 같이 vtable이 있는 주소를 인자로 넘겨서 준다.

IO_validate_vtable 은 다음과 같다

C
IO_validate_vtable (const struct _IO_jump_t *vtable)
{
  /* Fast path: The vtable pointer is within the __libc_IO_vtables
     section.  */
  uintptr_t section_length = __stop___libc_IO_vtables - __start___libc_IO_vtables;
  const char *ptr = (const char *) vtable;
  uintptr_t offset = ptr - __start___libc_IO_vtables;
  if (__glibc_unlikely (offset >= section_length))
    /* The vtable pointer is not in the expected section.  Use the
       slow path, which will terminate the process if necessary.  */
    _IO_vtable_check ();
  return vtable;
}

여기서 보면

C
  uintptr_t section_length = __stop___libc_IO_vtables - __start___libc_IO_vtables;

다음과 같이 특정 섹션의 길이를 구하는데 디버깅 심볼이 있는 glibc로 보면

C

pwndbg> p &__start___libc_IO_vtables
$1 = (<data variable, no debug info> *) 0x7ffff7dc9760 <_IO_helper_jumps>

다음과 같이 특정 주소가 나온다. 그리고 _IO_helper_jumps 영역으로 시작하는 것을 알 수 있는데

_IO_file_jumps 말고도 _IO_*_jumps 형태의 점프 테이블이 엄청 많은 것을 알 수 있다.

C
pwndbg> x/500gx 0x7ffff7dc9760
0x7ffff7dc9760 <_IO_helper_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9770 <_IO_helper_jumps+16>:	0x00007ffff7a70c60	0x00007ffff7a3ada0
0x7ffff7dc9780 <_IO_helper_jumps+32>:	0x00007ffff7a703b0	0x00007ffff7a703c0
0x7ffff7dc9790 <_IO_helper_jumps+48>:	0x00007ffff7a71c50	0x00007ffff7a70420
0x7ffff7dc97a0 <_IO_helper_jumps+64>:	0x00007ffff7a705d0	0x00007ffff7a70f90
0x7ffff7dc97b0 <_IO_helper_jumps+80>:	0x00007ffff7a70990	0x00007ffff7a70860
0x7ffff7dc97c0 <_IO_helper_jumps+96>:	0x00007ffff7a70c50	0x00007ffff7a70a00
0x7ffff7dc97d0 <_IO_helper_jumps+112>:	0x00007ffff7a71db0	0x00007ffff7a71dc0
0x7ffff7dc97e0 <_IO_helper_jumps+128>:	0x00007ffff7a71d90	0x00007ffff7a70c50
0x7ffff7dc97f0 <_IO_helper_jumps+144>:	0x00007ffff7a71da0	0x0000000000000000
0x7ffff7dc9800 <_IO_helper_jumps+160>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9810:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9820 <_IO_helper_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9830 <_IO_helper_jumps+16>:	0x00007ffff7a655e0	0x00007ffff7a473d0
0x7ffff7dc9840 <_IO_helper_jumps+32>:	0x00007ffff7a703b0	0x00007ffff7a703c0
0x7ffff7dc9850 <_IO_helper_jumps+48>:	0x00007ffff7a65420	0x00007ffff7a65b40
0x7ffff7dc9860 <_IO_helper_jumps+64>:	0x00007ffff7a65e00	0x00007ffff7a70f90
0x7ffff7dc9870 <_IO_helper_jumps+80>:	0x00007ffff7a70990	0x00007ffff7a70860
0x7ffff7dc9880 <_IO_helper_jumps+96>:	0x00007ffff7a70c50	0x00007ffff7a662e0
0x7ffff7dc9890 <_IO_helper_jumps+112>:	0x00007ffff7a71db0	0x00007ffff7a71dc0
0x7ffff7dc98a0 <_IO_helper_jumps+128>:	0x00007ffff7a71d90	0x00007ffff7a70c50
0x7ffff7dc98b0 <_IO_helper_jumps+144>:	0x00007ffff7a71da0	0x0000000000000000
0x7ffff7dc98c0 <_IO_helper_jumps+160>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc98d0:	0x0000000000000000	0x0000000000000000
0x7ffff7dc98e0 <_IO_cookie_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc98f0 <_IO_cookie_jumps+16>:	0x00007ffff7a6e330	0x00007ffff7a6f300
0x7ffff7dc9900 <_IO_cookie_jumps+32>:	0x00007ffff7a6f020	0x00007ffff7a703c0
0x7ffff7dc9910 <_IO_cookie_jumps+48>:	0x00007ffff7a71c50	0x00007ffff7a6d930
0x7ffff7dc9920 <_IO_cookie_jumps+64>:	0x00007ffff7a705d0	0x00007ffff7a61050
0x7ffff7dc9930 <_IO_cookie_jumps+80>:	0x00007ffff7a70990	0x00007ffff7a6c850
0x7ffff7dc9940 <_IO_cookie_jumps+96>:	0x00007ffff7a6c6d0	0x00007ffff7a60100
0x7ffff7dc9950 <_IO_cookie_jumps+112>:	0x00007ffff7a60f50	0x00007ffff7a60f80
0x7ffff7dc9960 <_IO_cookie_jumps+128>:	0x00007ffff7a60fd0	0x00007ffff7a61020
0x7ffff7dc9970 <_IO_cookie_jumps+144>:	0x00007ffff7a71da0	0x00007ffff7a71dd0
0x7ffff7dc9980 <_IO_cookie_jumps+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dc9990:	0x0000000000000000	0x0000000000000000
0x7ffff7dc99a0 <_IO_proc_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc99b0 <_IO_proc_jumps+16>:	0x00007ffff7a6e330	0x00007ffff7a6f300
0x7ffff7dc99c0 <_IO_proc_jumps+32>:	0x00007ffff7a6f020	0x00007ffff7a703c0
0x7ffff7dc99d0 <_IO_proc_jumps+48>:	0x00007ffff7a71c50	0x00007ffff7a6d930
0x7ffff7dc99e0 <_IO_proc_jumps+64>:	0x00007ffff7a705d0	0x00007ffff7a6cb90
0x7ffff7dc99f0 <_IO_proc_jumps+80>:	0x00007ffff7a70990	0x00007ffff7a6c850
0x7ffff7dc9a00 <_IO_proc_jumps+96>:	0x00007ffff7a6c6d0	0x00007ffff7a60100
0x7ffff7dc9a10 <_IO_proc_jumps+112>:	0x00007ffff7a6d910	0x00007ffff7a6d190
0x7ffff7dc9a20 <_IO_proc_jumps+128>:	0x00007ffff7a6c910	0x00007ffff7a623b0
0x7ffff7dc9a30 <_IO_proc_jumps+144>:	0x00007ffff7a6d180	0x00007ffff7a71dd0
0x7ffff7dc9a40 <_IO_proc_jumps+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dc9a50:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9a60 <_IO_wstrn_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9a70 <_IO_wstrn_jumps+16>:	0x00007ffff7a66c90	0x00007ffff7a64da0
0x7ffff7dc9a80 <_IO_wstrn_jumps+32>:	0x00007ffff7a66800	0x00007ffff7a65660
0x7ffff7dc9a90 <_IO_wstrn_jumps+48>:	0x00007ffff7a66c70	0x00007ffff7a65b40
0x7ffff7dc9aa0 <_IO_wstrn_jumps+64>:	0x00007ffff7a65e00	0x00007ffff7a66d90
0x7ffff7dc9ab0 <_IO_wstrn_jumps+80>:	0x00007ffff7a70990	0x00007ffff7a70860
0x7ffff7dc9ac0 <_IO_wstrn_jumps+96>:	0x00007ffff7a70c50	0x00007ffff7a662e0
0x7ffff7dc9ad0 <_IO_wstrn_jumps+112>:	0x00007ffff7a71db0	0x00007ffff7a71dc0
0x7ffff7dc9ae0 <_IO_wstrn_jumps+128>:	0x00007ffff7a71d90	0x00007ffff7a70c50
0x7ffff7dc9af0 <_IO_wstrn_jumps+144>:	0x00007ffff7a71da0	0x00007ffff7a71dd0
0x7ffff7dc9b00 <_IO_wstrn_jumps+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dc9b10:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9b20 <_IO_wstr_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9b30 <_IO_wstr_jumps+16>:	0x00007ffff7a66c90	0x00007ffff7a66860
0x7ffff7dc9b40 <_IO_wstr_jumps+32>:	0x00007ffff7a66800	0x00007ffff7a65660
0x7ffff7dc9b50 <_IO_wstr_jumps+48>:	0x00007ffff7a66c70	0x00007ffff7a65b40
0x7ffff7dc9b60 <_IO_wstr_jumps+64>:	0x00007ffff7a65e00	0x00007ffff7a66d90
0x7ffff7dc9b70 <_IO_wstr_jumps+80>:	0x00007ffff7a70990	0x00007ffff7a70860
0x7ffff7dc9b80 <_IO_wstr_jumps+96>:	0x00007ffff7a70c50	0x00007ffff7a662e0
0x7ffff7dc9b90 <_IO_wstr_jumps+112>:	0x00007ffff7a71db0	0x00007ffff7a71dc0
0x7ffff7dc9ba0 <_IO_wstr_jumps+128>:	0x00007ffff7a71d90	0x00007ffff7a70c50
0x7ffff7dc9bb0 <_IO_wstr_jumps+144>:	0x00007ffff7a71da0	0x00007ffff7a71dd0
0x7ffff7dc9bc0 <_IO_wstr_jumps+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dc9bd0:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9be0 <_IO_wfile_jumps_maybe_mmap>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9bf0 <_IO_wfile_jumps_maybe_mmap+16>:	0x00007ffff7a6e330	0x00007ffff7a68470
0x7ffff7dc9c00 <_IO_wfile_jumps_maybe_mmap+32>:	0x00007ffff7a680c0	0x00007ffff7a65660
0x7ffff7dc9c10 <_IO_wfile_jumps_maybe_mmap+48>:	0x00007ffff7a65420	0x00007ffff7a688a0
0x7ffff7dc9c20 <_IO_wfile_jumps_maybe_mmap+64>:	0x00007ffff7a6d590	0x00007ffff7a67820
0x7ffff7dc9c30 <_IO_wfile_jumps_maybe_mmap+80>:	0x00007ffff7a70990	0x00007ffff7a6c880
0x7ffff7dc9c40 <_IO_wfile_jumps_maybe_mmap+96>:	0x00007ffff7a68710	0x00007ffff7a61820
0x7ffff7dc9c50 <_IO_wfile_jumps_maybe_mmap+112>:	0x00007ffff7a6d910	0x00007ffff7a6d190
0x7ffff7dc9c60 <_IO_wfile_jumps_maybe_mmap+128>:	0x00007ffff7a6c910	0x00007ffff7a6c840
0x7ffff7dc9c70 <_IO_wfile_jumps_maybe_mmap+144>:	0x00007ffff7a6d180	0x00007ffff7a71dd0
0x7ffff7dc9c80 <_IO_wfile_jumps_maybe_mmap+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dc9c90:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9ca0 <_IO_wfile_jumps_mmap>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9cb0 <_IO_wfile_jumps_mmap+16>:	0x00007ffff7a6e330	0x00007ffff7a68470
0x7ffff7dc9cc0 <_IO_wfile_jumps_mmap+32>:	0x00007ffff7a68100	0x00007ffff7a65660
0x7ffff7dc9cd0 <_IO_wfile_jumps_mmap+48>:	0x00007ffff7a65420	0x00007ffff7a688a0
0x7ffff7dc9ce0 <_IO_wfile_jumps_mmap+64>:	0x00007ffff7a6d590	0x00007ffff7a67820
0x7ffff7dc9cf0 <_IO_wfile_jumps_mmap+80>:	0x00007ffff7a70990	0x00007ffff7a6c880
0x7ffff7dc9d00 <_IO_wfile_jumps_mmap+96>:	0x00007ffff7a68710	0x00007ffff7a61820
0x7ffff7dc9d10 <_IO_wfile_jumps_mmap+112>:	0x00007ffff7a6d910	0x00007ffff7a6d190
0x7ffff7dc9d20 <_IO_wfile_jumps_mmap+128>:	0x00007ffff7a6c910	0x00007ffff7a6c8e0
0x7ffff7dc9d30 <_IO_wfile_jumps_mmap+144>:	0x00007ffff7a6d180	0x00007ffff7a71dd0
0x7ffff7dc9d40 <_IO_wfile_jumps_mmap+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dc9d50:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9d60 <_IO_wfile_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9d70 <_IO_wfile_jumps+16>:	0x00007ffff7a6e330	0x00007ffff7a68470
0x7ffff7dc9d80 <_IO_wfile_jumps+32>:	0x00007ffff7a671a0	0x00007ffff7a65660
0x7ffff7dc9d90 <_IO_wfile_jumps+48>:	0x00007ffff7a65420	0x00007ffff7a688a0
0x7ffff7dc9da0 <_IO_wfile_jumps+64>:	0x00007ffff7a6d590	0x00007ffff7a67820
0x7ffff7dc9db0 <_IO_wfile_jumps+80>:	0x00007ffff7a70990	0x00007ffff7a6c850
0x7ffff7dc9dc0 <_IO_wfile_jumps+96>:	0x00007ffff7a68710	0x00007ffff7a61820
0x7ffff7dc9dd0 <_IO_wfile_jumps+112>:	0x00007ffff7a6d910	0x00007ffff7a6d190
0x7ffff7dc9de0 <_IO_wfile_jumps+128>:	0x00007ffff7a6c910	0x00007ffff7a6c840
0x7ffff7dc9df0 <_IO_wfile_jumps+144>:	0x00007ffff7a6d180	0x00007ffff7a71dd0
0x7ffff7dc9e00 <_IO_wfile_jumps+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dc9e10:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9e20 <_IO_wmem_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9e30 <_IO_wmem_jumps+16>:	0x00007ffff7a69360	0x00007ffff7a66860
0x7ffff7dc9e40 <_IO_wmem_jumps+32>:	0x00007ffff7a66800	0x00007ffff7a65660
0x7ffff7dc9e50 <_IO_wmem_jumps+48>:	0x00007ffff7a66c70	0x00007ffff7a65b40
0x7ffff7dc9e60 <_IO_wmem_jumps+64>:	0x00007ffff7a65e00	0x00007ffff7a66d90
0x7ffff7dc9e70 <_IO_wmem_jumps+80>:	0x00007ffff7a70990	0x00007ffff7a70860
0x7ffff7dc9e80 <_IO_wmem_jumps+96>:	0x00007ffff7a69300	0x00007ffff7a662e0
0x7ffff7dc9e90 <_IO_wmem_jumps+112>:	0x00007ffff7a71db0	0x00007ffff7a71dc0
0x7ffff7dc9ea0 <_IO_wmem_jumps+128>:	0x00007ffff7a71d90	0x00007ffff7a70c50
0x7ffff7dc9eb0 <_IO_wmem_jumps+144>:	0x00007ffff7a71da0	0x00007ffff7a71dd0
0x7ffff7dc9ec0 <_IO_wmem_jumps+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dc9ed0:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9ee0 <_IO_mem_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9ef0 <_IO_mem_jumps+16>:	0x00007ffff7a6a0d0	0x00007ffff7a71f60
0x7ffff7dc9f00 <_IO_mem_jumps+32>:	0x00007ffff7a71f00	0x00007ffff7a703c0
0x7ffff7dc9f10 <_IO_mem_jumps+48>:	0x00007ffff7a722e0	0x00007ffff7a70420
0x7ffff7dc9f20 <_IO_mem_jumps+64>:	0x00007ffff7a705d0	0x00007ffff7a72430
0x7ffff7dc9f30 <_IO_mem_jumps+80>:	0x00007ffff7a70990	0x00007ffff7a70860
0x7ffff7dc9f40 <_IO_mem_jumps+96>:	0x00007ffff7a6a080	0x00007ffff7a70a00
0x7ffff7dc9f50 <_IO_mem_jumps+112>:	0x00007ffff7a71db0	0x00007ffff7a71dc0
0x7ffff7dc9f60 <_IO_mem_jumps+128>:	0x00007ffff7a71d90	0x00007ffff7a70c50
0x7ffff7dc9f70 <_IO_mem_jumps+144>:	0x00007ffff7a71da0	0x00007ffff7a71dd0
0x7ffff7dc9f80 <_IO_mem_jumps+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dc9f90:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9fa0 <_IO_strn_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dc9fb0 <_IO_strn_jumps+16>:	0x00007ffff7a72300	0x00007ffff7a6a820
0x7ffff7dc9fc0 <_IO_strn_jumps+32>:	0x00007ffff7a71f00	0x00007ffff7a703c0
0x7ffff7dc9fd0 <_IO_strn_jumps+48>:	0x00007ffff7a722e0	0x00007ffff7a70420
0x7ffff7dc9fe0 <_IO_strn_jumps+64>:	0x00007ffff7a705d0	0x00007ffff7a72430
0x7ffff7dc9ff0 <_IO_strn_jumps+80>:	0x00007ffff7a70990	0x00007ffff7a70860
0x7ffff7dca000 <_IO_strn_jumps+96>:	0x00007ffff7a70c50	0x00007ffff7a70a00
0x7ffff7dca010 <_IO_strn_jumps+112>:	0x00007ffff7a71db0	0x00007ffff7a71dc0
0x7ffff7dca020 <_IO_strn_jumps+128>:	0x00007ffff7a71d90	0x00007ffff7a70c50
0x7ffff7dca030 <_IO_strn_jumps+144>:	0x00007ffff7a71da0	0x00007ffff7a71dd0
0x7ffff7dca040 <_IO_strn_jumps+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dca050:	0x0000000000000000	0x0000000000000000
0x7ffff7dca060 <_IO_obstack_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca070 <_IO_obstack_jumps+16>:	0x0000000000000000	0x00007ffff7a6aa30
0x7ffff7dca080 <_IO_obstack_jumps+32>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca090 <_IO_obstack_jumps+48>:	0x0000000000000000	0x00007ffff7a6a970
0x7ffff7dca0a0 <_IO_obstack_jumps+64>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca0b0 <_IO_obstack_jumps+80>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca0c0 <_IO_obstack_jumps+96>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca0d0 <_IO_obstack_jumps+112>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca0e0 <_IO_obstack_jumps+128>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca0f0 <_IO_obstack_jumps+144>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca100 <_IO_obstack_jumps+160>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca110:	0x0000000000000000	0x0000000000000000
0x7ffff7dca120 <_IO_file_jumps_maybe_mmap>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca130 <_IO_file_jumps_maybe_mmap+16>:	0x00007ffff7a6e330	0x00007ffff7a6f300
0x7ffff7dca140 <_IO_file_jumps_maybe_mmap+32>:	0x00007ffff7a6dc60	0x00007ffff7a703c0
0x7ffff7dca150 <_IO_file_jumps_maybe_mmap+48>:	0x00007ffff7a71c50	0x00007ffff7a6d930
0x7ffff7dca160 <_IO_file_jumps_maybe_mmap+64>:	0x00007ffff7a6c980	0x00007ffff7a6c7c0
0x7ffff7dca170 <_IO_file_jumps_maybe_mmap+80>:	0x00007ffff7a70990	0x00007ffff7a6c880
0x7ffff7dca180 <_IO_file_jumps_maybe_mmap+96>:	0x00007ffff7a6c6d0	0x00007ffff7a60100
0x7ffff7dca190 <_IO_file_jumps_maybe_mmap+112>:	0x00007ffff7a6d910	0x00007ffff7a6d190
0x7ffff7dca1a0 <_IO_file_jumps_maybe_mmap+128>:	0x00007ffff7a6c910	0x00007ffff7a6c840
0x7ffff7dca1b0 <_IO_file_jumps_maybe_mmap+144>:	0x00007ffff7a6d180	0x00007ffff7a71dd0
0x7ffff7dca1c0 <_IO_file_jumps_maybe_mmap+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dca1d0:	0x0000000000000000	0x0000000000000000
0x7ffff7dca1e0 <_IO_file_jumps_mmap>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca1f0 <_IO_file_jumps_mmap+16>:	0x00007ffff7a6e330	0x00007ffff7a6f300
0x7ffff7dca200 <_IO_file_jumps_mmap+32>:	0x00007ffff7a6de60	0x00007ffff7a703c0
0x7ffff7dca210 <_IO_file_jumps_mmap+48>:	0x00007ffff7a71c50	0x00007ffff7a6d930
0x7ffff7dca220 <_IO_file_jumps_mmap+64>:	0x00007ffff7a6d240	0x00007ffff7a6d7f0
0x7ffff7dca230 <_IO_file_jumps_mmap+80>:	0x00007ffff7a70990	0x00007ffff7a6c880
0x7ffff7dca240 <_IO_file_jumps_mmap+96>:	0x00007ffff7a6c920	0x00007ffff7a60100
0x7ffff7dca250 <_IO_file_jumps_mmap+112>:	0x00007ffff7a6d910	0x00007ffff7a6d190
0x7ffff7dca260 <_IO_file_jumps_mmap+128>:	0x00007ffff7a6c910	0x00007ffff7a6c8e0
0x7ffff7dca270 <_IO_file_jumps_mmap+144>:	0x00007ffff7a6d180	0x00007ffff7a71dd0
0x7ffff7dca280 <_IO_file_jumps_mmap+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dca290:	0x0000000000000000	0x0000000000000000
0x7ffff7dca2a0 <_IO_file_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca2b0 <_IO_file_jumps+16>:	0x00007ffff7a6e330	0x00007ffff7a6f300
0x7ffff7dca2c0 <_IO_file_jumps+32>:	0x00007ffff7a6f020	0x00007ffff7a703c0
0x7ffff7dca2d0 <_IO_file_jumps+48>:	0x00007ffff7a71c50	0x00007ffff7a6d930
0x7ffff7dca2e0 <_IO_file_jumps+64>:	0x00007ffff7a6d590	0x00007ffff7a6cb90
0x7ffff7dca2f0 <_IO_file_jumps+80>:	0x00007ffff7a70990	0x00007ffff7a6c850
0x7ffff7dca300 <_IO_file_jumps+96>:	0x00007ffff7a6c6d0	0x00007ffff7a60100
0x7ffff7dca310 <_IO_file_jumps+112>:	0x00007ffff7a6d910	0x00007ffff7a6d190
0x7ffff7dca320 <_IO_file_jumps+128>:	0x00007ffff7a6c910	0x00007ffff7a6c840
0x7ffff7dca330 <_IO_file_jumps+144>:	0x00007ffff7a6d180	0x00007ffff7a71dd0
0x7ffff7dca340 <_IO_file_jumps+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dca350:	0x0000000000000000	0x0000000000000000
0x7ffff7dca360 <_IO_str_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca370 <_IO_str_jumps+16>:	0x00007ffff7a72300	0x00007ffff7a71f60
0x7ffff7dca380 <_IO_str_jumps+32>:	0x00007ffff7a71f00	0x00007ffff7a703c0
0x7ffff7dca390 <_IO_str_jumps+48>:	0x00007ffff7a722e0	0x00007ffff7a70420
0x7ffff7dca3a0 <_IO_str_jumps+64>:	0x00007ffff7a705d0	0x00007ffff7a72430
0x7ffff7dca3b0 <_IO_str_jumps+80>:	0x00007ffff7a70990	0x00007ffff7a70860
0x7ffff7dca3c0 <_IO_str_jumps+96>:	0x00007ffff7a70c50	0x00007ffff7a70a00
0x7ffff7dca3d0 <_IO_str_jumps+112>:	0x00007ffff7a71db0	0x00007ffff7a71dc0
0x7ffff7dca3e0 <_IO_str_jumps+128>:	0x00007ffff7a71d90	0x00007ffff7a70c50
0x7ffff7dca3f0 <_IO_str_jumps+144>:	0x00007ffff7a71da0	0x00007ffff7a71dd0
0x7ffff7dca400 <_IO_str_jumps+160>:	0x00007ffff7a71de0	0x0000000000000000
0x7ffff7dca410:	0x0000000000000000	0x0000000000000000
0x7ffff7dca420 <_IO_str_chk_jumps>:	0x0000000000000000	0x0000000000000000
0x7ffff7dca430 <_IO_str_chk_jumps+16>:	0x00007ffff7a72300	0x00007ffff7b13f20
0x7ffff7dca440 <_IO_str_chk_jumps+32>:	0x00007ffff7a71f00	0x00007ffff7a703c0
0x7ffff7dca450 <_IO_str_chk_jumps+48>:	0x00007ffff7a722e0	0x00007ffff7a70420
0x7ffff7dca460 <_IO_str_chk_jumps+64>:	0x00007ffff7a705d0	0x00007ffff7a72430
0x7ffff7dca470 <_IO_str_chk_jumps+80>:	0x00007ffff7a70990	0x00007ffff7a70860
0x7ffff7dca480 <_IO_str_chk_jumps+96>:	0x00007ffff7a70c50	0x00007ffff7a70a00
0x7ffff7dca490 <_IO_str_chk_jumps+112>:	0x00007ffff7a71db0	0x00007ffff7a71dc0
0x7ffff7dca4a0 <_IO_str_chk_jumps+128>:	0x00007ffff7a71d90	0x00007ffff7a70c50
0x7ffff7dca4b0 <_IO_str_chk_jumps+144>:	0x00007ffff7a71da0	0x00007ffff7a71dd0
0x7ffff7dca4c0 <_IO_str_chk_jumps+160>:	0x00007ffff7a71de0	0x0000000000000000
C
pwndbg> p &__stop___libc_IO_vtables
$2 = (<data variable, no debug info> *) 0x7ffff7dca4c8

_IO_str_chk_jumps 를 마지막으로 libc_IO_vtables 영역이 끝

_IO_helper_jumps _IO_cookie_jumps _IO_proc_jumps _IO_wstrn_jumps

_IO_wstr_jumps _IO_wfile_jumps_maybe_mmap _IO_wfile_jumps_mmap

_IO_wfile_jumps _IO_wmem_jumps _IO_mem_jumps _IO_strn_jumps

_IO_obstack_jumps _IO_file_jumps_maybe_mmap _IO_file_jumps_mmap

_IO_file_jumps _IO_str_jumps _IO_str_chk_jumps

다음과 같이 수많은 점프 테이블이 있음을 알 수 있다.

그러면 다시 본론으로 돌아와서 IO_validate_vtable 함수의 역할을 보면

C
IO_validate_vtable (const struct _IO_jump_t *vtable)
{
  /* Fast path: The vtable pointer is within the __libc_IO_vtables
     section.  */
  uintptr_t section_length = __stop___libc_IO_vtables - __start___libc_IO_vtables;
  const char *ptr = (const char *) vtable;
  uintptr_t offset = ptr - __start___libc_IO_vtables;
  if (__glibc_unlikely (offset >= section_length))
    /* The vtable pointer is not in the expected section.  Use the
       slow path, which will terminate the process if necessary.  */
    _IO_vtable_check ();
  return vtable;
}

영역의 길이를 계산한뒤

uintptr_t offset = ptr - __start___libc_IO_vtables;

인자로 받은 ptr 의 위치와 시작 영역을 뺀뒤에

if (__glibc_unlikely (offset >= section_length))

만약 그 값이 영역의 길이 보다 크면 ( 즉, libc_IO_vtables 영역 안에 없으면 )

_IO_vtable_check 함수를 발생시키고 아니면 vtable 값을 정상적으로 반환한다.

_IO_vtable_check 함수

C
_IO_vtable_check (void)
{
#ifdef SHARED
  /* Honor the compatibility flag.  */
  void (*flag) (void) = atomic_load_relaxed (&IO_accept_foreign_vtables);
#ifdef PTR_DEMANGLE
  PTR_DEMANGLE (flag);
#endif
  if (flag == &_IO_vtable_check)
    return;

  /* In case this libc copy is in a non-default namespace, we always
     need to accept foreign vtables because there is always a
     possibility that FILE * objects are passed across the linking
     boundary.  */
  {
    Dl_info di;
    struct link_map *l;
    if (!rtld_active ()
        || (_dl_addr (_IO_vtable_check, &di, &l, NULL) != 0
            && l->l_ns != LM_ID_BASE))
      return;
  }

#else /* !SHARED */
  /* We cannot perform vtable validation in the static dlopen case
     because FILE * handles might be passed back and forth across the
     boundary.  Therefore, we disable checking in this case.  */
  if (__dlopen != NULL)
    return;
#endif

  __libc_fatal ("Fatal error: glibc detected an invalid stdio handle\n");
}

이 함수는 뭐 여러가지 조건에 따라 분기가 나뉘지만, 모두 특정한 상황을 한해 나눈다.

즉, 일반적인 상황이라면

__libc_fatal ("Fatal error: glibc detected an invalid stdio handle\n")

이 코드를 만나고 프로세스가 즉시 종료가 된다.

그러면 이 함수 때문에 일반적으로 vtable overwrite는 불가능 할까?

아니다. 위에서 보았다싶이 libc_IO_vtables 영역 안에서 바꾸면 된다.

bypass는 다음글에서 다룬다.