How to obfuscate String literals?

Is there any compiler flag that we can use to entirely obfuscate string literals?


Quick example, an app contains urls for different servers:


fileprivate extension Environment {

  var url: String {
    switch self {
    case .dev:
      return "https://mydevserver.com/api"
   case .prod:
     return "https://myprodserver.com/api"
  }
}


But once the binary is compiled, it's quite easy to just open it and see the string inside.


https://i.ibb.co/3M2zX0F/Screen-Shot.png


Initially, I thought this was just related to Swift literals, but further testing indicates that it also happens to Obj-C string literals.

Shouldn't the compiled code be a safe binary, at least obfuscating any literals inside the code base?


I would rather not take the path of manipulating the string in the code base, like using it encrypted, base64, or scrambled string literals mixing parts of string, etc...

Replies

Is there any compiler flag that we can use to entirely obfuscate string literals?

There is not.

Shouldn't the compiled code be a safe binary, at least obfuscating any literals inside the code base?

No. General wisdom is that a product should be secure even if someone has full knowledge about how it works. While I’m not in the “security through obscurity is completely pointless” camp, I do agree that it’s pointless in many cases. For example, if an attacker wants to see what servers your app talks to, they can use a network debugging tool to observe your on-the-wire traffic.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks for the response.


It's just surprising that this is so easily exposed.

When it comes down to Swift, even enums with undeclared string raw values becomes plain text in the assembly level.


private enum MySecrets : String {
    case mySecretEnumA
    case mySecretEnumB
}


Just by having this in your code base is enough to expose them all as strings like "mySecretEnumA", which is very annoying.

If someone is really determined to reverse engineer your app that's fine, the hacker may come down to code level anyways, but having this as a pure plain simple string after compilation should not be the case.


The base principle of security is all about layers, nothing is 100% secure, however, sounds like this layer should be compiler responsibility, not developers' responsibility. Like some other compiled languages.


Just sayin'

When it comes down to Swift, even enums with undeclared string raw values becomes plain text in the assembly level.

OK, that’s very different from your original question, which is about string literals. Some, but not all, of this runtime metadata is required, but some is optional and can be disabled via the Reflection Metadata Level (

SWIFT_REFLECTION_METADATA_LEVEL
) build setting.

If you’d like to see even more control over this, my recommendation is that you have a chat with the folks over on Swift Evolution.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi dineybomfim,


If you want to encrypt sensitive strings (like test urls) for runtime configuration purposes (essentially what you're trying to achieve in your Environment swift extension posted above), then check out https://github.com/electricbolt/appfiguratesdk iOS SDK. Its designed exactly for this purpose. Strings are encrypted using a public key, and can only be decrypted by the included Appfigurate app - which uses the matching private key. (Your private key is only known by you). No plain text is included in your app.


Cheers,

Matt.

It appears that Quinn "The Ekimo" is not aware of how hackers work. As a pen tester with almost a decade of experience I LOVE the fact that there is no way to protect string literals, as the senior software security engineer of a large company I'm horrified by his stance.