CrewLink icon indicating copy to clipboard operation
CrewLink copied to clipboard

WIP support for GamePass/Xbox/WindowsStore edition of Among Us

Open cspotcode opened this issue 4 years ago • 17 comments

I've started working on support for the Windows Store version of Among Us, to fix #411.

I'm able to use a powershell.exe invocation to get a version number: 2020.12.4.0. This version number looks different than the Steam release. Partly I think this is because Windows appx manifests must have a version number with 4 parts, hence the trailing .0. But also it appears that the 2x newest offsets files are not correct for this binary, so offsets will need to be recomputed.

To make things easier for myself, I've increased the window size and hardcoded the offsets data rather than fetching it from crewl.ink. I'll need to remove those changes from the PR before it can be merged.

EDIT: like I said in a comment below, I've run out of free time to invest in this. Anyone else can take this branch and fix it, improve it, whatever is needed to make it work.

cspotcode avatar Dec 19 '20 00:12 cspotcode

Great work. Can't wait to use it

HalsahafPT avatar Dec 19 '20 03:12 HalsahafPT

What tools are used to figure out the memory offsets? I've been using Artmoney and the source code of https://github.com/denverquane/amonguscapture but I'm not sure if there are any tricks being used to figure out the memory offsets when a new release of Among Us is released.

cspotcode avatar Dec 19 '20 06:12 cspotcode

@cspotcode CrewLink uses the pointers I acquire after we update.

varedz avatar Dec 19 '20 20:12 varedz

What tools are used to figure out the memory offsets? I've been using Artmoney and the source code of https://github.com/denverquane/amonguscapture but I'm not sure if there are any tricks being used to figure out the memory offsets when a new release of Among Us is released.

The game is written in unity you can use tools like: https://github.com/Perfare/Il2CppDumper or https://github.com/djkaty/Il2CppInspector/ to get the offsets pretty easy. I recommend to download an old version of the game first tho because they added an obfuscation to the classnames 3 months ago. The other way is reading debugging among us with tools like cheatengine, IDA.

But to the point of the PR I myself think we just need to implement pattern scanning for the base addresses, if you do that it will support any version of the game (steam, windows store, beta, cracked etc). But this is a nice small temp fix I guess. // nvm just saw that the game on store is x64 which changes things _ (nvm didn't see the changes in the windows store ver)

OhMyGuus avatar Dec 20 '20 02:12 OhMyGuus

Unfortunately I've hit the following issues with the Windows Store binary:

DRM prevents reading the binary files at all. I believe @varedz was saying this makes it impossible to use Il2CppDumper or Il2CppInspector.

Also, the classes / structures appear to have a different memory layout than in the Steam release of the game. So I'm not sure we can merely update the base addresses; we'll also need to update the offsets and struct layouts. I suspect this is because Unity->UWP is accomplished by exporting an .sln to Visual Studio, then building from there. So the compiler toolchain and emitted code are different.

Let me know if I'm wrong about any of the above.

cspotcode avatar Dec 20 '20 02:12 cspotcode

Here's some extra info for you:

You can open UWP apps from the command line. For example, explorer.exe shell:appsFolder\Microsoft.MinecraftUWP_8wekyb3d8bbwe!App will open up Minecraft: Windows 10 Edition. I don't own Among Us on the Microsoft Store, though, so I can't tell you what the command to open Among Us with would be.

Epic Games has its own web protocol, com.epicgames.launcher://, although it can't be used within a browser. To launch Rocket League, for example, you'd use com.epicgames.launcher://apps/Sugar?action=launch&silent=true to launch the app without opening a window for the launcher itself.

itch.io has its own web protocol, itch://. I don't know how to directly open it with the itch.io launcher, though, but I'm going to assume it's stored in C:\Users\-\AppData\Roaming\itch\apps\among-us.

jbmagination avatar Dec 20 '20 02:12 jbmagination

Has anyone considered allowing the user to input their version manually? Or is there some other gotcha there that would make that infeasible?

davidt314159 avatar Dec 20 '20 03:12 davidt314159

