Phương pháp làm xáo trộn Unity và bảo vệ chống hack

Cuối cùng, bạn đã phát hành game mà bạn đã dày công xây dựng và thậm chí có thể thêm leaderboard để thêm thử thách cho trò chơi. Nhưng nhiều ngày trôi qua và bạn nhận thấy một số người chơi xuất hiện ở đầu bảng điểm với số điểm cao đến mức phi thực tế. Suy nghĩ đầu tiên của bạn tất nhiên là họ đang hack, nhưng họ làm điều đó bằng cách nào?

Câu trả lời là, rất có thể họ đang sử dụng một chương trình để đưa các giá trị của riêng họ vào bộ nhớ, trong đó chương trình phổ biến nhất là Cheat Engine. Giờ đây, trong các trò chơi một người chơi, việc hack không thực sự quan trọng lắm, nhưng nó sẽ trở thành vấn đề khi đó là trò chơi nhiều người chơi có sự tham gia của những người chơi khác.

Trong bài đăng này, tôi sẽ hướng dẫn cách làm cho trò chơi của bạn an toàn hơn trước các cuộc tấn công như vậy, từ đó sẽ cải thiện trải nghiệm cho những người chơi không hack.

LƯU Ý: Bài viết này chỉ đề cập ngắn gọn về các cuộc tấn công phổ biến nhất và biện pháp bảo vệ cơ bản chống lại chúng. Nếu bạn cần thêm giải pháp sẵn có, vui lòng kiểm tra Asset Store Gói này.

Khi nói đến hack bằng Cheat Engine có 2 cách tấn công phổ biến nhất: Hack tốc độ và Quét giá trị.

Hack tốc độ

Là cách dễ thực hiện nhất (chỉ cần 2 lần nhấp chuột), Hack tốc độ thường là lựa chọn hàng đầu cho người dùng mới làm quen.

Hack tốc độ hoạt động bằng cách tăng tốc độ cập nhật của trò chơi, khiến mọi thứ nhanh hơn, do đó giúp tin tặc có lợi thế hơn những người chơi chơi ở tốc độ bình thường.

May mắn thay, có một cách để phát hiện vụ hack này trong Unity. Kiểm tra tập lệnh dưới đây:

LƯU Ý: Tính đến hôm nay, phương pháp này không còn hoạt động nữa, do đó, việc phát hiện hack tốc độ đã trở nên khó khăn hơn nhiều trong các trò chơi một người chơi. Tuy nhiên, trò chơi nhiều người chơi vẫn có thể thực hiện điều đó bằng cách dựa vào kiểm tra phía máy chủ để phát hiện bất kỳ sự không khớp nào về thời gian giữa người chơi và máy chủ và thực hiện hành động thích hợp (đá/cấm người chơi, v.v.).

SC_SpeedhackDetector.cs

using UnityEngine;
using System;

public class SC_SpeedhackDetector : MonoBehaviour
{
    //Speed hack protection
    public int timeDiff = 0; 
    int previousTime = 0;
    int realTime = 0;
    float gameTime = 0;
    bool detected = false;

    // Use this for initialization
    void Start()
    {
        previousTime = DateTime.Now.Second;
        gameTime = 1;
    }

    // Update is called once per frame 
    void FixedUpdate()
    {
        if (previousTime != DateTime.Now.Second)
        {
            realTime++;
            previousTime = DateTime.Now.Second;

            timeDiff = (int)gameTime - realTime;
            if (timeDiff > 7)
            {
                if (!detected)
                {
                    detected = true;
                    SpeedhackDetected();
                }
            }
            else
            {
                detected = false;
            }
        }
        gameTime += Time.deltaTime;
    }

    void SpeedhackDetected()
    {
        //Speedhack was detected, do something here (kick player from the game etc.)
        print("Speedhack detected.");
    }
}

Đoạn script trên so sánh thời gian trong trò chơi với thời gian (hệ thống) của máy tính. Thông thường cả hai lần đều được cập nhật với tốc độ như nhau (giả sử Time.timeScale được đặt thành 1), nhưng khi SpeedHack được kích hoạt, nó sẽ tăng tần suất cập nhật trong trò chơi, khiến thời gian trong trò chơi tích lũy nhanh hơn.

Khi sự khác biệt giữa cả hai thời điểm trở nên quá lớn (trong trường hợp này là 7 giây, nhưng bạn có thể chọn bất kỳ giá trị nào, chỉ cần đảm bảo rằng nó không quá nhỏ để tránh kết quả dương tính giả), tập lệnh sẽ gọi phương thức SpeedhackDetected() để báo hiệu sự hiện diện của SpeedHack.

Để sử dụng tập lệnh, hãy đảm bảo rằng nó được đính kèm với bất kỳ Đối tượng nào trong Cảnh.

Quét giá trị

Quét giá trị là quá trình tìm kiếm các giá trị liên quan trong bộ nhớ được phân bổ của trò chơi và ghi đè chúng bằng các giá trị khác nhau. Được sử dụng phổ biến nhất để tăng Sức khỏe của người chơi, Đạn vũ khí hoặc bất kỳ giá trị nào có thể mang lại cho hacker lợi thế không công bằng trong trò chơi.

