18. fsb
FSB (Format string bug) 취약점 문제로 보인다.
brain fuck?
flag, 바이너리, 코드가 있다.
코드를 확인해보면 다음과 같다.
먼저 난수를 발생시켜 key를 만들고 이 키를 맞히면 쉘을 얻을 수 있는 문제이다.
fsb 함수에서는 사용자에게 키를 입력받고 이게 key와 일치하면 쉘을 실행시키는데
22번 라인에 있는 반복문에서 4개의 문자열을 입력받는데 printf
에서 형식 지정자format string
을
사용하지 않고 그냥 출력하는 것을 확인할 수 있다. 여기서 취약점이 있다.
당연 buf에 입력받기 때문에 처음엔 return address
를 갖고있는 스택 주소를 buf
에 쓰고
다시 format string bug로 return address
를 쉘을 실행시키는 구문으로 돌리면 될거라 생각했는데..
buf
가 전역변수였다.
즉, 내가 원하는 임의의 주소에 값을 쓰지는 못한다는 건데, 어셈을 본다..
read
함수를 통해 4회 반복을 돌며 입력을 받는 부분인데, buf
에 입력 직후 스택 상황을 보기 위해 fsb+212
에 bp를 걸고 실행해본다.
buf
가 전역변수이기 때문에 스택 상에서 입력한 문자열을 확인할 수 없었다.
고민을 하다가 스택에 값을 쓸 수 없다면 이미 쓰여져 있는 값 중에 활용할만한게 없나 살펴봤다.
스택에 특정 접근 가능한 주소값이 쓰여져있으면 해당 주소값을 이용하여 원하는 곳에 값을 쓸 수 있을 것이다.
저 위치에 쓰여져있던 주소가 실행 도중 esp에서 비교적 가까운 위치의 주소를 담고있었다.
이를 이용해서 0xff8322230
위치에 있는 메모리에 원하는 값을 쓸 수 있게 된다.
for문이 총 4회
반복되기 때문에 총 4번
의 format string
이 가능하다.
이를 어떻게 이용할까 고민해보고 처음엔 return address
를 덮으려 했으나.. return address
를 담고있는 주소가 터무니 없이 커서
format string
을 위해 그 주소만큼 공백 문자를 채워 출력하려니 너무 오래걸릴 것 같았다.
다른 방법을 고민하다가 got를 쓰는 것도 가능할 것 같아서 시도했다.
먼저 타겟 함수를 찾아본다.
다행히 덮어쓸만한 함수가 많다.
printf
, read
, sleep
함수들을 덮어써도 되겠지만 나는 strtoull
로 결정했다.
이제 필요한 주소들을 확인해본다.
strtoull
함수의 got 상의 주소는 0x804a020
쉘을 실행시킬 수 있는 점프 주소는 0x0804869f
주소는 다 구했으니 공격을 하면
첫 번째 format string bug로 아까 스택 상에서 접근할 수 있던 주소에 strtoull
의 got 주소인 0x804a020
을 쓰고
두 번째 format string bug로 0x804a020
에 쉘을 실행시키는 주소인 0x804869f
를 쓰면
strtoull
함수가 호출될 때 쉘을 얻을 수 있을 것이다.
공격을 해보면,
입력 직후 화면에서 esp부터 출력한거고, 맨 위에서 두 번째 0x0804a100
이 buf
의 주소니까
format string bug로 접근이 가능한 주소의 시작부분은 맨 위에서 두 번째0xff83e1e4
이다.
목표 지점인 0xff832218
까진 %x
가 13번
필요하고 14번째에 %n
을 통해 0x804a020
을 쓴다.
마지막 %x
는 출력 바이트 수를 조정하기 위해 0x804a020
에서 현재까지 출력한 0x8*12
만큼을 빼준다.
두 번째 format string에선 목표 지점인 0xff832230
에 0x804a020
이 쓰여졌을 것이고
여기까지 다시 접근 후 %n을 이용하여 쉘을 실행시키는 주소인 0x804869f
를 쓴다.
마찬가지로 목표 지점까진 %x
가 19번
필요하고 마지막 %x
에서는 출력 문자의 수를 맞춰준다.