티스토리 뷰

시스템 인터럽트는 프로세스간에 주고받는 신호로 시스템 개발에서는 중요한 요소이다.


소스코드 상에서 시그널을 전달하는 방법을 알아보자. 시그널을 발생시키려면 아래 표와 같이 signal() 함수를 사용하면 된다.


 signal() 함수의 사용법

사용 예 

설명 

signal(시그널 번호, SIG_DFL)

signal(SIGINT, SIG_DFL)

SIGINT 시그널 실행 

signal(시그널 번호, SIG_IGN)

signal(SIGQUIT, SIG_IGN)

SIGQUIT 시그널 무시 

signal(시그널 번호, handler 함수) 

signal(SIGINT, handler)

SIGINT(Ctrl + C)가 입력되면 handler 함수를 실행 


위의 표를 참조해서 시그널 함수를 구현해보면 아래의 소스를 볼 수가 있다.


마지막 줄의 while(1)을 한 이유는 시그널로 입력되는 키를 확인하기 위해 무한히 실행하는 것이다. 즉, 프로세스가 무한히 실행되므로 어떤 인터럽트가 입력되는 확인할 수 있다.


위에서 구현한 것을 실행하면 SIGINT(CTRL+C), SIGSTP(CTRL+Z), SIGQUIT(CTRL+\) 을 이용해서 중단을 시켜보면 각각의 시그널의 번호가 출력되고 다시 한번 입력하면 SIGINT와 SIGQUIT는 종료가 되지만 SIGSTP는 시그널 번호(20)을 출력하고 다시 입력을 해봐도 종료가 되지 않는다. 위에서 SIG_IGN 옵션으로 설정을 해주었기 때문이다. 


stty --all 명령으로 시그널의 단축키를 확인하는 것도 가능하다.


이제 문제에 대해서 들어가보자. level6으로 로그인 하자마자 hint가 바로 출력이 된다.


엔터를 누르면 아래와 같이 90년대의 서비스를 출력해서 당황스럽게 한다.


아래와 같이 1번을 선택 했더니 접속시도만 하고 인터럽트를 가하면 지금 접속했던 FTZ 서버도 끊기게 된다.(1~3번 동일)


인터럽트를 입력해도 막혀있다. 어떤 인터럽트는 아예 서버를 종료 시켜 버려서 계속 접속을 하는 경우도 있어서 개빢쳤다.


답이 안나올땐? "리버싱"

초기화면에서 CTRL+C를 눌러서 level6으로 진입후에 "tn"이라는 파일을 gdb로 리버싱을 진행했다.


gdb로 본 "tn" 파일인데, 앞서 보면 어느 파일과 마찬가지로 스택을 구성하고 system 명령어로 실행을 한다.


위의 system 명령어로 실행을 하는 것은 "cat hint"이다. 아까 앞서 봤던 것처럼 실행하자마자 hint가 출력되는 것을 봤다.


밑의 getchar 부분은 위에서 천리안~~뭐어쩌고에서 번호를 하나 택하라고 하는데 그 중 한 문자를 택하는 부분이다.


위의 system에서 출력하는 것은 바로 clear이다. 아마 정확한 문자열을 입력했을 때 clear을 하는 것으로 보인다.


위에서 본 것같이 접속하고 싶은 bbs를 선택하라는 것까지 출력이 되었다. 위에 부분은 너무 많아서 시간 관계상 올리지는 않겠습니다.


signal 함수로 0x2(SIGINT)와 0x80484e0의 인자를 넣고 실행합니다. 아래의 0x80484e0을 x/s로 문자열을 출력하면 <sing_func>라고 출력되는 것이 보이는데, signal(2, sig_func)를 출력하게 됩니다. 이 말은 즉, SIGINT(CTRL+C)를 실행하게 되면 sig_func 함수를 실행한다는 말이다.


