FTZ Level 9 & Level 11

RINM·2022년 11월 28일
0

FTZ Level 9

level 9 | apple

우선 hint를 살펴본다. 소스코드가 주어진다.


다음은 /usr/bin/bof의 소스이다.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

main(){

  char buf2[10];
  char buf[10];

  printf("It can be overflow : ");
  fgets(buf,40,stdin);

  if ( strncmp(buf2, "go", 2) == 0 )
   {
        printf("Good Skill!\n");
        setreuid( 3010, 3010 );
        system("/bin/bash");
   }

}

이를 이용하여 level 10의 권한을 얻어라

stdin을 통하여 buf에 문자열을 받는다. 이후 buf의 첫 두 문자가 "go"와 같으면 setuid를 사용하여 level 10의 권한으로 shell을 실행시킨다. 따라서 이번 문제에서는 BOF를 사용하여 buf2의 문자열을 조작해야한다.
해당 소스코드를 복사한 뒤 컴파일한다. 만들어진 프로그램을 gdb로 분석한다.

메모리 상에서 buf의 위치와 buf2의 위치를 찾아야한다. 더 정확히는 두 버퍼가 얼만큼 떨어져있는지 알아내야 buf에 입력한 문자열이 buf2의 값을 변경시키는 BOF를 유도할 수 있다.

main 함수의 프롤로그이다. 0x28(=40)byte의 공간을 사용한다. esp의 위치는 ebp로부터 0x28떨어진 곳이 된다.

esp에서 0xc를 뺀다. esp의 위치는 다시 ebp로부터 0x34 떨어진 곳이 된다.

0x8048554의 4바이트를 push한다. 이 값은 printf의 인자로 주어질 값이 저장된 곳의 주소이다. 스택이 8바이트 증가함에 따라 esp는 ebp로부터 0x3C 떨어진 곳이 된다. printf를 호출한다.

printf에서 리턴하면 스택을 줄여준다. esp의 위치는 ebp로부터 0x2C 떨어진 곳이 된다.
다시 esp에서 0x4만큼 빼서 스택을 늘려준다. esp는 ebp로부터 0x30 떨어진 곳이 된다.

0x8049698rhk 0x28을 각각 push한다. esp의 위치는 0x30+0x4+0x4=0x38 떨어진 곳이 된다.
eax에 ebp+0xffffffd8(= ebp-0x28)의 값을 저장한다. 이 값을 스택에 push한다. esp 값은 ebp-0x3C가 된다. 곧바로 fgets를 호출하는 것으로 보아 스택에 push된 세 값은 fgets의 인자임을 알 수 있다. 차례대로 stdin, 40, buf이다. 즉, buf의 위치는 ebp-0x28이다.

fgets에서 리턴한 뒤 스택의 크기를 조정한다. esp의 값은 ebp-0x3C에서 0x10만큼 더하고 0x4만큼 뺀 ebp-0x30이 된다.

strncmp를 호출하기 위한 과정이다. 0x2와 0x804856a를 push한다. 각각 strncmp의 인자 2와 문자열 "go"이다. esp의 값은 ebp-0x38이 된다.
eax에 ebp+0xffffffe8(=ebp-0x18)의 값을 저장한다. 이 위치가 buf2의 위치이다. esp의 값은 스택이 4바이트 늘어나 ebp-0x3C가 된다.

이제 buf와 buf2의 위치를 알았으니 BOF를 시도할 수 있다. buf의 위치는 ebp-0x28이고 buf2의 위치는 ebp-0x18이다. 10진수로 변환하면 두 버퍼는 16바이트 만큼 떨어져있다. 즉, buf에 16바이트의 값을 담고 나면 그 이후는 buf2에 담긴다.
다음과 같이 16자의 문자열 뒤에 go를 입력하면 level10의 권한을 얻을 수 있다.

level10 | interesting to hack!

FTZ Level 11

level11 | what!@#$?

hint를 확인한다. 마찬가지로 소스코드가 존재한다.

#include <stdio.h>
#include <stdlib.h>

int main( int argc, char *argv[] )
{
        char str[256];

        setreuid( 3092, 3092 );
        strcpy( str, argv[1] );
        printf( str );
}

setuid가 실행된다. 즉, 프로그램 실행시 쉘코드를 수행시키면 level12의 권한을 얻을 수 있다. main 첫번째 인자로 주어진 값이 변수 str에 길이 확인 없이 복사되고 있다. 이 취약점을 이용하여 쉘코드를 실행하도록 BOF 공격을 시도할 수 있다.
소스코드를 복사하여 컴파일한 후 실행 파일을 gdb로 분석한다.

메모리상에서 str의 위치를 찾아내야한다.

main 함수의 프롤로그 부분이다. 0x108만큼의 공간을 사용한다.

strcpy를 호출하기 전 과정이다. ebp+0xc에 0x4를 더한 8byte의 값을 push한다.
ebp+0xfffffef8(=ebp-0x108=ebp-264)의 값을 push한다. strcpy의 두 인자를 스택에 저장한 것이다. 즉, str의 위치는 ebp-264이다. str의 크기가 256바이트이므로 8바이트의 더미값 후에 4바이트의 SFP가 존재한다. 그 이후에 존재하는 리턴주소를 덮어써야 한다.
24바이트의 쉘코드를 사용할 것이므로 256+8+4=268바이트의 값 중 24바이트를 뺀 244바이트의 NOP 슬래드가 필요하다.
즉 다음과 같이 입력해야한다.

0x90(NOP)*244 + 쉘코드(25byte) + RET(4byte)

이제 gdb를 사용하여 RET로 입력할 값을 찾아야한다.

0xbfffde50을 리턴주소로 잡는다.
python을 이용하여 입력값을 넣는다.

./attackme `python -c 'print "\x90"*244+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\x50\xde\xff\xbf"'`

다음과 같이 level12 권한으로 쉘코드를 실행시킬 수 있다.

level12 | it is like this

0개의 댓글