Adventure Travel Abroad

Reading Player Position with DLL Injection – Pwn Adventure 3

Reading Player Position with DLL Injection – Pwn Adventure 3

I really wanted to implement a proper fly-hack
for Pwn Adventure 3. After failing around when doing this on Linux,
I thought I could need some help when doing this on Windows. So I contacted Guided Hacking, who makes awesome
easy to follow game-hacking videos, and asked for some help. I asked him if he can figure out how to make
a fly-hack and then explain it to me, and then we have a YouTuber collab. He said yes and followed up with a basic plan. The best way to do a fly hack is to overwrite
your current position values, like you do. But you get the next position variable (for
flying forward), using trigonometry. You do what’s called a translation moving
a 3d coordinate in a specific direction. You can do this with matrix multiplication
using the world view projection matrix, but it’s easier just to do simple trigonometry
cosine, sine, arctang etc. I already have code written for this that
I can share. I actually wrote this code because Stephen
Chapman asked a question on Stack Overflow and I knew the answer. So I felt like a boss. Stephen Chapman is another awesome youtuber
with some game hacking videos. So that’s why that is funny. So here is the code. You can see here a function MoveInCameraDirection
and then it does some trigonometry. If you are still in school, you should really
pay attention to trigonometry and especially matrix stuff. If you are interested in game hacking or game
development, you need that foundation. Anyway. A few hours later Guided Hacking got back
to me with a Visual Studio project and some code. But he added that “something is not right. Here it is in it’s broken state if you want
to take a look. Of course I want to take a look! So what is it that Guided Hacking sent me? In the folder you can find a .sln file, so
that’s a “solution” file (a project file) for Visual Studio. Let’s open it up and have a look. Let’s start with the dllmain.cpp. This defines the entry point for the DLL application Based on this here. “How to hack any game – First Internal Hack
DLL Tutorial”. And here is a good description of what this
is all about: Internal hacks are created by injecting a
dynamic link library or DLL into the game process. when you do this you have direct access to
the process’s memory which means fast performance and simplicity. Normally a DLL is used to export functions
and to be used like a lib, accessing the functions from the lib when necessary. But in our case, we’re just going to use them
to get our code to run in a target process. Injected DLL’s can be made more sneaky by
using different injection methods such as Manual Mapping. So yeah. This Visual Studio project is just creating
a .dll And when the dll is injected into the target
process, the DLL main entry point will be executed. The system calls the entry-point function
for a DLL when it is loaded or unloaded using the LoadLibrary and FreeLibrary function. And upon the DLL_PROCESS_ATTACH case, we create
a new Thread so that it can run in parallel in the background. The HackThread. And this HackThread then does the magic. Remember, you have to imagine that this code
is now running in the PwnAdventure game process. And so here you can see that it uses GetModuleHandle
to get a handle to the GameLogic.dll module, which basically returns the address where
it is loaded. And you can see it being used here in the
function “FindDMA” (direct memory access) addres. And here we have the start address, followed
by a pointer path list. Pointer paths. They are just everywhere. We can also peek into that FindDMAAddy function
to see how it works. It’s very simple. Ptr is the starting address and is assigned
to the variable address. offsets is a vector, or list of the offsets. And here we have a loop that loops over those
offsets. So addr, and at this address we have a value
that is another address. So we dereference that now, which means we
follow that address. So addr is now the new address. Then we add the offset to that address. This should now point to a new location that
stores another pointer (or address). So in the next loop we dereference that and
follow that address. So now addr is that new address, we add the
offset and we get the new location. And we do that for all offsets, and then return
the final address. If we then cast the pointer we found to for
example a 3d vector, then we have now a position variable pointing into that memory. That’s how we can then read or write those
values. So apparently Guided hacking found some position
and angle vectors at these locations in memory. Around this code you can also see GetAsyncKeyState,
which checks if you press a certain key. This is used to enable or disable the fly
hack, here the numpad key. And also numpad 5 is apparently used to move
into camera direction, so this should fly around. And with the END key, it should break, then
of course return, thus exit the thread. By the way there is also a call to “AllocConsole”,
which is another wondows API function that will create a new console for the calling
process. And then with std::cout, you can write text
out to the console. I actually didn’t know that it’s that
simple to create a console for a process. Cool. Alright. Now Guided Hacking already said that it doesn’t
work. But this is already very helpful, because
we can build upon that. We can use it as a template. In the last video I showed you how I found
the camera position and view direction. This means we could now use those pointer
paths! So let’s create a new DLL project. Visual C++, Windows Desktop, Dynamic-Link
Library (DLL). And we call it pwn3hax. If we look into the source files, we can see
that Visual Studio already created the dllmain.cpp file with the DLLMain entry point function. As you can see, looks pretty similar to the
example code by Guided Hacking. So let’s just copy and paste that code. Visual Stdio already warns us about types
like FILE that they can’t be find. For that we need to include stdio – standard
in and out. Looks already better. But of course the mem namespace and this vector
3 is also still unkown. Let’s add the include of the mem header
and then we have to add a new file, header, mem.h
Copy and paste that code. And then we also need the mem.cpp file. Copy that too. Wow!! We are incredible fast programmers. Copy&paste! But don’t tell anybody this secret of programming. *shhhh* Let them all think you need to remember
everything! So the mem.cpp by Guided Hacking defines three
functions. Patch, Nop and FindDMAddy. The last function we already looked at. Path and NOP are very similar. They both use the VirtualProtect Windows API
function to change the permissions of this memory area to be writeable. You have to do this in case it;s non-writable
memory like the assembly code. But after that you can simply use memcpy,
or memset to that address and overwrite it. Patch will of course copy the bytes you want
to patch. And memset writes assembly NOP instructions,
which is a hex 0x90. Cool! This will be useful. And let’s also add the geometry files geom.h,
which gives us this 3-d vector vec3 and the geom.cpp file, which contains some trigonometry
functions. After we include the mem.h in the dllmain,
we can also try to compile it. STRG+SHIFT B.
And we built it. We have pwn3hax.dll. Let me quickly modify a bit the code. Because my keyboard doesn’t have a numpad. The key that should toggle the fly hack enable
or disable I set to Left Control key. And the flying around I set to the right mouse
key. We know this doesn’t work yet, so let’s
remove some of the code here, only keep the position, and then add a debug output with
cout, to print the position. Let’s try it out. Compile the .dll, there we go. Now we just need to figure out how to inject
the DLL. Because I don’t want to go into detail right
now how DLL injection works, we are just using a tool. Actually Cheat Engine can also inject a dll. It’s here in the tools menu. But I’m going to use Guided Hacking’s
Injector tool. It has a lot of features. I guess at least. I have no clue. I’m just gonna try to load a dll. So here we specify the process we want to
inject to, and here we select the dll file. The built dll is in the Debug folder. Pwn3hax.dll. After that we can hot Inject. And that seems to have worked, because we
get the console with the debug output. Now we are in game. If we press the left control key, we should
be able to toggle between the fly hack on and off. That works. Now that it’s on, let’s try to press the
right mouse key and see what happens. Oh… game crashed… I guess this doesn’t work at all. So let’s quickly take the pointer path we
have identified with Cheat Engine and replace it here. By the way, pay attention to the correct pointer. Because we cast this memory to a 3d vector,
we need the pointer to the first x coordinate. And it turned out I labeled them wrong, and
when I tested it I read garbage values. So the first coordinate is at offset hex 0x90. So let’s build it again, and inject it into
the game. Enable the fly hack. Press right mouse button, and there we see
output!!!! We can now move around and observe the player’s
position. Or more precidely, the camera’s position. If we jump we also only see the z value change. Awesome! We can build upon that. Thanks Guided Hacking for making this so easy
for me!

