새소식

인기 검색어

TL

21/04/04 TL. FSB를 이용한 공격

  • -

FSB를 이용한 공격을 수행해 본다. 그 전에 printf()를 호출하기 직전에 Stack에 저장되는 구조를 알아야 한다.

#include<stdio.h>
int main(){
	int a=10;
	int b=20;
	printf("A:%d, B:%d and B's address: %08x\n",a,b,&b);
	return 0;
}

포맷스트링이란 변수의 출력 형태를 결정하는 것이다.

%d : 10진수, %u : 부호 없는 정수, %x : 16진수, %p : 주소출력, %c : 1byte(문자 하나), %s : 문자열(a에 대한 주소부터 0x0까지), %l = 8byte

다음과 같은 코드를 실행하면, A와 B의 값을 알려주고 B의 주소를 알려준다.

 

우선 이번에도 ASLR을 해제하자. 코드는 다음과 같다.

sudo sysctl -w kernel.randomize_va_space=0

 

disass main으로 main 함수를 disassemble하고, print하기 전에 Stack 구조와, regi에 어떤 값들이 들어가 있는지 확인하자.

현재 printf를 실행할 때는 인자를 4개 받는다. 각각 String, A, B, B의 주소 값이 들어있다.

 

이제 Format String에 대한 이해를 돕기 위한 코드를 분석하자.

#include <stdio.h>
int main(){
	int buf[30];
	gets(buf);
	printf(buf);
	printf("\n%s\n",buf);
	return 0;
}

간단하게 말하면, buffer(4 * 30)을 만들어 버퍼 값을 보는 코드이다. 그런데 해당 코드에선 print할 때 필요한 인자가 부족하다. 그렇게 되면 출력할 형태를 지정해주지 않았기 때문에 공격자가 원하는 값을 넣을 수 있어 취약한 코드가 된다.

컴파일한 뒤, aaaa만 실행하면 은 값이 2번 나온다.
컴파일한 뒤, aaaa만 실행하면 같은 값이 2번 나온다. 그러나, 이런 식으로 메모리 값을 읽어올 수도 있다.

 

gdb를 이용해 열어보니, esp 처음엔 buffer의 주소를 담고 있다.

esp 값을 봤을 때, 2번째 들어있는 값이 0x00000001이다. 이건 Stack의 값이다. 아까 전 %x를 수행헀을 때 나왔던 1과 같다. 즉, 이런 식으로 메모리 주소를 들여다볼 수 있다는 말이다.

 

같은 식으로, %x 를 10개 넣고 수행한다면, 메모리를 10개 들여다볼 수 있다.

이제는 %n이 어떤 역할을 하는지 알아보자.

 

#include <stdio.h>
void main () {
	int num = 0;
	char buf[100];
	gets(buf);
	printf("buf=%s%n", buf, &num);
	printf("\nnum=%d\n", num);
}

다음 코드는 사용값을 저장해서 출력하는 코드이다. 여기서 %n은 지정한 변수에 데이터 쓰기가 가능한 format string이다.

"buf=aa" 총 6byte가 num에 들어간다.

따라서 해당 프로그램의 %n을 이용해서 원하는 임의의 값을 num에 넣을 수 있다.

 

마지막 실습으로 FSB를 이용해서 num 값을 7777로 overwrite하고 Success를 출력하게 하는 코드를 수행해보자.

#include <stdio.h>
int num =1111;
int main(void)
{
	char buf[20];
	gets(buf);
	printf(buf);
	puts("");
	if(num == 7777)
		printf("Success!!\n"); // Can you print me?!
	else
		printf("fail..\n");
	printf("num : %d\n",num);
}

 

Stack에 들어있는 값들이다.

여기서 little endian으로 읽기 때문에, buffer의 시작인 30303030부터, 25 78 20... 이렇게 들어가는데, ASCII 코드표를 보면 30 : 0, 25 : %, 78 : x, 20 : (space) 이다. "즉, %s "가 계속 들어가고 있다는 뜻이다. 그리고, Stack에서 $esp부터 6개 만큼 떨어져 있기 때문에 24byte 만큼 떨어져 있는 곳이 Buffer의 주소인 것을 알 수 있다.

num의 주소를 찾을 수 있다.

elf는 linux의 실행파일이다. windows에서 실행파일(바이너리)파일이라고 생각하면 된다. readelf를 사용하면 compile된 binary를 분석해서 정보를 알려준다.

 

그래서 정답은

가 된다.

4 + 3 + 8 * 4 + 1 + 7736 = 7777

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.