컴퓨터 구조

태그
생성 일시
Jun 19, 2026 08:16 AM
최종 편집 일시
Last updated June 19, 2026
Date

자료형 사이즈 확인하기

#include <stdio.h> int main() { printf("Size of char: %zu bytes\n", sizeof(char)); printf("Size of short: %zu bytes\n", sizeof(short)); printf("Size of int: %zu bytes\n", sizeof(int)); printf("Size of long: %zu bytes\n", sizeof(long)); printf("Size of long long: %zu bytes\n", sizeof(long long)); printf("Size of float: %zu bytes\n", sizeof(float)); printf("Size of double: %zu bytes\n", sizeof(double)); printf("Size of long double: %zu bytes\n", sizeof(long double)); printf("Size of pointer: %zu bytes\n", sizeof(void*)); return 0; }
출력

문자열 오버플로우

#include <stdio.h> #include <limits.h> int main() { char value = CHAR_MAX; printf("Original value: %d\n", value); value = value + 1; printf("Value after adding 1: %d\n", value); return 0; }
 

비트연산

특정 위치의 비트 값이 1인지 확인하는 함수

int is_bit_set(unsigned char value, int position) { return (value & (1 << position)) != 0; }
특정 위치가 1인 마스크 생성 (1 << position)
and 연산으로 두 비트를 곱함
만약 원본 비트가 1이라면 1&1 != 0

특정 위치의 비트를 1로 설정하는 함수

unsigned char set_bit(unsigned char value, int position) { return value | (1 << position); }
특정 위치가 1인 마스크 생성 (1 << position)
or 연산으로 두 비트를 곱함
마스크에 의해 하나 이상의 1이 존재 → 1 | x[0,1] = 1

특정 위치의 비트를 끄는 함수

unsigned char clear_bit(unsigned char value, int position) { return value & ~(1 << position); }
특정 위치가 1인 마스크 생성 (1 << position)
not 연산으로 마스크를 뒤집음 ~
특정 위치만 마스크가0 이고 나머지는 1 때문에, and 연산시 원하는 위치만 0 으로 처리됨

검증하기

#include <stdio.h> int main() { unsigned char value = 0b00001000; // 예: 3번째 비트만 1입니다. // 3번째 비트가 설정되어 있는지 확인 if (is_bit_set(value, 3)) { printf("3rd bit is set!\n"); } else { printf("3rd bit is not set!\n"); } // 2번째 비트를 설정 value = set_bit(value, 2); printf("Value after setting 2nd bit: %d\n", value); return 0; }

실습

오버플로우 예제를 언더플로우로 바꿔보자

#include <stdio.h> #include <limits.h> int main() { char value = CHAR_MIN; printf("Original value (CHAR_MIN): %d\n", value); value = value - 1; printf("Value after subtracting 1: %d\n", value); return 0; }

컴파일 과정 실습

notion image

전처리 과정 (.i 파일 확인하기)

gcc-E hello_world.c-o hello_world.i

컴파일 과정 (.s 파일 확인하기)

gcc-S hello_world.i-o hello_world.s

어셈블 과정 (.o 파일 확인하기)

gcc-c hello_world.s-o hello_world.o
오브젝트 파일(.o)이란?
소스 코드가 컴파일된 후의 중간 결과물로, 링커에 의해 실행 가능한 바이너리나 라이브러리로 만들어지기 전의 형태입니다.

오브젝트 파일의 주요 특징

  • 바이너리 형태: 기계어 코드를 포함하는 바이너리 파일입니다. 그러나 이 파일 자체로는 실행될 수 없으며, 다른 오브젝트 파일이나 라이브러리와 링크되어야 비로소 실행 가능한 바이너리가 됩니다.
  • 재배치 가능: 다른 오브젝트 파일이나 라이브러리와 링크되어 완전한 프로그램을 형성합니다. 이 과정에서 링커는 각각의 변수나 함수 참조를 올바른 메모리 주소나 함수로 연결해 줍니다.
  • 심볼 테이블: 파일 내에 심볼 테이블을 포함합니다. 이는 파일 내의 각 함수나 변수의 이름과 위치 정보를 나타내며, 링커가 다른 파일들과 링크 작업을 수행할 때 참조하는 중요한 정보입니다.
  • 플랫폼 및 컴파일러 특정: 특정 아키텍처, 운영 체제, 컴파일러에 따라 형태가 다릅니다. 대표적인 확장자로는 UNIX/Linux 시스템에서는 .o, Windows에서는 .obj를 사용합니다.

