_rtld_global 구조체의 _dl_rtld_lock_recursive를 못 찾겠어요.

Overwrite _rtld_global exploit tech

main 함수가 종료되면 __libc_start_main+231 -> __GI_exit() -> __run_exit_handlers() -> _dl_fini()

등 여러 함수와 그 안에 있는 구조체의 포인터를 거치는데, 

_dl_fini에서 불러오는 _dl_rtld_lock_recursive() 함수와 인자를 덮어쓰면 실행흐름 조작이 가능한 exploit tech이다. 

 

_dl_rtld_lock_recursive가 없어요.

glibc 2.34 이후 버전에서 _rtld_global 구조체의 레이아웃이 변경되어 오프셋을 쉽게 못 가져온다.

 

최신 버전에서 exploit 하는 방법은 아래 사이트로 들어가서 소스 코드를 분석하거나 직접 디버깅하면서 __rtld_lock_recursive로 추정되는 오프셋의 값을 바꿔보는 수밖에 없다.

https://elixir.bootlin.com/glibc/glibc-2.34/source/elf/rtld.c#L315

 

본인이 exploit 하고 싶은 ELF의 어느 버전의 라이브러리와 매칭되는지 확인하자

 

glibc 구조체 비교 2.27 vs 2.35

더보기

 

Ubuntu 18.04 (glibc 2.27) Ubuntu 22.04 (glibc 2.35)
pwndbg> p _rtld_global
$1 = {
  _dl_ns = {{
      _ns_loaded = 0x7ffff7ffe170, 
      _ns_nloaded = 4, 
      _ns_main_searchlist = 0x7ffff7ffe428, 
      _ns_global_scope_alloc = 0, 
      _ns_unique_sym_table = {
        lock = {
          mutex = {
            __data = {
              __lock = 0, 
              __count = 0, 
              __owner = 0, 
              __nusers = 0, 
              __kind = 1, 
              __spins = 0, 
              __elision = 0, 
              __list = {
                __prev = 0x0, 
                __next = 0x0
              }
            }, 
            __size = '\000' <repeats 16 times>, "\001", '\000' <repeats 22 times>, 
            __align = 0
          }
        }, 
        entries = 0x0, 
        size = 0, 
        n_elements = 0, 
        free = 0x0
      }, 
      _ns_debug = {
        r_version = 0, 
        r_map = 0x0, 
        r_brk = 0, 
        r_state = RT_CONSISTENT, 
        r_ldbase = 0
      }
    }, {
      _ns_loaded = 0x0, 
      _ns_nloaded = 0, 
      _ns_main_searchlist = 0x0, 
      _ns_global_scope_alloc = 0, 
      _ns_unique_sym_table = {
        lock = {
          mutex = {
            __data = {
              __lock = 0, 
              __count = 0, 
              __owner = 0, 
              __nusers = 0, 
              __kind = 0, 
              __spins = 0, 
              __elision = 0, 
              __list = {
                __prev = 0x0, 
                __next = 0x0
              }
            }, 
            __size = '\000' <repeats 39 times>, 
            __align = 0
          }
        }, 
        entries = 0x0, 
        size = 0, 
        n_elements = 0, 
        free = 0x0
      }, 
      _ns_debug = {
        r_version = 0, 
        r_map = 0x0, 
        r_brk = 0, 
        r_state = RT_CONSISTENT, 
        r_ldbase = 0
      }
    } <repeats 15 times>}, 
  _dl_nns = 1, 
  _dl_load_lock = {
    mutex = {
      __data = {
        __lock = 0, 
        __count = 0, 
        __owner = 0, 
        __nusers = 0, 
        __kind = 1, 
        __spins = 0, 
        __elision = 0, 
        __list = {
          __prev = 0x0, 
          __next = 0x0
        }
      }, 
      __size = '\000' <repeats 16 times>, "\001", '\000' <repeats 22 times>, 
      __align = 0
    }
  }, 
  _dl_load_write_lock = {
    mutex = {
      __data = {
        __lock = 0, 
        __count = 0, 
        __owner = 0, 
        __nusers = 0, 
        __kind = 1, 
        __spins = 0, 
        __elision = 0, 
        __list = {
          __prev = 0x0, 
          __next = 0x0
        }
      }, 
      __size = '\000' <repeats 16 times>, "\001", '\000' <repeats 22 times>, 
      __align = 0
    }
  }, 
  _dl_load_adds = 4, 
  _dl_initfirst = 0x0, 
  _dl_cpuclock_offset = 60430389095796, 
  _dl_profile_map = 0x0, 
  _dl_num_relocations = 92, 
  _dl_num_cache_relocations = 3, 
  _dl_all_dirs = 0x7ffff7ffec90, 
  _dl_rtld_map = {
    l_addr = 140737351856128, 
    l_name = 0x555555400238 "/lib64/ld-linux-x86-64.so.2", 
    l_ld = 0x7ffff7ffce68, 
    l_next = 0x0, 
    l_prev = 0x7ffff7fee000, 
    l_real = 0x7ffff7ffd9f0 <_rtld_global+2448>, 
    l_ns = 0, 
    l_libname = 0x7ffff7ffe030 <_dl_rtld_libname>, 
    l_info = {0x0, 0x0, 0x7ffff7ffcee8, 0x7ffff7ffced8, 0x7ffff7ffce78, 0x7ffff7ffce98, 0x7ffff7ffcea8, 0x7ffff7ffcf18, 0x7ffff7ffcf28, 0x7ffff7ffcf38, 0x7ffff7ffceb8, 0x7ffff7ffcec8, 0x0, 0x0, 0x7ffff7ffce68, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7ffff7ffcef8, 0x0, 0x0, 0x7ffff7ffcf08, 0x0 <repeats 12 times>, 0x7ffff7ffcf58, 0x7ffff7ffcf48, 0x0, 0x0, 0x7ffff7ffcf78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7ffff7ffcf68, 0x0 <repeats 25 times>, 0x7ffff7ffce88}, 
    l_phdr = 0x7ffff7dd3040, 
    l_entry = 0, 
    l_phnum = 7, 
    l_ldnum = 0, 
    l_searchlist = {
      r_list = 0x0, 
      r_nlist = 0
    }, 
    l_symbolic_searchlist = {
      r_list = 0x0, 
      r_nlist = 0
    }, 
    l_loader = 0x0, 
    l_versions = 0x7ffff7fee900, 
    l_nversions = 6, 
    l_nbuckets = 17, 
    l_gnu_bitmask_idxbits = 3, 
    l_gnu_shift = 8, 
    l_gnu_bitmask = 0x7ffff7dd32d8, 
    {
      l_gnu_buckets = 0x7ffff7dd32f8, 
      l_chain = 0x7ffff7dd32f8
    }, 
    {
      l_gnu_chain_zero = 0x7ffff7dd3338, 
      l_buckets = 0x7ffff7dd3338
    }, 
    l_direct_opencount = 0, 
    l_type = lt_library, 
    l_relocated = 1, 
    l_init_called = 1, 
    l_global = 1, 
    l_reserved = 0, 
    l_phdr_allocated = 0, 
    l_soname_added = 0, 
    l_faked = 0, 
    l_need_tls_init = 0, 
    l_auditing = 0, 
    l_audit_any_plt = 0, 
    l_removed = 0, 
    l_contiguous = 0, 
    l_symbolic_in_local_scope = 0, 
    l_free_initfini = 0, 
    l_rpath_dirs = {
      dirs = 0x0, 
      malloced = 0
    }, 
    l_reloc_result = 0x0, 
    l_versyms = 0x7ffff7dd3914, 
    l_origin = 0x0, 
    l_map_start = 140737351856128, 
    l_map_end = 140737354129776, 
    l_text_end = 140737351992656, 
    l_scope_mem = {0x0, 0x0, 0x0, 0x0}, 
    l_scope_max = 0, 
    l_scope = 0x0, 
    l_local_scope = {0x0, 0x0}, 
    l_file_id = {
      dev = 0, 
      ino = 0
    }, 
    l_runpath_dirs = {
      dirs = 0x0, 
      malloced = 0
    }, 
    l_initfini = 0x0, 
    l_reldeps = 0x0, 
    l_reldepsmax = 0, 
    l_used = 1, 
    l_feature_1 = 0, 
    l_flags_1 = 0, 
    l_flags = 0, 
    l_idx = 0, 
    l_mach = {
      plt = 0, 
      gotplt = 0, 
      tlsdesc_table = 0x0
    }, 
    l_lookup_cache = {
      sym = 0x7ffff7dd3480, 
      type_class = 1, 
      value = 0x7ffff7fee000, 
      ret = 0x7ffff79e7110
    }, 
    l_tls_initimage = 0x0, 
    l_tls_initimage_size = 0, 
    l_tls_blocksize = 0, 
    l_tls_align = 0, 
    l_tls_firstbyte_offset = 0, 
    l_tls_offset = 0, 
    l_tls_modid = 0, 
    l_tls_dtor_count = 0, 
    l_relro_addr = 2266752, 
    l_relro_size = 2432, 
    l_serial = 0, 
    l_audit = 0x7ffff7ffde60 <_rtld_global+3584>
  }, 
  audit_data = {{
      cookie = 0, 
      bindflags = 0
    } <repeats 16 times>}, 
  _dl_rtld_lock_recursive = 0x7ffff7dd40e0 <rtld_lock_default_lock_recursive>, 
  _dl_rtld_unlock_recursive = 0x7ffff7dd40f0 <rtld_lock_default_unlock_recursive>, 
  _dl_make_stack_executable_hook = 0x7ffff7de6ea0 <__GI__dl_make_stack_executable>, 
  _dl_stack_flags = 6, 
  _dl_tls_dtv_gaps = false, 
  _dl_tls_max_dtv_idx = 1, 
  _dl_tls_dtv_slotinfo_list = 0x7ffff7fee990, 
  _dl_tls_static_nelem = 1, 
  _dl_tls_static_size = 4160, 
  _dl_tls_static_used = 144, 
  _dl_tls_static_align = 64, 
  _dl_initial_dtv = 0x7ffff7fefe40, 
  _dl_tls_generation = 1, 
  _dl_init_static_tls = 0x7ffff7ddf780 <_dl_nothread_init_static_tls>, 
  _dl_wait_lookup_done = 0x0, 
  _dl_scope_free_list = 0x0
}
pwndbg> p _rtld_global
$1 = {
  _dl_ns = {{
      _ns_loaded = 0x7ffff7ffe2e0,
      _ns_nloaded = 4,
      _ns_main_searchlist = 0x7ffff7ffe5a0,
      _ns_global_scope_alloc = 0,
      _ns_global_scope_pending_adds = 0,
      libc_map = 0x7ffff7fbb160,
      _ns_unique_sym_table = {
        lock = {
          mutex = {
            __data = {
              __lock = 0,
              __count = 0,
              __owner = 0,
              __nusers = 0,
              __kind = 1,
              __spins = 0,
              __elision = 0,
              __list = {
                __prev = 0x0,
                __next = 0x0
              }
            },
            __size = '\000' <repeats 16 times>, "\001", '\000' <repeats 22 times>,
            __align = 0
          }
        },
        entries = 0x0,
        size = 0,
        n_elements = 0,
        free = 0x0
      },
      _ns_debug = {
        base = {
          r_version = 0,
          r_map = 0x0,
          r_brk = 0,
          r_state = RT_CONSISTENT,
          r_ldbase = 0
        },
        r_next = 0x0
      }
    }, {
      _ns_loaded = 0x0,
      _ns_nloaded = 0,
      _ns_main_searchlist = 0x0,
      _ns_global_scope_alloc = 0,
      _ns_global_scope_pending_adds = 0,
      libc_map = 0x0,
      _ns_unique_sym_table = {
        lock = {
          mutex = {
            __data = {
              __lock = 0,
              __count = 0,
              __owner = 0,
              __nusers = 0,
              __kind = 0,
              __spins = 0,
              __elision = 0,
              __list = {
                __prev = 0x0,
                __next = 0x0
              }
            },
            __size = '\000' <repeats 39 times>,
            __align = 0
          }
        },
        entries = 0x0,
        size = 0,
        n_elements = 0,
        free = 0x0
      },
      _ns_debug = {
        base = {
          r_version = 0,
          r_map = 0x0,
          r_brk = 0,
          r_state = RT_CONSISTENT,
          r_ldbase = 0
        },
        r_next = 0x0
      }
    } <repeats 15 times>},
  _dl_nns = 1,
  _dl_load_lock = {
    mutex = {
      __data = {
        __lock = 0,
        __count = 0,
        __owner = 0,
        __nusers = 0,
        __kind = 1,
        __spins = 0,
        __elision = 0,
        __list = {
          __prev = 0x0,
          __next = 0x0
        }
      },
      __size = '\000' <repeats 16 times>, "\001", '\000' <repeats 22 times>,
      __align = 0
    }
  },
  _dl_load_write_lock = {
    mutex = {
      __data = {
        __lock = 0,
        __count = 0,
        __owner = 0,
        __nusers = 0,
        __kind = 1,
        __spins = 0,
        __elision = 0,
        __list = {
          __prev = 0x0,
          __next = 0x0
        }
      },
      __size = '\000' <repeats 16 times>, "\001", '\000' <repeats 22 times>,
      __align = 0
    }
  },
  _dl_load_tls_lock = {
    mutex = {
      __data = {
        __lock = 0,
        __count = 0,
        __owner = 0,
        __nusers = 0,
        __kind = 1,
        __spins = 0,
        __elision = 0,
        __list = {
          __prev = 0x0,
          __next = 0x0
        }
      },
      __size = '\000' <repeats 16 times>, "\001", '\000' <repeats 22 times>,
      __align = 0
    }
  },
  _dl_load_adds = 4,
  _dl_initfirst = 0x0,
  _dl_profile_map = 0x0,
  _dl_num_relocations = 94,
  _dl_num_cache_relocations = 3,
  _dl_all_dirs = 0x7ffff7fbb000,
  _dl_rtld_map = {
    l_addr = 140737353887744,
    l_name = 0x555555400238 "/lib64/ld-linux-x86-64.so.2",
    l_ld = 0x7ffff7ffce80,
    l_next = 0x0,
    l_prev = 0x7ffff7fbb160,
    l_real = 0x7ffff7ffdaf0 <_rtld_global+2736>,
    l_ns = 0,
    l_libname = 0x7ffff7ffe280 <_dl_rtld_libname>,
    l_info = {0x0, 0x0, 0x7ffff7ffcf00, 0x7ffff7ffcef0, 0x7ffff7ffce90, 0x7ffff7ffceb0, 0x7ffff7ffcec0, 0x7ffff7ffcf30, 0x7ffff7ffcf40, 0x7ffff7ffcf50, 0x7ffff7ffced0, 0x7ffff7ffcee0, 0x0, 0x0, 0x7ffff7ffce80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7ffff7ffcf10, 0x0, 0x0, 0x7ffff7ffcf20, 0x0 <repeats 13 times>, 0x7ffff7ffcf70, 0x7ffff7ffcf60, 0x0, 0x0, 0x7ffff7ffcf90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7ffff7ffcf80, 0x0 <repeats 25 times>, 0x7ffff7ffcea0},
    l_phdr = 0x7ffff7fc3040,
    l_entry = 0,
    l_phnum = 11,
    l_ldnum = 0,
    l_searchlist = {
      r_list = 0x0,
      r_nlist = 0
    },
    l_symbolic_searchlist = {
      r_list = 0x0,
      r_nlist = 0
    },
    l_loader = 0x0,
    l_versions = 0x7ffff7fbbb60,
    l_nversions = 8,
    l_nbuckets = 37,
    l_gnu_bitmask_idxbits = 3,
    l_gnu_shift = 8,
    l_gnu_bitmask = 0x7ffff7fc3440,
    {
      l_gnu_buckets = 0x7ffff7fc3460,
      l_chain = 0x7ffff7fc3460
    },
    {
      l_gnu_chain_zero = 0x7ffff7fc34f0,
      l_buckets = 0x7ffff7fc34f0
    },
    l_direct_opencount = 0,
    l_type = lt_library,
    l_relocated = 1,
    l_init_called = 1,
    l_global = 1,
    l_reserved = 0,
    l_main_map = 0,
    l_visited = 1,
    l_map_used = 0,
    l_map_done = 0,
    l_phdr_allocated = 0,
    l_soname_added = 0,
    l_faked = 0,
    l_need_tls_init = 0,
    l_auditing = 0,
    l_audit_any_plt = 0,
    l_removed = 0,
    l_contiguous = 0,
    l_symbolic_in_local_scope = 0,
    l_free_initfini = 0,
    l_ld_readonly = 0,
    l_find_object_processed = 0,
    l_nodelete_active = false,
    l_nodelete_pending = false,
    l_property = lc_property_unknown,
    l_x86_feature_1_and = 0,
    l_x86_isa_1_needed = 0,
    l_1_needed = 0,
    l_rpath_dirs = {
      dirs = 0x0,
      malloced = 0
    },
    l_reloc_result = 0x0,
    l_versyms = 0x7ffff7fc3c12,
    l_origin = 0x0,
    l_map_start = 140737353887744,
    l_map_end = 140737354130136,
    l_text_end = 140737354064661,
    l_scope_mem = {0x0, 0x0, 0x0, 0x0},
    l_scope_max = 0,
    l_scope = 0x0,
    l_local_scope = {0x0, 0x0},
    l_file_id = {
      dev = 0,
      ino = 0
    },
    l_runpath_dirs = {
      dirs = 0x0,
      malloced = 0
    },
    l_initfini = 0x0,
    l_reldeps = 0x0,
    l_reldepsmax = 0,
    l_used = 1,
    l_feature_1 = 0,
    l_flags_1 = 0,
    l_flags = 0,
    l_idx = 0,
    l_mach = {
      plt = 0,
      gotplt = 0,
      tlsdesc_table = 0x0
    },
    l_lookup_cache = {
      sym = 0x7ffff7fc38d8,
      type_class = 1,
      value = 0x7ffff7fbb160,
      ret = 0x7ffff7d90e60
    },
    l_tls_initimage = 0x0,
    l_tls_initimage_size = 0,
    l_tls_blocksize = 0,
    l_tls_align = 0,
    l_tls_firstbyte_offset = 0,
    l_tls_offset = 0,
    l_tls_modid = 0,
    l_tls_dtor_count = 0,
    l_relro_addr = 230944,
    l_relro_size = 6624,
    l_serial = 0
  },
  _dl_rtld_auditstate = {{
      cookie = 0,
      bindflags = 0
    } <repeats 16 times>},
  _dl_x86_feature_1 = 0,
  _dl_x86_feature_control = {
    ibt = cet_elf_property,
    shstk = cet_elf_property
  },
  _dl_stack_flags = 6,
  _dl_tls_dtv_gaps = false,
  _dl_tls_max_dtv_idx = 1,
  _dl_tls_dtv_slotinfo_list = 0x7ffff7fbbc20,
  _dl_tls_static_nelem = 1,
  _dl_tls_static_used = 144,
  _dl_tls_static_optional = 512,
  _dl_initial_dtv = 0x7ffff7d87160,
  _dl_tls_generation = 1,
  _dl_scope_free_list = 0x0,
  _dl_stack_used = {
    next = 0x7ffff7ffe0c8 <_rtld_global+4232>,
    prev = 0x7ffff7ffe0c8 <_rtld_global+4232>
  },
  _dl_stack_user = {
    next = 0x7ffff7d86a00,
    prev = 0x7ffff7d86a00
  },
  _dl_stack_cache = {
    next = 0x7ffff7ffe0e8 <_rtld_global+4264>,
    prev = 0x7ffff7ffe0e8 <_rtld_global+4264>
  },
  _dl_stack_cache_actsize = 0,
  _dl_in_flight_stack = 0,
  _dl_stack_cache_lock = 0
}

 

 

