C언어 - 코드 분석 연습 (중급 예제)

1. C언어 코드 분석 중급 예제 1.1. 포인터의 크기와 길이 문자열 리터럴을 가리키는 문자 포인터의 동작을 이해한다. sizeof 와 strlen 이 서로 다른 기준으로 값을 계산 한다는 것을 확인한다. #include <stdio.h> #include <string.h> int main ( void ) { char * text = " 0123456789 " ; size_t result = sizeof (text) + strlen (text); printf ( "%zu\n" , result); return 0 ; } char *text 는 문자열 내용을 저장하는 배열이 아니라 문자열 리터럴의 시작 주소를 저장하는 포인터이다. sizeof(text) 는 포인터 변수 자체의 크기이며, 가리키는 문자열 길이와 다르다. strlen(text) 는 포인터가 가리키는 위치부터 '\0' 을 만나기 전까지의 문자 수를 센다. 포인터 크기는 실행 환경에 따라 달라질 수 있으며, 64비트 환경을 기준으로 설명한다. 1.2. 포인터 산술 배열 이름은 배열의 첫 번째 원소 주소를 나타내는 값처럼 동작하기 때문에 배열 이름을 포인터처럼 사용할 수 있다. 포인터에 +1을 하면 단순히 1만큼 이동하는 것이 아니라, 자료형 크기만큼 이동 하여 다음 배열 원소를 가리키게 된다. 즉, 배열 이름은 시작 주소 역할을 하며, 포인터 연산을 하면 배열의 다음 칸으로 이동하는 것과 같은 의미이다. #include <stdio.h> int main ( void ) { int nums[] = { 4 , 8 , 15 , 16 , 23 , 42 }; int *p = nums + 1 ; int result = *(p + 2 ) + p[- 1 ]; printf ( "%d...

C언어 - 포인터를 이용한 함수 인자

이미지
1. C언어의 함수 인자 프로그래밍 언어의 함수 인자 전달 방법에는 값에 의한 전달( Call by Value ) 방법과 참조에 의한 전달( Call by Reference ) 방법이 있다.  그런데 C언어에서 함수의 인자 전달은 항상 Call by Value  방식이다. 즉, 함수에 전달되는 값은  복사본 이며, 함수 내부에서 원본 변수에 직접 접근할 수는 없다. 이러한 이유로 포인터를 사용하여 변수의 주소를 값으로 전달하는 방법으로 Call by Reference 효과 를 얻고 있다. 1.1. 함수 인자 전달 방식 방식 전달 내용 원본 변경 Call by value 변수의 값 불가 Call by reference 변수의  주소 가능 1.1.1. Call by Value Call by Value는 인자로 전달되는 값의  복사본을 함수에 전달하는 방식 이다. 따라서, 함수 내부에서 값을 변경하더라도, 원본 변수에는 아무런 영향을 미치지 않는다. 1.1.2. Call by Reference Call by Reference는 포인터로  변수의 실제 주소를 전달하는 방식 이다. 이 방식으로는 함수로 전달된 주소를 통해 원본 변수의 주소에 접근할 수 있으며, 원본 변수의 값을 변경하는 것도 가능하다. C언어에서는 이러한 참조 전달(Call by Reference)을  포인터(pointer)를 사용하여 구현한다 . C 언어에서 Call by Reference는  포인터를 이용해 주소를 전달하는 방식 으로 이해할 수 있다. 1.2. 함수 인자 전달 예제 #include <stdio.h> /* receives a copy, caller's variable is unchanged ...

아무것도 신뢰하지 않고 검증한다. Zero Trust 보안이란?