sig_func를 디스어셈블 해보면 아까 위에서 오류가 출력되는 것과 동일하다. "Can`t use ctrl+c\n" 즉, SIGINT(CTRL+C) 시그널이 실행되면 해당 문자열을 화면에 출력하는 것이다. 이 코드 때문에 위에서 CTRL+C를 실행해도 종료가 되지 않고 이 문자열이 출력된다는 것을 알 수가 있다.


x/s로 scanf받는 부분을 확인해 보면 %d로 정수를 받아들인다.


어떤 숫자를 받아 들이는지 확인기 위해 BP를 걸고 실행을 한다. 처음 화면이 보일 것이다.


16진수 값으로 eax를 보면 0xbfffebb4 주소에 0x42130a14값이 들어가 있다. 무슨 값을 비교하는지 알기 위해서 밑의 cmpl의 주소 0x080485e9를 두번째로 BP를 건다.


BP를 건 상태에서 cont로 진행을 하면 bbs를 선택하라고 나온다. <main+241> 부분에서 0x1과 비교하므로 1을 입력하면 

0xbfffebb4 주소에 저장이 되는 것을 볼 수가 있다.


입력 값이 위에서 1이라면 system 명령어로 아래와 같이 telnet으로 203.245.15.76 접속을 시도하게 된다. 1,2,3을 입력하는 코드도 위와 동일하니 생략 하겠다.


위에서 0x1, 0x2, 0x3을 입력하지 않으면 점프되는 것을 볼 수가 있는데, 그 부분을 출력해보면 아래와 같이 출력된다.


복원된 코드중에서 주요 코드는 바로 아래와 같다.

for ( i = 1; i < 32; i++){

if(i == SIGINT) signal(i, sig_func); // Ctrl+C 시그널이 메뉴 출력 다음에 처리됨.

else signal(i, SIG_IGN); //각종 시그널을 무시.

}


위와 같이 gdb로 소스를 복원 하는데 시간이 많이 걸린다. 이 부분을 빠르게 한다면 분석 속도에 큰 힘이 될 것이다.


환경 설정 파일을 보면 힌트를 얻을 수가 있다. 보다시피 로그인 후에, 취약점이 있는 문제의 파일인 tn을 실행하고, tn의 실행이 끝나면 logout 명령이 실행된다. 그러므로 우리가 tn 명령을 종료시키는 상황을 만들면 셸이 나타나지 않고 세션이 끊어진다. 

이는 텔넷에 로그인되는 순간을 제거하기 위해 사용한 트릭이겠지만 이 설정 때문에 많은 시간을 빼앗기게 되는 것이다.



처음으로 돌아가서 level6을 접속해보자. 그럼 이상태에서 아무 명령을 하지 않으면 셸이 뜨지 않게 된다는 것을 위에서 확인했을 것이다. CTRL+C를 실행하게 되면 아래와 같이 level6 셸이 나타난다.


ls -al을 실행하여 보면 password라는 디렉터리가 보이고 확인해 보면 간단히 답을 찾을 수가 있다. 이 원리는 문제의 프로그램이 root 권한으로 실행되고 있어서 CTRL+C를 누르는 순간 root 계정의 셸이 떨어지는 것을 볼 수가 있지만, 일반적으로는 root계정의 셸이 떨어지지 않아서, root 계정을 획득하는 추가 공격을 해야만 한다.

위와 같이 password파일과 tn파일이 보통 UID가 level7로 되어 있어야 하지만, root인 이유는 셸을 획득한 다른 사용자가 파일을 삭제하거나 수정하는 것을 방지하기 위한 것임을 알아두자.


'시스템해킹 > FTZ' 카테고리의 다른 글

FTZ LEVEL8 문제풀이  (0) 2015.07.22
FTZ LEVEL7 문제풀이  (0) 2015.07.22
FTZ LEVEL5 문제풀이(Race condition)  (0) 2015.07.20
FTZ LEVEL4 문제풀이  (0) 2015.07.18
FTZ LEVEL3 문제풀이  (0) 2015.07.15
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함