Hellop 0 Posted May 4, 2008 This is a Request for Information, a Brainstorm, an Informative Analysis of hack prevention useful to mission makers: When coding an Arma mission, should we think about where we store game data in order to reduce hacking? For example, your players have an attribute called "Money". You could: 1. Have a Money variable on the client only 2. Have a Money variable server that keeps track of all clients' money. Then when the player earns/transfers/uses money, his client must get or set the Money variable on the server. Assume the hacker client has a "console" where they can run any scripting command. So, they can change any local variable, but can't directly change anything on another client or server. They can also publish Public Variables with any value. If the mission is designed in such a way that allows the clients to set data on other computers or the sever, then the hacker could alter other people's games. So, a good practice would be to only allow clients to run a limited number of scripts, or change a limited number of Public Variables. IOW, have a subset of your scripts that are only used for network communication. "PV functions". Then as a mission designer, your could more easily monitor the communication and potentially detect cheating. For Example: The hacker could run the script that deposits money in his Bank. The server keeps track of the players cash on hand, and the bank balance. So, if the player sends a command that deposits more money then he has on hand, you have detected a hacker. Now, the createVehicle or setVehicleInit commands are able to bypass any such checks, so the whole idea of trying to stop hackers at all is pointless. Unless, the Init eventhandler is executed before any type of object executes it's initline. Then the server could just monitor spawned vehicles checking for anomalies. It says it only fires on createVehicle, so we're probably SOL. Now, assuming we could guarantee the clients can't improperly alter data on other computers. They could still run local commands that had global affect. Like, setPos, setVelocity, setDammage on any unit or object. Well, after thinking about it, it seems hopeless to have a scripting defense from hackers. Is there anything we can do to prevent or detect hackers? Share this post Link to post Share on other sites
mattxr 9 Posted May 4, 2008 Use DooACS anticheat and it stops people with script consoles etc etc, then use BE to stop those running outside of the game cheat programs. Happy GaMeInG Share this post Link to post Share on other sites
brit~XR 0 Posted May 5, 2008 Doo acs is outdated man. It wont stop cheaters. Theres cheats that can bypass it but i wont name them ofcourse. Signed files is the best way to go vs pbo hacks. Battleye is best way to go vs memory hacks Share this post Link to post Share on other sites
Hellop 0 Posted May 5, 2008 Doo acs is outdated man. It wont stop cheaters. Theres cheats that can bypass it but i wont name them ofcourse. Signed files is the best way to go vs pbo hacks. Battleye is best way to go vs memory hacks Brit, I hope you will send those new cheats to Doolittle so he can update DooAcs. Share this post Link to post Share on other sites
brit~XR 0 Posted May 5, 2008 He already knows about them. There listed on a well known cheat site. Doo acs which used to be called dacs was kept private and only released to centain people. they got hold of the scripts from that cheat by captureing the packets server sent to clients from that dacs so he made it pubic. It wont stop cheaters. Maybe some noob cheaters but thats it. It was good anticheat tool for its time but not much use vs cheaters now. Me and squadserver have our own way of detecting and dealing with cheaters. Share this post Link to post Share on other sites
Dwarden 1125 Posted May 5, 2008 only correct way is to validate all server side, if someone stores money into bank, counter check against what should he got in wallet etc. in short never ever trust anything from client ofc You need to trust his position, movement, speeds, fire etc. but even that could be validated to some degree (e.g. if moved between locations faster than possible etc) Share this post Link to post Share on other sites
Hellop 0 Posted May 12, 2008 Maybe a good way to stop cheaters would be to have some flags like you guys suggested... Some checks that determine that a client is doing something weird. That combined with player reporting, then: -Have a script that allows an admin to camera/watch players for cheating.... Share this post Link to post Share on other sites
maddogx 13 Posted May 13, 2008 Ideally, addon signatures + BattlEye should suffice to stop cheats like this, but it definitely won't do any harm to make sure such important variables are kept local to the server. Also make sure the server handles them as local ("_money" for example) instead of global. Otherwise it would be possible for clients to overwrite them using the publicVariable command. Share this post Link to post Share on other sites
mattxr 9 Posted May 14, 2008 Doo acs is outdated man. It wont stop cheaters. Theres cheats that can bypass it but i wont name them ofcourse. Signed files is the best way to go vs pbo hacks. Battleye is best way to go vs memory hacks We use DooACS and it hasnt once let a cheater into our server. Only the outside game hacks but they dont disrupt our games. Share this post Link to post Share on other sites
max power 21 Posted May 14, 2008 If there are cheats that bypass dooacs, there are many more that don't. To say that an outdated cheat prevention software will not stop cheaters is overstating the point by a large margin. It's like saying there is no point to use outdated antivirus definitions. I think that some protection, say, 90% protection is better than 0%. Even 1% is better than 0, but there's a risk vs reward judgement you must make. If I had 1% virus protection, I wouldn't be on the internet. In terms of games, though, I think that if cheaters comprise 10% of arma gamers, and you stop 90% of those, then you're left with only 1% troublemakers- all but the most serious cheaters. These numbers I just pulled out of thin air, but in a situation like this, I don't think that even outdated anti cheat protection is not worth while. Share this post Link to post Share on other sites
Hellop 0 Posted May 15, 2008 I think that some protection, say, 90% protection is better than 0%. Even 1% is better than 0, but there's a risk vs reward judgement you must make. If I had 1% virus protection, I wouldn't be on the internet. LOL, I have no anti-virus. I have a hardware firewall with ethereal tho... Share this post Link to post Share on other sites
Crowe 0 Posted May 20, 2008 Do not use PublicVariable often. Instead of broadcasting a variable each time a player does connect, you can also create an obect and use setvehicleinit instead. Keep all other variables local if the other clients do not need them. Stop cheaters - use signature verification and BattlEye. Yours Crowe Share this post Link to post Share on other sites
Hellop 0 Posted May 21, 2008 Do not use PublicVariable often.Instead of broadcasting a variable each time a player does connect, you can also create an obect and use setvehicleinit instead. Yours Crowe Crowe, can you discuss why using setVehicleInit with code is better then using publicVariable and the new publicVariableEventHandler? I'm guessing that your thinking is that instead telling the server of a state change like this: player5Money = 1000; publicVariable player5Money; You could do: player setVehicleInit "player5Money = 1000;"; processInitCommands; But, I'm not seeing how that's better. Thanks for your input, Crowe. -hellop Share this post Link to post Share on other sites
maddogx 13 Posted May 21, 2008 The general difference between publicVariable and setVehicleInit is, that everything that happens via setVehicleInit will be executed on JIP clients. This is not the case for publicVariable. For example, if you create a mission which contains a variable definition, such as myVar = true, that variable will be true for everyone who joins. Now, if at some point this variable is set to false on all clients by using publicVariable, all clients who were connected at the time will be affected, so all will have myVar = false. But, if a new client joins in progress after the publicVariable command has be executed, it will not affect him - so on his machine myVar will still be true. If you want to make sure this doesn't happen, you'll need to use setVehicleInit+processInitCommands instead. That way, when the JIP client joins, all commands that were executed using processInitCommands will be executed for him too. This has a drawback though: every processInitCommands that has been called will be stored and transferred to JIP players when they join - so if you use this too much, it will greatly increase the time it takes to join. You'll need to decide which method to use, depending on whether the transferred data is important for JIP players too. Here's a quick roundup: publicVariable + no increased join time - not synchronized to JIP players setVehicleInit / processInitCommands + synchronized to JIP players - increased join time Share this post Link to post Share on other sites
suma 8 Posted May 21, 2008 publicVariable+ no increased join time - not synchronized to JIP players Are you sure this is what you see? publicVariable should be synchronized during JIP, the only optimization is only the last value for each variable is stored. Could you perhaps create some very short demo mission showing this? Share this post Link to post Share on other sites
Hellop 0 Posted May 21, 2008 MadDogX, thank you for the detailed reply. It seems to me that using setVehicleInit as a replacement for public variable is not desirable. It's not what it is meant for. Most likely, it was designed to be run one time for each vehicle. It seems unpredictable and redundant to use it for network communication. It seems to me that the desired way for initlines to be run for JIP players, is for the initline to run one time for each vehicle, for whatever the initline happens to be at the time the JIP client joins. But it seems like what you are telling me is that when a JIP client joins every single initline code is run for every single time processInitCommands was run. I can't imagine what the purpose of that is. I don't suggest using setVehicleInit in this manner. Furthermore, the whole concept of publicVariable of "global" variables that can be altered by any client at any time doesn't seem desirable to me either. Because, you do not have control over what your current state is. To overcome this, I use publicVariable in a different way. I simulate a client/server architecture and allow a certain limited number of "commands" to be run. In this environment there is no such thing as a global variable, and the server alone keeps track of the state of the game. This technique, I think, adds to reliability by reducing the possibility of race conditions, and improves performance by reducing polling. Share this post Link to post Share on other sites
Hellop 0 Posted May 21, 2008 Ideally, addon signatures + BattlEye should suffice to stop cheats like this, but it definitely won't do any harm to make sure such important variables are kept local to the server. Also make sure the server handles them as local ("_money" for example) instead of global. Otherwise it would be possible for clients to overwrite them using the publicVariable command. I think this is a very important point and something that I completely overlooked. Your suggestion is to not use server-side global variables to store game state information. However using script-scoped variables would require a certain script that just runs in a loop all the time and never exits. I don't have any infinite loops in my mission yet, and I'd like to keep it that way. What I have in mind to prevent hackers from being able to change values on the server using publicVariable is to have the server randomly generate names of the global variables. Now that will require parsing the scripts and replacing the variable names. Even though concepts like that are un-heard of in most programming languages, it's something that I've always wanted, and thankfully BI provides this functionality with the "call compile format" command. This ability would be synonymous with a java program that altered it's own source code then re-compiled it with javac then ran it. Back to the player money example: When the client gets some money, it needs to tell the server. It runs the "sendToServer publicVariable command" which is basically a public variable scalar value that contains information identifying the sending client, which "PV function" to run, and the data. It would look something like this: "Player15, DepositMoneyFunction, $1000". Now, the DepositMoneyFunction has been altered at mission start so that the name of the server-side global variable that holds the bank-balance information for each player has been changed to a randomly generated name. So, on the server the function is called like this: [15, 1000] call DepositMoneyFunction; Then inside the script would be something like this: kd93kd72sk set [_this select 0, _this select 1]; //kd93kd72sk is the randomly generated name of the array that holds the bank balances for all the players. Inside the DepositMoneyFunction is where you can put your hack-detection checks, and/or logging. In this way, the clients will never know the names of the server's global variables and cannot alter them. This is probably confusing, but if mission designers can use this information in any way to reduce hacking, that would be great. I would be happy to discuss this further with anyone. Share this post Link to post Share on other sites
maddogx 13 Posted May 21, 2008 publicVariable+ no increased join time - not synchronized to JIP players Are you sure this is what you see? publicVariable should be synchronized during JIP, the only optimization is only the last value for each variable is stored. Could you perhaps create some very short demo mission showing this? You're probably right. I guess I made a false assumption there, based on some of the multiplayer scripts I've been working on recently. I've been using publicVariable and the public variable event handler to execute code on all clients, but JIP clients were yielding unexpected results. processInitCommands was working as expected, so I assumed that publicVariable doesn't work at all on clients that join later. Sorry about that misinformation. Share this post Link to post Share on other sites