ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [HackCTF] RTL_Core Write-up
    표튜터와 함께하는 Pwnable/HackCTF Write-up 2019.04.23 18:10

    이번 문제는 RTL_Core 입니다.



    해당 바이너리는 NX만 걸려있다.



    문제를 실행시켜보면 패스코드를 입력하라는

    문자열이 출력된다. 그래서 뭔가 입력해보았는데

    정답이 아니기 때문에 분석을 통해서 정답을 맞춰야했다.



    IDA를 이용해서 코드를 보도록 하자.

    hashcode를 맞춰야 다음단계로 넘어갈 수 있다.


    hashcode는 0x0C0D9B0A7 이라는 것을 확인했다.

    우리가 입력한 값은 check_passcode함수의 인자로 넘어가고

    거기서 계산된 값이 바로 위에서 찾은 hashcode와 같아야한다.




    그럼 check_passcode함수를 보도록 하자.

    동작원리는 간단했다. 기준이되는 메모리부터 4바이트씩

    커진 위치의 메모리 위치(+4, +8, +12, +16)의 값을 읽었고

    그 값들을 계속해서 더한 값이 바로 hashcode가 되어야 했다.

    그러므로  0x0C0D9B0A7를 5로 나누어서 입력해주면 됬다.

    하지만 5로 딱 나누어져 떨어지지 않았기 때문에 마지막 4바이트는

    다른 4개의 4바이트보다 2가 큰 값을 주면 된다.



    위의 설명대로 Payload를 구성하여 진행해보았더니

    그림과 같은 힌트가 주어졌다. 이 주소가 무얼까?라는 생각이 들었다.

    우선적으로 해당 문자열이 출력되는 함수는 core함수였으므로

    core함수를 살펴보기로 하였다.


    해당 함수를 살펴보니 위에서 힌트로 준 주소를 알 수 있었다.

    dlsym함수를 이용하여 printf의 주소를 출력해준 것이었다.

    또한 core함수를 보니 read함수를 이용하여 입력도 받고 있었다.



    그러므로 우리는 이 read함수와 printf의 주소를 이용해서 문제를

    풀어야함을 알 수 있었다. 도대체 어떤 방법을 이용해야할까??


    해당 서버는 ASLR이 걸려있어서 주소값이 항상 바뀌는 것을 확인했다.

    바로 offset을 이용하는 것이다. printf함수의 주소는 항상바뀌지만

    이 주소는 힌트로 항상 넘어오기 때문에 우리가 사용할 수 있다.

    또한 우리는 system함수와 "/bin/sh"을 이용해서 쉘을 딸 것인데

    그러기 위해서는 항상 변화하는 해당 함수들의 정확한 주소를 알아야한다.

    이 때 offset을 이용하는 것이다. printf의 주소와 해당 함수와 문자열간의

    주소 차이를 이용하면 정확한 주소를 다시 leak 할 수 있기 때문이다.



    이런식으로 system함수와 printf함수간의 거리 offset을 구하였다.



    마찬가지로 기준이 될 printf함수와 "/bin/sh"간의 거리 Offset도 구해준다.


    이렇게 구한 offset과 파이썬을 이용해서 정확한 주소를 구해준다.

    -와 +의 차이는 system의 경우 printf보다 주소가 작기 때문이고

    "/bin/sh"의 경우는 printf함수보다 크기 때문이다. 주소가 항상 달라지더라도

    함수간의 거리차이는 항상 똑같기 때문에 이러한 leak이 가능한 것이다.


    그럼 이제 RTL을 위한 ret를 찾아보도록 하자~

    ebp부터 - 0x3e이 버퍼의 시작위치임을 알 수 있다.

    그러므로 우리는 0x3e + 4(sfp) 크기를 dummy값으로 

    덮어주고난 다음부터 ret를 핸들링 할 수 있을 것이다.


    ret는 아까 구해놓은 system함수의 주소로 하도록하고

    인자로는 역시 아까구해놓은 "/bin/sh"의 주소를 넘겨주면 된다.


    그럼이제 필요한 것들을 다 구했으므로 Payload를 다 구성해보도록 하겠다

     

    우선 로컬에서 한번 진행해보았다~



    이런식으로 Payload를 구성했더니 역시나 성공했다!!


    그럼 이번에는 서버 차례~

    오잉??? 실패했다... 뭐지??


    그 이유는 바로 해당 문제를 줄 때 libc파일도 같이 주었는데

    이걸 왜줬지??라는 의문이 바로 해결하는 열쇠였다.


    리눅스의 경우 LD_LIBRARY_PATH를 따라서 라이브러리를 참조한다.

    그러므로 기본적으로 설정되어있는 라이브러리를 참조했기 때문에

    우리가 로컬에서 진행한 것은 성공한 것이고 서버의 경우

    바이너리와 같이준 libc.so.6파일을 참조했기 때문에

    offset이 달라서 성공하지 못하게 된 것이다. 그러므로 우리는

    다시 libc.so.6에서 참조하는 offset으로 구해주어야 한다.



    printf 함수와 system 함수의 offset차이는 아까의 방법처럼

    libc.so.6에서 구하면 쉽게 구할 수 있다~



    하지만 실행을 할 수 없으므로 "/bin/sh"은 같은 방법으로 구할 수 없었다.

    하지만 분명히 "/bin/sh"이 libc.so.6에 있다는 것은 명령어를 통해

    확인할 수 있었다. 방법은 파이썬을 이용하면 구할 수 있다.


    * Thanks to malatto *


    < Payload >

    ELF명령을 이용해서 변수에 넣게되면 libc에 구조체처럼

    ELF에 대한 정보들이 저장된다. 그래서 libc.symbols와 search를

    이용해서 아까처럼 offset차이를 찾아주면 된다.



    이런식으로 Payload를 구성하여 작동시키면~

    FLAG를 딸 수 있게 된다~~

    '표튜터와 함께하는 Pwnable > HackCTF Write-up' 카테고리의 다른 글

    [HackCTF] Gift Write-up  (0) 2019.04.25
    [HackCTF] ROP Write-up  (0) 2019.04.24
    [HackCTF] RTL_Core Write-up  (0) 2019.04.23
    [HackCTF] Random Key Write-up  (0) 2019.04.22
    [HackCTF] BOF_PIE Write-up  (0) 2019.04.21
    [HackCTF] RTL_Wolrd Write-up  (0) 2019.04.21

    댓글 0

Designed by Tistory.