ACSC2021 - Histogram
csv파일 개념 자체도 몰랐으며 nan이라는 값도 몰라 풀지 못했던 문제이다.
공격 벡터는 알았으나 실제로 이를 적용하지 못해 풀지 못했던 아쉬운 문제.
우선 개념부터 짚고 넘어가자.
CSV(영어: comma-separated values)는 몇 가지 필드를 쉼표(,)로 구분한 텍스트 데이터 및 텍스트 파일이다. 확장자는 .csv이며 MIME 형식은 text/csv이다. comma-separated variables라고도 한다.
출처: 위키피디아
예시
1.01, 2.01
1.01, 2.01
1.01, 2.01
1.01, 2.01
1.01, 2.01
1.01, 2.01
1.01, 2.01
1.01, 2.01
1.01, 2.01
NaN(Not a Nuber)데이터
표현 불가능한 수치형 데이터
분석
read_data부분에서 취약점이 발생한다.
int read_data(FILE *fp) {
/* Read data */
double weight, height;
int n = fscanf(fp, "%lf,%lf", &weight, &height);
if (n == -1)
return 1; /* End of data */
else if (n != 2)
fatal("Invalid input");
/* Validate input */
if (weight < 1.0 || weight >= WEIGHT_MAX)
fatal("Invalid weight");
if (height < 1.0 || height >= HEIGHT_MAX)
fatal("Invalid height");
/* Store to map */
short i, j; // short= -32768~32767
i = (short)ceil(weight / WEIGHT_STRIDE) - 1;
j = (short)ceil(height / HEIGHT_STRIDE) - 1;
map[i][j]++;
wsum[i]++;
hsum[j]++;
return 0;
}
아래 코드에서 정확하게 취약점이 발생한다.
i = (short)ceil(weight / WEIGHT_STRIDE) - 1;
j = (short)ceil(height / HEIGHT_STRIDE) - 1;
취약점이 발생하는 이유는 weight / WEIGHT_STRIDE(10)부분인데 weight값을 10으로 나눈다.
이때 weight값이 1미만이면 weight / WEIGHT_STRIDE는 0.~~이 되거나 다른 값이 되는데, ceil함수때문에 0으로 바뀌고 0-1 = -1이 되어 인덱스가 음수가 되는 상황이 발생한다.
ceil함수 = ceil() 함수는 소수점 자리의 숫자를 무조건 올리는 함수, 실수를 정수로 만든다.
그럼 예시의 값을 넣어보고 메모리 구조를 관찰해보자.
1.0, 1.0
2.0, 2.0
3.0, 3.0
4.0, 4.0
5.0, 5.0
위 값을 넣으면


즉 동일한 값을(ex)5.0, 5.0) 10번 입력하면 map에 10이라는 값이 쓰여진다. 이를 통해 map에 원하는 값을 쓸 수 있다.
하지만 weight의 값을 nan으로 넣어준다면, (nan/10) -1 = i가 되기 때문에 결론적으로 i는 -1이 된다.

메모리 구조를 보면 0x405cbc부분이 4라는 값이 들어감을 볼 수 있다.
즉 weight의 값을 nan으로 주면 i를 -1로 하여 map 이전의 값을 변경할 수 있다는 의미이다.
map[-1][j]이고, j에 따라 저장할 수 있는 위치가 달라지니, j를 3주고 인덱스 위치에 잘 맞춰서 fclose 함수를 win함수로 뒤 덮으면 됨(뒤 3바이트만)

nan,30 을 520번 써주면 끝