Opening the application is not our problem @jbmagination

varedz avatar Dec 20 '20 04:12 varedz

meetingHud: [0x21D03E0, 0xB8, 0]
meetingHudCachePtr: [0x10]
meetingHudState: [0xC0]
gameState: [0x21D0EA0, 0xB8, 0, 0xAC]
allPlayersPtr: [0x21D0E60, 0xB8, 0, 0x30]
allPlayers: [0x10]
playerCount: [0x18]
playerAddrPtr: 0x20
exiledPlayerId: [0xff, 0x21D03E0, 0xB8, 0, 0xE0, 0x10]
gameCode: [0x1D50138, 0xB8, 0, 0x40, 0x48]
player:
  struct:
  - type: SKIP
    skip: 16
    name: unused
  - type: UINT
    name: id
  - type: SKIP
    skip: 4
    name: unused
  - type: UINT
    name: name
  - type: SKIP
    skip: 4
    name: unused
  - type: UINT
    name: color
  - type: UINT
    name: hat
  - type: UINT
    name: pet
  - type: UINT
    name: skin
  - type: UINT
    name: disconnected
  - type: SKIP
    skip: 4
    name: unused
  - type: UINT
    name: taskPtr
  - type: SKIP
    skip: 4
    name: unused
  - type: BYTE
    name: impostor
  - type: BYTE
    name: dead
  - type: SKIP
    skip: 6
    name: unused
  - type: UINT
    name: objectPtr
  - type: SKIP
    skip: 4
    name: unused
    
  isLocal: [0x78]
  localX: [0x90, 0x6C]
  localY: [0x90, 0x70]
  remoteX: [0x90, 0x58]
  remoteY: [0x90, 0x5C]
  bufferLength: 80
  offsets: [0, 0]
  inVent: [0x3D]

The new correct offsets, be aware you need to change the readstring as well to 0x10 -> length 0x14 -> char* same for the offsetAddress change the uint32 to uint64

Here is the dump from il2cppdumper: https://gist.github.com/OhMyGuus/c227bde024b2de9665d88afacbfa2d69

OhMyGuus avatar Dec 20 '20 10:12 OhMyGuus

Thanks, I was having a rough time making heads or tails of that dump. I'll update the PR.

cspotcode avatar Dec 20 '20 19:12 cspotcode

I've pushed the code I have so far. It's still not working. Could be a silly typo on my part, could be a uint32 -> uint64 change I missed, could be something with the offsets. I'm not sure. It appears to be reading garbage from memory.

This is probably the limit of how much time I'm able to invest here. Github should allow anyone to take this branch, fix it, improve it, do whatever and make it work.

cspotcode avatar Dec 20 '20 20:12 cspotcode

cross-reference: https://github.com/Rob--/memoryjs/issues/74

cspotcode avatar Dec 20 '20 21:12 cspotcode

@varedz There's a big "Open Game" button when you launch CrewLink if you don't have Among Us open. Seems to me like that info could be useful

jbmagination avatar Dec 21 '20 02:12 jbmagination

@jbmagination i have it on gamepass, so i installed it to get the launch string for you.

explorer.exe shell:appsFolder\Innersloth.AmongUs_fw5x688tam7rm!Game

xenoguy avatar Dec 21 '20 16:12 xenoguy

Made a working version & PR for this issue: #444

OhMyGuus avatar Dec 22 '20 01:12 OhMyGuus

