Reverse engineering Pokemon GO (Phần 1)

0

Chắc hẳn bạn đã từng nghe qua hoặc chơi qua về game Pokemon GO, gần đây nó đã trở thành một trào lưu mới và mang lại hàng triệu dollar mỗi ngày cho Nintendo và Niantic.

Hôm nay chúng ta sẽ nghiên cứu về Pokemon GO thông qua kĩ thuật Reverse engineering Pokemon GO, chúng ta sẽ lần lượt tìm hiểu từ nguồn gốc sau đó đến cách giao tiếp

Phần 1 : Tìm hiểu về nguồn gốc

 

Trước hết, Pokemon GO được làm bằng Unity ( Unity Game Engine) với 2 sản phẩm đóng gói là Android và IOS. Hầu hết các thành phần của game đều dễ dàng được tìm thấy, trong đó có thể kể đến là: các logo của trò chơi, items, thậm chí là cả 1 logo của McDonalds. Một số đoạn script cũng có thể được tìm thấy nhưng ad cũng chưa xem qua mấy đoạn đó 😀 vì phần hay nhất có lẽ phải kể đến Network Protocol.

Phần 2: Giao tiếp trong Pokemon GO

Pokemon GO giao tiếp với backend server thông qua HTTPS, nhưng lại không có xét duyệt bảo mật nào được thực thi, chính vì vậy, nếu bạn kiểm soát thiết bị thì bạn có thể tấn công đơn giản qua MITM. Request và Responses sử dụng Google’s Protocol Buffers , gần như tạo nên một hệ thống RPC.

Gói tin handshake đầu tiên được thực hiện với pgorelease.nianticlabs.com/plfe , giúp chỉ định channel cho seasion đó. Gói tin handshake này còn chứa authentication token, địa điểm, múi giờ và các tập tin nhị phân khác. Các tập tin nhị phân này có cấu trúc sắp xếp vô cùng chặt chẽ và hợp lí, dường như được dung thay cho sign của các dữ liệu được mã hóa khác.

Phần 3: Xử lí giao tiếp

Bây giờ là lúc chúng ta tìm hiểu protocol buffer encoding. AD có một công cụ mang tên protofudger của một bạn nước ngoài chia sẻ. Bạn có thể tìm thấy nó tại :

https://github.com/deoxxa/protofudger/blob/master/main.go

Về encoding bạn có thể tìm hiểu tại đây : https://developers.google.com/protocol-buffers/docs/encoding

Protobuf được tạo nên từ rất nhiều cặp key/values. Keys ở dạng chữ số, còn values được xác định bởi three-bit trong key. Key chủ yếu thuộc kiểu VARINT tức là các biến thuộc kiểu integer. Có 2 loại số đó là 32-bit và 64-bit

Tiếp sau đó, để chuẩn hóa và thông dịch các thông tin lấy từ protobuf, bạn cần hiểu cơ bản về lược đồ ( schema) bởi vì một protobuf type có thể chứa rất nhiều loại ứng dụng hoặc thậm chí có thể chứa cả múi giờ. Tuy nhiên bạn vẫn có thể decode chính xác mà không cần biết schema của nó, bởi vì nó đã được thiết kế với độ dài và thông số xác định riêng. Bạn có thể làm như sau :

protoc --decode_raw < message

Nó sẽ cho bạn chuẩn đoán đầu tiên để có thể xác định được các thông số.

Quy luật để xác định được các số giống nó nhất đó là tìm vị trí của các số gần số 0 nhất.

Ví dụ : timestamp được xác định bằng các số từ 1400000000000 đến 15000000000, như vậy, để đưa ra kết quả chính xác thì bạn nên xác định trước một vài điểm đặc biệt trong đoạn số trên.

Và như ad đã nói, Protofudger là một công cụ hoàn hảo để có thể kiểm tra các Protobuf khi chưa biết cấu trúc và nguồn gốc của nó. Chỉ dành để thông dịch J))

Hãy xem nó hoạt động như nào nhé.

Đây là một đoạn Protobuf được sinh ra khi ad đang chơi Pokemon GO ( Tất nhiên là chơi ở trong nhà)

Nó đã được mã hóa base64


