자료형
C언어 자료형
자료형 | 크기 | 범위 | 용도 |
(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 바이트 |
주소 |
같은 자료형이더라도 운영체제에 따라 크기가 달라질 수 있다.
ex) long
32 bit => 4 byte
64 bit => 8 byte
Type Error는 크기, 용도, 부호 여부 등을 고려하지 않고 부적절한 자료형을 사용하면 발생한다.
#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));
}
Q. 위의 C 코드에서 자료형 T로 가장 적절한 것은?
A. unsigned long long
50! 까지 담을 수 있는 unsigned
Out of Range: 데이터 유실
#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);
}
int res에 unsigned long long factorial 값을 반환한다.
17보다 18을 입력했을 때 더 작은 값이 나오는 것을 볼 수 있다.
양수를 곱했는데 왜일까?
res가 저장할 수 있는 최대 범위를 넘은 값을 저장하려 했기 때문이다.
18! = 0x16beecca730000
res는 4 byte이기에 상위 4바이트는 버려지고 하위 4바이트인 0xca730000 만 들어가서 출력된다.
이처럼 변수에 저장될 수 있는 범위를 벗어난 값을 대입하면 범위 외의 값은 유실된다.
Out of Range: 부호 반전과 값의 왜곡
#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);
}
main 함수의 변수 n의 자료형: unsigned int -> int
즉, 음수 입력 -> if (n >= 50) 검사 우회 가능
-1을 입력하면 시간이 한참 지나도 결과가 출력되지 않는다.
int n에 -1을 저장 -> 2의 보수로 인해 n의 메모리 공간에 0xffffffff 저장
factorial 함수는 int n을 인자로 받음 -> 부호 없는 정수인 4294967295로 전달 -> 4294967295번 반복문 실행 -> 시간 오래 걸리고 연산도 어려움
양수로만 쓰일 값엔 반드시 unsigned를 붙이도록 하자.
Out of Range와 버퍼 오버플로우
#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;
}
자료형을 잘못 사용하면 스택 버퍼 오버플로우가 발생할 수 있다.
size가 int형 -> 음수를 전달 -> size가 32보다 작은지 검사하는 부분 우회 -> 버퍼 오버플로우
read 함수의 세번째 인자는 부호가 없는 size_t 형 -> 음수를 전달 -> 매우 큰 수로 해석
ssize_t read(int fd, void *buf, size_t count);
-1을 입력하고 32바이트보다 큰 데이터 입력 -> 스택 버퍼오버플로우
64비트로 컴파일하면 안 되는 이유
64 비트에서 size_t 는 8바이트 크기 부호 없는 정수
-1 = 0xffffffffffffffff = 18446744073709551615
read 함수는 count 값으로 큰 값이 들어오면 동작하지 않고 에러 값을 반환
타입 오버플로우와 언더플로우
변수 값이 연산 중에 자료형의 범위를 벗어나면, 갑자기 크기가 작아지거나 커지는 현상
정수 자료형에서 발생하면 Integer Overflow/Underflow
#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 Overflow와 버퍼 오버플로우
#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;
}
Integer Overflow -> Heap Buffer Overflow
사용자로부터 size 값을 입력받고, size+1 크기의 버퍼를 할당해, size만큼 입력 값을 받는다.
size에 unsigned int 최댓값 4294967295 입력 -> Integer Overflow -> size+1 = 0
-> malloc 에 전달되면 최소 할당 크기 32 바이트 청크 할당, 그러나 read 함수는 size 값 그대로 사용
-> 32 바이트 청크에 4294967295만큼 값을 쓸 수 있음 -> Heap Buffer Overflow
'SYSTEM HACKING' 카테고리의 다른 글
[SWING] Pwnable 06 - Path Traversal (0) | 2023.11.25 |
---|---|
[SWING] Pwnable 06 - Command Injection (0) | 2023.11.25 |
[SWING] Pwnable 05 - Tcache Poisoning (0) | 2023.11.19 |
[SWING] Pwnable 05 - Double Free Bug (0) | 2023.11.19 |
[SWING] Pwnable 04 - Use After Free (0) | 2023.11.11 |