2 điểm bởi GN⁺ 2024-01-15 | 1 bình luận | Chia sẻ qua WhatsApp
  • Môi trường addon Lua của World of Warcraft cho phép thay đổi UI rất dễ dàng, nhưng để ngăn tự động hóa hành vi trong game, nó tách biệt quyền truy cập thông tin và quyền thực thi hành động
  • Mô hình bảo mật của Blizzard chia thành môi trường không bảo mật có thể đọc nhiều thông tin và môi trường bảo mật thực hiện hành động, và ranh giới này là cốt lõi của cơ chế chống tự động hóa
  • Hàm random được cho phép trong môi trường bảo mật lại chỉ là một lớp bọc mỏng quanh rand của C trong MSVC, một bộ sinh đồng dư tuyến tính yếu dùng chung trạng thái toàn cục, nên có thể trở thành kênh truyền thông tin
  • Chỉ với hai đầu ra RNG có thể thu hẹp ứng viên trạng thái nội bộ xuống tối đa 8 trường hợp, rồi dùng thêm đầu ra để chọn ra một ứng viên duy nhất trước khi đẩy RNG tiến lên cho tới khi xuất hiện chỉ số hành động mong muốn
  • Bề ngoài trông như chọn hành động ngẫu nhiên, nhưng thực tế có thể ép nó chọn hành động mong muốn như một phép thuật cụ thể, và hiện không rõ Blizzard đã sửa theo cách nào sau đó

Addon World of Warcraft trở thành điểm khởi đầu học lập trình

  • Addon World of Warcraft có cấu trúc rất đơn giản: chỉ cần đặt vài tệp nguồn .lua viết bằng Lua vào một thư mục là game sẽ tự nạp
  • Sau khi sửa tệp và lưu lại, chỉ cần tải lại giao diện là có thể thấy kết quả ngay, nên rào cản gia nhập rất thấp
  • Lúc đầu, tác giả tạo nhiều addon bằng cách sao chép mã của người khác rồi refactor hoặc ghép lại để làm ra tính năng mình muốn
  • Theo thời gian, tác giả dành nhiều thời gian viết addon hơn cả chơi game, và World of Warcraft đã trở thành cơ duyên để bắt đầu lập trình một cách nghiêm túc

Mô hình bảo mật addon của Blizzard

  • Nếu người dùng có thể tạo addon lập trình hoàn toàn tự do, vấn đề bot sẽ xuất hiện, nên Blizzard đã xây dựng một cơ chế giới hạn mức tự động hóa mà người chơi bình thường có thể thực hiện
  • Phần lớn các phần tử UI và API thu thập thông tin có thể được dùng không hạn chế
    • Ví dụ, có thể tạo thanh máu bằng cách đọc máu nhân vật rồi điều chỉnh kích thước khung hiển thị phía trước
  • Các API thực hiện hành vi thực sự trong game như di chuyển nhân vật, niệm phép hay dùng vật phẩm đều được bảo vệ và chỉ mã chính thức của Blizzard mới có thể gọi
  • API lấy vị trí chính xác trong thế giới game và hướng camera cũng đã trở thành đối tượng được bảo vệ từ một thời điểm nào đó
    • Đây là biện pháp để đối phó với các addon vẽ phần tử 3D lên trên thế giới game nhằm làm các trận boss dễ hơn

Sự tách biệt giữa môi trường bảo mật và không bảo mật

  • Vì một số phần tử UI cần tương tác với hành vi thực tế trong game, người ta có thể tạo các nút đặc biệt chạy mã trong môi trường bảo mật khi được nhấp
  • Những nút như vậy không thể được tạo, xóa hoặc di chuyển trong lúc đang chiến đấu
    • Điều này chặn cách tự động hóa bằng cách đặt nút có điều kiện dưới con trỏ trong lúc chiến đấu
  • Môi trường bảo mật cho phép lập trình để xác định sẽ niệm phép nào, nhưng chặn quyền truy cập vào trạng thái bên ngoài cần thiết cho tự động hóa tùy ý
  • Chỉ một phần API thu thập thông tin ở mức hệ thống macro được cho phép, còn các thông tin cần để chọn phép tối ưu như thời gian hồi chiêu hay máu của đơn vị thì không được cung cấp
  • Kết quả là hai môi trường có quyền hạn khác nhau
    • Môi trường không bảo mật: lấy được nhiều thông tin nhưng không thể hành động
    • Môi trường bảo mật: có thể hành động nhưng không lấy được thông tin cần cho tự động hóa

