New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature Request] Code Obfuscation in AIR sdk #494
Comments
Or as an alternative, maybe compile AS3 to native code for Android and Windows, as it happens already on iOS? |
This is one I had always wondered about (having done my fair share of decompiling of SWFs - though of course mostly this was to solve our customers' bugs!). The SWF and AS3 specifications are open so anyone can create a decompiler.. AOT compiling is a major piece of work and I suspect third-party or shared SWF libraries may still be needed with non-native code, so I would more be thinking of a way that the SWF files could be encrypted and then for AIR to decrypt them as it loads (like right now it compresses them - again, using open standards) - maybe we could compress them with built-in encryption. The challenge then is authorising the decryption. We can try to add some obfuscated mechanism within AIR (we'd need to make sure it's not clear to anyone who's trying to work out how we're doing the decryption by looking at the assembler code of the AIR library..)... let me talk to some of our folk internally; we'd welcome other comments/suggestions on this though! thanks |
+1 for code obfuscation support. |
I have for a while thought there should an option to strip the text which decompilers use. I can see why it's there. Flash in particular lets you dynamically load content such as other Flash/SWF apps, access their symbols and methods by name. This was used extensively for advertising/publisher preloaders and to embed adverts in webgames. But no-one is making webgames any more. We are instead making standalone apps. Dynamically loading code is generally poor practice if not explicitly disallowed. Apps are distributed independently not via preloaders on websites. Adverts are supplied by native code in ANEs. So it makes sense to strip out code from the SWF, or at least replace it with symbols. At least make it an option for developers who know they are making a final, standalone app. Get it out there quickly and developers can try it and see if there are any issues. |
Maybe there is a way to integrate Proguard or even better on top of Proguard, make Android compile like iOS apps do, so it will be even harder to decompile. |
I also would like to see this added.. but....what ever ends up being added to the SDK, please do not change the default actions of the build process and make add ons like this optional via command line vars. Thanks. |
Is it possible for Harman to work along with Kindi or acquire them? they have been out of business for a long time. Their obfuscation software is pretty impressive, if that can be included in AIR sdk that would be a great boost for our fraework. |
I could actually imagine that when there was proper code obfuscation more developers would out themselves using as3/flash/AIR. I would think that since its easy to decompile swf a bunch of devs would prefet to not tell anyone about it in order to keep their "secrets" and prevent others from "stealing" their sources/assets |
I couldn't see any way of contacting folk from Kindi, wondering if anyone has a contact there? To gauge the idea of some priorities though: are people looking mostly to encrypt their assets (images, sound files etc), or to prevent decompilers from showing off the ActionScript source code? The one thing I wonder is that - if you're using a Windows app at least - it's possible to do a memory dump of a process and then inspect that, which someone could use to get at a decrypted copy of the contents. So I'm not sure whether it's possible to do something completely secure. If we just encrypted the SWF contents and then decrypted them at runtime, it should prevent casual folk from getting at stuff, but anyone with access to the process memory could see the decrypted stuff. |
@ajwfrost I would think that Mobile iOS and Android are more important and a target to decompilation than Windows/Mac are since these (mostly) mobile games are likely lightweight in their codebase and assets are more likely to get stripped out and used in other games - e.g. see
"Chinese companies also frequently copy U.S. games, creating unauthorized “clones,” or steal U.S. IP assets. ": It is more common than you might think. |
The only contact I have from them from back in 2012, when I bought their SecureSWF application is: Kindi Software, LLC Phone:+962 6 533 5152 (ext 36) |
Thanks @2jfw I'll drop them a mail in case they're still around.. In terms of protecting things: Essentially it would always need the ability to decrypt - keys etc - to be present in the app and/or runtime. So it would make it harder, but I don't know whether it would dissuade any "professional" thieves... |
"Or as an alternative, maybe compile AS3 to native code for Android and Windows, as it happens already on iOS?" |
Oh yeah, it is/was - I had made very good experience with their software and obfuscating capabilities. I did decompile my obfuscated AIR mobile app at that time and found that it was not readable. The app used some ANEs and SWCs too, so the obfuscator was able to handle that all (though it may not have obfuscated them). |
I just checked in LinkedIn and found this contact : - https://www.linkedin.com/in/hosam-abu-alam-b4b6524/
As an independent developer, I dont care much about my code getting exposed, but its difficult to convince our clients who are very much worried about both. |
Just as an update, we will be including a utility to encrypt a SWF file into a forthcoming version of the AIR SDK. Limitations will be:
As mentioned earlier, it's stand-alone encryption so not completely impervious to cracking by someone who's very dedicated, but it should be at least as good as the Kindi approach.. |
This is amazing news! Thanks a lot for taking care on this, Andrew! Just curious, was there any contact/communication with Kindi? |
Great news! |
I'd sent a mail to the support email address but didn't hear .. but from earlier info it looked like they weren't supporting the product now anyway.
It's just encrypting the SWF as a whole - so basically a bit like when you compress a SWF, there is an 8-byte header but then the rest of the content can be uncompressed, zlib-compressed or LZMA-compressed; we've just added a further option for this to be encrypted. So you wouldn't be able to read strings... the file is then decrypted upon loading (in the same location as the decompression) so everything is protected up to the point you've loaded in the SWF file to memory. Which does mean that if someone were to load in the application and then do a memory-dump of the whole process, they could search the memory to find the decrypted SWF. Hmm... so, maybe we (also?) need to provide a utility class for the encryption of individual assets... |
I think asset protection is an important part since they are actually getting stolen (see #494 (comment)) |
So I've just been looking through the features that Kindi has and I really am not sure how they do some of that without being able to update the runtime, unless they're having everything accessed via some kind of library and are recompiling all of the ActionScript (which is very possible given the amount of obfuscation and optimization they're able to do...) So we have a slight advantage by being able to update the runtime itself, but are also perhaps not able to offer the levels of code obfuscation etc that they've put in place! But in terms of asset protection:
Let me know of any other priorities... thanks |
ActionScript-wise, as far as I remember, Kindi have renamed all variables and method names by something like "_loc1", "_loc2" etc.. so it will be hard for anyone who decompiles the code to read and understand it. So I am wondering, when someone now makes a memory dump form the SWF, will they see the variable and method names I used @ajwfrost ? |
@2jfw I'm not sure if this is called obfuscation, but Kindi did made Strings unreadable converting them to kind of functions. Here you can see levels of String encription/obfuscation: Key can be chosen from 32-bit to 288-bit. I made small example: in Animate I just wrote code
And here's result of Kindi procesing it in RC4 mode with 96-bit key (decompiled it with online decompiler):
with bunch of other .as files: Here's both decompiled files for analysis: I find obfuscation of Strings most important so you can store private keys in the app for encryption and decryption of other assets. That way you can make your own encryption algorithm. |
Thanks for the insight!
|
@MalacTheLittle is it possible to get hold of that 'protected' SWF file itself? I'd be interested by the ABC instructions (rather than by the "decompiled to human-readable" output...) Normally, a string literal would be stored into the constant pool and then retrieve by the ActionScript via a "pushstring" command and then e.g. "setproperty". So it would need to change the "pushstring" instruction to turn it into a function call, not quite sure what bytecode would make the decompiler look like that though... Interestingly though, in the avmplus it looks like a string retrieved in this manner is kept in memory i.e. string literals are not then subject to garbage collection. Whereas for things like this, you would want to have a string that's just instantiated and then cleaned up when not in use (and see the new If so .. this would be simplest to do via a separate function call ... so you could have Interesting stuff :-) thanks |
Just realised:
It's a function called Rather than risk playing around with existing AS3 bytecode, it would be easier for us to provide a separate tool for you to create a block of encrypted strings, and a library to use them (or we build that decryption into the runtime, more likely.. which then gets a little more secure..) Let us have a bit of a play with that... |
How about:
It may even be possible for us to do something like:
to skip step 2... (and actually, adding that tag to 'embed' would be useful for other types too e.g. images!....) |
This is the one I used to use. You may want to contact them and see if it's something you can work with. |
Sure thing, sorry I missed to attach that one too :) |
Thanks ... so yes:
and later we have:
Well, I can see why decompilers wouldn't like it! But after this class has been loaded, the strings would be decrypted (from what I can make out!) so yes it's similar to what we're looking at. @dmunsie thanks for that link, will take a look.. cheers |
Some time ago when we develop games for some brands ( games with prizes like PlayStation and things like that ) we hide the code attached in images. You take a JPG, get the bytes length of the original image, attach a swf at byte level, and break them apart when you load them, in that moment you load that swf and execute functions hidden there. It's not very complicated and is an effective way to avoid decompilations. We also use a lot of honeypots, with typical variable names "user_total_points" and those ones are what the users modify with memory readers, then we compare that with the real points that were stored hidden in some element .x property for example and we track de "hackers" banning their accounts ... Was a funny cat and mouse game :) |
I would like to know if these obfuscation or encrypting would lead to any performance issues or not? @MalacTheLittle Could you please share your experience with Kindi so far? Have you seen any performance issue on mobile devices? Also is Kindi still supported? |
@Shaunmax As you can see on image above, Kindi states that String encription entails an overhead on performance, so you need to use it carefully. When you import complex .swf to Kindi, it reads all the strings and you can choose the ones you want to encrypt. In some apps I used to encrypt up to 70 Strings and didn't feel any performance issues, though performance also depends how often you're accessing particular String according to Kindi statement. Therefore I can’t say for sure that it didn’t affect performance. |
@ajwfrost super excited this has landed in 50.0.0.1. We would love to adopt this feature for our game swf, and also our asset swfs. Currently the asset swfs are served on CDN and then stored / loaded from disk (cache manager - is there anything built in nowadays? it was much easier when the browser managed it :)), ideally we would persist the encrypted swf to disk and then be able to load that when required. |
@johnou hope it's useful.. I think it should work fine if you have a SWF you've encryped with the SDK utility, you can load that in via So this is a first step, and we can see where people want to take it, how we can make it more useful/secure/etc... As always, suggestions are welcome! thanks |
@ajwfrost looks like https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLRequest.html#cacheResponse should already cache swf files using the "operating system's HTTP cache"..? (something like %temp% for Windows?) I assume encrypted swfs are also cached as encrypted swfs and decryption only happens in memory? |
Correct, if there is any caching going on with the SWF or the system, then this would be the encrypted file. The decryption of an entire SWF happens as it's loaded into memory within the AIR runtime. |
Sorry, I'm a bit confused, saw johnou's comment about it being included in 50.0.0.1 but I don't see anything in the release notes about code obfuscation. Can anyone please briefly write what was added and how it works for anyone stumbling on this question and this thread? I'm just wondering about the basic case of how to better prevent swf decompiling |
github-494: Incorporating support for encrypted SWF formats |
@ajwfrost I tried running it through swfencrypt.xml but it seems the captive runtime doesn't support encrypted SWF format? When opening the application I receive the error "Initial content could not be loaded for this application. Try re-installing or contacting the publisher for assistance."
|
Yes I'm just finding the same currently, but not sure quite what's happening (initial debugging actually looks like there's some data mismatch/corruption, as the decryption is failing).... will try to get this sorted out! |
FYI @johnou - the issue was with some handling code when dealing with chunked and compressed data, the decryption process didn't handle this properly hence failed to decipher the SWF file. Got a fix for this coming up.. |
What about this idea:
|
I think that's redundant, the entire SWF will be encrypted. |
Actually @Mintonist @johnou that is one of the options we're looking at ... the disadvantage of encrypting the whole swf is that you can do a memory dump (at least on Windows) and find the decrypted copy; but keeping individual elements as encrypted means that we could decrypt and return a single string from this, keeping everything else protected and the memory used for the string would be wiped as soon as you're done with it. I think it's already supported for embedded data as byte arrays actually.. will have to check whether that's actually made it into a release! |
@ajwfrost sounds great, could this also be used on class field members which have sensitive memory to deter memory hacking? |
@johnou sorry, not sure what you mean about class field members? Normal AS3 classes/objects would always have a representation in normal memory (not the easiest representation to decipher perhaps, but I don't think we can encrypt object property values etc if that's what you mean?) |
my bad, love how the terminology changes between languages! yeah giving it further thought I don't think the encryption would be relevant for what I had in mind so ignore my previous question 👍 |
Hi there, we are very interested to use the swfencrypt to protect our own game, but there seem to be no documentation so far on how to. Am I just missing the correct tag in my search or can someone provide a link or an example? |
Currently this is just a command-line utility (well, AIR app) that encrypts the whole of the SWF file using internal information to generate the key/IV. The file can then just be read back into AIR which will decrypt it again as it does so. So e.g.
You need to have swfencrypt on your path i.e. the AIR SDK "bin" folder, unless you're running it from there I guess. Please note the potential down-side to this which is that the entire SWF is decrypted and stored in memory so if someone dumps the process memory, they'll likely be able to pull out your SWF. |
@ajwfrost |
Android should work fine. But for iOS with the ahead-of-time compilation, the AOT tool wouldn't be able to pull the ActionScript code out of the SWF if it's encrypted. If you're looking to encrypt the rest of the SWF after it's been stripped by the ADT process, I guess we would be able to add that as an option? Or any stuff that needs to be secure could be put into a bytearray perhaps, via the 'embed' command?
then as/when you need it:
|
Well, in order for people to use this i think A PROCESS to streamine the work needed to be done on each export/compile would be extremely helpful. |
Nice try, but this is how to decrypt the encryption. |
@evaleries thanks for pointing that out, that's a shame .. Customising the key is fairly straightforward but it still then needs to be derived or obtained from somewhere. Securing the SWF itself, implies we need to take some data from the SWF (or the code that does this process needs to be specially obfuscated so that it's harder to reverse engineer, which is what I assume they've done to work out how to decrypt). The alternative is to keep the key separate and then to provide this via some mechanism, for example:
Potentially we could have a way for a key to be retrieved from a server when the app is first run and then stored locally, if we could do this securely (and we can't e.g. on Windows where the current user would normally be able to check all their stored credentials etc).
I think they have a few options, one of them is full swf encryption and then using a loader to decrypt it. The loader therefore must have all the logic in it to decrypt, but it's "heavily obfuscated" so maybe that's just where we went wrong with this.. The AS3 obfuscation option that Kindi has doesn't look too tricky i.e. it's just about renaming things, rather than any changes to the logic. I think it would still be better for the "loader" part (i.e. decryption) to be done in C++. We can adjust it perhaps - will check how we can obfuscate it - and we can provide ways to pass in a custom key for when encrypting embedded bits of data in AS3 files. Open to other suggestions then for how we could actually get the keys to be provided dynamically for whole-swf encryption! thanks |
Hello, any news on that? Maybe if the entry SWF it's fully encrypted with a random key each time and this key will need to be placed in a random and also encrypted part of the runtime AIR assembly to avoid finding this in easy way. Then with the entry SWF being "secure" each developer can build they own logic to handle protection of the others files using something in they loaders. |
Problem Description
With the use of decompilers, our SWF's from android apks are exposing precious code and game design/business logics to our competitors and amateur developers. We need a solid code obfuscation feature in AIR sdk, which should make it extremely harder for hackers to read the code and should make the decompilers to crash.
There were 3rd party developers like kindi providing support for code obfuscation, along with optimisation and asset compression but unfortunately their softwares seems to be outdate and they are no longer providing any support.
As it's extremely risky to release builds in Google Play Store with no code obfuscation. I request @ajwfrost & the harman team to look at this issue at the highest priority and provide us a valuable solution as soon as possible.
I sincerely request other developers to vote for this feature and share their valuable feedbacks.
Appreciate your support.
The text was updated successfully, but these errors were encountered: