├── img
├── L1.png
├── L2.png
├── L3.png
├── L4.png
├── L5.png
├── L6.png
├── L7.png
├── L1 CE Scan.png
├── L4 CE Search.png
├── L7 wackamole.png
├── L0 CE Settings.png
├── L1 Address List.png
├── L2 Address List.png
├── L4 dnSpy Code.png
├── L6 dnSpy Code.png
├── L4 dnSpy IL Code.png
├── L0 dnSpy anticheat.png
├── L6 dnSpy Code nopped.png
├── L7 wackamole method.png
├── L5 dnSpy Laser Turret.png
└── L0 dnSpy anticheat stubbed.png
├── L8.md
├── L9.md
├── L3.md
├── L5.md
├── L7.md
├── L6.md
├── L4.md
├── L2.md
├── L1.md
└── README.md
/img/L1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L1.png
--------------------------------------------------------------------------------
/img/L2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L2.png
--------------------------------------------------------------------------------
/img/L3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L3.png
--------------------------------------------------------------------------------
/img/L4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L4.png
--------------------------------------------------------------------------------
/img/L5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L5.png
--------------------------------------------------------------------------------
/img/L6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L6.png
--------------------------------------------------------------------------------
/img/L7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L7.png
--------------------------------------------------------------------------------
/img/L1 CE Scan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L1 CE Scan.png
--------------------------------------------------------------------------------
/img/L4 CE Search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L4 CE Search.png
--------------------------------------------------------------------------------
/img/L7 wackamole.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L7 wackamole.png
--------------------------------------------------------------------------------
/img/L0 CE Settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L0 CE Settings.png
--------------------------------------------------------------------------------
/img/L1 Address List.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L1 Address List.png
--------------------------------------------------------------------------------
/img/L2 Address List.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L2 Address List.png
--------------------------------------------------------------------------------
/img/L4 dnSpy Code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L4 dnSpy Code.png
--------------------------------------------------------------------------------
/img/L6 dnSpy Code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L6 dnSpy Code.png
--------------------------------------------------------------------------------
/img/L4 dnSpy IL Code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L4 dnSpy IL Code.png
--------------------------------------------------------------------------------
/img/L0 dnSpy anticheat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L0 dnSpy anticheat.png
--------------------------------------------------------------------------------
/img/L6 dnSpy Code nopped.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L6 dnSpy Code nopped.png
--------------------------------------------------------------------------------
/img/L7 wackamole method.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L7 wackamole method.png
--------------------------------------------------------------------------------
/img/L5 dnSpy Laser Turret.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L5 dnSpy Laser Turret.png
--------------------------------------------------------------------------------
/img/L0 dnSpy anticheat stubbed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jhllc/Unity-Game/HEAD/img/L0 dnSpy anticheat stubbed.png
--------------------------------------------------------------------------------
/L8.md:
--------------------------------------------------------------------------------
1 | # Level 8
2 |
3 | ## Objective
4 | Soon
5 |
6 | ## Solution
7 |
8 |
9 |
10 |
11 |
12 |
13 | Flag
14 | GHCTF{nice_shooting_tex}
15 |
16 |
17 |
18 |
19 | # [Next](L9.md)
20 |
--------------------------------------------------------------------------------
/L9.md:
--------------------------------------------------------------------------------
1 | # Level 9
2 |
3 | ## Objective
4 | Soon
5 |
6 | ## Solution
7 |
8 |
9 |
10 |
11 |
12 |
13 | Flag
14 | GHCTF{nice_shooting_tex}
15 |
16 |
17 |
18 |
19 | # [Home](README.md)
20 |
--------------------------------------------------------------------------------
/L3.md:
--------------------------------------------------------------------------------
1 | # Level 3
2 |
3 | ## Objective
4 | The Unicorn Raft is back! This time it has a shield. Well this one is not as straight forward...
5 |
6 | ## Solution
7 | For this level, we just need to search for the health and ammo, again, and lock them. We can then walk and sprint around
8 | the unicorn, and shoot while doing it. If you get in at the sides, you will be able to shoot him. Alternatively, you could
9 | look for the rotation of the Unicorn Raft and lock it, but, I was unable to find it. I might have just not tried enough.
10 |
11 |
12 | Flag
13 | GHCTF{the_best_defense_is_offense}
14 |
15 |
16 |
17 |
18 | # [Next](L4.md)
19 |
--------------------------------------------------------------------------------
/L5.md:
--------------------------------------------------------------------------------
1 | # Level 5
2 |
3 | ## Objective
4 | The Unicorn Raft has gotten a... fence? A laser fence? Guarded by laser turrets? Well this is just not realistic...
5 |
6 | ## Solution
7 | This level has a laser fence and a laser turret that kill you INSTANTLY when you run into them. The only way I know how to
8 | deal with this level immediately is to look at the game in dnSpy, again. We Open up the code in dnSpy and we find the `Laser
9 | Turret` class. Inside, we find a collision method called `OnTriggerEnter` and inside we can see it looks for the player,
10 | and will fire the lazer, if it is the player triggering this method call. If we replace that with a stub, we can jump through,
11 | no problem!
12 |
13 |
14 |
15 |
16 |
17 | Flag
18 | GHCTF{Ok_now_you_have_god_mode}
19 |
20 |
21 |
22 |
23 | # [Next](L6.md)
24 |
--------------------------------------------------------------------------------
/L7.md:
--------------------------------------------------------------------------------
1 | # Level 7
2 |
3 | ## Objective
4 | They said no more cheating at the start of this level, but, I took care of that, in the beginning...
5 |
6 | ## Solution
7 | This level announces that you can no longer cheat, and indeed, if you have not disabled the anticheat, this level WILL kill
8 | your game. We took care of that in the preamble to this challenge, so, now let's get on with level 7, shall we? Inside the
9 | Assembly, there is a `whackamole` class. I assume this is it, since it's a whackamole level. All we realy need to do is
10 | edit the CheckWin function to only take the path that returns `true`.
11 |
12 |
13 |
14 | We just need to right click, and edit the IL code. All we need to do is press `N` on the keyboard after the IL Code screen
15 | opens and then hit ok. The Method should just now show the entire body of the statement as the whole function, with `true`
16 | as the return value.
17 |
18 |
19 |
20 |
21 |
22 | Flag
23 | GHCTF{nice_shooting_tex}
24 |
25 |
26 |
27 |
28 | # [Next](L8.md)
29 |
--------------------------------------------------------------------------------
/L6.md:
--------------------------------------------------------------------------------
1 | # Level 6
2 |
3 | ## Objective
4 | There is a guardian protecting the exit. It wants a fish, but you only have.. apple?
5 |
6 | ## Solution
7 | Another level where we need to modify the running code. Luckily eveything is in plaintext, due to how CSharp works, but
8 | in the future, we will have to combine the skills from all of these levels to find the code we actually want.
9 |
10 | In this level, we just need to open up the `HasFish` class. We see this if statement here.
11 |
12 |
13 |
14 | If we click on the if statement and right click and hit `Edit IL Instructions...` we will get the IL instructions that make
15 | up the if statement, and then the branch (Which branches to line 75 if the check is equal to 0). We want to right click the
16 | code, and hit the `nop instructions` or hit `N` on the keyboard. If you did it right, it will nop the selected instructions
17 | and you can restart the game and pass through, no issue!
18 |
19 |
20 |
21 |
22 |
23 | Flag
24 | GHCTF{Kitty_appreciates_the_fish_magic}
25 |
26 |
27 |
28 |
29 | # [Next](L7.md)
30 |
--------------------------------------------------------------------------------
/L4.md:
--------------------------------------------------------------------------------
1 | # Level 4
2 |
3 | ## Objective
4 | The Unicorn Raft has given up... Now he is just going to GIVE you the flag... or is he?
5 |
6 | ## Solution
7 | In this level, I found two ways to approach it. We could modify the game inside of DNSpy. One of the classes in the game
8 | dll is called "Pitfall", and this happens to be the code for this level. We can keep the ground from dropping by changing
9 | the arguments to this function
10 |
11 |
12 |
13 | We need to change `ldc.l4.0` in both method calls to `ldc.l4.1`.
14 |
15 |
16 |
17 | The world no longer falls when we enter the arena, and you can walk to the exit and get the flag.
18 |
19 | The hard way, and possibly the intended way, would be to search for your Z axis value, or whatever axis the game engine
20 | uses to determine height. To do this, we need to fall down the world, and use the stairs to scan for an increase or decreased
21 | value. Let's just assume that the value is increasing as we go up. We can start the map at the regular height. Do our first
22 | scan for an initial unknown value, and then drop the floor, scan for a decreased value at the bottom of the steps and then
23 | search for an increased value as we climb the steps. I ended up with a few values, like 25 or so, and just added them all
24 | to the address list. I then locked all of them, and walked off the stairs. My character started moving up and down, like
25 | it was stuck on something. I then turned off individual addresses at the bottom until I found the one that controlled
26 | the height, directly. I then put that value to 2 and walked over to the exit, where the flag had spawned!
27 |
28 |
29 |
30 |
31 |
32 | Flag
33 | GHCTF{You_should_play_basketball}
34 |
35 |
36 |
37 |
38 | # [Next](L5.md)
39 |
--------------------------------------------------------------------------------
/L2.md:
--------------------------------------------------------------------------------
1 | # Level 2
2 |
3 | ## Objective
4 | Kill the Unicorn Raft! The Unicorn Raft has enough HP to absorb all of you bullets. If only there was a way to have infinite
5 | bullets... hmmm...
6 |
7 | ## Solution
8 | So, we start, again, looking for writeable memory. We start with the value of 10, and an exact match, fire the gun. Now
9 | restart the level because you shot at the unicorn. Make sure you don't start the fight, unless you want to have the
10 | "Dark Souls" experience (or you enjoy pausing the game to scan). Just keep changing the value and scanning for exact match. If you want, you can also scan for
11 | `Decreased Value` or `Changed Value`, but those scan methods will eliminate less results, on average. I usually use those
12 | when I am unsure of the value I am looking for. For instance, if we wanted to, we could find the HP of the Unicorn Raft,
13 | but in my experience, you end up running out of ammo before finding it.
14 |
15 | You might notice that you end up with 3 values, and they all seem to change when you shoot. You can select all three of
16 | these and drag them down too your `Address List`. You can right click and `Add to new group` and click "no" to "address
17 | support." Addr Support just gives you a memory address for that header, but this is just a group. You can rename this group
18 | `Ammo L2` by double clicking the description, and if you want to compact them, right click the top of the group and go to
19 | `Group config -> Hide children when deactivated`. Now you can click the check box on your new group to see the addresses.
20 | Check all the boxes under this group to lock them. Notice you will lose ammo once, but will not continue to lose ammo
21 | after subsequent shots. You can uncheck the boxes one-by-one to figure out which one is the real ammo, and then label it.
22 | I labeled the other two "UI/Mirror?", as this is the best guess I can come up with. These are either values for the UI,
23 | or they are redundant values that are part of a mirror. Could be wrong, though, just my guess.
24 |
25 |
26 |
27 |
28 |
29 | Flag
30 | GHCTF{oops_sorry_mr_unicorn}
31 |
32 |
33 |
34 |
35 | # [Next](L3.md)
36 |
--------------------------------------------------------------------------------
/L1.md:
--------------------------------------------------------------------------------
1 | # Level 1
2 |
3 | ## Objective
4 | Get the gun. For some reason, you have to kill the gun to get it. There's a turret in the corner of the room, and it shoots
5 | at you when you run into the gun in the middle of the room, and damages both of you. The gun has slightly more health than
6 | you, but you are armed with Cheat Engine!
7 |
8 | ## Solution
9 | In Cheat Engine, we will start by doing a scan for `Scan Type: Exact Value`, and `Value Type: All`. Make sure that your
10 | settings don't have Executable selected. A square in the checkbox means it will include memory with that permission in the
11 | scan, a check mark means it will only look for memory with that permission (so if writeable is checked and executable is
12 | checked, it will only find writeable executable memory). We do want to see writeable memory, though.
13 |
14 | Then we just want to search for our current hp. It's 100 at the start of the level, but if you already tested that the turret
15 | works as intended, change the scan value to whatever your current hp is and hit `First Scan`. You might get a ton of matches,
16 | and it might even show nothing in the panel, but say `Found: 400,000` or something like that.
17 |
18 |
19 |
20 |
21 | Don't be frightened, though. We are going to narrow that down. Cheat engine will only scan the addresses it found in the
22 | previous scan. You can even tell it to only compare to the first scan, if the situation calls for it. So, run into the gun
23 | in the center of the room, and take some damage. Now let's change the scan value to your current health and hit `Next Scan`,
24 | this time. This should narrow it down to a few results, and if you are lucky, just a single result. If the memory address
25 | for the health is not obvious, just repeat the process until you narrow it down to one obvious result.
26 |
27 | Double click the address and it will be saved to your `Address List`. If you click the check box, it will freeze that value,
28 | and you can now bump into the gun without consequence!
29 |
30 |
31 |
32 |
33 | You will need to jump to get the flag, and then open up the inventory (`i`) and get the actual flag!
34 |
35 |
36 | Flag
37 | GHCTF{this_is_the_first_flag_woot}
38 |
39 |
40 |
41 |
42 | # [Next](L2.md)
43 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GameHacking.gg
2 | There is a preamble, explaining the tools and installation of the tools, in this README. If you are already familiar with
3 | the tools, you may also want to do a cursory check of the game code, in dnSpy, as well. I disable the anti-cheat, here, before
4 | ever running the game.
5 |
6 | Thank you to the crew at [gamehacking.gg](https://gamehacking.gg/). It was great to meet you guys at defcon! This is a great
7 | introductory challenge to game reversing. When reversing modern games, I generally use Cheat Engine and some kind of decompiler,
8 | like [Ghidra](https://github.com/NationalSecurityAgency/ghidra). C# assemblies are much easier to understand, than a compiled
9 | binary, though, so this is a good way to get used to using these types of tools in tandem, while not having to get too far
10 | into the weeds with machine code.
11 |
12 | # Levels
13 | Guide for each level.
14 | ### [Level 1](L1.md)
15 | ### [Level 2](L2.md)
16 | ### [Level 3](L3.md)
17 | ### [Level 4](L4.md)
18 | ### [Level 5](L5.md)
19 | ### [Level 6](L6.md)
20 | ### [Level 7](L7.md)
21 | ### [Level 8](L8.md)
22 | ### [Level 9](L9.md)
23 |
24 | ## Unity games
25 | Today, we are going to look at a Unity game. We are going to use dnSpyEx for reading and editing the source code, and we are
26 | going to use Cheat Engine as our debugger. The game has not been release, yet, and was only available at defcon, but will
27 | be released, possibly with additions, eventually. You can check back here, or https://gamehacking.gg/ for updates, on that.
28 |
29 | ### [dnSpyEx](https://github.com/dnSpyEx/dnSpy/releases)
30 | Above is a link to the version of `dnSpyEx` that I downloaded and installed. After installing it, you will need to install
31 | the Unity game you want to RE, and then you need to navigate into the location of the actual game code, or what is unique
32 | to the particular game, is located at `GAMENAME\GAMENAME_Data\Managed` where `GAMENAME` is the actual name of the game you
33 | installed. In our case that is `GameHackingGG\GameHackingGG_Data\Managed`. Inside this is `Assembly-CSharp.dll`. We will
34 | drag that file into `dnSpyEx`, and see what's in it! The first thing we see, is, an anticheat class.
35 |
36 |
37 |
38 | We can actually stub most of this, although I think, by looking at the [Unity documentation](https://docs.unity3d.com/ScriptReference/MonoBehaviour.html)
39 | we can see that `MonoBehaviour` classes have a `Start` and `Update` function. I assume those are really the only two functions
40 | that need to be stubbed out, but I also replaced the `GetHashOfCode` function to return an empty string, and the `IsCheatProcessRunning`
41 | to return true, anyways, just because it's pretty easy to do. (Right click each function and use `Replace Method Body with
42 | stub...` menu option. I just had to edit the `GetHashOfCode` function to return empty string, as it return `null` by default
43 |
44 | All you have to do is right click the code you want to edit, click `Edit IL Instructions...` and change it to ldstr, and
45 | it automatically loads an empty string for return.
46 |
47 |
48 |
49 |
50 | You must select the module and then go to `File > Save Module` for your changes to take place.
51 |
52 | ### [Cheat Engine](https://www.cheatengine.org/)
53 | Cheat Engine is a fantastic dynamic analysis and debugging tool that is absolutely SLEPT on outside of the modding/cheating
54 | community. Even though it has "Cheat" in the name, it's really just a debugger and memory viewer that has x86 assembly,
55 | lua and C as a scripting language. It also comes with some really cool tutorials, so, you should check those out, too, if
56 | you haven't, already!
57 |
58 | Make SURE you skip all of the adware when you install this tool. It is a free tool, but, only free because of the advertisements
59 | and software "bundled" with Cheat Engine, of which you can clikc "Skip All" to skip all of them, at the start of installation.
60 |
61 | We also will want to go into our settings, and make hotkeys for the `next scan` types. I like to bind `Decrease Value` to
62 | F1, `Increase Value` to F2, `Changed Value` to F3 and `Unchanged Value` to F4. These will allow you to quickly scan the game
63 | as you are in it, via hotkey.
64 |
65 |
66 |
67 | More about CE will be explained as these levels progress.
68 |
--------------------------------------------------------------------------------