이미지
1. 제로 트러스트의 시작 1.1. Zero Trust 란 Zero Trust는 " 기본적으로 아무것도 신뢰하지 않고(never trust), 모든 접근을 지속적으로 검증(always verify)하는 보안 모델 " 이다. 1.1.1. Never Trust, Always Verify 절대 신뢰하지 말고, 항상 검증하라 사용자, 기기, 네트워크 위치를 기본적으로 신뢰하지 않는다. 내부망이라도 안전하다고 가정하지 않는다. 모든 접근 요청에 대해 항상 인증(Authentication)과 인가(Authorization)를 수행한다. 1.1.2. Least Privilege Access 최소 권한 원칙 사용자에게 업무 수행에 필요한 최소한의 권한만 부여한다. 불필요한 접근 권한은 허용하지 않는다. 1.1.3.  Assume Breach 침해를 가정하라 시스템이 이미 공격당했을 가능성을 전제로 설계한다. 공격이 발생해도 확산되지 않도록 설계한다. 1.2. Zero Trust 시작 배경 2010년, ‘ 오퍼레이션 오로라(Operation Aurora) ’라는 대규모 사이버 공격 사건이 발생하였다. 사건 개요: 이 공격은 구글을 포함한 20개 이상의 주요 IT 기업을 대상으로 한 대규모 APT( 지능형 지속 위협) 공격 이었다. 공격 수법: 웹 브라우저인 인터넷 익스플로러의 제로데이 취약점 을 악용한 ‘드라이브 바이 다운로드(Drive-by Download)’ 방식이 사용되었다. 공격 대응: 이 공격으로 큰 피해를 입은 구글은 기존의 네트워크 경계 기반 보안 모델만으로는 고도화된 사이버 공격을 방어하기에 한계가 있다고 판단하였다. 이에 따라 구글은 약 8년에 걸쳐  모든 접근을 검증하는 제로 트러스트(Zero Trust) 아키텍처로 인프라를 재설계  하였다. 이후 2014년, 그 성과를 ‘ 비욘드코프 (BeyondCorp)...

C언어 - 버퍼 오버플로우(Buffer Overflow) 취약점의 이해

이미지
1. Buffer Overflow 1.1. 보안 취약점 1.1.1. 발생 원인 Buffer Overflow는 버퍼의 크기를 초과하여 데이터를 기록하면서 인접한 메모리를 덮어쓰는 보안 취약점 이다. 버퍼의 경계를 넘어 데이터를 쓰면서 인접한 메모리를 덮어쓰게 된다. 1.1.2. 영향 및 위험성 프로그램이 비정상 종료(Crash) 되거나 오류가 발생할 수 있다. 중요한 데이터가 손상되어 예기치 않은 동 작이 발생할 수 있다. 공격자가 메모리를 조작하여 임의 코드 실행 또는 시스템 제어권을 탈취 할 수 있다. 1.2. Stack Buffer Overflow Stack Buffer Overflow는 Stack 영역에 할당된 버퍼의 크기를 초과하여 데이터를 쓰면서, 인접한 메모리 영역을 덮어쓰는 취약점이다. 주요 원인은 입력 길이에 대한 검증 부족과 경계 검사를 수행하지 않는 취약한 함수 사용에 있다. # include <stdio.h> # include <string.h> # include <stdlib.h> // Demonstrate stack buffer overflow: // Stack layout: [buffer 16 bytes][cmd 16 bytes] static void vulnerable ( const char *input) { char cmd[ 16 ] = "date"; // default command to execute char buffer[ 16 ]; // overflow target (no bounds check) // VULNERABLE: strcpy does not check input length. // Input longer than 16 byte...

C언어 - 포인터 이해하기

이미지
1. C언어 포인터 C언어의 포인터(pointer)는 메모리 주소를 저장하는 변수이다. 데이터가 있는 "위치"(주소) 를 저장 한다. #include <stdio.h> #include <string.h> #include <stdlib.h> int main() { const char *pstr = "Hello World!"; char *ptr = NULL ; const size_t len = strlen (pstr); ptr = malloc (len + 1); memset (ptr, 0x00, len + 1); memcpy (ptr, pstr, len); printf ("%p[%p] → %s\n", &ptr, ptr, ptr); free (ptr); return 0; } ptr 포인터 변수는 Stack 영역 에 존재한다. malloc 을 사용하여 Heap 영역 에 메모리 공간을 할당하고, 그 주소를 Stack 영역 ptr 변수에 저장한다. memcpy 를 통해 "Hello World!" 문자열 데이터를 Heap 영역 의 할당된 공간에 복사한다. 0x7ffffc12fd50[0x5a14a05396b0] → Hello World! &ptr 은 포인터 변수 자체의 주소이고, ptr 변수에 저장된 주소에 문자열 데이터가 저장된다. 포인터는 데이터를 직접 저장하지 않고, 데이터가 저장된 메모리 주소를 저장한다. 1.1. Stack vs. Heap 1.1.1. Stack 함수 호출 시 생성되는 지역 변수, 매개변수, 반환 주소 등을 저장하는 메모리 영역이다. ...