PART 8 - 강의 2/2

안티치트 패턴

서버 측 치트 탐지와 방지 기법

01

치트 유형 분석

일반적인 치트 패턴

치트 유형 ┌─────────────────────────────────────────────────────────────┐ │ 주요 치트 유형 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ [스피드핵] │ │ - 이동 속도 증가 │ │ - 대응: 서버 측 이동 검증 │ │ │ │ [에임봇] │ │ - 자동 조준 │ │ - 대응: 비정상적 정확도/반응 속도 탐지 │ │ │ │ [월핵 (ESP)] │ │ - 벽 뒤 적 표시 │ │ - 대응: 시야 외 Actor 복제 제한 │ │ │ │ [텔레포트] │ │ - 순간 이동 │ │ - 대응: 위치 변화량 검증 │ │ │ │ [무한 자원] │ │ - HP/탄약 무한 │ │ - 대응: 자원은 서버에서만 관리 │ │ │ └─────────────────────────────────────────────────────────────┘
02

이동 검증 시스템

스피드핵 및 텔레포트 탐지

C++ // 서버에서 이동 검증 void UMyCharacterMovement::ServerMove_Implementation( float TimeStamp, FVector_NetQuantize InAccel, FVector_NetQuantize ClientLoc, ...) { // 1. 이동 속도 검증 float DeltaTime = TimeStamp - LastServerMoveTime; FVector PrevLocation = LastValidLocation; float MoveDistance = FVector::Dist(ClientLoc, PrevLocation); float MaxAllowedDistance = GetMaxSpeed() * DeltaTime * SpeedHackTolerance; if (MoveDistance > MaxAllowedDistance) { SpeedViolationCount++; if (SpeedViolationCount > MaxViolationsBeforeAction) { // 치트 의심 - 서버 위치로 강제 보정 ClientAdjustPosition(TimeStamp, LastValidLocation, ...); ReportSuspiciousActivity("SpeedHack", MoveDistance); return; } } else { SpeedViolationCount = FMath::Max(0, SpeedViolationCount - 1); } // 2. 순간이동 감지 if (MoveDistance > TeleportThreshold && !bJustTeleported) { ReportSuspiciousActivity("Teleport", MoveDistance); ClientAdjustPosition(TimeStamp, LastValidLocation, ...); return; } // 검증 통과 LastValidLocation = ClientLoc; LastServerMoveTime = TimeStamp; Super::ServerMove_Implementation(TimeStamp, InAccel, ClientLoc, ...); }
03

전투 검증 시스템

에임봇 및 비정상 전투 탐지

C++ // 전투 통계 수집 및 분석 USTRUCT() struct FCombatStats { GENERATED_BODY() int32 TotalShots = 0; int32 Headshots = 0; int32 Hits = 0; TArray<float> ReactionTimes; // 적 발견 후 첫 발사까지 TArray<float> AimAngularVelocities; // 조준 각속도 }; void AMyWeapon::ServerValidateHit_Implementation(...) { // 통계 수집 FCombatStats& Stats = PlayerCombatStats.FindOrAdd(ShooterId); Stats.TotalShots++; if (bValidHit) { Stats.Hits++; if (HitResult.BoneName == "head") { Stats.Headshots++; } } // 주기적으로 분석 if (Stats.TotalShots % 50 == 0) { AnalyzeCombatStats(ShooterId, Stats); } } void AMyGameMode::AnalyzeCombatStats( FUniqueNetIdRepl PlayerId, const FCombatStats& Stats) { // 헤드샷 비율 분석 float HeadshotRatio = (float)Stats.Headshots / Stats.Hits; if (HeadshotRatio > 0.8f && Stats.Hits > 20) { FlagForReview(PlayerId, "HighHeadshotRatio", HeadshotRatio); } // 명중률 분석 float Accuracy = (float)Stats.Hits / Stats.TotalShots; if (Accuracy > 0.95f && Stats.TotalShots > 30) { FlagForReview(PlayerId, "UnrealisticAccuracy", Accuracy); } // 반응 속도 분석 float AvgReactionTime = CalculateAverage(Stats.ReactionTimes); if (AvgReactionTime < 0.1f) // 100ms 미만은 비인간적 { FlagForReview(PlayerId, "InhumanReaction", AvgReactionTime); } }
통계 기반 탐지

단일 이벤트로 판단하지 말고 누적 통계를 분석하세요. 프로 게이머도 가끔 놀라운 플레이를 합니다. 지속적인 비정상 패턴만 신고하세요.

04

월핵(ESP) 방지

시야 외 정보 차단

C++ // Relevancy로 시야 외 적 복제 차단 bool AMyCharacter::IsNetRelevantFor( const AActor* RealViewer, const AActor* ViewTarget, const FVector& SrcLocation) const { // 자기 자신은 항상 관련 if (this == RealViewer || this == ViewTarget) return true; // 같은 팀은 항상 복제 if (IsSameTeam(RealViewer)) return true; // 거리 체크 float DistSq = (GetActorLocation() - SrcLocation).SizeSquared(); if (DistSq > FMath::Square(MaxRelevantDistance)) return false; // 시야 체크 (비용이 높으므로 주의) if (bUseVisibilityForRelevancy) { // 최근에 보였거나 소리를 냈으면 관련 if (GetWorld()->GetTimeSeconds() - LastSeenTime < 3.f) return true; // 라인 트레이스로 시야 확인 FHitResult HitResult; FCollisionQueryParams QueryParams; QueryParams.AddIgnoredActor(this); QueryParams.AddIgnoredActor(RealViewer); bool bBlocked = GetWorld()->LineTraceSingleByChannel( HitResult, SrcLocation + FVector(0, 0, 50), GetActorLocation() + FVector(0, 0, 50), ECC_Visibility, QueryParams); if (bBlocked) return false; } return true; }
성능 주의

모든 Actor 쌍에 대해 라인 트레이스를 수행하면 서버 성능에 심각한 영향을 줍니다. 거리 체크로 먼저 필터링하고, 중요한 Actor에만 시야 체크를 적용하세요.

SUMMARY

핵심 요약

  • 이동 검증 - 최대 속도와 위치 변화량으로 스피드핵 탐지
  • 전투 통계 - 명중률, 헤드샷 비율, 반응 속도 분석
  • 월핵 방지 - IsNetRelevantFor로 시야 외 정보 차단
  • 누적 분석 - 단일 이벤트가 아닌 패턴 기반 탐지
PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: 이동 속도 검증

ServerMove에서 클라이언트가 보낸 위치 변화량이 MaxSpeed * DeltaTime * 1.2f(허용 오차 20%)를 초과하면 이동을 거부하는 속도핵 감지 로직을 구현하세요.

실습 2: EOS Anti-Cheat 연동

EOS Anti-Cheat 클라이언트/서버 인터페이스를 초기화하고, BeginSession/EndSession 호출을 게임 세션 라이프사이클에 통합하세요.

심화 과제

서버 측 이상 행동 감지 시스템을 구현하세요. 이동 속도, 발사 빈도, 히트율 등의 통계를 수집하고, 임계값 초과 시 경고 로그를 남기는 행동 분석 프레임워크를 구축하세요.