ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [FTZ]해커스쿨(HackerSchool) LEVEL18 풀이(Solution)
    미사용/##Security 2015. 8. 15. 01:21

    HackerSchool FTZ WARGAME Solution

     

    Start : 15.07.03

     

    LEVEL18

     

    [그림 1]

     

    hint를 열어보면 [그림 1]과 같이 꽤 긴 코드가 출력된다. 코드에 나온 함수를 검색해보니 네트워크 소켓 프로그래밍에서 사용되는 다중 입출력에 사용되는 함수였다. 이를 풀기 위해선 다중 입출력에 대해 공부를 해야 했는데 시간이 너무 오래걸려 주요 함수 부분이 하는 역할정도만 파악을 하고 문제를 풀었다.

     

    우선 count가 100 이상이 되면 어떤 동작을 하든 "what are you trying to do \n"이 출력이 되는데 이 코드는 버퍼 오버플로우를 방어하기 위한 방어 코드라는 것을 알 수 있다. 그리고 check 변수의 값이 0xdeadbeef 일 경우 shellout() 이라는 함수를 실행시키는데 이 함수에 정의된 내용이 상위 권한으로 쉘을 실행시키는 코드이다.

     

    그렇다면 우리가 해야할 것은 count 값이 100이 되지 않으면서 check 에 0xdeadbeef 값을 저장해야 하는 것이다.

     

    [그림 2]

     

    코드 아래쪽을 보면 switch 문이 나오고 x 값에 따라 분기가 달라진다. x값이 \r이거나 \n인 경우에는 \a 동작(비프음)을 내고 다시 입력을 기다린다. x값이 0x08인 경우 count-- 를 수행하며, 그 외에는 string[count] 에 x값을 저장하고 count++을 동작한다.

     

    처음 이 코드를 봤을 때는 조금 당황했으나 FD_SET 함수의 인자값이 STDIN_FILENO를 fds에 set 시키는 것을 보고 사용자 입력값에 따라 프로그램이 동작하는 것이라 예상했었고, FD_ISSET 함수는 입력값이 있을 때 참이 되어 분기가 동작되는 것이라 판단했다. (실제로 검색 했을 때 나온 내용이다) 그리고 read 함수로 stdin 에 있는 1byte 만큼을 x 변수에 저장시킨다.

     

    이제 대충의 프로그램의 logic은 파악을 했고 공격을 어떻게 진행을 시킬지 생각해야 하는데 우선 count 를 증가시켜서 오버플로우를 발생시켜 RET 에 1byte 씩 0xdeadbeef 를 입력하는 것을 생각할 수 있으나 버퍼 오버플로우 보안 코드 때문에 불가능하다. 약간의 역발상이 필요하고 c언어의 지식이 필요한데 우선 변수가 스택에 할당된 순서를 보면 string 배열이 먼저 선언되고 check 변수가 그 다음에 선언이 되었다. 그 말은 스택상으로 string 배열이 먼저 할당이 되고, 그 다음에 check 변수 영역이 할당이 된다. (이 때문에 사실 일반적인 버퍼 오버플로우로는 check 변수에 값을 덮어쓸 수 없다)

     

    c언어의 배열 인덱스에 양수가 아닌 음수를 넣으면 기준 주소값에 음수값만큼 뺀 곳을 가리키게 된다.

     

    [그림 3]

     

    [그림 3]을 보면 string 의 인덱스가 -1인 경우 string 주소를 기준으로 반대쪽의 메모리 공간을 가리킨다는 것을 볼 수 있다.

     

    우리는 hint 코드의 switch case 문의 x값이 0x08 일 때의 분기가 동작하는 코드를 봐야하는데 count--를 하고 있다. 즉 반대로 값을 넣게 되면 check 변수의 값을 덮어 쓸 수 있게 된다는 것이다. 이를 생각하고 공격 파일을 만들면 된다.

     

    [그림 4]

     

    [그림 4]는 본인이 작성한 공격 코드인데 조금 풀어서 써본다면 우선 0xdeadbeef 를 원래 일반적인 경우라면 리틀엔디언으로 거꾸로 \ef\xbe\xad\xde 순서로 넣는게 맞지만 지금은 메모리의 반대로 값을 넣고 있기 때문에 원래 순서대로 넣어주면 된다. 그리고 \x08을 넣어준 것은 switch 에서 x 값에 0x08 이 저장되게 하기 위해서 넣은 것이다. 이 때 단순히 8을 넣으면 그냥 문자로 취급해 다른 값이 들어가기 때문에 우리가 원하는데로 동작이 되지 않는다. print 순서대로 봤을 때 "\x08"로 count가 감소하고 "\xde"를 입력, 이 때 count가 다시 증가하기 때문에 그 다음 부터는 "\x08"을 두 번씩 입력되게 해서 count가 2씩 감소되게 해야 check 변수에 정상적으로 0xdeadbeef가 입력 된다.

     

    [그림 5]

     

    만들어진 공격 파일을 attackme 에 전달하면 [그림 5]와 같이 공격에 성공한 것을 확인할 수 있다.

    댓글

Designed by Tistory.