부정 행위에 대한 메모리 편집기를 물리 치기위한 전략-데스크탑 게임 [닫기]


35

플레이어가 로컬 컴퓨터에서 다운로드하여 실행하는 데스크톱 게임에 대해 이야기하고 있다고 가정합니다. 플레이어의 건강과 같은 값을 감지하고 고정 할 수있는 메모리 편집기가 많이 있습니다.

메모리 수정을 통한 부정 행위를 어떻게 방지 합니까? 이런 종류의 부정 행위를 퇴치하는 데 효과적인 전략은 무엇입니까?

참고로, 나는 플레이어가 할 수 있다는 것을 알고 있습니다.

나는 좋은 것을 찾고 있습니다. 평범한 두 가지를 사용합니다.

  • 숫자 대신 백분율로 값 표시 (예 : 46/50 = 92 % 건강)
  • 배열에 값을 보유하고 변경 될 때마다 값을 이동시키는 저수준 클래스입니다. (예를 들어, int 대신 int의 배열 인 클래스가 있으며 값이 변경 될 때마다 무작위로 선택한 다른 배열 항목을 사용하여 값을 보유합니다)

이 게임은 오프라인, 무료 및 싱글 플레이어입니다.

편집 : 후손을 위해 이것을 C #으로 해결하고 내 솔루션을 여기 블로그에 게시했습니다.

답변:


21

(정수 값에 대한) 다른 가능성은 기존 변수의 비트 단위 보수를 보유하는 두 번째 구성원 변수를 갖는 것입니다.

당신이있어 그래서 상상 health, 당신은 또한 할 것이다 healthComplement. 구현은 다음과 같습니다.

// setter sets value and complement
void setHealth(int value){
    health = value;
    healthComplement = ~value;
}

// getter checks if value was changed outside of the setter
int getHealth(){
    if(value != ~healthComplement){
        // launch some cheat-counter-measure, like crashing the game?
        exit;
    }
    return health;
}

부정 행위를하고 싶은 사람은 health and healthComplement를 올바르게 설정해야합니다. 그렇지 않으면 게임이 중단됩니다.

이런 것들을 막으려 고 노력하는 것은 무의미하다고 생각합니다. 사람들은 훨씬 더 복잡한 것을 위해 해킹 / 치트를 성공적으로 만들었으며 코드를 난독 화하거나 게임 성능을 불필요하게 만듭니다.


12

누군가가 오래 전에 보드에서 요구했을 때 생각해 낸 한 가지 계획이 있습니다. "임의의"값을 검색하여 고정 할 수 있으므로 백분율 또는 이중 변수를 사용하면 실제로 작동하지 않습니다.

대신, 데이터 유형의 몬스터를 만드십시오.

기본적으로 중요한 값을 다음과 같은 구조로 저장하십시오.

  • 비트 32 포인터
  • 빠른 읽기를 위해 구조체에 현재 값도 일반 int로 포함 시키십시오.

조작을 위해 별도로 할당 된 비트 (참 / 거짓 정수일 수 있음)에서 현재 값을 수집하고 값을 변경 한 다음 다시 저장하십시오.

불쾌한 비트는 다음과 같습니다. 값을 조작 할 때마다 비트를 해제하고 비트를 다시 할당하십시오. 할당은 임의의 순서로 이루어져야 하므로 데이터가 메모리에서 이동하여 쉽게 고정 할 수 없습니다.

추가적인 보호 조치는 값의 체크섬 (및 "plain"int)을 저장하고 조작 호출 중에도이를 비교하는 것입니다. 불일치가 발견되면 게임 진행을 위해 문을 잠금 해제하는 데 필요한 임의의 키를 제거하는 등 미묘한 작업을 수행하십시오.

편집 : 추가 메모리 이동을 위해 이전 "비트"를 해제하기 전에 새 "비트"를 할당하십시오.

편집 : 멀티 플레이어 게임의 경우 데이터 구조를 직렬화하고 압축하여 네트워크를 통해 전송할 수도 있습니다. 네트워크를 가장 효율적으로 사용하는 것은 아니지만 패킷 스니핑을 통해 알아내는 것이 더 어렵습니다.


9

상태를 저장할 때마다 생성 된 임의의 값으로 보완 된 상태를 저장하는 방법은 무엇입니까? 이것은 적어도 건강을 찾기 위해 메모리에서 값을 증가 / 감소시키는 간단한 검색 메커니즘을 물리 칠 것입니다.

class Player
{
  int m_Health;
  int m_RandomHealth;
  Random m_Rnd = new Random();

  public int Health {
    get
    {
      return m_Health ^ m_RandomHealth;
    }

    set
    {
      m_RandomHealth = m_Rnd.Next();
      m_Health = value ^ m_RandomHealth;
    }
  }
}