CAIYhICAgIDH9YMtIgIIAiICCH4iCwgEEgcI2uj5690qIgMIgQEiLggFEioKKDRhMmU5YmMzMz
BkYWU2MGU3Yjc0ZmM4NWI5ODg2OGFiNDcwMDgwMmUyqAQIBhKjBAqgBG7GaKm7Pw0q1Cc2QLtM
GMC5m4LGKR7jNoEgJhkOqyaUiU1vNExYDB7R0BanfBLTYKcTjgBSxpIj5kiDJj95L0+ri5SucL
sl1KRMuf/0N5A38gmJlKp/9KUhJ42J36NRCqtantd9bZw6r0VZq0/dH/GoK1xPx/lYi18NHlHM
BDdwB7sKh1LcQ3VRlPp9Se28SvG18kFrGXMi9W7U1HcWWsACtv7og3gSf1GVXyyA5C70y0BdOq
O7WP0I8cJjZ6i6W2fI+6CfBBxZMB+MNNIPdAW49dDitKk1cts/aHdcMnMjobLGaYye99nT25CC
mGaMyHl9KbRyu6HvwMBUQGu2qvmsZRvDoWFw33QaskRhB987DF5p7KeN12kODt7LAtZmnyHvzh
QT1qbolqKpQCwhZpdPGRkDTMoPVhzWOkoNhnQab1n8gK7GiHA5mWEBU4JKMvkRpi7wzciAiuTk
s1FFKT5ywRChW+TOJRZ0aNVyhJ8yg9yZABoe42rTo30mwL2Q3qG6oShyyrNPg9b1MrXwf+LcBz
QkGnC/RiGOwybWHuPCC5uP5PWqIIoDJP3ArGZMrNJwrEYK/aTlj7eAZEH/PO+VvlZkzdurBvKf
jb6sNO/z0POrzgR08FqqKGjIOcxysVbHlbs7vufiH6rIDKqnQh0Xm/UX/KApQCGQX9qAQ5P+yt
skrLmVEzrCPS42DqJRN7ACsJU5UOVfeGqz0RJMp6w5AAAAwGnmQsBBAAAAwNkeYkBJAAAA4Gg3
VkBaWwpAjak/Co8vA9rnxeP5tKpOApMdlWxWyeYUJyIftyjJ6EdIEotI0ueUrZQkcOCoR10J+B
xoocpdD6o4RxwTT7OcRBDD1+fs3SoaELr5MxmdQYKC7HQaxg5tat5gnzY=

Tiếp sau đó, nếu bạn decode bằng lệnh protoc –decode_raw đã được nêu trên, thì đây là kết quả bạn thu được:


1: 2
3: 3244797592550244356
4 {
1: 2
}
4 {
1: 126
}
4 {
1: 4
2 {
1: 1468299899994
}
}
4 {
1: 129
}
4 {
1: 5
2 {
1: "4a2e9bc330dae60e7b74fc85b98868ab4700802e"
}
}
6 {
1: 6
2 {
1: "n\306h\251\273?\r*\324\'6@\273L\030\300\271\233\202\306)\036..."
}
}
7: 0xc042e669c0000000
8: 0x40621ed9c0000000
9: 0x40563768e0000000
11 {
1: "\215\251?\n\217/\003\332\347\305\343\371\264\252N\002\223\035..."
2: 1468301700035
3: "\272\3713\031\235A\202\202\354t\032\306\016mj\336"
}
12: 6943

Và tiếp theo là dùng Protofudger:


decoded 13 fields

1: (varint) 2
3: (varint) 3244797592550244356
4: {
1: (varint) 2
}
4: {
1: (varint) 126
}
4: {
1: (varint) 4
2: {
1: (varint, microseconds) 2016-07-12 15:04:59 +1000 AEST
}
}
4: {
1: (varint) 129
}
4: {
1: (varint) 5
2: {
1: (string) "4a2e9bc330dae60e7b74fc85b98868ab4700802e"
}
}
6: {
1: (varint) 6
2: {
1: (bytes) 6ec668a9bb3f0d2ad4273640bb4c18c0b99b82c6291ee3368120...
}
}
7: (doublele) -37.800102
8: (doublele) 144.964081
9: (doublele) 88.865776
11: {
1: (bytes) 8da93f0a8f2f03dae7c5e3f9b4aa4e02931d956c56c9e61427221f...
2: (varint, microseconds) 2016-07-12 15:35:00 +1000 AEST
3: (bytes) baf933199d418282ec741ac60e6d6ade
}
12: (varint) 6943

Hầu như các trường được đưa ra đều hơi thần bí và khó hiểu :v Trong các phần tiếp theo ad sẽ giải thích những thứ này nếu bạn còn hứng thú để tiếp tục đọc series này 😀

Có một số công cụ của hãng thứ 3 giúp bạn tương tác được với các dữ liệu Protocol này, cái mà ad hay dùng nhất có tên : PokeRev Mapper

Nó sẽ cho bạn thấy được backend và tương tác. Từ đó việc RE của bạn sẽ dễ dàng hơn.

Giờ thì đi bắt Pokemon thôi nào, catch ‘em all!

Leave A Reply

Your email address will not be published.