random trở thành một kênh cửa sau

  • Mục tiêu không phải là dùng phần mềm bên thứ ba để tắt các giới hạn bảo mật, mà là kiểm tra xem có thể lách môi trường bảo mật chỉ bằng các công cụ được cho phép về mặt kỹ thuật hay không
  • Khi xem danh sách các hàm được cho phép trong môi trường bảo mật, tác giả phát hiện ra random
  • Vì bộ sinh số ngẫu nhiên trong máy tính phần lớn là bộ sinh giả ngẫu nhiên có trạng thái nội bộ, nên nếu thao túng được trạng thái đó thì có thể truyền thông tin từ bên ngoài vào môi trường bảo mật
  • Trên thực tế, random chỉ là một lớp bọc nhỏ quanh rand của C
  • Vì World of Warcraft được biên dịch bằng MSVC, triển khai rand là một bộ sinh dựa trên trạng thái toàn cục
uint32_t state;

int rand() {
    state = state * 214013 + 2531011;
    return (state >> 16) & 0x7fff;
}
  • Cách triển khai này dùng chung một trạng thái ngẫu nhiên toàn cục trong toàn bộ tiến trình và là một bộ sinh đồng dư tuyến tính yếu

Khôi phục trạng thái của MSVC rand

  • Đầu ra của rand trực tiếp làm lộ 15 bit là một phần của trạng thái
  • Vì không gian trạng thái nhỏ và một phần đầu ra nhìn thấy được, có thể giữ danh sách các trạng thái ứng viên rồi loại dần bằng những đầu ra tiếp theo
  • Cách hiệu quả hơn là quan sát hai đầu ra RNG r0, r1 để tính các ứng viên cho phần 16 bit trạng thái bị ẩn
  • Các hằng số của MSVC rand là:
    • a = 214013
    • b = 2531011
  • Nếu gọi phần 16 bit bị ẩn sau lần gọi thứ nhất và thứ hai lần lượt là h0, h1, thì có thể suy ra các ứng viên của h0 từ phương trình chuyển trạng thái
  • Kết quả tính toán cho thấy chỉ cần xét k trong khoảng -1 <= k < 7, nên số ứng viên trạng thái ẩn giảm xuống tối đa còn 8 trường hợp
  • Sau đó chỉ cần so sánh kết quả của các lần gọi RNG tiếp theo với đầu ra của từng RNG ứng viên để loại bỏ các trường hợp sai
  • Bản cài đặt Python minh họa dùng vòng lặp while, nhưng trên thực tế dường như chỉ cần tới đầu ra thứ ba là đủ để thu hẹp còn một ứng viên duy nhất
  • Khi đó tác giả thấy khó tự mình dẫn xuất phần toán rời rạc này nên đã đặt câu hỏi trên crypto.SE, với lý do là “muốn cho đồng nghiệp thấy RNG này yếu đến mức nào”

