c언어는 배열의 경계를 체크 안함 -> out of bounds(OOB)
배열의 속성
배열은 연속된 메모리 공간을 점유하며, 배열이 점유하는 공간의 크기는 요소의 개수와 요소 자료형의 크기를 곱한 값
배열 요소의 개수를 배열의 길이라고도 부름
OUT OF BOUNDS
OOB는 요소를 참조할 때, 인덱스 값이 음수이거나 배열의 길이를 벗어날 때 발생
EX) 예제 코드
// Name: oob.c
// Compile: gcc -o oob oob.c
#include <stdio.h>
int main() {
int arr[10];
printf("In Bound: \n");
printf("arr: %p\n", arr);
printf("arr[0]: %p\n\n", &arr[0]);
printf("Out of Bounds: \n");
printf("arr[-1]: %p\n", &arr[-1]);
printf("arr[100]: %p\n", &arr[100]);
return 0;
}
$ gcc -o oob oob.c
$ ./oob
In Bound:
arr: 0x7ffebc778b00
arr[0]: 0x7ffebc778b00
Out of Bounds:
arr[-1]: 0x7ffebc778afc
arr[100]: 0x7ffebc778c90
임의 주소 읽기
읽으려는 변수와 배열의 오프셋을 알아야 함
배열과 변수가 같은 세그먼트에 할당되어 있다면, 둘 사이의 오프셋은 항상 일정하므로 디버깅으로 알아낸다.
만약 다른 세그먼트라면 다른 취약점을 통해 두 변수의 주소를 구하고 차이를 계산해야한다.
// Name: oob_read.c
// Compile: gcc -o oob_read oob_read.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char secret[256];
int read_secret() {
FILE *fp;
if ((fp = fopen("secret.txt", "r")) == NULL) {
fprintf(stderr, "`secret.txt` does not exist");
return -1;
}
fgets(secret, sizeof(secret), fp);
fclose(fp);
return 0;
}
int main() {
char *docs[] = {"COMPANY INFORMATION", "MEMBER LIST", "MEMBER SALARY",
"COMMUNITY"};
char *secret_code = secret;
int idx;
// Read the secret file
if (read_secret() != 0) {
exit(-1);
}
// Exploit OOB to print the secret
puts("What do you want to read?");
for (int i = 0; i < 4; i++) {
printf("%d. %s\n", i + 1, docs[i]);
}
printf("> ");
scanf("%d", &idx);
if (idx > 4) {
printf("Detect out-of-bounds");
exit(-1);
}
puts(docs[idx - 1]);
return 0;
}
$ echo "THIS IS SECRET" > ./secret.txt
$ ./oob_read
What do you want to read?
1. COMPANY INFORMATION
2. MEMBER LIST
3. MEMBER SALARY
4. COMMUNITY
> 0
THIS IS SECRET
임의 주소 쓰기
// Name: oob_write.c
// Compile: gcc -o oob_write oob_write.c
#include <stdio.h>
#include <stdlib.h>
struct Student {
long attending;
char *name;
long age;
};
struct Student stu[10];
int isAdmin;
int main() {
unsigned int idx;
// Exploit OOB to read the secret
puts("Who is present?");
printf("(1-10)> ");
scanf("%u", &idx);
stu[idx - 1].attending = 1;
if (isAdmin) printf("Access granted.\n");
return 0;
}
인덱스 범위 검사 없음
ISADMIN 조작하면 가능
pwndbg> i var isAdmin
Non-debugging symbols:
0x0000000000201130 isAdmin
pwndbg> i var stu
Non-debugging symbols:
0x0000000000201040 stu
pwndbg> print 0x201130-0x201040
$1 = 240
$ ./oob_write
Who is present?
(1-10)> 11
Access granted.

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