컴파일러는 변수의 자료형을 참고하여 변수에 관한 코드를 생성한다.
한 번 정의된 변수의 자료형은 바꿀 수 없다. 1바이트 크기의 변수에 1을 더하다가 그 값이 0xff를 넘어서게 되면, 0x100이 되는 것이 아니라 0x00이 된다. 이런 현상을 데이터가 넘쳐서 유실됐다고 하여 overflow라고 부른다.
마찬가지로 변수의 크기보다 큰 값을 대입하려 할 때도 데이터가 유실될 수 있다. 예를 들어 4바이트 크기의 변수에 0x0123456789abcdef를 대입하면 하위 4바이트인 0x89abcdef만 저장되고 나머지 값은 모두 버려진다.
1. 자료형
| 자료형 | 크기 | 범위 | 용도 |
| (signed) char | 1바이트 | 정수, 문자 | |
| unsigned char | |||
| (signed) short (int) | 2바이트 | 정수 | |
| unsigned short (int) | |||
| (signed) int | 4바이트 | 정수 | |
| unsigned int | |||
| size_t | 32bit: 4바이트 64bit: 8바이트 |
생략 | 부호 없는 정수 |
| (signed) long | 32bit: 4바이트 64bit: 8바이트 |
정수 | |
| unsigned long | |||
| (signed) long long | 32bit: 8바이트 64bit: 8바이트 |
정수 | |
| unsigned long long | |||
| float | 4바이트 | 실수 | |
| double | 8바이트 | 실수 | |
| Type * | 32bit: 4바이트 64bit: 8바이트 |
주소 |
type error: 변수를 선언할 때 변수를 활용하는 동안 담게 될 값의 크기, 용도, 부호 여부 등을 고려 없이 부적절하게 사용했을 때 발생
ex) type.c
//Name: type.c
//Compile: gcc -o type type.c
#include <stdio.h>
T factorial(unsigned int n) {
T res = 1;
for (int i = 1; i <= n; i++) {
res *= i;
}
return res;
}
int main() {
unsigned int n;
printf("Input integer n: ");
scanf("%d", &n);
if (n >= 50) {
fprintf(stderr, "Input is too large");
return -1;
}
printf("Factorial of N: %llu\n", factorial(n));
}
T는 unsigned long long
2. out of range: 데이터 유실
// Name: out_of_range.c
// Compile: gcc -o out_of_range out_of_range.c
#include <stdio.h>
unsigned long long factorial(unsigned int n) {
unsigned long long res = 1;
for (int i = 1; i <= n; i++) {
res *= i;
}
return res;
}
int main() {
unsigned int n;
unsigned int res;
printf("Input integer n: ");
scanf("%d", &n);
if (n >= 50) {
fprintf(stderr, "Input is too large");
return -1;
}
res = factorial(n);
printf("Factorial of N: %u\n", res);
}
-> 18에서 값이 작아짐
$ ./out_of_range
Input integer n: 17
Factorial of N: 4006445056
$ ./out_of_range
Input integer n: 18
Factorial of N: 3396534272
18! = 0x 16 be ec ca 73 00 00 인데 이를 4바이트 unsigned int에 대입하면 상위 4바이트는 버려지고 하위 4바이트만 옮겨짐.
따라서 데이터가 유실된다.
부호 반전과 값의 왜곡
oor_signflip은 앞의 예제에서 main 함수의 변수 n의 자료형이 int로 바뀜 이는 음수를 입력하면 23번 줄의 검사를 우회
// Name: oor_signflip.c
// Compile: gcc -o oor_signflip oor_signflip.c
#include <stdio.h>
unsigned long long factorial(unsigned int n) {
unsigned long long res = 1;
for (int i = 1; i <= n; i++) {
res *= i;
}
return res;
}
int main() {
int n;
unsigned int res;
printf("Input integer n: ");
scanf("%d", &n);
if (n >= 50) {
fprintf(stderr, "Input is too large");
return -1;
}
res = factorial(n);
printf("Factorial of N: %u\n", res);
}
$ ./oor_signflip
Input integer n: -1
n 에 저장되는 값은 0xffffffff이다. 그런데 factorial의 함수는 unsigned int n 을 인자로 받으므로 이 값은 부호없는 정수로 전달됨.
따라서 큰 수가 전달되어 연산이 늦어짐. 양수로만 쓰려면 unsigned 필수
버퍼 오버플로우
oor_bof는 잘못된 자료형의 사용이 sbo 유발.
size가 int형이므로 음수 전달 -> 매우 큰 수
// Name: oor_bof.c
// Compile: gcc -o oor_bof oor_bof.c -m32
#include <stdio.h>
#define BUF_SIZE 32
int main() {
char buf[BUF_SIZE];
int size;
printf("Input length: ");
scanf("%d", &size);
if (size > BUF_SIZE) {
fprintf(stderr, "Buffer Overflow Detected");
return -1;
}
read(0, buf, size);
return 0;
}
read함수에서 원래 ssize_t read(int fd, void *buf, size_t count);인데 세번째인자는 size_t 부호없는 형, 음수 전달하면 큰 수로 해석

타입 오버플로우와 언더플로우
변수의 값이 연산 중에 자료형의 범위를 벗어나면 갑자기 크기가 커지거나 작아짐

// Name: integer_example.c
// Compile: gcc -o integer_example integer_example.c
#include <limits.h>
#include <stdio.h>
int main() {
unsigned int a = UINT_MAX + 1;
int b = INT_MAX + 1;
unsigned int c = 0 - 1;
int d = INT_MIN - 1;
printf("%u\n", a);
printf("%d\n", b);
printf("%u\n", c);
printf("%d\n", d);
return 0;
}
$ ./integer_example
0
-2147483648
4294967295
2147483647
integer overflow & bof
integer -> heap bof
// Name: integer_overflow.c
// Compile: gcc -o integer_overflow integer_overflow.c -m32
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
unsigned int size;
scanf("%u", &size);
char *buf = (char *)malloc(size + 1);
unsigned int read_size = read(0, buf, size);
buf[read_size] = 0;
return 0;
}
size에 u int 최대값 입력하면 size+1 = 0이 됨
이를 malloc에 전달하면 최소 할당 크기인 32바이트만큼 청크를 할당해줌
반면 read는 size값을 그대로 사용함 -> 32바이트 크기의 청크에 4294967295만큼 값을 쓸 수 있게됨 bof발생

'system hacking > theory' 카테고리의 다른 글
| [Dreamhack] Unit 15. Path Traversal (0) | 2026.05.17 |
|---|---|
| [Dreamhack] Unit 14. Command Injection (0) | 2026.05.17 |
| [Dreamhack] Unit 13. Out of Bounds (0) | 2026.05.17 |
| [Dreamhack] Unit12. Hook Overwrite, One_gadgets (fho) (0) | 2026.05.15 |


