중급 이상의 c언어 프로그래밍 개발자라면 파일 시스템의 활동 상태를 감시할수 있는 inotify 함수 응용에 대해서 알고 있을 것이다. 

본 포스팅은 리눅스에서 inotify를 응용한 C언어 코딩과 그 안의 시스템 함수를 응용 하여 쉘 컨트롤을 중첩 활용한 '디펜드 파일시스템 '를 설계하고 구현해 보고 '파일 시스템 방어 구축'에 관한 그 가능성을 짚어 보도록하는 데에 그 취지가 있다. 

우선 전체적인 원리는 단순하다.


글씨를 참 못쓴다. 누가 보면 초딩인줄 알겠다..... 참 나는 전자펜 으로 그리는 데에는 아직(?) 재주가 없다. 



중요한 것은 본 프로그래밍 가이드에 필요한 모듈에 필요한 함수가 의외로 많다는 것이고 특별한 헤더에는 "sys/inotify.h(파일 시스템 감독)" , "setjmp.h(지점 "sys/types.h (타입 파악)" 이 있다.

자 그렇다면 본격적인 프로그래밍을 해보도록 하자.

                 Source_File name : dfs.c             |             Type : C                  |                        |           


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define _Event_		( sizeof (struct inotify_event) )	/* Inotify 함수의 이벤트 처리를 위한 전처리 지정 */
#define Buffer_size	( 1024 * ( _Event_ + 64 ) )

jmp_buf point;	/* setjmp 모듈을 활용할 변수 지정 */

