라벨이 프로그래밍인 게시물 표시

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 ...

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 함수 호출 시 생성되는 지역 변수, 매개변수, 반환 주소 등을 저장하는 메모리 영역이다. ...