그러면 실습환경을 맞춰야지

CTF나 워게임에서 _rtld_global overwrite 문제가 나왔는데, glibc 버전이 구버전이라면 실습 환경을 맞춰주는게 편하다.

또한 도커가 제공될테니 본인의 우분투 버전을 낮추면 된다. (도커로)

 

Docker Ubuntu 18.04 로 내리기

더보기

Dockerfile

FROM ubuntu:18.04
ENV PATH="${PATH}:/usr/local/lib/python3.6/dist-packages/bin"
ENV LC_CTYPE=C.UTF-8
RUN apt update
RUN apt install -y \
    gcc \
    git \
    python3 \
    python3-pip \
    ruby \
    sudo \
    tmux \
    vim \
    wget
# install pwndbg
WORKDIR /root
RUN git clone https://github.com/pwndbg/pwndbg
WORKDIR /root/pwndbg
RUN git checkout 2023.03.19
RUN ./setup.sh
# install pwntools
RUN pip3 install --upgrade pip
RUN pip3 install pwntools
# install one_gadget command
RUN gem install one_gadget
# install patchelf
WORKDIR /root
RUN apt install -y dh-autoreconf
RUN git clone https://github.com/NixOS/patchelf
WORKDIR /root/patchelf
RUN git checkout 0.17.2
RUN ./bootstrap.sh
RUN ./configure
RUN make
RUN make check
RUN sudo make install
WORKDIR /root

 

실행하기

$ CONTAINER_NAME=my_container; \
docker build . -t ubuntu1804; \
docker run -d -t --privileged --name=$CONTAINER_NAME ubuntu1804; \
docker exec -it -u root $CONTAINER_NAME bash