Frame Pointer Overwrite(FPO)

2020. 11. 30. 01:38
FPO란

FPO는 Saved Frame Pointer의 최하위 1 바이트를 오염시킴으로써 발생되는 취약점입니다.
이 기법을 사용하기 위해서는 메인 함수 이외에 서브 함수가 필요합니다.

공격 조건
1. SFP 영역에서 1 바이트 오버플로우가 반드시 일어난다.
2. 메인 함수 이외에 서브 함수가 있다.

 

공격 과정

스택 프레임 에필로그 과정을 숙지하고 있다는 것을 전제로 합니다.
어셈블리어는 Intel x86을 사용하였으며, 이 글에서 표현한 주소는 임의의 주소입니다.

다음과 같은 코드가 있다고 가정합시다.

#include <stdio.h>

void Vuln(char *sfp)
{
	char buffer[40];
	strncpy(buffer, sfp, 41);
	printf("%s", buffer);
}
int main(int argc, char *argv[])
{
	if (argc < 2)
	{
		printf("No way");
		exit(0);
	}

	Vuln(argv[1]);

	return 0;
}


서브 함수의 스택 프레임에서 buffer 변수의 공간으로 할당된 40바이트와 SFP 사이에 dummy가 없다면, 이는 SFP의 최하위 1 바이트를 덮어버릴 것입니다.

스택 프레임의 변화 과정을 더욱 자세히 봅시다.

이 그림은 Vuln 함수가 모두 끝나고 에필로그 과정 바로 전의 스택 프레임 모습을 담은 그림이다.
각 상자 안의 오른쪽 상단은 주소이고 왼쪽 하단은 값이다.

buffer의 값 처음에 buffer 변수 공간 시작 주소 + 4 바이트 한 값이 리틀엔디안으로 들어가있는 것을 볼 수 있다.
그 뒤에는 NOP 바이트와 shellcode가 자리한다.

또한, SFP 최하위 1 바이트가 a4로 덮여지면서 buffer 변수 공간 시작 주소보다 4 바이트 위의 주소를 가지고 있다는 것을 알 수 있다.

이렇게 되면 어떠한 방향으로 프로그램이 흘러가는지 알아보자.


먼저 ebp 값을 esp에 복사함으로써 할당했던 공간을 삭제한다.


이제 스택 프레임에서 pop을 실행함으로써 esp가 가리키는 곳의 4바이트를 날려버리고, esp가 가리켰던 곳의 값을 ebp에 저장한다.

이 과정에서 ebp가 0xbffffca4를 가리키게 된다.


이제 이 다음부터는 메인 함수의 코드가 정상적으로 실행된다. (아무 문제없이)

하지만, 메인 함수의 에필로그가 진행될 때 페이로드의 영향을 받는다.
메인 함수의 코드가 모두 실행되었고 에필로그가 시작하기 전으로 가서 그 안을 들여다보자.


이 그림만 봐도 느낌이 쎄~ 해진다 ㅋㅋ

어쨋든, ebp의 값을 esp에 복사한다.


pop ebp를 진행한다.


ebp는 쓰레기 값을 가지게 되면서 어디론가 사라졌다.
하지만 더 이상 ebp는 필요하지 않기 때문에 신경안써도 된다.

pop eip를 통해 esp가 가리키는 곳의 4 바이트를 날려 그 값을 eip에 저장한다.
이 과정에서 buffer의 첫 4 바이트에 저장했던 쉘코드 시작 부분의 주소를 eip가 가지게 된다.


이제 jmp eip를 하게 되면 비로소 쉘코드를 eip 레지스터가 가리키게 되고, 쉘코드가 실행된다.

 

예제

이를 직접 로컬 환경에서 테스트 해보는 것이 베스트이다.

하지만, 귀찮다면 LOB 문제 중 darkknight를 풀어보는 것을 추천한다 ㅋㅋ