* You can set a read watchpoint using debugging APIs (ptrace);
* You could place the honeypot in a memory page(s) that has its read permission revoked. An attempt to read the page(s) causes a signal to fire. In order to not crash the application, the code would then handle the signal by making the mapping readable, before continuing execution as normal.
Other approaches probably exist too, these are just the two options I would personally try first.
There is also userfaultfds on Linux: they're a file descriptor on which the kernel will send fault events, and let a userland process handle the page fault.
So, e.g., you alloc a blank page into memory: it isn't mapped yet, so the first read will trigger a page fault. You register that page with your userfaultfd. You (Dota, here) never read from it. If the userfaultfd receives an even that the page is faulting, then it isn't Dota/you that's reading from it.
Judging from the comments it sounds like Windows has similar capabilities.
… there are all sorts of false-positives here. (Or with any honeypot, really.) Many are mentioned elsewhere in the comments…
> You can set a read watchpoint using debugging APIs (ptrace);
What kind of read is sufficient to trigger this? If dota makes a read watchpoint with ptrace, my cheat process calls the linux equivalent of readprocessmemory on the dota process, then dota gets notified by the kernel? So every time a process directly interacts with the memory of another process, the kernel has to look through a list of which processes have called ptrace and run some kind of handler? As an aside it seems like this would be bad for performance of the whole OS
If ptrace is a syscall and ptrace (according to wikipedia) allows one program to intercept and manipulate another program's syscalls, then couldn't I just launch my cheat first, have it ptrace dota, and intercept dota's ptrace call, so that the read watchpoint never gets set up in the first place?
The old saying goes (basically the same as with Malware vs Anti-Malware): Whoever loads first, wins. So you are right in theory, you could intercept any call that would allow you to detect malicious behaviour. That being said two things:
1.) Windows is a closed-source and really huge system. There are many places you will leave traces, and they change all the time. Getting it right is hard.
The super exotic theory would be a rootkit, in those cases not even windows can help you. But as with security, as long as there is easy money to be made (because most anti-cheat systems are simply bad), those very expensive solutions will be limited to selected few professionals.
I think throwaway40602 from the previous discussion had it right - there's a variable that clients can't normally set (dota_use_particle_fow) that allows seeing some particles/spells and allows guessing where the enemies are trough fog of war. You can even find open source implementations years back for this. It appears to be a popular feature in cheats.
They probably just query the clients to see if it's set. Querying client cvars from the server is already built in the game engine.
If true then the announcement just made it sound way more amazing than it is.
Could just be a simple property that existed on some game object, which was exposed in the interface but nothing in the game ever accessed the property. Then a getter would report the read to their backend. The cheat programs probably automatically read every property of these objects.
I'm no reverse engineering expert but I doubt cheats would actually call getters when they have access to the raw memory underneath.
Maybe lazy cheats do use that mechanism, but it's hardly a foolproof system. If this is how detection was done, I imagine Valve has targeted this detection system for a specific cheat tool/framework.
Yes I'm seeing now how unsophisticated and probably incorrect my approach is, clearly running into the limits of my understanding of compiled programs / cheat engines :)
Possibly - a lot of Source engine (and so probably Source 2 as well) plugins work by reverse engineering Linux/Mac builds of the games and building class definitions for in-game objects and calling the methods to get health/armor/ammo counts etc.
You could potentially use a timing-based approach - if the "first" read to the area is fast enough to suggest it has already been demand-paged in then that would indicate someone else already touched the page. Obviously there's lots of caveats, you can't guarantee a page won't be loaded in anyway without anybody touching it, and it also requires the cheat software to touch that section of memory even though it's effectively unused. If you had a good understanding of how the cheat software worked and went about probing your process's memory I suspect you could make it work though (whether the accuracy would be acceptable is a different matter).