Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Response Route: /raw
Web Interface to View Protos: /
Traffic Route mode /traffic
Golbat Route mode /golbat
PolyX Route mode /PolygonX/PostProtos


Web Interface:
Expand Down Expand Up @@ -83,6 +84,33 @@ interface CombinedMessage {
}
```

### Support for PolygonX interfaces
**Sent to** `/PolygonX/PostProtos`

```js
interface CombinedMessage {
protos: [
{
method: number
proto: bytes
request: bytes
trainer_id: string
trainer_level: number
has_geotargeted_ar_scan_quest: boolean
}
]
push_gateway_protos: [
{
method: number
proto: bytes
trainer_id: string
trainer_level: number
has_geotargeted_ar_scan_quest: boolean
}
]
}
```

### Requirements

```
Expand Down
45 changes: 43 additions & 2 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ export const requestMessagesResponses = {
REQUEST_TYPE_METHOD_SATURDAY_TRANSACTION_COMPLETE: [828, POGOProtos.Rpc.SaturdayCompleteProto, POGOProtos.Rpc.SaturdayCompleteOutProto],
REQUEST_TYPE_METHOD_REIMBURSE_ITEM: [829, null, null],
REQUEST_TYPE_METHOD_LIFT_USER_AGE_CONFIRMATION: [830, POGOProtos.Rpc.LiftUserAgeGateConfirmationProto, POGOProtos.Rpc.LiftUserAgeGateConfirmationOutProto],
REQUEST_TYPE_METHOD_SOFT_SFIDA_START: [831, POGOProtos.Rpc.SoftSfidaStartProto, POGOProtos.Rpc.SoftSfidaStartOutProto],
REQUEST_TYPE_METHOD_SOFT_SFIDA_PAUSE: [832, POGOProtos.Rpc.SoftSfidaPauseProto, POGOProtos.Rpc.SoftSfidaPauseOutProto],
REQUEST_TYPE_METHOD_SOFT_SFIDA_CAPTURE: [833, POGOProtos.Rpc.SoftSfidaCaptureProto, POGOProtos.Rpc.SoftSfidaCaptureOutProto],
REQUEST_TYPE_METHOD_SOFT_SFIDA_LOCATION_UPDATE: [834, POGOProtos.Rpc.SoftSfidaLocationUpdateProto, POGOProtos.Rpc.SoftSfidaLocationUpdateOutProto],
REQUEST_TYPE_METHOD_SOFT_SFIDA_RECAP: [835, POGOProtos.Rpc.SoftSfidaRecapProto, POGOProtos.Rpc.SoftSfidaRecapOutProto],
REQUEST_TYPE_METHOD_GET_NEW_QUESTS: [900, POGOProtos.Rpc.GetNewQuestsProto, POGOProtos.Rpc.GetNewQuestsOutProto],
REQUEST_TYPE_METHOD_GET_QUEST_DETAILS: [901, POGOProtos.Rpc.GetQuestDetailsProto, POGOProtos.Rpc.GetQuestDetailsOutProto],
REQUEST_TYPE_METHOD_COMPLETE_QUEST: [902, POGOProtos.Rpc.CompleteQuestProto, POGOProtos.Rpc.CompleteQuestOutProto],
Expand All @@ -127,6 +132,7 @@ export const requestMessagesResponses = {
REQUEST_TYPE_METHOD_PROGRESS_QUEST: [906, POGOProtos.Rpc.ProgressQuestProto, POGOProtos.Rpc.ProgressQuestOutProto],
REQUEST_TYPE_METHOD_START_QUEST_INCIDENT: [907, POGOProtos.Rpc.StartQuestIncidentProto, null],
REQUEST_TYPE_METHOD_READ_QUEST_DIALOG: [908, POGOProtos.Rpc.ReadQuestDialogProto, POGOProtos.Rpc.ReadQuestDialogOutProto],
REQUEST_TYPE_METHOD_DEQUEUE_QUEST_DIALOGUE: [909, POGOProtos.Rpc.DequeueQuestDialogueProto, POGOProtos.Rpc.DequeueQuestDialogueOutProto],
REQUEST_TYPE_METHOD_SEND_GIFT: [950, POGOProtos.Rpc.SendGiftProto, POGOProtos.Rpc.SendGiftOutProto],
REQUEST_TYPE_METHOD_OPEN_GIFT: [951, POGOProtos.Rpc.OpenGiftProto, POGOProtos.Rpc.OpenGiftOutProto],
REQUEST_TYPE_METHOD_GIFT_DETAILS: [952, POGOProtos.Rpc.GetGiftBoxDetailsProto, POGOProtos.Rpc.GetGiftBoxDetailsOutProto],
Expand Down Expand Up @@ -183,7 +189,7 @@ export const requestMessagesResponses = {
REQUEST_TYPE_METHOD_INVASION_ENCOUNTER: [1204, POGOProtos.Rpc.InvasionEncounterProto, POGOProtos.Rpc.InvasionEncounterOutProto],
REQUEST_TYPE_METHOD_PURIFY_POKEMON: [1205, POGOProtos.Rpc.PurifyPokemonProto, POGOProtos.Rpc.PurifyPokemonOutProto],
REQUEST_TYPE_METHOD_GET_ROCKET_BALLOON: [1206, POGOProtos.Rpc.GetRocketBalloonProto, POGOProtos.Rpc.GetRocketBalloonOutProto],
REQUEST_TYPE_METHOD_START_ROCKET_BALLOON_INCIDENT: [1207, POGOProtos.Rpc.StartRocketBalloonIncidentProto, null],
REQUEST_TYPE_METHOD_START_ROCKET_BALLOON_INCIDENT: [1207, POGOProtos.Rpc.StartRocketBalloonIncidentProto, POGOProtos.Rpc.StartIncidentOutProto],
REQUEST_TYPE_METHOD_VS_SEEKER_START_MATCHMAKING: [1300, POGOProtos.Rpc.VsSeekerStartMatchmakingProto, POGOProtos.Rpc.VsSeekerStartMatchmakingOutProto],
REQUEST_TYPE_METHOD_CANCEL_MATCHMAKING: [1301, POGOProtos.Rpc.CancelMatchmakingProto, POGOProtos.Rpc.CancelMatchmakingOutProto],
REQUEST_TYPE_METHOD_GET_MATCHMAKING_STATUS: [1302, POGOProtos.Rpc.GetMatchmakingStatusProto, POGOProtos.Rpc.GetMatchmakingStatusOutProto],
Expand Down Expand Up @@ -234,6 +240,7 @@ export const requestMessagesResponses = {
REQUEST_TYPE_METHOD_REMOTE_GIFT_PING: [1503, POGOProtos.Rpc.RemoteGiftPingRequestProto, POGOProtos.Rpc.RemoteGiftPingResponseProto],
REQUEST_TYPE_METHOD_SEND_RAID_INVITATION: [1504, POGOProtos.Rpc.SendRaidInvitationProto, POGOProtos.Rpc.SendRaidInvitationOutProto],
REQUEST_TYPE_METHOD_SEND_BREAD_BATTLE_INVITATION: [1505, POGOProtos.Rpc.SendBreadBattleInvitationProto, POGOProtos.Rpc.SendBreadBattleInvitationOutProto],
REQUEST_TYPE_METHOD_UNLOCK_TEMPORARY_EVOLUTION_LEVEL: [1506, POGOProtos.Rpc.UnlockTemporaryEvolutionLevelProto, POGOProtos.Rpc.UnlockTemporaryEvolutionLevelOutProto],
REQUEST_TYPE_METHOD_GET_DAILY_ENCOUNTER: [1601, POGOProtos.Rpc.GetDailyEncounterProto, POGOProtos.Rpc.GetDailyEncounterOutProto],
REQUEST_TYPE_METHOD_DAILY_ENCOUNTER: [1602, POGOProtos.Rpc.DailyEncounterProto, POGOProtos.Rpc.DailyEncounterOutProto],
REQUEST_TYPE_METHOD_OPEN_SPONSORED_GIFT: [1650, POGOProtos.Rpc.OpenSponsoredGiftProto, POGOProtos.Rpc.OpenSponsoredGiftOutProto],
Expand Down Expand Up @@ -419,6 +426,10 @@ export const requestMessagesResponses = {
REQUEST_TYPE_METHOD_START_PVP_BATTLE: [3071, POGOProtos.Rpc.StartPvpBattleProto, POGOProtos.Rpc.StartPvpBattleOutProto],
REQUEST_TYPE_METHOD_COMPLETE_PVP_BATTLE: [3072, POGOProtos.Rpc.CompletePvpBattleProto, POGOProtos.Rpc.CompletePvpBattleOutProto],
REQUEST_TYPE_METHOD_AR_PHOTO_REWARD: [3074, null, null],
REQUEST_TYPE_METHOD_UPDATE_FIELD_BOOK_POST_CATCH_POKEMON: [3075, POGOProtos.Rpc.UpdateFieldBookPostCatchPokemonProto, POGOProtos.Rpc.UpdateFieldBookPostCatchPokemonOutProto],
REQUEST_TYPE_METHOD_GET_TIME_TRAVEL_INFORMATION: [3076, POGOProtos.Rpc.GetTimeTravelInformationProto, POGOProtos.Rpc.GetTimeTravelInformationOutProto],
REQUEST_TYPE_METHOD_DAY_NIGHT_POI_ENCOUNTER: [3077, POGOProtos.Rpc.DayNightPoiEncounterProto, POGOProtos.Rpc.DayNightPoiEncounterOutProto],
REQUEST_TYPE_METHOD_MARK_FIELDBOOK_SEEN: [3078, POGOProtos.Rpc.MarkFieldbookSeenRequestProto, POGOProtos.Rpc.MarkFieldbookSeenResponseProto],
REQUEST_TYPE_PLATFORM_REGISTER_PUSH_NOTIFICATION: [5000, POGOProtos.Rpc.PushNotificationRegistryProto, POGOProtos.Rpc.PushNotificationRegistryOutProto],
REQUEST_TYPE_PLATFORM_UNREGISTER_PUSH_NOTIFICATION: [5001, null, null],
REQUEST_TYPE_PLATFORM_UPDATE_NOTIFICATION_STATUS: [5002, POGOProtos.Rpc.UpdateNotificationProto, POGOProtos.Rpc.UpdateNotificationOutProto],
Expand Down Expand Up @@ -469,6 +480,19 @@ export const requestMessagesResponses = {
REQUEST_TYPE_PLATFORM_SET_BIRTHDAY: [5048, POGOProtos.Rpc.SetBirthdayRequestProto, POGOProtos.Rpc.SetBirthdayResponseProto],
REQUEST_TYPE_PLATFORM_FETCH_NEWSFEED_ACTION: [5049, POGOProtos.Rpc.PlatformFetchNewsfeedRequest, POGOProtos.Rpc.FetchNewsfeedResponse],
REQUEST_TYPE_PLATFORM_MARK_NEWSFEED_READ_ACTION: [5050, POGOProtos.Rpc.PlatformMarkNewsfeedReadRequest, POGOProtos.Rpc.MarkNewsfeedReadResponse],
REQUEST_TYPE_ENABLE_CAMPFIRE_FOR_REFEREE: [6001, POGOProtos.Rpc.EnableCampfireForRefereeProto, POGOProtos.Rpc.EnableCampfireForRefereeOutProto],
REQUEST_TYPE_REMOVE_CAMPFIRE_FOR_REFEREE: [6002, POGOProtos.Rpc.RemoveCampfireForRefereeProto, POGOProtos.Rpc.RemoveCampfireForRefereeOutProto],
REQUEST_TYPE_GET_PLAYER_RAID_ELIGIBILITY: [6003, POGOProtos.Rpc.GetPlayerRaidEligibilityProto, POGOProtos.Rpc.GetPlayerRaidEligibilityOutProto],
REQUEST_TYPE_GRANT_CAMPFIRE_CHECK_IN_REWARDS: [6004, null, null],
REQUEST_TYPE_GET_NUM_POKEMON_IN_IRIS_SOCIAL_SCENE: [6005, POGOProtos.Rpc.GetNumPokemonInIrisSocialSceneProto, POGOProtos.Rpc.GetNumPokemonInIrisSocialSceneOutProto],
REQUEST_TYPE_GET_RSVP_COUNT: [6006, null, null],
REQUEST_TYPE_GET_RSVP_TIMESLOTS: [6007, null, null],
REQUEST_TYPE_GET_PLAYER_RSVPS: [6008, null, null],
REQUEST_TYPE_CAMPFIRE_CREATE_EVENT_RSVP: [6009, null, null],
REQUEST_TYPE_CAMPFIRE_CANCEL_EVENT_RSVP: [6010, null, null],
REQUEST_TYPE_CAMPFIRE_UPDATE_EVENT_RSVP_SELECTION: [6011, null, null],
REQUEST_TYPE_GET_MAP_OBJECTS_FOR_CAMPFIRE: [6012, POGOProtos.Rpc.GetMapObjectsForCampfireProto, POGOProtos.Rpc.GetMapObjectsForCampfireOutProto],
REQUEST_TYPE_GET_MAP_OBJECTS_DETAIL_FOR_CAMPFIRE: [6013, POGOProtos.Rpc.GetMapObjectsDetailForCampfireProto, POGOProtos.Rpc.GetMapObjectsDetailForCampfireOutProto],
REQUEST_TYPE_SOCIAL_ACTION_SEARCH_PLAYER: [10000, POGOProtos.Rpc.InternalSearchPlayerProto, POGOProtos.Rpc.InternalSearchPlayerOutProto],
REQUEST_TYPE_SOCIAL_ACTION_SEND_FRIEND_INVITE: [10002, POGOProtos.Rpc.InternalSendFriendInviteProto, POGOProtos.Rpc.InternalSendFriendInviteOutProto],
REQUEST_TYPE_SOCIAL_ACTION_CANCEL_FRIEND_INVITE: [10003, POGOProtos.Rpc.InternalCancelFriendInviteProto, POGOProtos.Rpc.InternalCancelFriendInviteOutProto],
Expand Down Expand Up @@ -533,6 +557,23 @@ export const requestMessagesResponses = {
REQUEST_TYPE_SOCIAL_ACTION_RESERVED_ACTION_4: [20401, null, null],
REQUEST_TYPE_SOCIAL_ACTION_RESERVED_ACTION_5: [20402, null, null],
REQUEST_TYPE_SOCIAL_ACTION_GET_FRIEND_RECOMMENDATION: [20500, POGOProtos.Rpc.InternalGetFriendRecommendationRequest, POGOProtos.Rpc.InternalGetFriendRecommendationResponse],
REQUEST_TYPE_SOCIAL_ACTION_BATCH_GET_FEATURED_MOMENTS: [20600, null, null],
REQUEST_TYPE_SOCIAL_ACTION_REACT_TO_MOMENT: [20601, null, null],
REQUEST_TYPE_SOCIAL_ACTION_UPDATE_MOMENT_SETTINGS: [20602, null, null],
REQUEST_TYPE_SOCIAL_ACTION_GET_MOMENT_SETTINGS: [20603, null, null],
REQUEST_TYPE_SOCIAL_ACTION_GET_MOMENT_HISTORY: [20604, null, null],
REQUEST_TYPE_SOCIAL_ACTION_GET_LAST_UNPINNED_PLAYER_MOMENT: [20605, null, null],
REQUEST_TYPE_SOCIAL_ACTION_PIN_PLAYER_MOMENT: [20606, null, null],
REQUEST_TYPE_SOCIAL_ACTION_UNPIN_PLAYER_MOMENT: [20607, null, null],
REQUEST_TYPE_SOCIAL_ACTION_LIST_MOMENT_REACTIONS: [20608, null, null],
REQUEST_TYPE_SOCIAL_ACTION_SEND_ACTIVITY_INVITE: [20700, null, null],
REQUEST_TYPE_SOCIAL_ACTION_RESERVED_ACTION8: [20701, null, null],
REQUEST_TYPE_SOCIAL_ACTION_RESERVED_ACTION9: [20702, null, null],
REQUEST_TYPE_SOCIAL_ACTION_LIST_INCOMING_ACTIVITY_INVITES: [20703, null, null],
REQUEST_TYPE_SOCIAL_ACTION_LIST_OUTGOING_ACTIVITY_INVITES: [20704, null, null],
REQUEST_TYPE_SOCIAL_ACTION_UPDATE_ACTIVITY_INVITE: [20705, null, null],
REQUEST_TYPE_SOCIAL_ACTION_CANCEL_ACTIVITY_INVITE: [20706, null, null],
REQUEST_TYPE_SOCIAL_ACTION_CHECK_ACTIVITY_INVITE_INBOX: [20707, null, null],
REQUEST_TYPE_DOWNSTREAM_ACTION_NEW_INBOX_MESSAGE_ACTION: [121000, null, null],
REQUEST_TYPE_DOWNSTREAM_ACTION_CUSTOM_DOWNSTREAM_ACTION: [121001, null, null],
REQUEST_TYPE_DOWNSTREAM_ACTION_CHAT_SIGNAL: [121002, null, null],
Expand Down Expand Up @@ -590,7 +631,7 @@ export const requestMessagesResponses = {
REQUEST_TYPE_GAME_ACCOUNT_REGISTRY_ACTION_LINK_TO_ACCOUNT_LOGIN_ACTION: [600006, POGOProtos.Rpc.InternalLinkToAccountLoginRequestProto, POGOProtos.Rpc.InternalLinkToAccountLoginResponseProto],
REQUEST_TYPE_GAME_ACCOUNT_REGISTRY_ACTION_GET_APP_REQUEST_TOKEN_REDIRECT_URL_PLATFORM_ACTION: [600007, null, null],
REQUEST_TYPE_GAME_TELEMETRY_ACTION_COLLECT_CLIENT_TELEMETRY: [610000, POGOProtos.Rpc.MapsClientTelemetryBatchProto, POGOProtos.Rpc.MapsClientTelemetryResponseProto],
REQUEST_TYPE_GAME_TELEMETRY_ACTION_GET_CLIENT_TELEMETRY_SETTINGS: [610001, null, null],
REQUEST_TYPE_GAME_TELEMETRY_ACTION_GET_CLIENT_TELEMETRY_SETTINGS: [610001, POGOProtos.Rpc.ClientTelemetrySettingsRequestProto, POGOProtos.Rpc.ClientTelemetryClientSettingsProto],
REQUEST_TYPE_TITAN_PLAYER_SUBMISSION_ACTION_ADD_NEW_POI: [620000, POGOProtos.Rpc.TitanSubmitNewPoiProto, POGOProtos.Rpc.TitanSubmitNewPoiOutProto],
REQUEST_TYPE_TITAN_PLAYER_SUBMISSION_ACTION_GET_AVAILABLE_SUBMISSIONS: [620001, POGOProtos.Rpc.TitanGetAvailableSubmissionsProto, POGOProtos.Rpc.TitanGetAvailableSubmissionsOutProto],
REQUEST_TYPE_TITAN_PLAYER_SUBMISSION_ACTION_GET_SIGNED_URL_FOR_PHOTO_UPLOAD: [620002, null, null],
Expand Down
84 changes: 82 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import http from "http";
import fs from "fs";
import crypto from "crypto";
import { WebStreamBuffer, getIPAddress, handleData, moduleConfigIsAvailable, redirect_post_golbat } from "./utils";
import { decodePayload, decodePayloadTraffic } from "./parser/proto-parser";
import { decodePayload, decodePayloadTraffic, decodeProtoFromBytes } from "./parser/proto-parser";
import SampleSaver from "./utils/sample-saver";
import POGOProtos from "@na-ji/pogo-protos";

// try looking if config file exists...
let config = require("./config/example.config.json");
Expand Down Expand Up @@ -206,6 +207,85 @@ const httpServer = http.createServer(function (req, res) {
}
});
break;
case "/PolygonX/PostProtos":
req.on("data", function (chunk) {
incomingData.push(chunk);
});
req.on("end", function () {
try {
const binaryData = Buffer.concat(incomingData);
res.writeHead(200, { "Content-Type": "application/json" });
res.end("");

if (binaryData.length === 0) {
console.error("Invalid PolygonX data: empty request body");
return;
}

// Decode the RawProtoCollection from binary protobuf
const decoded = POGOProtos.Rpc.AllTypesAndMessagesResponsesProto.Hexagon.RawProtoCollectionMessage.decode(binaryData);

// Process RawProto entries (have both request and response)
if (decoded.protos && Array.isArray(decoded.protos)) {
for (const rawProto of decoded.protos) {
const identifier = rawProto.trainer_id || "unknown";
const method = rawProto.method?.valueOf() || 0;
const requestBytes = rawProto.request;
const responseBytes = rawProto.proto;

// Decode request
if (requestBytes && requestBytes.length > 0 && method !== 0) {
const parsedRequestData = decodeProtoFromBytes(method, requestBytes, "request");
if (typeof parsedRequestData !== "string") {
parsedRequestData.identifier = identifier;
outgoingProtoWebBufferInst.write(parsedRequestData);
}
}

// Decode response
if (responseBytes && responseBytes.length > 0) {
const parsedResponseData = decodeProtoFromBytes(method, responseBytes, "response");
if (typeof parsedResponseData !== "string") {
parsedResponseData.identifier = identifier;
incomingProtoWebBufferInst.write(parsedResponseData);
}
}

// Save sample if enabled
if (sampleSaver && requestBytes && responseBytes) {
const requestB64 = Buffer.from(requestBytes).toString("base64");
const responseB64 = Buffer.from(responseBytes).toString("base64");
const parsedRequest = decodeProtoFromBytes(method, requestBytes, "request");
const parsedResponse = decodeProtoFromBytes(method, responseBytes, "response");
if (typeof parsedRequest !== "string" && typeof parsedResponse !== "string") {
sampleSaver.savePair(parsedRequest, parsedResponse, requestB64, responseB64, "polygonx");
}
}
}
}

// Process RawPushGatewayProto entries (response only)
if (decoded.push_gateway_protos && Array.isArray(decoded.push_gateway_protos)) {
for (const pushProto of decoded.push_gateway_protos) {
const identifier = pushProto.trainer_id || "unknown";
const method = pushProto.method?.valueOf() || 0;
const responseBytes = pushProto.proto;

// Decode response
if (responseBytes && responseBytes.length > 0) {
const parsedResponseData = decodeProtoFromBytes(method, responseBytes, "response");
if (typeof parsedResponseData !== "string") {
parsedResponseData.identifier = identifier;
incomingProtoWebBufferInst.write(parsedResponseData);
}
}
}
}
} catch (error) {
console.error("Error processing PolygonX request:", error);
}
});
break;
case "/traffic":
req.on("data", function (chunk) {
incomingData.push(chunk);
Expand Down Expand Up @@ -387,7 +467,7 @@ Server start access of this in urls: http://localhost:${portBind} or WLAN mode h

- Clients MITM:
1) --=FurtiF™=- Tools EndPoints: http://${getIPAddress()}:${portBind}/traffic or http://${getIPAddress()}:${portBind}/golbat (depending on the modes chosen)
2) If Other set here...
2) PolygonX EndPoint: http://${getIPAddress()}:${portBind}/PolygonX/PostProtos (application/x-protobuf)
3) ...

ProtoDecoderUI is not responsible for your errors.
Expand Down
Loading
Loading