meetingHud: [0x21D03E0, 0xB8, 0]
meetingHudCachePtr: [0x10]
meetingHudState: [0xC0]
gameState: [0x21D0EA0, 0xB8, 0, 0xAC]
allPlayersPtr: [0x21D0E60, 0xB8, 0, 0x30]
allPlayers: [0x10]
playerCount: [0x18]
playerAddrPtr: 0x20
exiledPlayerId: [0xff, 0x21D03E0, 0xB8, 0, 0xE0, 0x10]
gameCode: [0x1D50138, 0xB8, 0, 0x40, 0x48]
player:
  struct:
  - type: SKIP
    skip: 16
    name: unused
  - type: UINT
    name: id
  - type: SKIP
    skip: 4
    name: unused
  - type: UINT
    name: name
  - type: SKIP
    skip: 4
    name: unused
  - type: UINT
    name: color
  - type: UINT
    name: hat
  - type: UINT
    name: pet
  - type: UINT
    name: skin
  - type: UINT
    name: disconnected
  - type: SKIP
    skip: 4
    name: unused
  - type: UINT
    name: taskPtr
  - type: SKIP
    skip: 4
    name: unused
  - type: BYTE
    name: impostor
  - type: BYTE
    name: dead
  - type: SKIP
    skip: 6
    name: unused
  - type: UINT
    name: objectPtr
  - type: SKIP
    skip: 4
    name: unused
    
  isLocal: [0x78]
  localX: [0x90, 0x6C]
  localY: [0x90, 0x70]
  remoteX: [0x90, 0x58]
  remoteY: [0x90, 0x5C]
  bufferLength: 80
  offsets: [0, 0]
  inVent: [0x3D]

The new correct offsets, be aware you need to change the readstring as well to 0x10 -> length 0x14 -> char* same for the offsetAddress change the uint32 to uint64

Here is the dump from il2cppdumper: https://gist.github.com/OhMyGuus/c227bde024b2de9665d88afacbfa2d69

Could you go through the process from downloading il2cppdumper to having the offset results. I've been trying to do my research but it seems as is there is so many methods and it this point I just need something straight up.

realwakils avatar Dec 22 '20 22:12 realwakils

Could you go through the process from downloading il2cppdumper to having the offset results. I've been trying to do my research but it seems as is there is so many methods and it this point I just need something straight up. Sure, --- Getting the files. to get Ill2CppDumper to work u need 2 files the GameAssembly.dll and the global-metadata.dat. These 2 files are all just in the install folder one next to the Among Us.exe and the oter one in /Among Us_Data/il2cpp_data/Metadata. But if you want them for the Windows version like I did back then it requires a little bit more since only Users on your pc can access these files with the condition Win://SYSAPPID contains "INNERSLOTH...." to resolve this I made a small dll in c++ that copies these files towards another folder and then I used cheatengine to load this dll into the game.

--- Dumping After You get the files you just double click Ill2CppDumper.exe and it will prompt u to open the Binary file select here the "GameAssembly.dll", after that it will Ask u for the metadata file. Now it will dump you 3 files a dump.css with all classes & structures and a script.json containing all the addresses for each function basically.

--- Getting the offsets Now you got the 2 imported files the Dump.cs and the Script.json, but you will see now it has all randomized names which is quite anoying but we can manage with it. Especially since it wasn't randomized in an earier version of the game (like the one 3 months ago) so what I did is just dump that one as well and then u have a obfucated version and an non obfucated version. Lets open both dump.cs and see if we can find the new playerlist which is in the GameData, lets see if now we can find something "special" in this class to find it in the new one lets take for Example the "DisconnectedPlayerId" which is a constant and has the value 254 so if we search for " = 254;" in the new file you will only get around 7 results which is pretty neat.

Now if you compare those results you will end up with "EGLJNOMOGNP" (steam ver: 2020.12.9) now u can also see that for example the Playerlist is at 0x24 etc. Ok so now what? we have the Gamedata classname and how do we get the actual class now? It is pretty easy tbh since the Gamedata is a singelton with a static instance we can basically get the playerlist from there, so now you need to open the Scripts.json and search for "EGLJNOMOGNP_TypeInfo" which is the reference to the typeinfo of the class which has the static properties at 0x5c for x86 or 0xB8 for x64 You will find the address 29719528 now which is 1C57BE8 in hex like we needed and thats the basic idea to find offsets this way.

Here is the old among us dump forgot which game version it was tbh. https://gist.github.com/OhMyGuus/292fca58de9bf859054ef49f238f01e6 Hopefully this was a little bit clear but yeah :p

OhMyGuus avatar Dec 24 '20 02:12 OhMyGuus