해킹/시스템해킹

[시스템해킹 도전기 12편] Format String Bug(1)

놀고싶다~ 2021. 2. 16. 10:22

안녕하세요!

 

오늘은 Format String Bug에 대해서 알아보겠습니다!

 

먼저 Format String Bug 의미에 대해서 알아보겠습니다

 

먼저 Format String 란 문자열 함수에서 사용하는 형식적인 문자열을 의미합니다.

ex) printf(“hello %s \n”,a); << Format String

 

Format String에는 특수 이스케이프 시퀀스가 존재합니다.

 

먼저 출력유형을 표로 정리 해보았습니다.

인자 출력 유형 참조
%d 10진수
%u 부호 없는 10진수
%x 16진수
%s 문자열 포인터
%n 지금까지 출력한 바이트 수 포인터

 

다음으로 Format String을 올바르게 사용한 예시와 잘못된 예시를 만들어 보겠습니다.

 

올바른 예시

 

잘못된 예시

위 두 파일을 컴파일 하고 실행 해보겠습니다.

 

실행 결과

 

값을 똑같이 주고 실행한 결과 결과는 똑같지 잘 나오게 됩니다.

 

하지만 bad 파일에는 어떠한 값인지 체크하는 부분이 없기 때문에 버그가 발생하게 됩니다.

 

다음 printf의 원형을 통해 알아보겠습니다.

 

printf()의 원형 : int printf(const char *format,...);

const char *format에서 const는 전달된 format 문자열의 값을 printf() 함수 내에서 변화시킬 수 없는, 문자열 상수처럼 사용한다는 것이다.

 

그렇다면 bad 파일에 인자값을 추가로 주고 실행을 해보도록 하겠습니다.

 

 

%x3번 한 것과 %x4번 한 것에 차이는 %x4번을 하니 61616161 (16진수로 a61)

직접 입력한 값(buf)이 나오게 되었습니다.

 

다음으로 %n를 활용하여서 버그가 나오는 것인지 확인해보겠습니다.

 

%n을 활용한 결과

%n이 나오기 전까지 출력된 글자수 계산

스택의 다음 4byte에 있는 값을 주소로 참고하여 글자수 입력

따라서 특정 메모리 주소에 값을 쓴다는 것을 알 수 있습니다.

 

 

지금까지 알아본 결과를 정리해보겠습니다.

 

%x를 이용하여 스택의 값을 읽음.

%n을 이용하여 지정한 곳에 값을 씀.

 

 

결론적으로 RET Shellcode 주소를 덮어 씀으로써 공격이 가능하다는 것을 알 수 있습니다.

 

하지만 ASLR 보호 기법으로 인해서 RET의 주소가 매번 바뀌어서 공격이 불가능 합니다. 이 문제를 해결 하기 위해서 dtros의 영역을 이용하게 됩니다.

 

먼저 GNU COmpiler(gcc)는 컴파일 할 때 ,ctors, .dtors segment를 생성합니다.

 

두 영역의 특징에 대해서 알아보겠습니다.

.ctors - 속성의 함수는 main() 전에 실행 됩니다.

.dtors 속성의 함수는 main() 종료 후에 실행 됩니다.

 

그러므로 main() 종료 후에 .dtors 속성의 함수가 실행되는 것을 이용해서 그 부분을 쉘 코드가 있는 주소 값으로 덮음으로써 쉘 코드가 실행 될 수 있도록 하게 만드는 것입니다.

 

오늘은 여기서 마무리 하겠습니다.

 

다음시간에는 공격을 준비할 수 있는 작업을 하고 실제로 공격하여 결과를 도출해보겠습니다.

 

수고많으셨습니다!