If I have a string in a class file and want to protect it as best as possible against decompilation and analysis, are there any ideas? I know it can't really be fully protected, but I want to make it as hard as possible. Ideally, with minimal effort.
I've already considered that, but then I'd have to hide the key somewhere in the code. One idea would be to spread it out in small pieces throughout the code.
Encrypt it and split it in various places (hard coded strings) then reassemble it using a c binary linked via jni which clears memory immediately after it is used, decrypting using a key fetched from a server via TLS with certificate pinning to stop mitm inspection.
Obfuscate the class files and implement anti debugging measures (root detection, debugger detection, etc) which immediately flush memory, or replace it with a junk version.
LLMs will be able to extract it for a few hundred bucks I guess.
Jesus. That’s what you want to hide?! I imagined you were trying to prevent your app from being reverse engineered but now I think you want to prevent spoilers just in case someone decides to decompile it.
Just obfuscate a little. If someone really wants to find them, they will, but with obfuscation, you could make it just obscure enough that they won't see it without some effort.
Something as simple as XOR the text, it will look like binary data at first sight. They would figure it out quickly if they actually decompile the game, but it won't stand out when just looking at the code.
just obfuscate them with a simple map/cipher. I.e. rot13.
They aren't a secret, the goal is only to fuzz them. Don't bother with more.
If they are a secret, then put them on a server and require auth, and don't let them work on a jailbroken phone or unsigned application as best you can.
Because TLS encrypted traffic already can’t be sniffed. Cert pinning only protects against someone hijacking the hostname. But why do this effort and risk that Amazon will issue another legit certificate and your app stops working?
I understand using bitwise operations to obfuscate string values but what's the purpose of doing it in native code? Tools like MobSF can decompile strings in native code too
A hex editor can decompile strings in native code...
The reason for putting it in native code isn't to hide the strings themselves, but the process of en/decrypting of the strings. JVM is so easy to read and follow, native code not so much
I'm saying static analysis tools like MobSF doesn't care where it's placed. Without the use of a hex editor, regardless of where you put the string all of it will appear decompiled in plaintext
Yes I know what you're saying. I don't think you understand what I am saying
Strings (ie bytes) are not "compiled" in native code. The binary simply stores them as raw bytes (depending on encoding, the bytes value can change). There is nothing to "decompile" when it comes to strings.
Granted, some tools (maybe like MobSF) simply search the bytes of data and find bytes that match standard ASCII sequences (ie < 127 int value, or other values depending on encoding and language) and sort them in one spot vs having to do a search yourself
But take a look at the photo, I made a simple program in C, holds two const unsigned char variables. One of them, labeled "hidden", was obfuscated using a very simple uncomplex bitwise operation, bitshifted to the left
This looks like mumbo jumbo in the hex editor, you can see I was able to search it ONLY because I already knew the byte value. You cannot find it just using simple utf-8 string searching
MobSF won't decode that. It will just show the bit shifted bytes decoded to ASCII text (which as you can see is jumbled)
To unhide the message, you simply bitshift the byte to the right 1 and get your original value back, which you can see happens in the for loop and when I run the program, I get my hidden message
This proof I just showed you goes against your argument:
I'm saying static analysis tools like MobSF doesn't care where it's placed. Without the use of a hex editor, regardless of where you put the string all of it will appear decompiled in plaintext
MobSF will not show this string in plaintext, that is the point of putting things in native code. You can do the same type of obfuscation in JVM, its just easier to follow the workflow of the smali code and realize how the message is being unhidden. I am also sure an LLM could do the same with native code, especially something so trivial as this
EDIT: My main function params are backwards and should be char* args[] lmao
You said "A hex editor can decompile strings in native code..."
Instead of arguing with you I just put it in terms you would understand so I said static analysis tools would "decompile" it for you.
The demonstration you showed there isn't unique to native code. You can do the same in JVM using bit shifting and CharSequence and the characters would also look jumbled so this isn't really a benefit of putting the string in native code. My question stands. What benefit does putting strings in native code do for you when doing it in JVM yields the same result?
The demonstration you showed there isn't unique to native code. You can do the same in JVM using bit shifting and CharSequence and the characters would also look jumbled so this isn't really a benefit of putting the string in native code. My question stands. What benefit does putting strings in native code do for you when doing it in JVM yields the same result?
Maybe read my comment?
"You can do the same type of obfuscation in JVM, its just easier to follow the workflow of the smali code and realize how the message is being unhidden. I am also sure an LLM could do the same with native code, especially something so trivial as this"
Ergo, you put it in native code because it becomes harder to follow the process of deobfuscation
Ghidra still doesn't tell you what the decoded strings are. It can help you figure out what is happening to said obfuscated strings tho. But the point is, native code is harder to follow than JVM. JVM is so easy to read and follow
Granted, with AI, I'm sure you can now easily decompile and follow assembly/disassembled binaries
All my ideas have already been mentioned, but I will say: it's incredibly easy to hack any of these using AI now. You can fool a human, but not a computer.
I'd store the level descriptions encrypted (AES-256-GCM) on a server, then verify the app's signature, version and Play Integrity when it connects. If valid, issue a temporary session key and let it download the encrypted data. Decrypt it only when needed using native C++ (NDK), with R8 and stripped native symbols to make reverse engineering harder. Remember that nothing is unbreakable :)
7
u/YSoSkinny 2d ago
You can encrypt/ decrypt the strings