소스코드다
//Name: chall.c
//Compile: gcc chall.c -o chall -no-pie -fno-stack-protector
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
int main(int argc, char *argv[]){
unsigned int a = 0;
int b = 0;
initialize();
printf("Your input : \n");
scanf("%u", &a);
if(a > 0){
b = (int)a + 1;
if(b == 0){
printf("Success.\nYour second input : \n");
scanf("%d", &b);
if(b < 1){
b = b-1;
if(b > 0){
system("/bin/sh");
} else{
printf("fail!\n");
}
} else{
printf("Input is too large!\n");
}
} else{
printf("fail!\n");
}
} else{
printf("Input is too small!\n");
}
return 0;
}
이 코드는 특정 조건을 만족시키면 /bin/sh을 실행하는 프로그램입니다. 프로그램의 핵심 동작과 조건을 분석하며, 어떻게 동작하는지 설명하겠습니다.
1. 프로그램 초기화 (initialize 함수)
- setvbuf:
- 입력과 출력의 버퍼링을 비활성화합니다. 이는 입력과 출력이 즉각적으로 처리되도록 보장합니다.
- signal과 alarm:
- 30초 후에 타이머가 만료되면 TIME OUT 메시지를 출력하고 프로그램을 종료합니다.
- 이는 프로그램의 실행 시간을 제한하여 의도적인 무한 루프를 방지하기 위한 조치입니다.
2. main 함수 분석
(1) 첫 번째 입력 처리 (scanf("%u", &a);)
- a는 unsigned int형입니다. 즉, 음수가 아닌 정수만 입력받을 수 있습니다.
- 조건:
c코드 복사if (a > 0) { ... }
- a가 양수일 경우에만 다음으로 진행합니다.
(2) 두 번째 조건 (b = (int)a + 1;)
- a를 int로 형변환하고 1을 더해 b에 저장합니다.
- 조건:
c코드 복사if (b == 0) { ... }
- 여기서 b == 0이 성립하려면 (int)a + 1의 값이 0이어야 합니다.
- 이는 a가 **0xFFFFFFFF (unsigned 최대값)**일 때 발생합니다.
- 0xFFFFFFFF + 1은 오버플로우로 인해 0이 됩니다
int 타입 오버플로우/언더플로우
int 형의 경우 범위가 –2,147,483,648 ~ 2,147,483,647 이고,
unsigned int(부호없는 정수)형의 경우 범위가 0 ~ 4,294,967,295 까지입니다.
만약 int 형이 2,147,483,647 + 1 이 되면 최대값을 넘겨져서 –2,147,483,648로 돌아옵니다.
쉽게 이해하자면 값이 고리로 이어져 있다고 생각하면 편합니다!
출처: https://lucykorea414.tistory.com/49 [지은이는 지은이:티스토리]
당신이 올바르게 이해한 것처럼, 2147483648은 signed int의 음수 범위로 인식됩니다. 그 이유를 명확히 설명하겠습니다:
1. 2147483648이 음수값으로 인식되는 이유
2147483648은 32비트 정수에서 signed int의 양수 범위를 초과하는 값입니다.
32비트 signed int 범위
- 양수 범위: 0 ~ 2147483647 (0x00000000 ~ 0x7FFFFFFF)
- 음수 범위: -1 ~ -2147483648 (0xFFFFFFFF ~ 0x80000000)
2147483648이 signed int로 처리되는 과정
- C 언어에서 unsigned int 값을 signed int로 변환할 때, 비트 패턴은 그대로 유지되지만 부호가 달라집니다.
- 2147483648은 32비트로 표현하면 0x80000000입니다.
- 이 값은 signed int에서 최상위 비트(부호 비트)가 1이므로 음수로 해석됩니다.
- 따라서, 0x80000000은 signed int로는 -2147483648 (INT_MIN)입니다.
- b에 2147483648을 넣을 때
- b는 signed int이므로 2147483648은 -2147483648로 변환됩니다.
2. 왜 2147483648 - 1은 2147483647인가?
다시 계산 과정을 살펴보면:
- b에 2147483648을 입력하면 b는 -2147483648이 됩니다.
- b - 1 연산이 수행되면:
- -2147483648 - 1은 2의 보수 연산에 따라 오버플로우가 발생합니다.
- 오버플로우 결과로 값은 양수의 최대값인 2147483647(INT_MAX)가 됩니다.
3. 핵심 요약
- 2147483648이 음수로 인식되는 이유
- 2147483648 (0x80000000)은 signed int에서 음수의 최소값인 -2147483648로 해석됩니다.
- 이는 C 언어의 정수 변환 규칙과 2의 보수 표현 방식 때문입니다.
- b - 1 연산
- -2147483648 - 1은 오버플로우를 발생시키며, 결과는 2147483647(양수의 최대값)가 됩니다.
- 결론
- 2147483648은 signed int로 변환될 때 음수로 처리되며, 오버플로우 연산으로 인해 양수 범위로 넘어가는 상황이 발생합니다.
'Dreamhack > Dreamhack Wargame (Challenge)' 카테고리의 다른 글
[127] IT 비전공자 [dreamhack]angry_darim문제 풀기 (0) | 2025.01.15 |
---|---|
[126] IT 비전공자 [dreamhack]Find The Lost Flag문제 풀기 (0) | 2025.01.14 |
[124] IT 비전공자 [dreamhack]Stupid GCC문제 풀기 (0) | 2025.01.12 |
[123] IT 비전공자 [dreamhack]chinese what?문제 풀기 (0) | 2025.01.11 |
[122] IT 비전공자 [dreamhack]Stop before stops!문제 풀기 (0) | 2025.01.10 |