변수 자료형 선언시 담을 값의 크기, 용도, 부호 여부 고려 필요
Type error 부적절한 자료형을 사용했을 때 발생
- Out of Range: 데이터 유실
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// 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);
}
|
cs |
정수를 입력받아 팩토리얼 결과를 반환하는 코드이다.
입력값을 1씩 증가하면서 넣어보면,
17까지는 꾸준히 증가하던 결과가 18을 입력한 순간 급격히 작아지는 일이 발생한다.
18!=0x16beecca730000인데, 이 결과를 4바이트 크기의 res에 대입하려 하면,
상위 4byte는 버려지고, 하위 4byte인 만 남는다.
=> 변수에 어떤 값을 대입할 때, 그 값이 변수에 저장될 수 있는 범위를 벗어나면,
저장할 수 있는 만큼만 저장하고 나머지는 모두 유실
- Out of Range: 부호 반전과 값의 왜곡
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// 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);
}
|
cs |
main 함수에서 입력값 n 이 int형이 되었다 = 음수 입력 통해 16번째 줄의 검사 우회 가능
factorial함수는 unsigned int n을 인자로 받으므로, int n 이 음수로 입력되면 부호가 없어진 매우 큰 값의 양수가 factorial 함수에 들어가게 됨
=> 이런 문제예방하려면 양수로만 쓰일 값에 반드시 unsigned를 붙이는 습관 필요
- Out of Range와 버퍼 오버플로우
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// 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; // int 형이므로 아래 검사 우회 가능
printf("Input length: ");
scanf("%d", &size);
if (size > BUF_SIZE) { //버퍼오버플로우 방지 위해 size 값 검사
fprintf(stderr, "Buffer Overflow Detected");
return -1;
}
read(0, buf, size);
return 0;
}
|
cs |
size에 음수 넣으면 13번 줄 검사 우회 가능
size에 -1을 넣고 32byte보다 큰 데이터 넣으면 스택 버퍼오버플로우 발생
- 타입 오버플로우와 언더플로우
Type Overflow/Underflow : 변수의 값이 연산 중에 자료형의 범위를 벗어나면, 갑자기 크기가 작아지거나 커지는 현상
- Integer Overflow와 버퍼 오버플로우
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// 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;
}
|
cs |
사용자가 size에 4294967295 (unsigned int의 최댓값) 입력시
size+1은 0 됨(intetger overflow 발생), malloc에 전달 되면 32byte(최소 할당 크기) 청크 할당
그러나 read 함수는 size 값 그대로 사용
=> 32byte 청크에 4294967295 만큼 값 쓸 수 잇음 -> 힙 버퍼오버플로우 발생
취약점이 될 수 있는 부분이기 때문에 개발 시 들어가는 값 고려해서 자료형 선언해야 함
'해킹 공부 > 시스템 해킹' 카테고리의 다른 글
DreamHack stage 9_Memory Corruption: Out of Bounds (0) | 2022.07.25 |
---|---|
DreamHack_System hacking stage 4 (0) | 2022.07.11 |
DreamHack_System hacking stage1 (0) | 2022.07.06 |
[해커스쿨 LOB] level11_skeleton (0) | 2022.05.15 |
[해커스쿨 LOB] level 6_wolfman (0) | 2022.04.07 |