ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • |Lord Of Bufferoverflow| #14 bugbear - giant
    Wargame Site/BOF 2019. 6. 23. 17:04

     

     

     

    아따~ 길다.. 하지만, 자세히 보면 그렇게 어렵지 않은 코드임을 알 수 있다.

    중간에 친절하게 주석처리까지 되어있는 것을 알 수 있다.

    // gain address of execve ,//end 인 것으로 알 수 있 듯, execve 의 주소를 가져오는 것이다.

    그리고 RET 에 execve 의 주소를 잘 넣어줬는지 확인하는 코드가 보인다.

     

    즉, execve 를 ret 로 두어 문제를 해결해야하는 것이다.

     

    24 번째 줄에서 보이는 저녀석이 걸림돌이 된다.

    기존의 풀이 방식을 파헤쳐보면 Core 분석 및 디버깅을 위해 실행파일을 복사했다.

    실행파일을 복사하면, 우리의 권한으로 파일을 실행시킬 수 있기 때문에 Core 가 생기며, Core Analysis 를 할 수 있었다.

     

    만약, 이문제에서 giant 를 복사한다고 하더라도

    우리의 권한으로는 /home/giant 에 접근할 수 없다.

    따라서, giant.c 자체를 수정해서 자유로운 환경을 만들어주자

     

     


    자유로운 분석환경 만들기


     

    1. giant.c 를 복사한다.

     

     

    2. /home/bugbear/giant 로 수정해준다.

     

     

    3. gcc 로 실행파일로 만들어준다.

     

     

    이로써, 우리에게 익숙한 환경을 갖추었다. 이제 본격적으로 문제풀이에 돌입해보자.

     


     

     

    우선, execve 의 주소를 구하는 것이 우선일 것이다.

     

    execve 의 주소 : /lib/libc.so.6 의 주소 + execve 의 offset  = 0x40018000 + 0x00091d48 = 0x400a9d48

     

     

     

     


    예외상황 1

     

    하지만.... RET 영역(buffer + 4 ~ buffer + 7)에 execve 의 주소를 넣어주어도 다음과 같은 'You must use execve' 문구가 뜨는 것을 볼 수 있었는데, execve 의 주소가 제대로 들어가지 않았음을 알 수 있었다.

    디버깅 결과 0x400a9d48 이 아니라, 0x40009d48 로 들어간 것을 볼 수 있다.

    마치, \xff 가 들어갔을 때와 비슷한 현상이 벌어진 것이다.

    검색결과 \x0a 가 개행문자로 들어가서 작동이 안된다고 한다.

     

    따라서, \x0a 를 문자 자체로 전달하기 위해서는 `python -c 'print '` 를 전체적으로 감싸주어야 한다는 것을 알았다.

    "`python -c 'print '`" 와 같은 형식으로 작성해야한다.

     

     

    RET 에 값이 제대로 들어간 것을 알 수 있다.

     

    공부를 하면서 항상느낀 건데, 뭔가 문제가 터지고 나서 '이런현상 때문이다' 라고 이해하는 경우가 많은데

    마치 문제 답안지를 보고 거기에 풀이를 맞추는 듯한 풀이같다...

    이런 기분이 정말 좋지 않지만, 나중에 꼭 짚고 싶은 부분이다.

    그러기 위해서는 문제풀이 이상의 개념에 도달해야한다. 그날까지 한걸음은 계속되야한다.


     

     

     

     


     

    이번 포스팅의 핵심!!

     

     

    RET 를 조정하여 execve 로 EIP 를 수정한 뒤에 execve 의 프롤로그가 시작된다.

     

    우리가 주목해야할 부분은 EBP 이다.

    그 이유는 앞서 풀었던 문제에서도 강조했던 부분으로 EBP 를 기준으로 인자와 지역변수를 구분짓기 때문이다.

    즉, EBP 가 ESP 가 있는 곳으로 이동한다는 것이다.

    execve 실행전 ESP 는 어디를 향해 있을까?

     

    그렇다. 바로 execve 주소를 적어준 바로 다음부분을 가르키고 있을 것이다.

    프롤로그가 시작되면 EBP (SFP 로 넣어줬던 'AAAA') 가 들어갈 것이고 ( 0x400a9d48 push ebp )

    그 뒤로, execve 의 다음인자들이 나열되는 구조가 될 것이다. 

     

    '기존의 \x48\x9d\x0a\x40 은 SFP 로 덮어질 것이다.'

     

     

    EBP + 4 : RET 주소       EBP + 8 : 인자 ~

    의 구조를 만들어 주면 되는 것이다.

     

     

    execve 의 기준에서 입력값을 바라볼때

    "A"*44 + "\x48\x9d\x0a\x40" + [ RET ] + 인자(execve) ...

    의 형태가 되는 것이다.

     

    인자부분에 exit( ) 를 넣어주고, RET 부분에 system 을 넣어주고, 이 또한 execve 의 형태를 생각했을 때 다음과 같은 구조를 지닐 것이다.

     

    system 의 기준에서 입력값을 바라볼때

    "A"*44 + "\x48\x9d\x0a\x40" + System + [ RET ] + 인자(system) ...

    의 형태가 되는 것이다.

     

     


     

    천천히 이해해보면 이해할 수 있다. 나 또한 이 개념을 받아들이기 까지 시간이 많이 걸렸던 것 같다.

    하나하나 디버깅을 해보면서 확인하면 잘 알 수 있다.

     

     

     

     

     

    그럼 최종적으로 작전을 다음과 같이 세우면 될 것이다.

    Buffer 44 Byte + execve 의 주소 + system 의 주소 + [       ] + /bin/sh 의 주소

     

    "`python -c 'print "A"*44 + "\x48\x9d\x0a\x40" + "\xe0\x8a\x05\x40" + "AAAA"+ "\xf9\xbf\x0f\x40"'`"

    다음과 같이 정리할 수 있다. [  ] 자리에는 아무값이나 들어가도 상관은 없다.

    정상적으로 동작이 되지않아 core 가 생긴다는 점 말고는 이상은 없다.

     

     

     

     

    OpenTRS 에서 Defcon 풀이를 듣던 도중 ROP Chaining 개념이 나왔는데,

    Chaining 의 개념을 접근하기 위해 선수되어야하는 문제였던 것 같다.

     

     

     

    프로그램 작동원리를 한단계 더 잘 이해할 수 있던 좋은 문제였던 것 같다.

    댓글

Designed by Tistory.