Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

Decompilation

Discussion in 'General Discussion' started by JamesLeeNZ, Nov 26, 2014.

  1. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    How easy is this to do?

    Only from devices, specifically iOS, but since its on Android, I guess someone with both device types could go through the effort of getting the game on Android if that was easier to decompile.

    Reason im asking, is because I have two new top scores on my leaderboard, and something about them makes me suspicious (could it be the top three scorers are named pin <- I know this ones legit, pan, and pon).. however they would need to know the secret key to be able to generate a false php request.

    It might well be legit, but for someone to get to the end so quickly is... unusual
     
  2. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,317
    They could use a packet analyzer to extract the secret key. You don't even necessarily have to use one on the mobile device if you have one of those routers with customizable firmware.
     
    Last edited: Nov 26, 2014
    Stoven and angrypenguin like this.
  3. Glader

    Glader

    Joined:
    Aug 19, 2013
    Posts:
    456
    I've never dealt with android builds but it appears they are packaged to a .apk file which "is generated with all the required libraries and serialized assets." http://docs.unity3d.com/Manual/android-BuildProcess.html

    A quick google search indicates there are projects aimed at unpacking this. If you can essentially get the actually .Net/Mono assembly from unpackaging then it'd be trivial to make modifications. If inside the package there is just a binary then it'd be a bit more difficult.

    Edit: Reference to a package aimed at unpacking https://code.google.com/p/android-apktool/

    As she/he has said, if you're sending a key over the wire or if it's hardcoded within the application then you're susceptible. Not enough information on what the key does and how you've setup handling requests is given to really know there though.

    Edit: about iOS, I'd imagine it'd be more difficult here as the build process looks less promising. http://docs.unity3d.com/Manual/iphone-BuildProcess.html
     
    Stoven likes this.
  4. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,631
    Yeah, there's no real safe way to determine the difference between a real and a fake client, so they don't need to decompile the code to be able to send dodgy messages. You can make this take longer, but you can not make it impossible.
     
    Cogent and Tomnnn like this.
  5. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    Altruism prevails! The best way is to just make the universe open source :D
     
  6. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,317
    Or record the game as it is played for later verification? :p
     
    Cogent, Stoven and angrypenguin like this.
  7. Stoven

    Stoven

    Joined:
    Jul 28, 2014
    Posts:
    171
    That's typically the best way. The only downside is more data needed per user for the database on the server.

    I guess this could easily be circumvented by only storing recordings for the highest score(s) of a particular category.
     
    Last edited: Nov 26, 2014
  8. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,631
    Yeah, you only need to store ones that matter. Plus, if you record it in a way that can be replayed and (automatically) verified, you don't need to store it for that long - once it's checked you can dump anything that doesn't look interesting and isn't a somehow important score. Plus plus, if you design around this from the start then you don't need to store a whole lot of data.
     
    Stoven likes this.
  9. goat

    goat

    Joined:
    Aug 24, 2009
    Posts:
    5,182
    Very east to decompile but it takes a good programmer to see the design & put it back together. Most likely your score site was hacked since you say 'your' leaderboard and not your leaderboard at Apple/Google's 'Social Game Boards'.
     
  10. greggtwep16

    greggtwep16

    Joined:
    Aug 17, 2012
    Posts:
    1,546
    As said above most likely culprit is a packet analyzer on the network traffic (although both are possible and fairly easy to do if you're motivated to do so). Sounds like you are using something lightweight but If you think about it, if someone was really motivated they could do both even if you started to get fairly tricky with https and some of the more rigorous cryptographic hashes. They would first decompile the game to figure out what tricks you are doing to the network traffic first and then use the packet analyzer after they knew the tricks to emulate the traffic for their purposes.

    Not that someone is likely to be this motivated but just to point out its possible even if as you start to tighten things up and make it harder on them client side.

    In addition to the suggestions above if you are not already capturing this information a timestamp and the client IP (yes they can always use a proxy but makes it harder) are also good things to always capture on all the submissions. That way you can add the following to your possible tools to weed out cheaters.

    1. Makes it easier to identify suspicious traffic that either come in rapid fire or from the same IP (also I would always recommend having a safeguard that makes sense for only 1 submission every x seconds from the same IP)
    2. Craft some common sql scripts for deleting identified suspicions after the fact (if they see their hard work not being fruitful they might stop).
    3. Capturing IP makes it possible to ban IP addresses

    Nothing is foolproof but this will give you additional server side tools to help keep your leaderboard clean.
     
    angrypenguin and Stoven like this.
  11. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,631
    Do be generous with stuff like this, though. You want to set a limit that'll severely slow down a cracker but not shut down people playing the same thing at a LAN party.
     
  12. greggtwep16

    greggtwep16

    Joined:
    Aug 17, 2012
    Posts:
    1,546
    The suggestion was more to plant the seed on what is possible from the server side. Good design can always make it a bit more robust in these use cases (i.e. only allowing submission from same IP AND username every x seconds). That way in your LAN party example the two users while they would have the same IP from being on the same wi-fi wouldn't have the same username. For every exception though there will be an equal trade off that if the cracker figures out what you are doing he can exploit it (i.e. they would then just spoof the traffic and not repeat usernames).

    In general though, one could go through that rabbit hole forever and usually its not warranted to be too paranoid. The objective is to make it hard not impossible and your particular design desires should dictate how much or little you want to do. A lot of time though people don't realize that you have a distinct set of tools you can leverage from the server side and they can be powerful. Obviously, though the server is also a target as they know where the traffic is going to, so make sure the OS patches are up to date and follow good security practices there too. In the day and age of Azure and EC2 being so dirt cheap a regular backup of the server (say daily) is very prudent if the server would ever become compromised you can essentially kill it and spin up a new one from the last backup instantly and with little to no scores lost (only the delta since last backup).
     
    Stoven likes this.
  13. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    ug, so its definitely happened, I now have 6 or so scores, all with names that vary, as for the secret key, it is used when generating the md5, so its not being transmitted directly.

    Its pretty obvious someone has figured a way around this. bugger. I can delete the scores easy enough. Be nice if the DeviceId didnt change on re-install's. Thanks apple...

    Can anyone confirm if this is still a regression? http://forum.unity3d.com/threads/unity-4-2-systeminfo-deviceuniqueidentifier-regression.194045/
     
  14. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,631
    MD5 has been 'solved' though, so you can't rely on it to keep stuff safe. The newer SHA algorithms are better for this kind of thing.
     
    Stoven likes this.
  15. greggtwep16

    greggtwep16

    Joined:
    Aug 17, 2012
    Posts:
    1,546
    If you capture it banning them via IP should still be possible. That should slow them down for a bit (until they use a proxy) and would slow them down whether they decompiled your game or used a packet analyzer.

    Unique identifier will only work to slow them down if they decompiled your game and not if they have just figured out the network traffic (they'll just send traffic that changes the unique identifier). MD5 is not secure by today's standards. Obviously, slowing them down by even a little bit helps though.

    Below only if it really comes a problem and above didn't work:
    In lieu of IP or in addition if it becomes and issue even after both above it is common for advertisers in the web world to try and uniquely identify you by any and all metadata your browser has (font's installed, OS version, IP, etc.). Each by themselves is not unique at all but when you combine all of them you'd be surprised at how unique you are with 30 or so factors being considered. In games we might not have all that so easily accessible but we do have quite a few factors if you think about what you capture for analytics. If they seem to outsmart both above try to look for a pattern in your analytics that maybe you can give a broader ban but yet still is fairly unique so real players can get through but he is banned.
     
  16. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    solved? I dont know much about crypto stuff tbh... what's the recommended replacement?
     
  17. greggtwep16

    greggtwep16

    Joined:
    Aug 17, 2012
    Posts:
    1,546
    As angrypenguin mentioned the SHA family of algorithms are a much better choice (pick one of the later variants as they are more future proof).

    http://en.wikipedia.org/wiki/Secure_Hash_Algorithm
     
  18. Stoven

    Stoven

    Joined:
    Jul 28, 2014
    Posts:
    171
    From .NET 2.0 (SHA1, 256, 384, 512)
     
    greggtwep16 likes this.
  19. tiggus

    tiggus

    Joined:
    Sep 2, 2010
    Posts:
    1,240
    Are you using the md5 hash just to identify the session/user or instead to verify the integrity of the message?

    If the secret key just generates a hash to identify the user or session it does nothing to protect against altering the score that is sent over the network, you would also need to do some message integrity checking. It is quite easy to setup a man in the middle proxy where the attacker simply needs to change the http header values in a nice simple to use gui. There are tons of these proxies and very easy to setup.

    example: http://www.kidozen.com/httphttps-debugging-on-mobile-apps-with-man-in-the-middle/

    edit: also, yeah use sha2 for this type of stuff.

    Ultimately the problem is the app/user has your private key being used to generate the hash so if they can extract that they can forge any message they want.
     
    Last edited: Nov 26, 2014
  20. Zeblote

    Zeblote

    Joined:
    Feb 8, 2013
    Posts:
    1,102
    Is this about that game linked in your signature?
     
  21. tiggus

    tiggus

    Joined:
    Sep 2, 2010
    Posts:
    1,240
    This is not really true, you don't send the private key over the network. However it is moot point since the private key is stored on the user's device so they already have access to it if they can extract it from your package.
     
  22. thxfoo

    thxfoo

    Joined:
    Apr 4, 2014
    Posts:
    515
    Collect different stats and verify them on the server. And send the same data multiple times in an obfuscated way to make tampering harder.

    E.g. with:
    #enemies killed
    time needed
    #level started
    points after each level

    On client (+ as concatenation):
    scoreMessage = iv + data + sig
    iv = random number
    sig = sha256(data+iv)
    data = score + #enemies killed + time needed + #level started + points after each level + sha512(score) + sha256(#enemies killed) + md5(time needed) + crc(#level started) + (points after each level PLUS PRIME MOD OTHER_PRIME)

    On server:
    - validate sig (calculate sig = sha256(data+iv) and compare), validate other sha256/md5/crc/plus/mod stuff. drop all invalid
    - automatically drop scores making no sense (if you can estimate from the score how long one must play at least, how many levels at least, how many enemies at least, upper bound for points per level, #single level scores == #level started, sum of level scores == complete score,...)

    The trick is to calculate the "sha512(score ) + sha256(#enemies killed) + md5(time needed) + crc(#level started) + (points after each level PLUS PRIME MOD OTHER_PRIME)"-components at completely different locations throughout the code base. So it is a lot of work to find out what you do exactly.

    Or even more hardcore, do it in C++.

    Edit: your sever should send the client the iv he has to use for this score message. A new random one each time. And for even more overkill: encrypt the whole thing with the public key of the server (asymmetric).
    Edit2: of course the server must use the iv he sent the client on validation, not the one the client sends (so you could remove the iv from the package, but I would keep it for debugging/error logging).
     
    Last edited: Nov 26, 2014
    Stoven likes this.
  23. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,317
    His wording seemed to indicate otherwise.
     
  24. lmbarns

    lmbarns

    Joined:
    Jul 14, 2011
    Posts:
    1,628
    You can sniff the individual packets being sent with software like wireshark.

    When your app posts to the online db, if someone captured those packets and simply keeps repeating them, is there any check on your database to only allow 1 update every x seconds/minutes?

    There's an apk decompiler apktools. Are you hashing the value every time you post to your db?
     
  25. thxfoo

    thxfoo

    Joined:
    Apr 4, 2014
    Posts:
    515
    Use a random IV that comes from the server. See my answer. Or better, also use SSL.

    But yes, having such a check makes sense often, but here you can have the problem that the customer and his girlfriend play on 2 devices at the same time under the same account (e.g. with his IPhone and his IPad).
     
    Last edited: Nov 26, 2014
    angrypenguin and tiggus like this.
  26. tiggus

    tiggus

    Joined:
    Sep 2, 2010
    Posts:
    1,240
    I like thxfoo's ideas but just realize at the end of the day, the server cannot trust the client and with enough time and know-how all these things can be defeated. But random IV and a very obscure hashing logic with server side checks would deter most people unless you make the next diablo/wow.

    PC it really doesn't matter since you could just use a memory editor and change the score value before it is sent.
     
  27. thxfoo

    thxfoo

    Joined:
    Apr 4, 2014
    Posts:
    515
    That would not defeat my method. You would also have to fake the other data and all data derived from it.

    Even faking the following with reasonable values would not defeat it:
    #enemies killed
    time needed
    #level started
    points after each level

    Because of the values derived of these (e.g. if the (points after each level PLUS PRIME MOD OTHER_PRIME) are calculated after finishing each level and stored into an array. You would have to analyze these whole logic too).

    Of course the scores can still be faked. That can never be prevented. But it is much much harder. You would have to invest a lot of time analyzing the game (e.g. the "PLUS PRIME" and the "MOD OTHER_PRIME" could be done at totally different locations anywhere in the code). Even at different locations for different levels with different primes.

    You have to find every location in the code that manipulates any of these numbers. And you must find reasonable fake values for all these values.
     
    Last edited: Nov 26, 2014
  28. greggtwep16

    greggtwep16

    Joined:
    Aug 17, 2012
    Posts:
    1,546
    In addition to all the suggestions (hopefully retroactively implementing a few of them helps in your next update) don't forget to take this annoyance as a huge compliment. Someone likely has deemed your game fun enough that he/she wants there name at the top of the leaderboard and is willing to cheat. I know its frustrating but since there is no monetary motivation and it's just a leaderboard this is the likely motivation. It shows promise that your game will do well.
     
    Stoven and angrypenguin like this.
  29. tswalk

    tswalk

    Joined:
    Jul 27, 2013
    Posts:
    1,109
    I suppose if your game has a ladder system, you would almost need to pack "point" messages to the server, verify that those point values are valid on an individual basis and let the server tally the score.. this way, only valid values would be accepted.

    Would it be possible for someone to get 10 points in your game in under 5ms?
    Would it be possible for someone to get 10,000 points at that level in the past 15ms?

    This sounds a bit difficult in my mind to handle, but I think it is the only option.. handle point messages and tally on the server side.
     
  30. tiggus

    tiggus

    Joined:
    Sep 2, 2010
    Posts:
    1,240
    Sure, my point being it is a bit easier to do this on desktop than mobile as there are quite advanced debuggers/crack programs available. Personally if it was my game I would take an iterative approach to see what is actually needed, and implement the common protections first before getting too complex.

    1. Encrypt the connection with SSL
    2. Log all client IP's/UUIDs that submit scores on server
    3. Hash the entire message using one-time IV and sha-256 and verify hash on server
    4. Use some pseudo random data as part of the hash(time,etc.)
    5. Check device UUID against list of known hacked client UUIDs on server

    After that if still getting hacked then implement thxfoo's more complicated logic which requires modifying more game code internals.
     
  31. thxfoo

    thxfoo

    Joined:
    Apr 4, 2014
    Posts:
    515
    What I described is probably complete overkill.
    Just sending data as:
    data = score + (points after each level) + (points after each level PLUS/TIMES PRIME MOD OTHER_PRIME)

    and computing these values as described above would probably prevent 99.9% of fakers. Then you only have to check that 'sum of level scores == complete score' and that the derived level scores match the level scores.
     
  32. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    tbh, I think the problem is I made it a little too easy to bypass the hash check (which is really only being used to ensure the message is valid). Its not like the person gets any real gain out of being able to post false messages except for a bit of false vanity.

    I looked at the code and I wasnt encoding the score into hash, so you can effectively just change the score in the request and it will be valid. #rookiemistake

    its easy enough for me to ban users for now, so will fix it in a future update.

    I guess I was just surprised someone went to the effort of doing it. ha. Next stop, pirated copies of game!
     
    Stoven likes this.
  33. tswalk

    tswalk

    Joined:
    Jul 27, 2013
    Posts:
    1,109
    if you figure that one out, I wanna be the first to buy your book... :)
     
  34. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    Its easy, just make a popular game, the pirates will come ;)

    being free usually makes it pointless though
     
  35. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,631
    Ahh, this makes sense, and it's probably all I'd have done for a first-pass as well. Though I'd still have used an SHA variant rather than an MD5, because (from memory) it's no extra effort on my end and gets a more reliable result.

    For a message integrity check that's not meant to be person-proof then MD5 might be fine, though. I can't remember the specifics of its flaws, I haven't read up on this stuff in a while.
     
  36. thxfoo

    thxfoo

    Joined:
    Apr 4, 2014
    Posts:
    515
    You can create another message with same sig if the message is long enough and has space to insert random stuff. But only with very very extreme computational effort.
    So nobody would do it to fake a score. And these messages are so short that they most probably are not affected by this.

    But this does not matter, because in this case the client sends the MD5 hash, so the attacker can compute a new one anyway. So any flaws in MD5 don't matter anyway in such a case.

    Edit:
    for the technically interested: this is relevant if you sign a md5 hash with your private key such that others can verify that the message comes from you by verifying with your public key (e.g. message=X509 certificates used for SSL in the browser).
    You (attacker) cannot fake the with private key signed md5 hash (because you don't have the private key), but with the flaw you can create a new message (or for X509 a new certificate) that has the same md5 hash as the original, so the existing signed md5 hash "proves" that this is the original even it is not.
     
    Last edited: Nov 27, 2014
  37. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,631
    Exactly. So if the idea is to check that the message isn't corrupt then it's probably fine. If the idea is to make sure a person hasn't messed with the data then it's pretty much useless. I guess I should have been more clear about the word "integrity".
     
  38. Dabeh

    Dabeh

    Joined:
    Oct 26, 2011
    Posts:
    1,614
    IMO everyone's over complicating it. There's no need for any of this packet sniffing. It's most likely someone is just modifying the memory, it takes about 1 minute in total to do.

    If you don't have any prevention for that, it's most likely that.

    Also, a pretty good fix to deterrent for a lot of these script kiddies(that I literally just came up with and goes with your hashing) is to just generate a random number with the seed as your score or something(s) that both the client and server know and use that as the secret. The same calculation can be done on the server with the same result.

    It takes about 5 minutes in total. It will stop anyone except someone sophisticated enough to analyze your code, which would also be sophisticated enough to just make some alterations no matter what security measures you put into place minus sending over some kind of log of the gameplay that can be watched/checked.


    Good crackers look for the easiest way in ;), it doesn't matter how "kiddish" it is.
     
    Last edited: Nov 27, 2014
  39. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,822
    Divide your level into 'sectors' and each time the client hits a sector (i.e a collider for the end of each sector) send a timestamp to the server. Then on the server calculate if these times together make sense, then only write a high score, server to server.

    Makes sense?
     
  40. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    Wont really work, as part of the score is the speed at which you can get there. Its a memory game, you can put as many moves as you can remember ahead of time and the game plays faster.

    so you can get a score of 40 pts that takes 30sec or score of 40pts that takes 20 sec. The 20 second score is higher in the rankings.

    since I banned the one user that figured it out, ive had no problems. Ill fix it on update but for now it doesnt really matter.
     
    Stoven likes this.
  41. arkon

    arkon

    Joined:
    Jun 27, 2011
    Posts:
    1,122
    I am suffering the exact same problem. And I think it's causing a negative effect on my income. Why? Because I only store the top 100 scores and the hackers fill the leaderboard. Now genuine players can't get on the leaderboard. I also use MD5 but I do put the score and the name in the string before hashing it. In hindsight the hash provides no security at all as you can easily find the key in the executable and just write a simple bit of code to send your own 'legit' scores. Back to the drawing board,
     
  42. greggtwep16

    greggtwep16

    Joined:
    Aug 17, 2012
    Posts:
    1,546
    As previously mentioned perhaps try switching to one of the SHA algorithms from MD5. Also, what are you doing on the server side? You should be able to delete the scores in the interim and start banning IP addresses.
     
    Last edited: Dec 5, 2014
  43. thxfoo

    thxfoo

    Joined:
    Apr 4, 2014
    Posts:
    515
    See my previous posts. MD5 vs SHA makes absolutely no difference here.
     
  44. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    The trickiest way I thought of to make it difficult was have 50~ secret keys, encode which key was used in the message sent to php. Sure they might pull out all the keys, and even get the encoding on a de-compile, but how you handle the secret key server side could make this difficult, and might make it painful enough to figure out that they dont bother.

    otherwise some kind of challenge request could possibly work.
     
  45. Zeblote

    Zeblote

    Joined:
    Feb 8, 2013
    Posts:
    1,102
    There's no point in making up ridiculous nonsense protocols to send your score to the server as someone can still edit your app to send a diff score without even caring about how it is sent.
     
  46. mbowen89

    mbowen89

    Joined:
    Jan 21, 2013
    Posts:
    639
    At the end of the day, this is the easiest and fastest thing for them to do isn't it, just modify the score in the game that will be uploaded...? There's pretty much no way to stop any of this unless you do "logic" checks of whether that score is plausible in whichever way would make sense...