버퍼는 메모리에서 데이터가 목적지로 이동되기 전에 보관되는 임시 저장소이다.
그래서 버퍼 오버 플로우란
용어 그대로는
사용자가 입력한 데이터의 크기가 너무 과하여 제한된 버퍼의 용량에서 넘쳐버렸다.
란 의미며
scanf, get, read 등 함수에서 메모리 구조를 이용해 일부러 버퍼에 큰 값을 넣어 오버 플로우를 이르켜 ret 주소를 변조해 실행 흐름을 마음대로 옮기거나, 데이터 유출, 데이터 변조를 할 수 있다.
위와 같은 버퍼 오버 플로우를 막기 위해 카나리 라는 보호 기법이 나왔는데
ret 값과 sfp 전에 어떠한 무작위 값을 넣고 그 값을 저장해 놓은 상태로 마지막에 변조가 되었는지 비교를 하여 만약 다르다면 강제로 종료하고, 다르지 않다면 그대로 실행하게 된다.
이 같은 카나리를 우회할 수 있는데.
무차별 대입으로 x64 아키텍처의 카나리 값을 알아내려면 최대 256^7번, x86 에서는 최대 256^3 번의 연산이 필요합니다. 연산량이 많아서 x64 아키텍처의 카나리는 무차별 대입으로 알아내는 것 자체가 현실적으로 어려우며, x86 아키텍처는 구할 순 있지만, 실제 서버를 대상으로 저정도 횟수의 무차별 대입을 시도하는 것은 불가능합니다.
카나리는 TLS에 전역변수로 저장되며, 매 함수마다 이를 참조해서 사용합니다. TLS의 주소는 매 실행마다 바뀌지만 만약 실행중에 TLS의 주소를 알 수 있고, 임의 주소에 대한 읽기 또는 쓰기가 가능하다면 TLS에 설정된 카나리 값을 읽거나, 이를 임의의 값으로 조작할 수 있습니다.
그 뒤, 스택 버퍼 오버플로우를 수행할 때 알아낸 카나리 값 또는 조작한 카나리 값으로 스택 카나리를 덮으면 함수의 에필로그에 있는 카나리 검사를 우회할 수 있습니다.