Cách chọn hành động mong muốn trong môi trường bảo mật

  • Một khi có thể khôi phục trạng thái nội bộ của RNG, tác giả có thể truyền quyết định tự động hóa tùy ý vào môi trường bảo mật
  • Quy trình hoạt động như sau
    • Đăng ký một hook không bảo mật chạy ngay trước khi mã của môi trường bảo mật được thực thi
    • Bên trong hook, có thể truy cập mọi thông tin nên quyết định sẽ thực hiện hành động nào
    • Chuyển hành động đã chọn thành chỉ số trong một danh sách hành động được hardcode sẵn
    • Khôi phục trạng thái RNG hiện tại bằng phương pháp ở trên
    • Nếu đầu ra RNG tiếp theo, tính theo phần dư khi chia cho độ dài danh sách hành động, chưa phải là chỉ số mong muốn thì tiếp tục đẩy RNG tiến lên và kiểm tra lại
    • Khi tới lượt xuất hiện đầu ra mong muốn, hook trả về, và môi trường bảo mật gọi random để thực hiện hành động ở chỉ số đó
  • Trong môi trường bảo mật, bề ngoài có vẻ như danh sách hành động đang được đánh chỉ mục bằng một số ngẫu nhiên, nhưng thực tế thời điểm của lần gọi random kế tiếp đã được điều chỉnh để chọn đúng hành động mong muốn
  • Nếu kích thước danh sách hành động là n, trung bình cần đẩy RNG tiến lên n bước để truyền giá trị mong muốn, nhưng trong thực tế điều này không gây vấn đề khi sử dụng

Tình trạng về sau

  • Vài năm sau khi thử lại, cách này không còn hoạt động nữa
  • Không rõ Blizzard đã sửa vấn đề RNG yếu và trạng thái chia sẻ này vào lúc nào, hoặc liệu họ có nhận ra đây là một vấn đề hay không
  • Những thay đổi có thể đã xảy ra gồm chuyển sang thuật toán khác hoặc tách hẳn trạng thái RNG riêng cho môi trường bảo mật
  • Dù đây không phải là đoạn mã mà tác giả định dùng thực sự, nó vẫn là một ví dụ hẹp về việc lách cơ chế bảo mật trong game bằng cách thao túng thứ trông bề ngoài như ngẫu nhiên để tạo ra kết quả mong muốn

