드림핵 set-int
파일 분석
우선 파일을 다운 받아 보면 다음과 같은 c 코드가 들어있습니다
//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;
}
여기서 봤을 때 a에는 양수를 넣어서 a+1=b 에서 b가 음수가 나와야 하고, b에 음수를 넣어서 b-1 한 값이 양수가 나와야 한다는 것을 알 수 있습니다.
딱 생각나는게 타입 오버플로우/언더플로우네여!!
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로 돌아옵니다.쉽게 이해하자면 값이 고리로 이어져 있다고 생각하면 편합니다!
풀이
그럼 이 문제에서는 어떻게 오버플로우/언더플로우를 발생시켜야할까요?
우선 a에 양수를 넣었는데 a+1 이 음수가 나오려면 a 에 unsigned int의 최댓값인 4,294,967,295 를 넣어주면 b가 +1이 된 0으로 되겠죠?!
굳 ^^
1단계는 성공했습니다.
그럼 이제 2단계인 b 값을 알맞게 입력해야하는데, 처음에는 음수를 넣으면 되지 않을까? 해서 –2,147,483,648도 넣어보고 헥스값인 0x80000000 도 넣어봤는데 다 안되더라구요 ㅜㅜ
(아마 a 는 (int)로 형변환을 했지만 b 는 안해서.. 차이가 생긴것 같음)
그러면 2,147,483,648 을 입력하면 오버플로우 발생해서 –2,147,483,648 로 치환되겠지! 라고 생각해서 넣었더니 맞았습니다!!
그러고는 shell 을 획득했으니 원하는 flag 파일을 출력해봅시다
굳 ^_^
'WARGAME > misc' 카테고리의 다른 글
[dreamhack] 64se64 (0) | 2023.06.29 |
---|---|
[dream hack] baby-linux (0) | 2023.05.30 |