CasualX/obfstr

constant byte array obfuscation

Closed this issue ยท 8 comments

Would be useful if there was obfbytes!, which takes a byte array (whether it be b"\x2A\x2A", [42, 42] or include_bytes!("data.bin")), and encrypts+obfuscates it.

My use case is making it more difficult to find a hardcoded public key used for validation.

Whoops, just realized all the stuff in the bytes module kinda does this.

Still though, would be useful to have it in a simple macro.

Shameless plug: I built a crate that does something like this: include_crypt. If you only want to include a single file, then you could probably just treat the bytes as a string and then simply use as_bytes().

@not-matthias ooh, that's nice, i'll certainly probably use that in the future, although it's a bit overkill for a 32-byte key which I already have in \xFF form

Hi @aspenluxxxy , thanks for taking interest!

I hadn't considered your use case, but the implementation seems trivial (since I already use a byte oriented obfuscation for strings itself). I'll consider a simple variation of obfstr but for bytes, eg. obfbytes.

That said I'm not sure what benefits you could have from obfuscating the encryption key itself since it's fairly short and is just a 32 random looking bytes. The goal of my crate specifically is to prevent automated analysis from deobfuscating all the strings in a binary to kick start analysis without prior understanding. It offers zero protection against a dedicated attacker who already knows what they're looking for. The obfuscation is fairly trivial to undo for a specific string.

Assuming the attacker already knows that your binary contains a hidden, encrypted file my approach would be to find the code which performs decryption (looking for aes instructions and constants used in popular encryption schemes) and xref the code until it reaches the code which supplies the concrete arguments to decrypt. From there either use an external tool with the extracted data and keys or breakpoint the decryption routine and extract the data after it is finished. None of this is prevented by this particular obfuscation library.

It would be more productive to disconnect the references to the decryption routines than trying to obfuscate the key. This functionality to specifically obfuscate function pointers appears missing in my library and I'll see what I can do to support it.

An important note is the usage of #[doc(hidden)]: I use it for two purposes:

  1. To export some stuff needed for the macros to work, I do not consider these hidden APIs to be stable and usage of them may break in the future. This includes the bytes and words modules. Eg. when Rust gets const generics which allow &str I intend to refactor the code to use it extensively.
  2. To soft-deprecate stuff without breaking backwards compat. This includes the ObfString and ObfBuffer wrappers and some of the helper macros I no longer like. In 0.3 and onwards these have been removed.

@not-matthias Interesting, I've looked through the code for some ideas and I have some observations:

You're using ObfString which I've removed in the 0.3 release (fairly recent). From the way you used it it seems to be constrained to keys which are valid utf-8, am I reading this right?

It is unclear to me what exactly the threat model is for your crate, what exactly does it hope to achieve? For obfstr I have a small blurb trying to explain what it should be used for.

@CasualX For my use case, it's more meant to prevent "lol change public key with hex editor" - nothing's uncrackable, but I might as well throw all I can at making it harder to do so.

@aspenluxxxy haha that's fair, I keep assuming the low bar is someone with a copy of IDA and the ability to do some scripting to automate their analysis. Of course it's not even close to the level needed to simply search for a pub key in a binary and hex edit it to something else and any basic obfuscation would raise the bar significantly.

@CasualX The general goal of include_crypt is to be able to include an entire folder and prevent the automatic extraction with tools like binwalk. There's some crates that allow you to embed folders, but even when they compress the files, you can still extract the files automatically.

@not-matthias that makes sense! In the end I realize that my obfuscation code is not and won't be suitable for large amounts of data which is a niche your crate can fulfill.

I'm working on making the obfuscation available to plain byte arrays but I won't specifically support obfuscating function pointers (which can be done instead by putting them in a static and obfuscating the reference to that static).