또한 상태가 변경되지 않더라도 각 프레임의 값을 재설정 할 수 있습니다. 이렇게하면 건강 상태가 변경 될 때 사람들이 변경된 주소를 검색하지 못하고 상태가 동일하게 유지 될 때 동일하게 유지됩니다.

보너스 : 메모리 추가가 변경 될 때마다 새 객체를 작성하고 메모리를 읽을 때 마다 메모리의 난수, xored 값 및 주소를 변경하도록 상태를 설정하십시오 .

class Player
{
  int [] m_HealthArray; // [0] is random int, [1] is xored health
  Random m_Rnd = new Random();

  public Player() {
    this.Health = 100;
  }

  public int Health {
    get
    {
      int health = m_HealthArray[0] ^ m_HealthArray[1];
      Health = health; // reset to move in memory and change xor value
      return health;
    }

    set
    {
      m_HealthArray = new int[2];
      m_HealthArray[0] = m_Rnd.Next();
      m_HealthArray[1] = m_HealthArray[0] ^ value;
    }
  }
}

8

비록 청중의 일부 경험을 명백하게 얻지 못하고 있다는 점에 의문을 제기 한 첫 번째 의견을 제시했지만, 기술적 인 관점에서 여전히 흥미로운 질문입니다.

방금이 아이디어를 가졌습니다. 사기꾼의 역할은 변화하고 동결하는 가치를 찾는 것입니다. 그런 다음 플레이어의 건강을 바꾼 사망 또는 사건 사이에서만 검색이 이루어집니다. 더욱이 사기꾼은 그가 죽지 않았을 때 무엇이 ​​바뀌 었는지 필터링하여 검색을 개선 할 수있었습니다.

"건강"카운터가 전체 시간을 변경하면 어떻게됩니까? 포인터를 만들고 성능 적중이 너무 큰 경우 매 프레임 또는 매 N 프레임마다 다시 할당하십시오. 또는 모든 프레임을 변경하는 임의의 값으로 XOR하십시오 (새로운 임의의 값으로 암호화하기 전에 해독을 위해 동일한 값에 대해 XOR을 다시 수행하십시오).

게임 내 다른 데이터도 플레이어 캐릭터의 x 및 y 위치 또는 시간 카운터를 포함하여 전체 시간을 변경하는 경우 변경되는 모든 데이터 중 어떤 것이 건강인지 찾기가 더 어려울 수 있습니다. 그리고 전체 게임 상태를 동결시키는 것은 사기꾼에게는 아무런 문제가되지 않습니다.

더 잘못 인도하려면 실제로 허니팟이라는 일반 쓰기 전용 변수에 건강을 저장할 수 있습니다.

편집 :

그럼에도 불구하고 사기꾼은 전체 시간을 변경하는 변수 중 시행 착오를 통해 동결되는 변수를 찾으려고 시도 할 수 있습니다. 가능한 해결책은 변수를 함께 결합하는 것입니다.

예를 들면 :

상태 (h)와 위치 (x)를 저장하는 대신 두 개의 변수 a와 b에 저장하여 나중에 값을 검색 할 수 있습니다.

a = x+h; b = x-h
x = (a+b)/2; h = (a-b)/2

이런 식으로 사기꾼이 그중 하나만 얼린 다음 캐릭터를 움직이면 위치가 영향을 받고 얼어 붙은 위치에 따라 h가 음수로 바뀝니다 (즉시 사망). 위의 수식과 다음 사이를 전환 할 수 있습니다.

a = x-h; b = x+h
x = (a+b)/2; h = (b-a)/2

연속적인 프레임에서 변수 중 하나가 고정 된 후 최대 2 개의 프레임에서 상태 x가 변경되는 순간 상태가 0으로 설정됩니다. a와 b 만 저장한다는 것을 기억하십시오. 위에서 언급 한 것처럼 이것을 연속 XOR과 결합하십시오. 결과적으로 모든 프레임이 임의의 임의의 값으로 변경되는 변수 모음이 생성되며, 단일 프레임 또는 하위 집합을 고정하면 게임에서 원하지 않는 부작용 만 발생하며 즉석 사망이 그 중 하나입니다.


7

내가 생각할 수있는 한 가지 가능한 옵션 (이 속임수 도구에 너무 익숙하지는 않습니다) : 숨기지 마십시오. 작업을 수행하고 특정 결과를 기대하십시오. 작업 후 (아마 다음 프레임) 결과가 예상과 같은지 확인하십시오. 건강을 빼고 확인하면, 건강이 변하지 않았 음을 찾기 위해서만, 그것이 잠겨 있다는 것을 확신 할 수 있습니다 (모호한 버그가없는 경우).

