https://dreamhack.io/wargame/challenges/974
Simple pwnable 101 challenge
Q. What is Return Address?
Q. Explain that why BOF is dangerous.
void win ()
{
char flag[100] = {0,};
int fd;
puts ("You mustn't be here! It's a vulnerability!");
fd = open ("./flag", O_RDONLY);
read(fd, flag, 0x60);
puts(flag);
exit(0);
}
win함수를 호출하면 플래그를 획득할 수 있습니다.
char name[16];
// don't care this init function
proc_init ();
printf ("the main function doesn't call win function (0x%lx)!\n", win);
이름을 입력받기 위해 16바이트 크기의 버퍼를 설정합니다.
이름을 입력하면 (0x%lx)!\n", win 를 통해 win 함수의 주소를 16진수(0x%lx)로 출력합니다. 이 주소를 확인해 win 함수를 호출할 수 있습니다.
printf ("hex value: ");
scanf ("%lx%c", &value);
printf ("integer count: ");
scanf ("%d%c", &count);
두 번째와 세 번째 입력입니다.
hex value 에서는 덮어쓸 값을 입력받아 value로 저장합니다. 플래그를 획득하기 위해서는 win 함수에 접근해야 함으로, 위에서 알아낸 16진수를 입력합니다.
integer count 에서는 덮어쓸 횟수를 정수로 입력받아 count로 저장합니다.
for (idx = 0; idx < count; idx++) {
*(long*)(name+idx*8) = value;
}
핵심 코드입니다.
name의 시작 주소부터 8바이트씩(long), 떨어진 메모리 주소에 value를 덮어씁니다.
하지만 for문은 name이 몇 바이트인지 제대로 확인하고 있지 않고, count의 입력을 허용하고 있습니다. 즉, name보다 큰 값이 들어오게 된다면 버퍼 오버플로우가 발생하게 되는 것입니다.
name은 앞에서 확인했듯 16바이트입니다. name을 덮어쓰기 위해서는 16바이트를 넘어야 하기에 integer count에서 입력값은 3을 초과해야 합니다. count값이 3을 초과하게 되면 name의 입력 범위를 넘어, 버퍼오버플로우가 발생하게 됩니다.

입력받은 name값과 name 배열의 시작 주소부터 8바이트 단위로 16번(0x10) 메모리 주소와 값을 출력하는걸 확인할 수 있었습니다.

정상적으로 플래그를 획득할 수 있었습니다.