ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Jmp table - pwnable.xyz
    Write-ups/pwnable.xyz 2020. 2. 12. 20:26

    Prob Info


    Prob Info
    Checksec

    int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
    {
      signed int v3; // [rsp+Ch] [rbp-4h]
    
      setup();
      while ( 1 )
      {
        print_menu();
        printf("> ", argv);
        v3 = read_long();
        if ( v3 <= 4 )
          (*(&vtable + v3))();
        else
          puts("Invalid.");
      }
    }

    main 함수의 내용이다. 여기서 vtable은 bss영역에 존재하는 전역변수이다. 

    .data:00000000006020B0                 public size
    .data:00000000006020B0 ; size_t size
    .data:00000000006020B0 size            dq 1                    ; DATA XREF: do_malloc+1E↑w
    .data:00000000006020B0                                         ; do_malloc+25↑r ...
    .data:00000000006020B8                 public heap_buffer
    .data:00000000006020B8 ; void *heap_buffer
    .data:00000000006020B8 heap_buffer     dq 1                    ; DATA XREF: do_malloc+3F↑w
    .data:00000000006020B8                                         ; do_malloc+50↑w ...
    .data:00000000006020C0                 public vtable
    .data:00000000006020C0 vtable          dq offset do_exit       ; DATA XREF: main+4E↑o
    .data:00000000006020C8                 dq offset do_malloc
    .data:00000000006020D0                 dq offset do_free
    .data:00000000006020D8                 dq offset do_read
    .data:00000000006020E0                 dq offset do_write
    .data:00000000006020E0 _data           ends

    5가지 함수 포인터가 있으며 0 ~ 4까지 메뉴를 선택할 수 있다. (*(&vtable + v3))(); 부분을 어셈블리어로 다시 보면 아래와 같다.

    mov     eax, [rbp+var_4]
    cdqe
    lea     rdx, ds:0[rax*8]
    lea     rax, vtable
    mov     rax, [rdx+rax]
    mov     rdx, rax
    mov     eax, 0
    call    rdx

    v3의 값을 더하는데 [rdx + rax]를 진행한다. read_long에서 -1을 입력하면 0xffffffffffffffff이 반환되기 때문에 OOB가 가능하다. vtable 바로 위에는 do_malloc에서 사용되는 두 변수가 있다.

     

    void *do_malloc()
    {
      unsigned __int64 v0; // rax
      void *result; // rax
    
      printf("Size: ");
      v0 = read_long();
      size = v0;
      result = malloc(v0);
      if ( result )
        heap_buffer = result;
      else
        heap_buffer = (void *)1;
      return result;
    }

    size는 할당되는 힙의 사이즈, heap_buffer는 할당된 힙을 가리키고 있다. 두 변수중에 호출할 수 있는 값을 넣어야 하는데, heap_buffer는 힙영역 주소가 들어가 우리가 적당히 조절할 수 없다. 그래서 size에 _ 함수 주소를 넣고 인덱스를 -2로 해주면 된다.

    'Write-ups > pwnable.xyz' 카테고리의 다른 글

    Game - pwnable.xyz  (0) 2020.02.12
    l33t-ness - pwnable.xyz  (0) 2020.02.12
    TLSv00 - pwnable.xyz  (0) 2020.02.12
    Free Spirit - pwnable.xyz  (0) 2020.02.12
    two targets - pwnable.xyz  (0) 2020.02.12

    댓글

Designed by Tistory.