부정 행위가 감지되면, 최대 슬픔에 걸맞게 게임 규칙을 자유롭게 변경할 수 있습니다. 당신의 의도가 부정 행위를 무시하고 게임이 계속 작동하도록하려면 메모리의 다른 곳에서 건강을 재 할당하고 포인터를 변경하여 새로운 값이 사용되고 이전 값은 무시되도록하십시오. 광고 인피니 엄을 반복하십시오.


6

단순히 난독 화를 시도하는 것은 이론상 실패 할 수밖에 없지만 실제로는 게임에서 성공하는 것보다 도전이 덜 재미있어지는 것을 깨뜨리는 데 어려움을 겪을 필요가 있습니다. 나는 당신의 게임이 무엇인지 모르므로 데이터 난독 화 방법을 제안 할 위험이 없습니다.

즉, 말하고, 당신은 아마 그것을 좋아하지 않습니다, 나는 당신이 찾고있는 생각 메모리 curtaining A는, 신뢰할 수있는 컴퓨팅 개념.


3

일부 로그 라이크 (DoomRL, Brogue)가 사용하는 매우 효과적인 기술 중 하나 는 실제 변수숨기는 것입니다. 이것은 건강을 "2/10"으로 표시하는 대신 "20 %"로 표시한다는 의미입니다.

대부분의 메모리 편집기는 특정 값 검색 / 필터링에 적합합니다. 특정 값을 모르는 경우에도 추적 할 수 있습니다 (예 : 플레이어 상태가 하락한 후 변경 / 감소 된 값 검색). 그렇게하는 데 시간이 훨씬 오래 걸립니다.

또한 치트 방지 백래시를 제안합니다. 예를 들어, 플레이어가 양의 피해를 입지 않고 체력이 떨어지지 않은 게임을하는 경우이를 쉽고 정확하게 확인하고 플레이어가 부정 행위를하는 것을 알 수 있습니다. 주위에 우버 적을 스폰하는 것과 같이 재미있는 것을하십시오 :)


2

응용 프로그램에서 ReadProcessMemory / WriteProcessMemory가 호출 될 때 SSDT를 연결하고 로그 / 차단하는 링 0 드라이버를 작성하십시오. 충돌 만하는 것이 아니라 시간이 지남에 따라 게임 동작을 천천히 변경할 수 있도록 로그인하는 것이 좋습니다.


저수준 구현 세부 정보 (Windows API?)에 대해 이야기하는 것처럼 들립니다. 일반적인 고수준 전략에 대해 묻고 있습니다.
ashes999

2

왜 플레이어가 자신을 속이는 것을 막을 것입니까 (단일 플레이어 게임에서 속이는 것입니까)? 멀티 플레이어 환경에서는 부 자연스러운 변화를 감지하고 그에 대응하는 것이 서버의 임무입니다. 해.

IOW, 멀티 플레이어 게임을 만들지 않는 한 비용 낭비이며 잘못된 장소를 강화할 생각입니다.


2

알려진 부정 행위 도구를 조사하고 가장 일반적인 도구가 실행중인 것으로 자주 확인되는지 확인하십시오 (프로세스 이름 확인?).

어떤 것이 감지되면, 플레이어가 부정 행위를하도록하세요 (오프라인 인 경우에는 무해합니다).

더 많은 해커를 막을 수는 없지만, 더 많은 캐주얼 속임수가 리더 보드를 망칠 가능성을 줄입니다.

(적절한 목적으로 개발 도구를 열고 최소화하고 게임 중단을 취하는 코더를 괴롭힐 수 있습니다 ...)


7
저는 배포 플랫폼으로서 Steam을 좋아했으며 2 년 전에 많은 팀 포트리스 II를 연기했습니다. 어느 날 저녁, 나는 긴 코딩 세션에서 휴식을 취하고 플레이하는 동안 Visual Studio와 디버거를 열어 두었습니다. 나는 "속임수"로 TF2에서 금지 된 것을 발견했다. 항소도 금지를 해제 할 프레임 워크도 없습니다. 하나의 "위법 행위"이며 계정에 대해 영구적입니다. 나는 왜 게임을 할 때 "메모리 편집기"를 열면 부정 행위가되고 금지 할 수 있다는 FAQ에 깊이 묻힌 것을 제외하고는 왜 그런지 잘 모르겠다. 와우.

1

이것에 대한 가장 간단한 해결책은 치트 옵션을 구현하는 것입니다. 치트 옵션에있는 동안 점수를 비활성화합니다.

또 다른 좋은 아이디어는, 어떻게 구현할 것인지 전혀 모른다는 것입니다. 고정 메모리 변수 또는 이와 유사한 것이있을 때 게임을 종료하는 것입니다 :)

행운을 빕니다 (Y)


3
치트를 구현하는 것이 좋습니다. 그다지 ... (이 잘못을 얻고, 합법적 인 플레이어를 종료하면 상상.), 게임 차단
ashes999
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.