Tuuna Computer Science

C 코드에 카나리(canary)값 삽입하기 with 인라인 어셈블리 inline assembly 본문

system hacking

C 코드에 카나리(canary)값 삽입하기 with 인라인 어셈블리 inline assembly

GuTTe 2019. 3. 30. 01:57

추가 :  코드 짜면서 인라인 어셈블리에 새로운 것을 많이 알았음

예를 들어 output, input이라던가 등등 첨엔 변수의 값을 어떻게 이동시킬 지 몰랐는데 input쪽에 따로 설정하는 구간을 보고 개놀램.

 

 

학교 과제를 훔쳐보는 도중에 bof 취약점을 어떻게 방어할 것인가를 생각하는 거였는데 이때 bof를 못하게 Canary값을 넣어 방지한느 것은 

이미 알고 있었지만 실제로 구현은 못해봤다.

 

그래서 오늘 한번 해보기로 함. 

 

일단 아래는 문제의 소스이다. 

 

 

32바이트 선언하고 뭐도 없고 BOF그냥 일어난다. 

 

근데 저 코드에 몇 몇의 인라인 어셈블리 코드를 삽입하여(Canary) BOF를 방지해보려 한다. 

 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

//check함수는 카나리값을 확인하여 0이 아니라면 종료시킴
//왜 0이 카나리값 변조가 아니냐면 같은 값끼리 xor하면 0이 나와야하기 때문! 즉, inspector의 값과 ebp-4 에 있는 값과 같아야 0이 나오니

int inspector=0;

void check(int canary)
{
	//printf("%d %d\n",inspector,canary);
	if(canary)
	{
		//printf("%d\n",inspector);
		printf("do you know how to eat banana juice?!\n");
		exit(1);
	}
	else
	{
		printf("OK!\n");
	}
}

void func(int key)
{
	srand(time(NULL));
	inspector = rand()%100000000+1;
	
	__asm__("movl %0, %%eax\n"  //%0(inspector)의 값을 eax레지스터로 이동 
		"pushl %%eax\n" 		//eax레지스터를 스택에 푸시  [ebp-4]: 카나리 위치
		"xorl %%eax, %%eax\n"	//eax 레지스터를 0으로 초기화 
		:
		:"g"(inspector) 		//inspector변수를 %0과 연결 
		);
	
	char overflowme[32];
	
	printf("overflow me : ");
	gets(overflowme); // smash me!
	
	if(key == 0xcafebabe){
		__asm__("movl -4(%%ebp), %%eax\n" //ebp-4에 있는 값을 eax로 이동 
				"xorl %0, %%eax\n"        //%0(inspector)과 eax xor연산 
				"pushl %%eax\n" 		  //결과값 스택에 인자로 푸시 
				"call check\n"			  //함수 호출 
				"addl $4, %%esp\n "       //스택정리 
				:
				:"b"(inspector)           //inspector변수를 %0과 연결 
				);
		system("/bin/sh");
	}
	else{
		printf("Nah..\n");
	}
	asm("popl %eax;");
}

int main(int argc, char* argv[]){
	func(0xdeadbeef);
	return 0;
}

일단 위 코드에서 보이는 것과 같이 func함수에서 gs세그먼트 14번째 세그먼트(?), 오프셋? (이부분에 대해선 아직 정확하게 못봄 이제 봐야징) 

암튼 저 둘중에 하나의 랜덤한 값을 가지고 와서 eax에 넣는다. 

 

그리고 eax는 func함수에서 어떠한 변수도 선언하지 않은 상태에서 push를 하면 카나리값은 언제나 ebp-4 가 된다. 

 

그럼 다음 eax를 0으로 초기화 해준다. 

 

그리고 gets함수로 BOF를 일으켰을 때 조건을 검사하는 어셈블리 루틴을 하나 만들어준다. 

 

바로 아까 불러왔던 카나리(ebp-4)의 값과 gs:0x14에서 다시 가지고 eax에 넣은 값과 XOR연산을 한뒤 

 

 

gs:0x14의 값이 변동되지 않아 그냥 rand함수 돌려서 카나리를 inspector 변수에 넣고 했음.

자세한건 주석 참고

 

결과값을 check함수에 인자로 넣는다. 

 

이때 인자값이 0이면 무사통과 

 

0이 아니라면 이는BOF과정에서 카나리(canary)값을 건드렸다는 증거가 된다. 

 

그래서 exit함수를 호출하게 되고 안정빵! 

 

암튼 이렇게 C 코드내에서 카나리값을 설정해면서 BOF를 방지해봤는데 은근 재밋음.  ㅎ

 

 

gcc -m32 -o bof bof.c -fno-stack-protector -mpreferred-stack-boundary=2

(메모리 보호 해제 옵션) 

Comments