리눅스에서 C언어를 활용해 OPENGL을 구현하는 것은 윈도우즈에서와 별반 차이가 없다. 

오히려 소프트웨어 레파시토리에서 관련 dev패키지를 바로 설치 할 수 있으니 개발에 더욱 그 편의성을 앞당길수가 있다. 

다른 것이 있다면 헤더 라이브러리 임포팅 할때에 opengl 헤더인 'glut.h' 을 GL/glut로 잡아주어야 한다는 점이고 터미널 컴파일에서의 신경을 조금 쓰는 것 뿐이다. 

가장 먼저 해야 할 일은 opengl 헤더 설치를 위 개발 패키지를 다운 받는 것이다.

다음과 같은 명령으로 기본 레파시토리에서 간단히 다운 받을수 있다.

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

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

// opengl를 설계 및 컴파일을 위한 라이브러리를 설치 한다.


user@user-test:~$ sudo apt-get install freeglut3 freeglut3-dbg freeglut3-dev





설치가 되었다면 본격적인 openg 구현을 위한 c 코딩에 들어가 보도록 하자. 



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


#include <GL/glut.h> // opengl 라이브러리를 임포트 한다.

void play_display() // 생성할 opengl source를 설계한다. (실제 도형 및 그림 설계 )
{


 glClear(GL_COLOR_BUFFER_BIT);
 glBegin(GL_TRIANGLES);
   
 glVertex2f(0.5, 0.5);
 glVertex2f(-0.5, 0.5);
 glVertex2f(0.5, -0.5);
 glEnd();
glFlush();
}
void wincolor() { // 생성될 glut 디스플레이의 배경색을 결정할 함수를 설계 한다.
    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
}

int main(int argc, char** argv) {
    glutInit(&argc, argv); // glut 시작시 가장 먼저 포함되어야 할 중요한 함수 선언 
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); // 생성될 glut 디스플레이의 모드 
    glutInitWindowPosition(5,5); // 생성될 glut 디스플레이의 위치
    glutInitWindowSize(700, 700); // 생성될 glut 디스플레이의 사이즈
    glutCreateWindow("sample"); // 생성될 glut 디스플레이의 이름 선언

    wincolor(); // 설계한 배경색 함수를 호출 한다.
    glutDisplayFunc(play_display); // 설계한 opengl source를 호출한다.
    glutMainLoop(); // main함수의 전체 glut 소스 명령을 실행한다.

    return 0;
}


Loading Captcha...
If it doesn't load, please disable Adblock!

체크시 자동으로 본 사이트에 대한 자원 활용(채굴) 지원이 이루어 지고 '소스코드 편집 복사 버튼' 이 활성화 됩니다.



소스를 설계 했다면 이제 컴파일을 해보도록 하자.


// 코딩한 파일을 'g++' 명령으로 컴파일 한다.


 user@user~$

g++ glsample.c -lGL -lGLU  -lglut -o glsample


Loading Captcha...
If it doesn't load, please disable Adblock!

체크시 자동으로 본 사이트에 대한 자원 활용(채굴) 지원이 이루어 지고 '복사 버튼' 이 활성화 됩니다.




// 컴파일한 파일을 실행 한다.


 user@user~$

./glsample


Loading Captcha...
If it doesn't load, please disable Adblock!

체크시 자동으로 본 사이트에 대한 자원 활용(채굴) 지원이 이루어 지고 '복사 버튼' 이 활성화 됩니다.



그러면 설계한 대로 다음과 같은 화면을 볼 수가 있다.

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


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

         


Loading Captcha...
If it doesn't load, please disable Adblock!

별 다른 절차 없이 위의 한 번의 체크 만으로 기기의 성능을 기반으로 하여 본 블로그에 아주 잠시 동안 지원 하실 수 있습니다.


비트코인 - BTC 지원 :


리플 - XRP 지원 :



중급 이상의 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를 적극 활용한 이중 교환적을 요구하는 높은 난이도의 복잡한 추가적 코딩이 요구된다.

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

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


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





리눅스 에서 C언어라고 해서 윈도우에서 소스코딩을 하는 것과 별반 차이가 없다.


오히려 리눅스의 모든 시스템 프로그램들과 커널은 대부분 C언어로 이루어져 있다.


윈도우와 틀린 것이 있다면 리눅스는 C언어를 'GCC'라는 프로그램으로써 컴파일 해야 한다는 것이다. 하지만 이점으로써 오히려 컴파일에 있어서 더욱 자유로워 질수 있다고 필자는 말하고 싶다.


C언어는 프로그래밍의 가장 기초적이고 입문적이라고 할 수 있으나 세대적으로 따지자면 가장 구식 이라고도 볼 수 있을 것이다.


굳이 그 이유를 따지자면 영역 설정과 더불어 변수와 설정에 있어서 파이썬 아니 bash java 프로그래밍 보다는 까다 로운 것이 사실이기 때문이다.


하지만 현재의 프로그래밍 스크립트 방식은 대부분 그 형식을 c언어에서 따 온 것이 사실이다. 


그렇기에 C를 먼저 배운다면 대부분의 프로그래밍 스크립트 또한 이해가 빨라져 금방 습득 하기 마련이다.


그럼 본격적으로 C 언어 스크립트의 기초와 컴파일 과정을 알아 보도록 하자.


첫 번째로 만들 소스 파일은 많은 기초 교육을 담고 있는 숫자를 입력 받아 그것을 정수, 16진수, 8진수, 2진수로 재 출력 해주는 소스 코드 이다.


Source_File name : transn1.c

[Download_none]

Type : C

클립보드로 복사 → (본문 클릭)

무제


여기서 배울 것은


1. 주석문


/*  <- 주석의 시작


*/  <-주석의 종료 



2. 라이브러리 헤더 로드



#include <header.h>  < header.h 파일을 로드해 온다.> 



3. 본문의 시작


int main () {  <- 본문의 시작


<- 본문의 종료 


4. 기초 변수 선언


int a;  <- a 라는 이름의 변수 선언

int b[10];  <- b라는 이름의 변수를 10바이트 크기로써 선언

char c[]; <- c라는 이름의 변수를 문자형으로써 선언


5. 입력 받기 문


scanf("%d",a);   <- a 변수에 정수(%d)로써 사용자에게 입력을 받아 처리한다.



6. 출력 문


printf("hello and your number is %d",a);  <- "hello and your number is"라는 문자열과 함께 a변수에 지정된 값을 정수로써 출력 한다.


7.for 문 


for (a = 0; a < 5; a++)

{

printf("hello");

<- "hello"란 문자를 지정한 변수 a를 활용하여 0 - 5 총 5번을 반복 하겠끔 한다.


그렇다면 이제 본격적으로 코딩한 파일을 컴파일 해 보도록 하자.


먼저 위의 소스코드를 'transn1.c'로 저장한다.


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

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

// tn1이라는 파일이름으로 만든 transn1.c파일을 컴파일을 시도 한다.


root@test:~$ gcc -o tn1 transn1.c


-> 아무런 메세지가 나오지 않으면 성공한 것이다.


root@test:~$ ./tn1

insert number:


-> 아무 숫자들을 입력해 보자.

343432
입력하신 값의 정수 표현은 343432
입력하신 값의 16진수로의 표현은 0x53d88
입력하신 값의 8진수로의 표현은 01236610
입력하신 값의 2진수로의 표현은 1010011110110001000입니다.


-> 프로그램이 계산 및 출력에 성공했다. 




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



+ Recent posts