파일 분석 도구

1. readelf

  • 전용 도구: ELF 파일 형식에 특화된 분석 도구로, ELF 파일의 모든 섹션과 헤더 정보를 아주 자세히 확인할 수 있습니다.
  • 출력 형식: 분석 결과를 사람이 읽고 이해하기 쉬운 텍스트 형식으로 제공합니다.
  • 주요 기능: ELF 파일의 헤더, 섹션 헤더, 프로그램 헤더, 심볼 테이블, 노트 섹션 등의 세부 정보를 화면에 표시합니다.

2. objdump

  • 다기능 도구: ELF 파일뿐만 아니라 다른 포맷의 바이너리 파일 분석에도 범용적으로 사용할 수 있는 도구입니다.
  • 디스어셈블 (Disassemble): 가장 강력한 기능 중 하나로, 바이너리 형태의 기계어 코드를 어셈블리 언어로 변환(디스어셈블)하여 보여줍니다. 이를 통해 프로그램의 내부 동작을 직접 코드로 뜯어볼 수 있습니다.
  • 다양한 정보 제공: 바이너리의 헤더 정보, 섹션 내용, 심볼 테이블은 물론 공유 라이브러리 의존성, 재배치 정보 등 폭넓은 정보를 확인할 수 있습니다.

바이너리 파일 정보 분석 결과

  1. ELF (Executable and Linkable Format)
      • 유닉스 및 유닉스 기반 운영체제에서 사용되는 표준 바이너리 파일 포맷입니다.
      • 주로 실행 파일, 오브젝트 파일, 공유 라이브러리 등에 사용됩니다.
  1. 64-bit
      • 해당 파일이 64비트 아키텍처 시스템 환경에 맞춰 컴파일되었음을 의미합니다.
  1. LSB (Least Significant Byte)
      • 리틀 엔디안(Little Endian) 방식의 바이트 정렬 순서를 사용한다는 뜻입니다.
  1. relocatable
      • 재배치가 가능한 오브젝트 파일임을 나타냅니다.
      • 즉, 링커(Linker)를 통해 다른 오브젝트 파일이나 공유 라이브러리와 결합(Link)될 수 있는 상태입니다.
  1. x86-64
      • 이 파일이 인텔의 x86-64 (또는 AMD64) CPU 아키텍처에서 동작하도록 컴파일되었음을 알려줍니다.
  1. version 1 (SYSV)
      • 사용된 ELF 포맷의 버전과 변형 종류를 나타냅니다. 여기서 SYSV는 System V 유닉스 규격을 뜻합니다.
  1. not stripped
      • 디버깅 정보나 심볼 테이블 등의 부가 정보가 파일 내에 그대로 포함되어 있는 상태입니다.
      • 참고로 "stripped" 상태는 파일 용량 최적화를 위해 이러한 부가 정보를 제거한 것을 의미합니다.

(.o)파일과 실행파일 비교하기

notion image

gdb 사용해 보기

명령어
설명
gcc -o char_overflow char_overflow.c -g
디버깅 심볼(-g)을 포함하여 프로그램 컴파일
gdb char_overflow
GDB 디버거로 해당 프로그램 열기
b main
main 함수에 중단점(Breakpoint) 설정
r
프로그램 실행 (Run)
n
다음 줄 실행 (Next)
p value
p [변수명] : 변수값 출력 (Print)
p/t value
p /[출력형식] [변수명] : 지정한 형식에 맞추어 변수값 출력 (여기서 t는 2진수 의미)