int main( int argc, char **argv ) {
	setjmp(point);	/* setjmp 함수 당 포인트를 셋팅 한다. */
	FILE *Write_file;	/* 로그 파일을 기록하기 위한 변수 선언 */

	char Fs_Path[4092]; /* 감시할 파일 경로를 입력받을 변수 */
	strcpy(Fs_Path, argv[1]);
	
	int ii;		/* 각 버퍼 사이즈 비교 대입 값을 위한 변수 */
	
	int Inotify_Buff; /* inotify 함수를 대입할 고정 버퍼값을 위한 변수 */
	
	char buffer[Buffer_size];	
	
	ii = inotify_init();	/* inotify 모듈을 초기화 로드 한다. */
	
int Back_Target() {
		char cpcon[2048] = "cp -rf ", bakpath[] = " /tmp/bak_path"; 	/* 파일 백업을 만들 변수 */
		system("rm -rf /tmp/bak_path");
		strcat(cpcon, Fs_Path);
		strcat(cpcon, bakpath);
		system(cpcon); /* 타겟 파일 백업을 만든다. */
	}
int syscon() {		/* 이벤트 발생시 해당 파일을 복원할 파일 시스템 제어 기초 함수 설계 */ 
		
		/* 시작 기존의 백업 파일을 삭제 */
		
		char Remove_Target[2048] = ("rm -rf ");		
		strcat(Remove_Target, Fs_Path);
		system(Remove_Target);
		
		/* 완료 기존의 백업 파일을 삭제 */
		
		/* 시작 변동시 복원을 위한 작업 */
		
		char Restore[2048] = "cp -rf /tmp/bak_path ";
		strcat(Restore, Fs_Path);
		system(Restore);
		
		/* 완료 변동시 복원을 위한 작업 */
		
		/* 시작 작업 내용 출력 및 시작 로그 기록 */ 
		
		Write_file = fopen("dfs.log", "a");
		fprintf(stderr,"\nTarget ' %s ' has restored.\n\n", Fs_Path);
		fprintf(Write_file, "Target ' %s ' has restored.\n\n", argv[1]);
		fclose(Write_file);
		
		/* 완료 작업 내용 출력 및 시작 로그 기록 */
	}


	if (ii < 0) {		/* 버퍼 비교에 의한 inotify 함수 초기화 */
		perror("inotify_init");
	}
	else
	
	system("date -R >> dfs.log; echo Defending_Start >> dfs.log");	/* 날짜 출력과 함께 로그 기록을 생성하고 시작 (존재 할시 이어서 기록한다. */
	
	if (argc < 2 ) { 	/* 외부 인자 값의 유.무를 파악 하여 작업 선언 */
		printf ("Do not start defend file system... Please running with insert Target path.\n\n BYE~!\n");
		exit (0);
	} else {
	
		if ( access(Fs_Path, F_OK) == -1 ) { /* 타겟 파일의 존재를 파악하여 없다면 종료 시킨다. */
			fprintf(stderr, "Target %s does not exist... to EXIT.", Fs_Path);
			exit (0);
		} 
	
		fprintf (stderr, "Defending start... \n File path = '%s' of systems\nIf you wnat exit to 'CTRL +C'.\n", argv[1]);

		Back_Target();	/* 타깃 파일을 백업 한다. */
	}
	
	Inotify_Buff = inotify_add_watch(ii, argv[1], IN_MODIFY | IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO | IN_MOVE_SELF);	/* inotify 각 이벤트 발생에 따른 함수 실행을 위한 변수 지정 */
	
	while(1) {	/* 지정한  타겟 파일에 대한 반복 감시 시작 */ 
		int origin_size, i = 0;
		origin_size = read(ii, buffer, Buffer_size);
		if (origin_size < 0) {
			perror("read");
		}
		
		while ( i < origin_size ) {	/* 이벤트 발생을 위한 반복 수행 */
			struct inotify_event *event = (struct inotify_event *) &buffer[i];	

			fprintf(stderr, "\nVariance check = Wd : %d , Mask : %d , Cookie : %d , Length : %d , Type : %s\n\n", event->wd, event->mask, event->cookie, event->len, (event->mask & IN_ISDIR)?"Directory":"File");	/* 타깃 파일에 대한 변화를 감지 하여 변화된 실제 파일의 타입을 출력하고 로그를 기록한다. */
			
			system("date -R >> dfs.log");
			
			Write_file = fopen("dfs.log", "a");
			
			fprintf(Write_file, "\nVariance check = Wd : %d , Mask : %d , Cookie : %d , Length : %d , Type : %s\n\n", event->wd, event->mask, event->cookie, event->len, (event->mask & IN_ISDIR)?"Directory":"File");	/* 변화된 사항과 만일 타깃 디렉터레에 추가된 사항이면 그것이 어떤 타입인지 확인 */
			
			fclose(Write_file);

			if (event->mask & IN_CREATE) {	/* 타깃 디렉터리에서 파일이나 디렉토리가 생성 되었을 경우 이벤트 처리 */
			
				printf("\n %s was created. at Watching in Target Directory.\n\n", event->name);
				
				/* 시작 출력과 출력 로그를 기록한다. */
				
				Write_file = fopen("dfs.log", "a");
				fprintf(Write_file, "\n %s was created in Target Directory. \n\n", event->name);
				fclose(Write_file);
				syscon();
				}
				
				/* 완료 출력과 출력 로그를 기록한다. */
				
			else if (event->mask & IN_DELETE || IN_DELETE_SELF) {	/* 타깃에 삭제가 발생할 경우 이벤트 처리 */

				printf(" %s was deleted at Watching Target.\n", event->name);
						
				Write_file = fopen("dfs.log", "a");
				fprintf(Write_file, " %s was deleted at Watching Target. \n", event->name);
				fclose(Write_file);
				syscon(); 
				}
				
			else if (event->mask & IN_MODIFY ) {	/* 타깃에 변동이 발생 되었을 경우 이벤트 처리 */ 

				printf(" %s was modified at Watching Target.\n", event->name);
				Write_file = fopen("dfs.log", "a");
				fprintf(Write_file, "%s was created. at Watching Target of file system.\n", event->name);
				fclose(Write_file);
				syscon(); 
				}

			else if (event->mask & IN_MOVED_FROM || event->mask & IN_MOVED_TO || event->mask & IN_MOVE_SELF) {	/* 타깃에 대한 이동 발생시 이벤트 처리 */

				printf("%s was moved at Watching Target.\n", event->name);
				Write_file = fopen("dfs.log", "a");
				fprintf(Write_file, "%s was moved at Watching Target.\n", event->name);
				fclose(Write_file);
				syscon(); 
				}
			i = 0;
			longjmp(point, 1);	/* jmp 셋팅한 지점으로 다시 되돌아 간다. */
			}
		}
	return 0;
	}



코딩이 완료 되었으면 컴파일 하고 실행해 보자.

-- 터미널 텍스트 박스 (Terminal text box) --

<Drag와 복사가 가능합니다.>

// 해당 파일을 컴파일 한다.


user@user-test:~$ gcc -f dfs dfs.c


// 컴파일된 프로그램을 실행해 본다.


user@user-test:~$ gcc -f dfs dfs.c


Do not start defend file system... Please running with insert Target path.


-> 하지만 코딩 했던것 처럼 인자값이 입력 되지 않으면 종료 된다.



이제 본격적으로 방어 능력을 테스트해 보자.




-- 터미널 텍스트 박스 (Terminal text box) --

<Drag와 복사가 가능합니다.>

// 아무 파일을 만든다.


user@user-test:~$ echo 1 > /tmp/a

 

// 만든 파일을 실행과 함께 인자값으로 지정한다.


user@user-test:~$  ./dfs /tmp/a


Defending start... 
 File path = '/tmp/a' of systems
If you wnat exit to 'CTRL +C'.


-> 라는 문구와 함께 해당 파일에 대한 감시 및 방어를 시작한다.