Về mặt kỹ thuật, mọi giá trị trong trò chơi đều có thể bị ghi đè/thay đổi, nhưng điều đó có nghĩa là tất cả chúng đều cần được bảo vệ? Không cần thiết. Nói chung, những hacker mới vào nghề chỉ nhắm mục tiêu vào các giá trị hiển thị trên màn hình và biết chúng được sử dụng để làm gì (Ví dụ: sức khỏe của người chơi, đạn, v.v.). Vì vậy, hầu hết chỉ có giá trị "exposed" cần được bảo vệ.

Ảnh chụp màn hình trò chơi Unity FPS

Ví dụ: trên ảnh chụp màn hình ở trên, mọi giá trị trên màn hình đều có thể là mục tiêu bị hack.

Vì vậy, câu hỏi đặt ra là làm cách nào để bảo vệ các giá trị quan trọng trước cuộc tấn công Quét giá trị? Câu trả lời là Làm xáo trộn.

Obfuscation là hành động làm cho điều gì đó trở nên mơ hồ, không rõ ràng hoặc khó hiểu.

Có nhiều cách để làm xáo trộn một biến, nhưng tôi sẽ sử dụng một phương thức mà tôi gọi là Randomizer. Giá trị ngẫu nhiên được tạo khi bắt đầu, sau đó giá trị thực được trừ khỏi giá trị đó (sau đó ẩn nó), sau đó khi cần, giá trị ẩn sẽ được trừ khỏi giá trị ngẫu nhiên được tạo, với chênh lệch là số ban đầu. Điều quan trọng là phải có một giá trị hiển thị trên màn hình có giá trị khác hoàn toàn với biến, khiến hacker hoàn toàn sai lầm khi quét.

  • Tạo một tập lệnh mới, đặt tên là 'SC_Obf' và dán mã bên dưới vào trong tập lệnh đó:

SC_Obf.cs

using UnityEngine;

public class SC_Obf : MonoBehaviour
{
    static float random = -1;

    public static void Initialize()
    {
        if(random == -1)
        {
            random = Random.Range(10000, 99999);
        }
    }

    public static float Obfuscate(float originalValue)
    {
        return random - originalValue;
    }

    public static float Deobfuscate(float obfuscatedValue)
    {
        return random - obfuscatedValue;
    }
}

Tập lệnh ở trên sẽ được sử dụng để tạo một số ngẫu nhiên và 2 phương pháp đơn giản để làm xáo trộn và giải mã các giá trị.

  • Bây giờ hãy chuyển sang một ví dụ thông thường về tập lệnh mà không có bất kỳ sự khó hiểu nào:
using UnityEngine;

public class SC_Test : MonoBehaviour
{
    public float health = 100;
    public int ammo = 30;

    public void Damage(float points)
    {
        health -= points;
    }

    void OnGUI()
    {
        GUI.Label(new Rect(5, 5, 150, 25), health + " HP");
        GUI.Label(new Rect(5, 30, 150, 25), ammo + " Ammo");
    }
}

Đoạn script trên chứa 2 biến đơn giản: health (float) và ammo (int). Cả hai biến đều được hiển thị trên màn hình:

Cách thực hiện này đơn giản và thuận tiện về mặt bảo trì nhưng hacker sẽ dễ dàng quét các giá trị và ghi đè lên bằng Cheat Engine hoặc phần mềm tương tự.

  • Đây là tập lệnh tương tự nhưng sử dụng các phương pháp làm xáo trộn từ 'SC_Obf.cs':
using UnityEngine;

public class SC_Test : MonoBehaviour
{
    public float health;
    public int ammo;

    void Awake()
    {
        SC_Obf.Initialize();
        health = SC_Obf.Obfuscate(100);
        ammo = (int)SC_Obf.Obfuscate(30);
    }

    public void Damage(float points)
    {
        health = SC_Obf.Obfuscate(SC_Obf.Deobfuscate(health) - points);
    }

    void OnGUI()
    {
        GUI.Label(new Rect(5, 5, 150, 25), SC_Obf.Deobfuscate(health) + " HP");
        GUI.Label(new Rect(5, 30, 150, 25), SC_Obf.Deobfuscate(ammo) + " Ammo");
    }
}

Thay vì khởi tạo trực tiếp các biến số máu và đạn, chúng tôi khởi tạo chúng ngay từ đầu trong void Awake() (Đảm bảo gọi SC_Obf.Initialize() trước khi gán các giá trị bằng cách sử dụng SC_Obf.Obfuscate(giá trị)).

Sau đó, khi hiển thị các giá trị, chúng tôi giải mã chúng một cách nhanh chóng bằng cách gọi SC_Obf.Deobfuscate(value) do đó hiển thị các giá trị thực.

Tin tặc sẽ cố gắng tìm kiếm 10030 nhưng không thể tìm thấy chúng vì các giá trị thực hoàn toàn khác nhau.

Để thao tác các giá trị bị xáo trộn (ví dụ: trừ đi sức khỏe), trước tiên, chúng tôi giải mã giá trị sau đó trừ đi giá trị cần thiết rồi làm xáo trộn kết quả cuối cùng.

Để có giải pháp nâng cao hơn, vui lòng kiểm tra Asset Store Gói này.