Pushing Valheim's Limits

I recently started playing the Viking survival game Valheim. A friend and I started a dedicated server and started playing pretty consistently, getting pretty close to endgame. At one point, he and I both died while exploring a swamp biome far away from our base, and we wanted to see if there was a way to fly back up there and get our stuff back with admin commands or something similar. Those commands existed, but it turned out that there was no way for either of us to access them on a server, even with admin privileges.

 

This got me thinking about how I could change that, because I knew that this game was made with Unity. I also know that, because Unity games are powered by C#, their code should be able to be easily decompiled using a tool such as dnSpy or something similar, due to the way C# is compiled (C# -> IL/Intermediate Language -> native (executable) binary at runtime). Because IL isn't as "obfuscated" from a human perspective as machine code would be, it can be easily converted back into C#. So I started poking around Valheim's binaries using dnSpy.

Dev Commands

It turns out that enabling the built-in developer commands for use in multiplayer wasn't hard. Not only that, but I was able to enable them no matter what, even if I wasn't an admin.

The first thing that caught my eye when I opened dnSpy was a class called Console.

 

Console.cs in dnSpy

 

I quickly started looking around in this class, and I found the first thing I was looking for.

In the Console class, there is a method called InputText. It was clear that this was the method responsible for handling all Console input, and for dealing with the behaviors necessary depending on what commands were entered.

 

The InputText method


It didn't take too much looking around to find what I was really here for. Scrolling down a bit, I could see the text "devcommands" encased in an if-statement:

 

devcommands!

 

At first glance, this was all I needed. However, looking deeper, I realized that nothing of value was actually happening here - the boolean 'm_cheat' was simply being toggled, and the fact that cheats were just turned on/off was being logged using (what I assumed was) a logging class called Gogan. But there was nothing here that would be preventing me from enabling the dev commands in multiplayer; it was just toggling a variable. So I knew what I was really looking for would be somewhere else.

 

I kept scrolling down, and eventually, I came across all of the developer commands themselves:

 

The meaty bits


This definitely has what I'm looking for. Specifically, in the if-statement at the top, there are two conditions that are of interest. Number one, ZNet.instance.IsServer() and number two, this.IsCheatsEnabled(). The first one would definitely cause me problems, because obviously, neither me or my friend are the server, we are just admins on the server. This condition would mean that dev commands simply cannot be used on a dedicated server, because with a dedicated server, no player is the server. Also, I needed to know what exactly caused this.IsCheatsEnabled() to return true. As I soon found out, this.IsCheatsEnabled() had the same condition:

 

 

Knowing this, I only had to do two things to (hopefully) gain access to the dev commands in multiplayer: remove the ZNet.instance.IsServer() requirement in InputText, and remove it in IsCheatsEnabled also. I was able to do that using dnSpy.

 

Some of dnSpy's extremely useful features, Edit Method highlighted

 

Using 'Edit Method', I removed the IsServer() requirement in IsCheatsEnabled:

 

 

and I removed it in InputText also:

 

 

So now, if all is working as intended, the game should only make sure we are 1. in an active server, 2. acting on the local player (our client & not someone else's), and 3. that we have enabled cheats (and that's all, no IsServer() checking). Opening up the game, joining the server, and running the devcommands console command, we get this result: 

 

 

This looks promising, but lets see if actually running a command does anything...

 

 

It worked! I can now spawn things, change the time of day, teleport, and change the weather (for example) on any server, regardless of admin status.


Copyright © 2014-2021 Iota