// 다른 터미널을 열어 만든 파일을 변조해 공격해 보자.


user@user-test:~$ echo 2 > /tmp/a


Variance check = Wd : 1 , Mask : 2 , Cookie : 0 , Len : 0 , Type : File


Target ' /tmp/a ' has restored.

Defending start...
 File path = '/tmp/a' of systems
If you wnat exit to 'CTRL +C'.

->  변경된 속성과 타입 출력, 그리고 복원했다는 메시지가 나온다.


// 정말 복원 되었는지 확인해 보자.


user@user-test:~$ cat /tmp/a


1

-> 아까 입력한 대로 '1' 을 출력하였고 복원에 성공한 것을 확인했다.



그렇다면 이젠 디렉토리 복원을 테스트해 보자.

-- 터미널 텍스트 박스 (Terminal text box) --

<Drag와 복사가 가능합니다.>

// 먼저 폴더를 만들고 파일 하나도 같이 만들자.


user@user-test:~$ mkdir /tmp/1 ; echo 1 > /tmp/1/2


// dfs로 디렉토리 방어를 시작해 보자


user@user-test:~$ ./dfs /tmp/1

Defending start...
 File path = '/tmp/1' of systems
If you wnat exit to 'CTRL +C'.


// 터미널을 새로 열고 변조를 통해 공격을 시도해 보자.


user@user-test:~$ rm /tmp/1/2


Variance check = Wd : 1 , Mask : 512 , Cookie : 0 , Len : 16 , Type : File


 2 was deleted at Watching Target.

Target ' /tmp/1 ' has restored.

Defending start... 
 File path = '/tmp/1' of systems
If you wnat exit to 'CTRL +C'.


-> 파일 '2'가 삭제 되었고 복원 하였다는 메시지가 출력한다.


// 마찬가지 복원을 확인하자.

user@user-test:~$ cat /tmp/1/2

1


-> 복원 성공을 확인할 수 있다. 



// 이번에는 타겟 폴더에 폴더를 생성해 보자.


user@user-test:~$ mkdir /tmp/1/3

Variance check = Wd : 1 , Mask : 1073742080 , Cookie : 0 , Len : 16 , Type : Directory



 3 was created. at Watching in Target Directory.


Target ' /tmp/1 ' has restored.

Defending start...
 File path = '/tmp/1' of systems
If you wnat exit to 'CTRL +C'.


-> '3' 폴더가 만들어 졌지만 복구 했다는 메세지가 출력 된다.



// 정말 복원 되었는지 확인하자.


user@user-test:~$ cd /tmp/1/3


-bash: cd: /tmp/1/3: 그런 파일이나 디렉터리가 없습니다


-> 정말 만든 폴더가 복원, 방어 되어 존재 하지 않는 것을 확인 할 수 있다. 


이뿐만이 아니라 해당 프로그램은 코드에서 봤다 시피 'dfs.log' 파일에 시간과 함께 작업 모든 기록을 보관 하고 있다.


-- 터미널 텍스트 박스 (Terminal text box) --

<Drag와 복사가 가능합니다.>

// 지금까지 작업한 로그 기록을 확인해 보자.


user@user-test:~$ cat dfs.log



이로써 C언어로 설계한 디펜드 파일 시스템이 정상적으로 성능을 발휘 할 수 있는 것을 확인 할 수 있지만 코드를 보아서 알다시피 전지전능한 프로그램은 아니기에 폴더 안의 폴더 안에 발생하는 이벤트를 처리 하지는 못한다. 이를 해결하려면 더 추가적인 코딩이 필요하다.

또 마찬가지 실행시 마다 백업 경로를 단일로 갈아 치우는 단순한 방법을 사용 하기 때문에 이 프로그램을 활용하여 여러 프로세스로 실행해 실제 파일 시스템의 여러 중요 파일들을 한번에 방어 하지 못한다. 마찬가지 실전용으로 만들려면 bash를 적극 활용한 이중 교환적을 요구하는 높은 난이도의 복잡한 추가적 코딩이 요구된다.

하지만 이러한 방식으로 말미앎아 파일 시스템을 직접적으로 방어 할 수 있는 새로운 방식의 보안 시스템을 구축 할 수 있다는 것을 선 보인 좋은 계기가 될 것이며 파일을 변조 및 암호화 하여 비트코인을 달라 하는 랜섬웨어 악성코드 발동도 결과적으로 방어 할 수 있는 이상적 시스템을 구상할 수가 있다.

도움이 되셨다면 '♡' 버튼을 꼭눌러 주시면 감사 하겠습니다.


그리고 글에 부족한 점이 있거나 틀린점이 있는 것 같다면 꼭 댓글로 알려 주시면 감사 하겠습니다.



+ Recent posts