Well, I don’t really know why I made this. It seemed like a good idea a few days ago, so I started investigating and it all kinda followed. I am not involved with DayZ or other RPG like mods for Arma any more, but I think my past experience with them must have had a say on the matter. Anyway, what is it and which way is up?

hash_id extension is a very fast hashing .dll that produces a hash based on some data you pass to it plus some secret internal data. The hash it is produces is a 10 digit number. So what do you do with it? Let’s say I have a server spawned object, something like a vehicle, for example. As server script spawns it from the database, with hash_id I can quickly assign a hash to it and store it on the object. Now imagine some script kiddie that would normally not have assess to scripts in mission, downloaded a cheat engine and was able to spawn himself an Apache. The thing is, if I check that Apache for whether or not it has a hash, it will not have one, so I can safely assume it has been spawned by 3rd party and do something about it.

I can also quickly check if the object I’m about to save in the database is also a legit one. For example in my DayZ days I made it possible to build a vehicle from scratch on our server, which meant inserting it in the database as someone assembled it. Or what about if you have created few rare objects as part of your game and need to be pretty sure whoever finds them did not just help themselves? There are probably other uses for it I can’t think of right now.

dayzmad_monitor

Of course there could be other script only solutions on how to distinguish legit objects from hacked. Such code will have to be kept on server side in secret. With my way it not necessary, hence I’m publishing this in the open. The .dll itself generates few random combinations when it stars so even I don’t know what they are. Of course if you leave a back door and let script kiddie run his scripts on the server, nothing in the world will be able to stop him. So I’d say, as long as server side is protected, it should do. Anyone can see the code and I will even explain how it works.

On the first start the .dll generates random id which will be stored in server variable which is based on profile name and hence custom, so more work for a script kiddie. Each object has a unique id and a class name. Both these values are passed to the .dll and mixed with some random per session generated secret word and converted into a hash, which then returned. This hash could be public, but script kiddie cannot know it either because it is stored on the object server side. A hacker can overwrite it out of spite but he needs to know the name of the variable in object namespace, which is also hidden behind two locks so to say.

The server knows where to find the hash, so when you want to verify it, the .dll will take the same id and class name of the object, generate hash for it again but this time compare it to the hash that stored on the object. If they match, you know the object is legit. Is this unbreakable? Of course not, but as long as it makes work for a script kiddie it is all that matters. Unless there is substantial gain to be had from a hacked object, I doubt anyone will waste their time trying to break it. And of course, if broken with few changes in the code server side, it is the whole new mountain to climb for the hacker again.

Now lets talk about performance. I can theoretically store ids of the objects on the server in an array and check against this array. As my array grows, so is the time it takes to check for matches. It is fine if you do it once or twice. If however you do it repeatedly, it becomes a problem. Running .dll to compare the hashes is actually much faster (depending on the length of the array). Could easily be like 5 times faster.

Anyway the code. You need to download the hash_id_v1.0.zip and place the .dll it contains in Arma 3 root directory on the server. You might need to download and install Visual C++ Redistributable for Visual Studio 2013 from Microsoft website to make sure the extension works without a hitch.

The following functions are wrappers to use with .dll and can be modified to your liking. I suggest compileFinal all public functions and maybe move them out of missionNamespace for a better security. Also put all that in server side file that is not part of the mission and will not get downloaded by clients.

This code should be executed only once on server start up:

with uiNamespace do { if (isNil profileName) then { uiNamespace setVariable [ profileName, "hash_id" callExtension "rID" ]; }; };

This code is the actual code for adding hash to an object. I suggest not to turn it into a function but copy paste it wherever you’re generating your objects:

_obj call { _this setVariable [ uiNamespace getVariable profileName, "hash_id" callExtension format [ "%1:%2", netId _this, typeOf _this ] ]; };

This code is to check if the hash matches. It will return true if it does, or false if it doesn’t. Furthermore you can make it spawn a function that will deal with failed authentication:

KK_fnc_checkHash = { if ("hash_id" callExtension format [ "%1:%2#%3", netId _this, typeOf _this, _this getVariable [ uiNamespace getVariable profileName, "NULL" ] ] == "PASS") exitWith {true}; 0 = _this spawn KK_fnc_logFailed; false };

Example function for failed authentication. I used my debug_console extension because it happens to be almost 10 times faster than native diag_log command, would you believe it?

KK_fnc_logFailed = { _dcout = { //log in yellow on screen and in file "debug_console" callExtension (format _this + "~1101"); }; [ "Vehicle => OBJ:%1, TYPE:%2, NETID:%1", _this, typeOf _this, netId _this ] call _dcout; //log vehicle and netId [ "Position => POS:%1, MAP:%2", position _this, mapGridPosition _this ] call _dcout; //log veh position and map grid { if (owner _x == owner _this) then { [ "Owner => ID:%1, NETID:%2, UID:%3, NAME:%4, OBJ:%5", owner _x, netId _x, getPlayerUID _x, name _x, _x ] call _dcout; //log current owner }; } count playableUnits; { [ "Crew => OBJ:%1, NAME:%2, UID:%3, SEAT:%4", _x, name _x, getPlayerUID _x, assignedVehicleRole _x ] call _dcout; //log current vehicle crew and vehicle seat } count crew _this; { if ( isPlayer _x && {_x distance _this <= 100} && {!(_x in _this)} ) then { [ "Near => OBJ:%1, NAME:%2, UID:%3, DISTANCE:%4", _x, name _x, getPlayerUID _x, _x distance _this ] call _dcout; //log near players and distance }; } count playableUnits; _this setDamage 1; //destroy it deleteVehicle _this; //delete it "debug_console" callExtension "A"; //alert beep //use url_fetch to alert admin anywhere? };

An extra function if you need a random string id:

KK_fnc_makeRandomId = { "hash_id" callExtension "rID" };

Enjoy,
KK