Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

This is absolutely incredible work! How hard was it to get your foot in the door on having code execute on an already running process? Do you do this from a separate process at runtime or is it all modifying the executable before you run it?

I've never done anything like that. I can imagine getting the memory offsets for things like camera transforms being reasonably straight forward with cheat engine, but mutating the values feels a like converting a train from diesel to electric while it's carrying a load. It reminds me of something Ross Scott (he makes youtube videos about games) has expressed a desire to have -- the ability to comprehensively map and record the 3d worlds of games that are going to get shut down. Admittedly I initially dismissed it a little on the grounds that if you want that, just extract the 3d model data from the client and load up blender.

Seeing what you and others have done is making me appreciate what he's after more. The whole composition, environments and characters and lighting and visual effects and post processing would not be preserved just by yanking out the .fbx files and textures. A lot would be lost. Despite being a gamedev myself, seems like I somehow lost the perspective a little.

It's awesome to see there's a community and a hobby doing what you're doing. Thanks for showing this to me.



> This is absolutely incredible work!

Thanks for your kind words!

> How hard was it to get your foot in the door on having code execute on an already running process? Do you do this from a separate process at runtime or is it all modifying the executable before you run it?

All is done at runtime. By nature of how Windows DLL work, they have a DllMain that's executed every time you load a dynamic library into a running process. From there you spawn a thread and you can do pretty much whatever you want within the same memory space of the games. There are multiple ways of injecting a DLL into a running process, and since I only care about offline games, I don't have to fight against any anticheat and stuff so it is pretty straightforward, it is a very interesting topic to read about to be honest!

> I can imagine getting the memory offsets for things like camera transforms being reasonably straight forward with cheat engine

Cheat Engine is an amazing tool, for real. I remember using it when I was a kid to do very rudimentary cheating -- just scanning and changing values; years have passed and one day I opened Cheat Engine again to... skip over an annoying mechanic of a game and I noticed it can do so much more! it has a very good debugger, disassembler, memory view, you can even inject your own assembly code. It was the gateway drug that I needed to get started on everything I do.

> but mutating the values feels a like converting a train from diesel to electric while it's carrying a load

Well, compilers are pretty straightforward (at least, most of the time), it's all about memory layout.

If you have something like

  struct vec {
    float x;
    float y;
    float z;
  };
Once you find the pointer to the objects you need, most certainly they're going to be each one after the other. This looks like obvious knowledge, but at least on my brain I had to build an extra bridge to realize how simple it is :) (of course things can always get complicated but this is the basic gist of it).

And as long as you know your programming language has a stable memory layout, you can map it from your code. I even was able to map some very basic virtual class from C++ within Rust by mapping the virtual tables.

What I enjoy the most, is that I learned a lot about low-level programming, assembly, how OS and compilers work together, while having fun playing games, and developing tools that people can use to create pretty images -- it felt like the outcome was extremely positive and it brings me a lot of joy.


Ah yeah, what you're saying about memory layouts makes sense to me. I'm writing a custom netcode that sends MessagePack serialized structs over udp. Looking at the raw bytes of the message makes debugging easier sometimes. When things get spooky, the first thing I do is turn off things-that-occlude the struct. Things like RLE / encryption / signing / compression and see if it fixes things. Divide and conquer from there. Series of techniques I honed writing a lidar driver with no documentation on a device years ago. Lot of staring at hex dumps from wireshark. :)

I guess I imagined more challenges in not getting any writes you do stomped by some other code that really wants to set a value on your vec every frame. Maybe I'm overthinking it and it's an easy happy path to get your injection to occur "at the end of the update" where your assignment actually makes it to the screen.

Cheers.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: