Level18 풀이.
pw = 'why did you do it'
일단 문제 접근을 위해 hint를 본다.
순간 hint가 아닌 줄 알았다. 아마 FTZ 문제 중에 hint가 제일 길 것이다.
후...하나하나 보자면, char string[100]은 문자형으로 string 변수에 100byte 만큼 크기를 할당한다는 것이고, int check는 int형으로 check 변수 선언한 것이고, int x = 0; int형으로 x변수 선언과 0 저장한다는 것.
fd_set fds;(구글링 참조) 관리하는 파일의 지정번호가 등록되어 있는 비트 배열 구조체.
printf(“enter your command”) enter your command를 출력한다는 것이다.
fflush(stdout)(구글링 참조) stdout에 지정된 출력이고, stream과 연관된 버퍼를 비우게 한다. while(1)은 무한 반복이다. if(count >=100) 은 count 변수 값이 100이거나 크면, if 조건문 수행. printf(“what are you trying to do? \n”)는 what are you trying to do를 출력. if(check == 0xdeadbeef)는 check 변수의 값이 0xdeadbeef라면 if문 실행한다. shellout()은 shellout 함수 호출.
else는 check 변수의 값이 0xdeadbeef가 아니라면, else문 수행. FD_ZERO(&fds)는 즉 FD변수로 선언된 fds를 초기화한다. int a = 0 같은 것. FD_SET(STDIN_FILENO,&fds)는 fd set에 해당 fd 정보를 설정. if(select(FD_SETSIZE, &fds, NULL, NULL, NULL) >=1) fds를 STDIN_FILENO로 표준입출력으로 설정한다. if(FD_ISSET(fileno(stdin),&fds))는
FD_ISSET(int fd,fd_set *fdset) fdset 중 소켓 fd에 해당하는 비트가 셋 되어 있으면 양수값 fd 리턴. read(fileno(stdin),&x,1); fd로 지정한 파일로부터 데이터를 읽어들인다.
즉 read(int filedes, void *buf, size_t count) 이 형태인데, &x => 파일로부터 읽어들인 내용 저장하가ㅣ 위한 공간. 1 => 읽어들일 파일 내용 크기 지정.
switch(x)는 x를 스위치. case ‘\r’와 case ‘\n’는 \r,\n 입력시 \a 출력. break는 고정 장치. case 0x08; count — printf(“ \b \b”); break; 즉 0x08 입력이 들어오면, count 변수의 값을 1 빼고 문자를 지운다. (\b)
default string[count] = x; count++ break 그 외에는 모두 일반 문자처럼 버퍼에 저장된다.
void shellout(void) shellout 함수 선언한다. setreuid(3099,3099) level19의 권한 같다. execl(“/bin/sh”,“sh”,NULL) /bin/sh 셀 실행.
일단 check 변수 값이 0xdeadbeef면 shellout 함수를 호출하는데, 다음 level19가 /bin/sh 셀이 실행된다. 근데 string[100]보다 뒤에 check 변수가 뒤에 존재해서 BOF로는 문제 해결 안된다. 일단 버퍼의 문자수를 조절해주는 count 변수가 0x08 들어오면, -1한다는 것이다.
일단 난이도가 확 올라간 거 같다. 일단 string[100]에서 check까지의 거리랑 check에서 0xdeadbeef를 덮어씌우는 과정을 알아야 될 거 같다.
main+91 cmp DWORD PTR [ebp-104],0xdeadbeef check변수에서 ebp까지의 거리 확인 가능, 즉 104.
즉 string 변수에서부터 check까지의 거리는 = [string[100]에서 ebp까지의 거리 -[check변수에서 ebp까지의 거리] 100 – 104 = -4.
일단 그러면, string에서부터 check까지의 거리 + 0xdeadbeef다. 근데 string에서 check까지의 거리 –4 는 0x08을 입력시 count변수가 –1 되는 것을 이용해서 돌아가는 걸 알아야 한다.
즉 (python –c ‘print “\x08”*4 + “\xef\xbe\xad\xde”’;cat)| ./attackme.
cf) hint가 상당히 당황스러웠다.