1 bình luận

 
GN⁺ 2024-01-15
Các ý kiến trên Hacker News
  • Hồi rất lâu trước, khi tôi làm GM cho WoW, có một phiên bản cụ thể của addon phổ biến Titan Bar bị lỗi, liên tục gọi API để mở UI “gửi ticket cho GM”.
    Dù bấm hủy thì nó lại hiện ra; ngoài việc xóa addon gây vấn đề, cách duy nhất để đóng cửa sổ là gõ gì đó vào ô văn bản rồi gửi.
    Từ phía GM, một hai ngày đó thật sự rất vất vả, và rất nhiều người chơi thậm chí không biết GM là gì, cũng không biết có thể gửi ticket.
    Việc giải thích rằng “có lẽ quý khách đã gửi ticket vì addon, nên tôi, nhân viên hỗ trợ khách hàng, liên hệ với quý khách” thường cũng không dễ.
    Vì nó gần như phá hỏng thời gian phản hồi bình thường, các lập trình viên đã phát hành hotfix và đưa lệnh gọi API đó vào vùng bảo vệ, chỉ cho phép gọi từ mã LUA của chính Blizzard.

    • Tôi nghĩ tên của nó là Titan Panel.
      Đó là addon gom nhiều phần tử UI như tổng số vàng, tỷ lệ độ bền cần sửa chữa... vào một thanh duy nhất.
  • Lạ là tôi từng trả lời trên StackOverflow về một câu hỏi gần như giống hệt liên quan đến “giải ngược bộ sinh số ngẫu nhiên”, vài tháng trước khi câu hỏi đó xuất hiện trên Crypto.SE: https://stackoverflow.com/a/15237585/1204143
    Chỉ khác là tôi tấn công bộ sinh số ngẫu nhiên của Java thay vì bộ sinh số ngẫu nhiên của MSVC.
    Cả hai đều là các bộ sinh đồng dư tuyến tính (LCG) đơn giản, xuất ra giá trị đã bị cắt bớt từ trạng thái nội bộ, nên cách tấn công cũng rất giống nhau.

    • Vì không giỏi toán, tôi đã nhờ Z3 tìm giúp các seed thuận tiện, và kết quả là đoạn mã dưới đây.
      import java.util.Random;
      public class Hayley {
      public static void main(String... args) {
      byte[] b1 = new byte[4], b2 = new byte[2];
      (new Random(0x2effe2140e00L)).nextBytes(b1);
      (new Random(0xc2f0097)).nextBytes(b2);
      System.out.println(new String(b1) + new String(b2));
      }
      }
  • Tôi tự hỏi liệu máy chủ có khả năng cũng dùng cùng bộ sinh số ngẫu nhiên đó không.
    Nếu vậy, về lý thuyết có vẻ có thể bị khai thác khi có một máy chủ có mức sử dụng rất thấp, độ trễ thấp, khả năng thu hẹp khá chính xác trạng thái hiện tại của bộ sinh số ngẫu nhiên, và khả năng nhanh chóng kích hoạt lại một sự kiện có độ chênh lệch kinh tế lớn tùy theo số ngẫu nhiên.

    • Máy chủ Vanilla WoW dùng Mersenne Twister; dù nó có nhiều vấn đề, nhưng không dễ bị phá một cách tầm thường như vậy.
      Blizzard đã công khai khá nhiều chi tiết về cách sinh số ngẫu nhiên phía máy chủ, trong một nỗ lực nhìn chung là thất bại nhằm dập tắt các tin đồn mà những người chơi mê tín tin chắc là có tồn tại thứ như “seed chiến lợi phẩm”.
  • Kinh tế học và động lực khuyến khích của bộ sinh số ngẫu nhiên rất thú vị.
    Nếu không có gì thực chất bị đặt cược và mọi người không dễ nhận ra, thì một bộ sinh số ngẫu nhiên không hoàn hảo, thậm chí tệ, vẫn có thể đủ dùng cho những thứ như trò chơi.
    Nhưng khi liên quan đến tiền hoặc bảo mật, như ví tiền mã hóa hay casino trực tuyến, nó bỗng trở nên cực kỳ quan trọng.

  • Nghiêm trọng hơn, bộ sinh số ngẫu nhiên đồng dư tuyến tính được nêu chỉ tạo ra 12.445 số khác nhau rồi lặp lại.
    Chỉ cần dùng các tham số tốt hơn cho thuật toán này thôi cũng đã hợp lý hơn rất nhiều.

    • Kỹ thuật là sự đánh đổi.
      Với các tác vụ đơn giản như chuyển động hạt trong vệt khói, bạn cần một bộ sinh số ngẫu nhiên nhanh và đơn giản.
      Còn trong mật mã học, trò chơi casino, v.v., người ta không chỉ dùng bộ sinh số ngẫu nhiên tốt hơn với trạng thái tối thiểu 32 byte, mà còn cho engine tiến thêm theo các khoảng ngẫu nhiên để càng khó dự đoán kết quả hơn.
  • World of Warcraft là lý do khiến tôi quan tâm đến lập trình.
    Khi game ra mắt tôi mới 6 tuổi, và khi các server private bắt đầu xuất hiện, tôi tò mò muốn biết cách tự tạo NPC nên đã học Lua.
    Nhiều bài viết trên diễn đàn MMOwned hồi đó vẫn còn, và một trong những người từng giúp tôi học lúc ấy đến nay vẫn thỉnh thoảng đăng bài.
    Khi tự biên dịch core server private, tôi đã học về biên dịch, SVN và áp dụng patch; hình như có một lỗi liên quan đến Fireball của pháp sư, nhưng tôi không nhớ chính xác.

    • Mỗi khi nhớ đến các diễn đàn ngày xưa, tôi lại thấy hoài niệm.
      Ngày nay, có cảm giác phần lớn những mặt tốt của Internet đã bị thay thế bởi các ứng dụng mạng xã hội kích thích dopamine và các diễn đàn khép kín như Reddit.
      Có lẽ lý do tôi vẫn ở lại HN cũng là vì nó gợi nhớ đến các diễn đàn cũ.
  • “Bất kỳ ai tìm cách tạo ra các chữ số ngẫu nhiên bằng phương pháp số học dĩ nhiên là đang ở trong trạng thái tội lỗi. Như đã nhiều lần được chỉ ra, không có thứ gọi là số ngẫu nhiên. Chỉ có các phương pháp tạo ra số ngẫu nhiên, và một quy trình số học nghiêm ngặt tất nhiên không phải là một phương pháp như vậy.” — John von Neumann

    • Với tư cách là một nhà mật mã học, câu trích dẫn này thật sự rất khó chịu.
      Tôi không có gì bất mãn với Neumann, nhưng những người lan truyền nó như một câu cách ngôn khôn ngoan thường chỉ truyền bá thông tin sai lệch.
      Trong ngữ cảnh, nó gần như chỉ là một câu đùa triết học không cần thiết.
      Chúng ta đã có bộ sinh số ngẫu nhiên mật mã học nhanh và đáng tin cậy trong nhiều thập kỷ rồi.
      Chúng hoạt động đúng chỉ với một seed rất nhỏ và các phép toán số học; các số được tạo ra không thể phân biệt với bất kỳ nguồn ngẫu nhiên đúng đắn nào khác và có thể dùng cho mọi mục đích.
      Quá nhiều người không hiểu điều này, đến mức còn có các công ty bán thứ dầu rắn mang tên “số ngẫu nhiên thật”.
  • Một ví dụ hay về bộ sinh số ngẫu nhiên thật sự khủng khiếp nằm trong Monster Hunter 3 Ultimate, và có lẽ cả các bản khác nữa.
    Nó không chỉ hoàn toàn có thể bị khai thác để lấy chiến lợi phẩm tốt, mà còn tạo ra cả “charm table”.
    Một số vật phẩm có chỉ số được tạo ngẫu nhiên, nhưng seed ban đầu được lưu trong file save, nên phạm vi vật phẩm có thể nhận được bị giới hạn.
    Nếu không may, bạn có thể rơi vào một “bảng bị nguyền rủa”, thực chất là một bộ sinh số ngẫu nhiên có chu kỳ rất ngắn, khiến bạn không bao giờ nhận được chỉ số tối đa.
    Nó không đến mức phá hỏng trò chơi, nhưng không tốt cho lối chơi cấp cao.

  • Tôi đã viết script cho nhà đấu giá.
    Nó quét toàn bộ phiên đấu giá, mua các vật phẩm bị định giá thấp rồi đăng bán lại.
    Nếu ai đó đăng rẻ hơn, tôi có thể hủy rồi đăng lại thấp hơn họ một chút, và về cơ bản có vàng vô hạn.

    • Sau khi nghe những người thật sự đang say ở Goldman giải thích tiền vận hành ra sao, tôi kể lại cho em trai, và nó đáp: “Vậy IRS là một gold sink à?”
      “Ừm, thật ra đó là một phép so sánh khá hay. Khác biệt là… ừm… đúng là khá hay đấy!”
    • Về cơ bản, đây giống giao dịch tần suất cao ngoài đời thực.
    • Có phải bạn là người tạo ra Auctioneer không? Hay là bạn làm một thứ tương tự Auctioneer nhưng quyết định không dùng công cụ “tiêu chuẩn ngành”?
    • Tôi tò mò bạn đã xác định việc định giá thấp bằng cách nào.
    • Bạn có phải là tác giả của addon Auctioneer không? Nếu đúng vậy, nó hẳn đã là một trong những addon WoW phổ biến nhất trong hơn 10 năm qua.
  • “Khi biến không biến đổi còn hằng số thì không hằng định”

    • Thú vị thật. Trông như một meme có gốc rễ sâu xa.
      https://www.theregister.com/2006/07/26/constants_are_not/
      “Lời than vãn về tính thất thường của lập trình trong tiêu đề bài này, ‘Variables Won't Constants Aren't’, lần đầu tôi đọc được trên Creative Computing là vài năm trước khi C ra đời.”
      Nếu có tài liệu cụ thể nào mà bạn cảm thấy là bản kinh điển của meme này, tôi rất muốn đọc.