Level18로 접속하고 늘 그렇듯이 hint를 확인해봅니다.

힌트 코드가 굉장히 길어졌네요.

우선 코드에 대한 설명부터 하겠습니다.

 

코드 내에 있는 낯설은 함수들의 설명은 다음과 같습니다.

FD_ZERO(fd_set *fdset) : *fdset의 모든 비트를 지운다.

FD_SET(int fd, fd_set *fdset) : *fdset 중 첫번째 인자 fd에 해당하는 비트를 1로 한다.

FD_CLR(int fd, fd_set *fdset) : *fdset 중 첫번째 인자 fd에 해당하는 비트를 0으로 한다.

FD_ISSET(int fd, fd_set *fdset) : *fdset 중 첫번째 인자 fd에 해당하는 비트가 세트되어 있으면 양수값인 fd를 리턴한다.

 

select()FD_SET으로 설정된 fd만을 확인한다. 그리고 확인 결과 read또는 write준비가 된 fdfdset내에서 세트시킨다. 따라서 select() 함수 직후에 FD_ISSET으로 특정 fd‘SET’되었는지 확인할 수 있다. 데이터가 변경된 파일의 개수 즉 fd_set에서 비트값이 1인 필드의 개수를 반환

(출처 : http://jsnim.blogspot.kr/2010/02/select-fdzero-fdset-fdclr-fdisset.html)

 

터미널에서 man select라고 입력하시거나, 구글에 select 함수에 대해서 검색하시면 관련 정보를 얻으실 수 있습니다.

 

코드의 내용을 간단하게 말하면 표준 입력으로부터 한글자씩 입력을 받아 string[count]에 넣는 코드 입니다.

입력이 ‘\r, \n’이면 에러음을 내구요.

입력이 ‘\b’이면 입력값을 지우기 위해서 count1감소합니다.

 

코드의 조건을 다음과 같이 정리할 수 있습니다.

1.    입력은 100자 이내

2.    check0xdeadbeef여야함 : clear

3.    사용자로부터 표준입력을 받음

 

gdb를 통해 어셈을 따라가다 보면 알수 있는 스택구조는 다음과 같습니다.

어셈코드가 상당히 길기때문에 첨부하진 않겠습니다.

string(100byte)

check(4byte)

x(4byte)

count(4byte)

fds

이 문제를 해결하기 위한 핵심은 count--string[count] = x입니다.

코드에서 보다시피 ‘\b’를 입력받으면 내용을 지우기 위해 count1감소시키게 됩니다.

그러나 코드 어디에서도 count가 음수일때를 체크하는 내용은 볼 수 없습니다.

즉 우리는 check에 값을 넣어야 하는데 count가 음수가 되면 string[count]로 인해 스택상 string밑에 있는 check에 값을 입력 할 수 있게 되는 것이죠.

 

이로인해 우리가 필요한 정보는 전부 획득했습니다.

‘\b’4번 입력하고 0xdeadbeef를 입력하면 문제를 해결 할수 있을 것으로 보입니다.

획득한 정보에 맞춰 커맨드를 입력했더니 예상이 맞았네요. Level19권한의 쉘을 획득하였습니다.

 

Level19의 패스워드는 swimming in pink입니다.

 

이번 문제는 낯설은 함수가 많아 전부다 분석하는데 시간이 걸렸을 뿐이지 취약한 원인이 되는 코드는 상당히 간단했네요.

+ Recent posts