Reader Comments

  1. Amazing video as always! By the way are there any good resources to practice binary exploitation and web exploitation? I have found blogs like but they present so many options that as a beginner to infosec, I find my self confused. Which sites / resources would you recommend for me to get started?

  2. the only vedio i liked all your vedio is this couse today your jocking i dont know what happen (copy and past hush🤐) the only channel i interest #thank @liveoverflow

  3. the next will be calling internal game functions via dll? just casting game function address to the function pointer with appropriate signature (args and return)

  4. What's the point of injecting (apart from raw speed) if you aren't gonna hook any function and just act like an external? Imho this could have been easily done just with RPM/WPM

  5. I want to try to save you from future frustrations, so here are some small pieces of advice. Be sure to compile your hack for the same architecture (x86 or x64) the game is using. Same goes for the injector, use matching architectures. Also, you may want to compile release builds instead of debug builds. I've had issues in the past compiling debug builds when doing these sorts of things.

  6. I wish you wrote the template code yourself instead of relying on ugly legacy c++ code with disgusting windows typedefs such as BYTE, unsigned int for size in memcpy (which should be void*, const void*, size_t), copying over the offsets vector each time the function is called instead of just using a const reference… the for loop in the FindMADaddy can also be modified into a for range based loop: for (const auto &offset : offsets) {…} where offset is now offsets[I]. besides, using unsigned int as the iterator is wrong in itself when it should have ben declared as std::size_t or even better std::vector<unsigned int>::size_type. also, note that offsets.size() is called in each iteration! this will most definitely cause performance issues. a better alternative is to either use a std::array<uint32_t, 4> where 4 is the size of the offsets given from the caller or the modernized for range based loop I described earlier, which relies on iterators.

    avoid c-style based casts! instead of writing uintptr_t moduleBase = (uintptr_t)GetModuleHandle("…"); you should write:
    const auto moduleBase = static_cast<uinptr_t>(GetModuleHandle("…"));

    or for dereferencing a pointer: instead of addr = *(uinptr_t)*addr; you should write:
    addr = *reinterpret_cast<uintptr_t*>(addr);
    this way you tell the programmer (mostly yourself) which cast is explicitly used instead of using the old c-style cast method.

    all these things just make the whole code base ugly and almost unmaintainable, especially for such projects where dereferencing a wrong type can cause surprises to some people, when you should've used the correct types from the beginning.
    also, things like const double pi = 3.141…; are evaluated at runtime not not compile time. one should rather use something like:
    constexpr double pi = std::acos(-1); // the compiler does the job for you (only works in gcc, I tested on trunk)
    for clang / msvc:
    constexpr double pi = 3.14159265358979323846;

    the vec3 struct in geom.h is not well written either and could even be declared as a constexpr template class imo, here's a quick implementation which is fast and does the job (note, that this implementation is in R^2 dimensions and not in R^3. however, this can easily be adjusted): // compiled with gcc -std=c++17 -O3 -Wall -Wextra -Wconversion -pedantic-errors

    please don't take this personally, I love your videos. I'm just nitpicking on these things because I find them extremely important as you're planning to build upon this code :).

  7. Hey m8 would you make a video or just answer this comment with recommended hacking channels? Every time I search for them i get a bunch of wack stuff

  8. I'm so happy I could help even tho the code didn't work! In theory it should have worked but I am super excited to see your solution in upcoming videos!

  9. Ich feier deine videos einfach, sie sind so unterhaltend und man kann ziemlich schnell neues lernen, auch, wenn man schon denkt, so ziemlich alles zu wissen! Bitte mach weiter so, schade, dass du nur so selten hochlädst!

  10. "Who has a numpad in 2019?" You need it all the time!!! Serously, the mech keyboard modding scene needs to get their stuff together! hmpf…

  11. 6:38 <3 :DD btw best quote I've ever heard regarding this is:
    "-Copying code (from StackOverflow): $1
    -Knowing which code to copy (from StackOverflow): $100000/year"

  12. Brings me back to my old America's Army hacking days. Oh man we were spoiled with a full SDK made by some boss programmers that reverse engineered the Unreal game engine. DLL injection was the method of choice, and we'd hook the render function and have access to all the good stuff

  13. Man, all this just to mess around in the game? Bah, this is why Unity is better, all you have to do is decompile the DLL using dnSpy and BAM, the entire game's code is right there.

  14. One thing i dont understand is why these games dont just make some kind of memory manager for sensitive game variables?
    I imagine it could work by first allocating a big chunk of memory on the heap, then obfuscate & break every single variable up into individual bytes (or even bits) and then scatter them around the chunk. All you would need to do is store the individual byte locations in some kind of table (which itself could be obfuscated).
    I suppose you could even move the memory around dynamically, say, every game tick as long as you just make sure to update the table.

    The only way i can see to get around this, would be to actually reverse the entire game (or the majority of it, atleast) from scratch.
    I believe there are already games that do this (like runescape), I just dont understand why big competitive games like csgo dont do it as well?

  15. Creating threads in DLLMain is risky. Yadayada loader lock, don't do anything in DLLMain. The use of another thread also introduces boring old, yet always complicated, threading issues, such as reading data that's not in a coherent state because another thread was busy modifying it. Much simpler to tell the main game thread to run your code at a time you find suitable.

  16. are you ever going to discuss anti debug or anti cheat bypassing (the basics obv, and anti cheat that’s meant to be broken into so you don’t get sewed ;))

  17. This is going to be veeery useful for a "cheat" that I need to build in the future. For what? Adding legit, non-cheaty functionality in a simulator 😀 (aka modding)

  18. You can use a math library called glm for easy to use vector/matrix math. (It's open source so if you don't want to include the entire lib, you can use the source code)

  19. I just wrote this same hack for pwn3. Its much easier if you rotate the coordinate system to be relative to the players looking direction then add/subtract for movement forward/backward, etc. You can then take the inverse of this rotated coordinate system to return a new location in the games coordinate system. I think your hack didn't work because pwn3 does some weird things with quaternions that have to be corrected for. Anyway, here's the code (dont judge it, i know its bad)

Leave a Reply

Your email address will not be published. Required fields are marked *