1. 문제
https://dreamhack.io/wargame/challenges/974
baby-bof
Description Simple pwnable 101 challenge Q. What is Return Address? Q. Explain that why BOF is dangerous.
dreamhack.io
Q. What is Return Address?
Q. Explain that why BOF is dangerous.
2. 풀이
문제에 두가지 질문이 제시되어 있으므로, 이 질문에 대한 답을 해결하면서 문제를 풀어볼 것이다.
먼저 문제 실행파일을 ida를 통해 디스어셈블 해보면, 아래와 같은 코드가 보여진다.
the main function doesn't call win function (0x40125b)!
win 함수의 주소와 main 함수가 win 함수를 call하지 않는다는 문자열이 출력되고 있는 것으로 보아, win 함수를 실행시키면 플래그가 출력될 것이라고 판단하였다.
디컴파일해보면 더욱 자세한 코드가 보이는데, name으로 15글자의 string을 scanf를 통해 입력받고 배열의 주소와 값을 출력해준다. 또한, hex value값과 integer count값을 입력받아 integer count의 개수만큼 hex value값으로 바꾼다.
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rdx
__int64 v4; // rdx
_QWORD v6[2]; // [rsp+0h] [rbp-10h] BYREF
proc_init(argc, argv, envp);
printf("the main function doesn't call win function (0x%lx)!\n", win);
printf("name: ");
__isoc99_scanf("%15s", v6);
printf("GM GA GE GV %s!!\n: ", (const char *)v6);
puts("| addr\t\t| value\t\t|");
for ( idx = 0LL; idx <= 15; ++idx )
printf("| %lx\t| %16lx\t|\n", &v6[idx], v6[idx]);
printf("hex value: ");
__isoc99_scanf("%lx%c", &value, v3);
printf("integer count: ");
__isoc99_scanf("%d%c", &count, v4);
for ( idx = 0LL; idx < count; ++idx )
v6[idx] = value;
puts("| addr\t\t| value\t\t|");
for ( idx = 0LL; idx <= 15; ++idx )
printf("| %lx\t| %16lx\t|\n", &v6[idx], v6[idx]);
return 0;
}
실제로 문자열이 출력되면서 name값을 입력받도록 하고, 입력을 해보면 스택의 주소와 값이 포함되어서 출력되는 것을 확인할 수 있다.
asdf를 여러번 입력해서 어떤식으로 결과가 나오는지 확인해보면, 입력한 문자열이 스택의 가장 최상단에 저장되고 있었다.
+)
그 다음 실제로 11개의 1111(지정한 hex값)이 스택에 저장된 것을 확인할 수 있다. 이때, count 값에 대한 검사가 전혀 존재하지 않는다. 즉, 배열의 범위를 넘어서서 더 많은 범위의 메모리 영역까지 영향을 끼칠 수 있다 -> bof 발생 가능
따라서 bof취약점을 통해 스택의 값을 0x40125b으로 바꿔버리면 win 함수가 실행되어 flag 값이 출력될 수 있을 것이다.
Q. What is Return Address? 즉 main 함수의 리턴 주소를 변조하여 원하는 임의의 주소로 이동하도록 변조한 것이다.
Q. Explain that why BOF is dangerous.
이렇게 bof 취약점은 임의의 함수를 마음대로 실행할 수 있도록 하기 때문에 매우 위험한 취약점이다.