이론/네트워크

게임 네트워크 - 보안

tsyang 2023. 9. 17. 23:29

패킷 스니핑

 

중간자 공격을 막기 위해서는 민감한 데이터를 암호화해야 한다. 평범한 리플리케이션 같은 정도라면 중간자가 감청해봤자 별 소용이 없을 것이다. 그럼에도 패킷 스니핑 측면에서는 암호화도 고려할만 한다. 


모든 네트워크 게임은 호스트 머신에서 수행하는 패킷 스니핑에 노출되어 있다고 봐야 한다. 아무리 암호화를 해도 실행 파일 어딘가에는 암호를 해독하는 체계가 있을 것이고 이런 체계를 밝히는 것은 시간 문제이다.

 

그럼에도 잠재적인 치터가 분석하기 어렵도록 암호화를 하는 게 좋다. 더 나아가 암호 키와 메모리 오프셋을 주기적으로 변경하는것이 좋은데, 치터를 귀찮게 할 수 있기 때문이다.

 

어쨋든 결국에 암호화는 뚫릴 것이기 때문에 호스트에게 내려주는 정보를 제한하는 것도 하나의 방법이다. (ex. FPS게임에서 시야에 보이지 않는 적의 정보는 보내주지 않음) 그러나 이렇게 정보를 제한하는 방법은 P2P게임에서는 불가능하다.

 

 

.

 

입력 검증

 

입력 검증은 네트워크로 받은 패킷을 수행하기 전에 유효한 것인지 검사하는 것이다. CS와 P2P모두 잘 동작한다. 

 

이런 방법은 클라이언트를 서버가 검증하거나, 피어가 다른 피어를 검증할 때는 잘 돌아간다. 그러나 서버가 내려주는 명령을 클라이언트에서 검증하는 것은 어렵다. 결국 플레이어에게 호스트 권한을 애초에 주지 않는것이 해결책 중 하나이다.

 

 

.

 

소프트웨어 치트 감지

 

에임핵이나 스타의 맵핵같은 것은 검증이 불가능하다. 그래서 소프트웨어 치트 감지가 필수적인데, 밸브 안티 치트(VAC)같은 게 대표적이다.

 

VAC에서는 치터를 바로 벤 하지 않는데, 이러면 바로 치터들이 치트를 그만 쓰게 되기 때문이다. 대신에 치터들을 기록해놨다가 한번에 제재하는 벤 웨이브 방식을 쓴다.

 

순수 서버라는 기능도 있는데, 이건 클라이언트가 서버에 접속하기 전에 게임 관련 파일에 대한 체크섬을 계산해 제출하도록 하는 것이다. 

 

 

.

 

소요 시간 분석 공격

bool Compare(int a[8], int b[8])
{
	for (int i = 0; i < 8; ++i)
		if (a[i] != b[i])
			return false;

	return true;
}

위와같이 int32 8개로 된 중요한 데이터를 비교하는 함수가 있다고 하자. 전혀 문제가 없는 코드이지만 오히려 중간에 false를 리턴하는 최적화가 문제가 된다. 왜냐면 많이 맞을수록 수행 시간이 오래 걸리기 때문이다.

 

이처럼 수행 시간을 통해 데이터가 얼마나 맞았는지 유추할 수 있기 때문에, 이런 코드들에는 대응이 필요하다.

 

bool Compare(int a[8], int b[8])
{
	int ret = 0;
	for (int i = 0; i < 8; ++i)
		ret |= a[i] ^ b[i];
	
	return ret;
}

위와 같은 코드를 작성한다면, 이제 1개가 맞든 7개가 맞든 동일한 시간이 걸리게 되어 소요시간을 통한 추측이 불가능해진다.