ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Stack 7]
    System/Protostar 2018. 2. 10. 22:34

    [Stack7 Code]



    [Stack7 실행]

    Stack6와 비슷한 코드지만, ret(EIP)가 0xb로 시작하면 예외처리에 걸리게 된다.

    따라서 0xb7로 시작하는 시스템함수로 변조하는 RTL공격은 불가능하다.

    그래서 이번에는 Chaining RTL공격으로 쉘을 따냈다.


    Chaining RTL공격은 ASLR이 걸려있지 않기때문에 가능하다.

    ASLR이 걸려있다면 ROP로 쉘을 따내야 할 것이다.




    [Chaining RTL]

    기본 개념은 RTL과 동일하다.

    우리가 RTL공격을 할 때 짠 페이로드를 한번 보자


    #RTL

    PAYLOAD : python -c 'print "A"*68+"System( )"+"AAAA"+"/bin/sh"

     buf[64]

     SFP

    System( )

     dummy

    "AAAA"

     /bin/sh

    여기서 dummy값이 아무의미 없는 값이 아니라는 것을 지난 RTL정리글에서 말했을 것이다.

    원래 저 dummy공간은 System( )가 끝나면 복귀할 주소가 저장되는 공간인데

    우리는 쉘을 따내고 나면 그 뒤에 뭐가 실행되던 상관없기 때문에

    그냥 "AAAA"를 넣어준 것이다.


    만약, dummy공간에 puts( )의 주소를 넣으면 System( )가 끝난 후, puts( )가 실행된다.

    확인을 위해 System( )가 끝나고 puts( )가 실행되는 페이로드를 한번 짜보도록 하자

    먼저 스택상황을 먼저 그려보면 이렇다.


    #Chaining RTL

    PAYLOAD : python -c 'print "A"*68+"System( )"+"pr gadget"+"/bin/sh"+"puts( )"+"AAAA"+"I'm py0zz1"

    buf[64] 

    SFP 

    System( ) 

    pop,ret

    gadget 

    /bin/sh 

    puts( )

    dummy

    "AAAA"

    I'm py0zz1 

    여기서 gadget이라는 개념이 나오는데 코드조각이라고 생각하면 된다.

    [pr gadget]은 POP과 RET명령어를 순서대로 실행하는 코드의 조각이다.


    System( )의 인자값이 하나이기 때문에 POP을 한번만 해주는 가젯을 따온 것이고

    strcpy( )처럼 인자값이 두개인 함수라면 [ppr gadget] 즉 POP을 두번하는 가젯을 따와야 한다.


    저 페이로드의 진행을 정리해보면

    1. System( )함수와 /bin/sh가 인자값으로 들어가서 System("/bin/sh")가 실행된다.


    2. System( )가 종료되면 RET에 저장되어 있는 주소로 복귀한다.


    3. 복귀한 주소에는 POP과 RET을 진행하는 코드가 있다.


    4. POP을 진행한다. (스택에서 /bin/sh가 POP되고 ESP는 puts( )를 가르키고 있다.)


    5. RET을 진행한다. (puts( )로 복귀한다)


    6. puts( ) 인자값으로 "I'm py0zz1"가 들어가서 실행된다.


    7. puts( )가 끝나면 [0x41414141]로 복귀한다.


    8. [0x41414141]은 존재하지 않기 때문에 종료된다.

    이렇게 진행될 것이다.

    Stack6번으로 직접 확인해보겠다.


    [Stack6 puts( )/문자위치]

    puts( )의 주소는 [0xb7ef4780]이며, 인자값으로 넘길 문자는 [0x80480e8]에 위치한 44[D]를 이용하겠다.


    [Stack6 pr gadget]

    가젯은 [0x08048507]에 위치한 pr gadget을 이용하겠다.

    이를 이용해서 쉘이 종료되면 D라는 문자를 출력하는 페이로드를 짜보면


    [Shell종료 후 'D'출력]

    보는바와 같이 exit명령 후 puts("D")가 실행되어 D가 출력됨을 확인할 수있다.






    [Stack7 Chaining RTL]


    다시 Stack7로 돌아와서 Chaining RTL을 어떤식으로 이용해야 쉘을 따낼 수 있을까?

    위 처럼 Chaining RTL을 사용해도 0xb~로 시작하는 System( )를 불러오는 건 똑같기 때문에 중간 예외처리에 걸리게 된다.


    눈치가 빠른사람은 알고있었을 것이다.

    우리가 꼭 처음에 함수의 주소값을 RET할 필요는 없다.

    PR grdget을 넘긴 후, 두 번째로 RET되는 함수를 System( )로 한다면?

    가젯의 주소는 [0x08~]로 시작하기 때문에 예외처리에 걸리지 않게 된다.ㅎㅎ

    자 그럼 쉘 따러 가자


    [EIP offset]

    ESP에서 EIP까지의 offset은 80이며


    [System( ) Address]

    System( )의 주소는 [0xb7ecffb0]이고


    [/bin/sh 문자열 위치]

    Stack7의 libc버전은 libc.so.6이므로 해당libc안에 있는 sh.exit를 파싱해서 /bin/sh문자열 offset를 찾는다.

    /bin/sh 문자열 offset : [0x11f3bf]

    /bin/sh 위치는 libc base주소를 구해서 offset을 더해주면 된다.


    [system( ) offset]

    libc base 주소는 아까 구한 System( ) - System( )offset을 하면된다.

    libc base 주소 : [0xb7e97000]

    libc base주소 + /bin/sh offset = [0xb7fb63bf](/bin/sh 위치)


    이제 제일 중요한 가젯을 구하면 된다.

    이번에는 위와 다르게 PPR gadget을 사용해 보겠다.

    [PPR gadget]

    PPR gadget의 위치는 [0x080485f7]이다.

    필요한 정보는 다 모았으니 이제 PAYLOAD를 작성해보자


    PAYLOAD : python -c 'print "A"*80+"PPR gadget"+"AAAA"+"BBBB"+"System( )"+"AAAA"+"/bin/sh"

    가젯 뒤에 "AAAA"와 "BBBB"는 POP을 두번 해주는 가젯이니까 dummy값을 넣어준 것이고

    dummy값 뒤엔 System( )의 주소를 넣어서 가젯의 RET에 맞추어줬다.

    그리고 그 뒤엔 System( )의 RET - 인자값 순으로 넣어준 것이다.

    결과를 보면 예외처리에 걸리지 않고 쉘을 딴 모습을 확인할 수 있다.


    다음에는 ROP를 이용한 Stack7 Write up을 진행해보겠다.


    'System > Protostar' 카테고리의 다른 글

    [Stack 6]  (0) 2018.02.10
    [Stack 4]  (0) 2018.02.02
    [Stack 3]  (0) 2018.02.02
    [Stack 2]  (0) 2018.02.01
    [Stack 1]  (0) 2018.02.01

    댓글

Designed by Tistory.