This is going to be a little messy. There are better ways (multiple vtables you can hook, also you can change a pointer in a script VM context to stop an individual thread from reporting to BE, etc.) but this has the advantage of not requiring any hooks, whether hard hooks or vtable hooks, which makes it considerably less detectable by Battleye, which currently checks a couple locations to check for BE Callback function VTable modifications. The giant disadvantage is you have to predict how the script engine will parse your scripts, which could be difficult.
Every time your client executes a script, it’s broken into expressions that are executed by the script engine. These expressions are pushed through a series of functions that eventually end up at Battleye’s callback function if you are in a multiplayer game with Battleye enabled. After it runs through Battleye’s callback function, it’s added to an AutoArray of recently run script expressions. Then, the next time a script is run, it’s checked against the array of recent expressions and if it matches one of these expressions perfectly (a map exists a few bytes earlier in the function, if the key for that expression exists in the map, it isn’t sent to Battleye for processing)
|This image has been resized. Click this bar to view the full image. The original image is sized 1274×772.|
I’m sure you all see where this is going.
The script expressions are just regular c strings – they’re pointers to character arrays with ascii strings of the expression.
|This image has been resized. Click this bar to view the full image. The original image is sized 1446×816.|
It’s in the NetworkClient class, the same place that links to your scoreboard. It’s at 0xDEEAE8 + 0x24] + 0x1DC. It contains a max of 200 expressions, and is a FIFO queue. So if you know you need to run a couple of expressions that will get you kicked, you could add these expressions to the end of the queue and run these expressions and these expressions would not be run through Battleye’s callback function, bypassing the server side script restriction filters in many cases and bypassing Battleye’s client side script detections entirely.