Git Product home page Git Product logo

obfstr's Introduction

String Obfuscation

MIT License crates.io docs.rs Build status

Compiletime string constant obfuscation for Rust.

The string constant itself is embedded in obfuscated form and deobfuscated locally. This reference to a temporary value must be used in the same statement it was generated. See the documentation for more advanced use cases.

Looking for obfuscating formatting strings? See fmtools (github, crates.io, docs.rs) with the optional dependency obfstr enabled to automatically apply string obfuscation to formatting strings.

Examples

The obfstr! macro returns the deobfuscated string as a temporary value:

use obfstr::obfstr as s;
assert_eq!(s!("Hello ๐ŸŒ"), "Hello ๐ŸŒ");

The wide! macro provides compiletime utf16 string constants:

let expected = &['W' as u16, 'i' as u16, 'd' as u16, 'e' as u16, 0];
assert_eq!(obfstr::wide!("Wide\0"), expected);

The random! macro provides compiletime random values:

const RND: i32 = obfstr::random!(u8) as i32;
assert!(RND >= 0 && RND <= 255);

Compiletime random values are based on file!(), line!(), column!() and a fixed seed to ensure reproducibility. This fixed seed is stored as text in the environment variable OBFSTR_SEED and can be changed as desired.

License

Licensed under MIT License, see license.txt.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, shall be licensed as above, without any additional terms or conditions.

obfstr's People

Contributors

aaron1011 avatar casualx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

obfstr's Issues

const String -> u32 ?

Heya, I came across your article at https://casualhacks.net/blog/2020-05-31/compiletime-processing/

Was wondering if you've looked into doing this for creating compile-time hashes from strings?

For example, I'd like to be able to do const U_POSITION:u32 = hash!("u_color"); and know that it's the same value as some other usage elsewhere. Speed and avoiding collisions are important, but it doesn't need to be cryptographically secure.

Edition 2021 breaks the L prefix for obfstr.

error: prefix `L` is unknown
   --> project/src/sys_windows.rs:183:38
    |
183 |         obfstr!(L"test.dll\0")
    |                 ^ unknown prefix
    |
    = note: prefixed identifiers and literals are reserved since Rust 2021
help: consider inserting whitespace here
    |
183 -         obfstr!(L"test.dll\0")
183 +         obfstr!(L "test.dll\0")
    |

Semantic Versioning

Hello! I was looking at your crate and according to a look at your Semantic Version, this is not a stable release. For astable release, a semantic version would be 1.0.0. If you don't understand semantic versioning that well, please check out the semver website. Thanks!

Don't enable RUST_BOOTSTRAP in build.rs

The crate is currently "usable" on stable rust, despite using nightly-only feature, by enabling RUST_BOOTSTRAP=1 in build.rs. This is a very bad idea. This flag is only meant to bootstrap the compiler itself, and any other use of it is unsupported and might lead to the code breaking if/when the API changes. This is not unheard of: Nightly features aren't finalized and often changes shape prior to stabilization.

The currently used features are also not very stable, const_generics and const_fn can easily cause ICEs in the compiler or soundness issues in the final binary, due to implementation bugs.

IMO, this crate shouldn't abuse RUST_BOOTSTRAP like this. The correct way is to tell the users to use a nightly compiler. If that's not possible, the use of RUST_BOOTSTRAP should at least be called out in the README so users can make an informed decision about using this crate.

constant byte array obfuscation

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.

Add license file into the `impl` sub-crate

Sadly archive on crates.io for obfstr-impl does not contain. That is resolvable in 3 simple ways: use license-file, add a symlink in the subdirectory, copy file in the subdirectory. Not sure which one you prefer, so not sending a PR.

Add support for C strings

With 1.72 adding the c"..." literal C string syntax and const support for much of CStr's methods, it would be nice if this crate had support for them. As far as I can tell, there is currently no way to have such a literal obfuscated without allocating on the heap. Having a specialized macro, for example obfcstr, should help in this regard. In terms of API, it should probably have everything obfstr already has, and only differ in the type of expressions allowed.

As an implementation detail, it should probably work well to mimic what obfstr already does: passing raw bytes to obfbytes with str::to_bytes and then reconstructing a &str from its returned value. Here, CStr::to_bytes_with_nul and CStr::from_bytes_with_nul_unchecked should fit in just fine.

IDA 7.5 can see through obfstr 0.2 obfuscation

When decompiling a binary obfuscating with obfstr 0.2 with IDA/Hexrays 7.5, the obfuscation is immediately undone, and the XREF immediately give away the string location. See below for the source code, and the decompiler and asm output. This was tested with rust 1.48.0.

obfstr 0.1 does not suffer from this: The strings are properly obfuscated, and IDA fails to find any xrefs for it. I believe the difference comes from obfstr 0.1 having a random offset into the string, which confuses IDA, leaving its XREF analysis and automatic deobfuscators inoperable. Another issue is that the one time pad to deobfuscate the string is kept in .rodata (due to being passed as an array to the deobfuscate method) while obfstr 0.1 would only get passed the initial round key.

I imagine the fix would go like this: Change the deobfuscate method to take a random offset like obfstr 0.1 in order to break the xrefs, and generate the XOR round keys at runtime instead of compile time.

Source code:

use obfstr::obfstr;
fn main() {
    println!("aaaaaaaaaaaa");
    println!("{}", obfstr!("bbbbbbbbbbbb"));
    println!("{}", obfstr!("cccccccccccc"));
}
0.2 Hexrays decompiler view

Image Pasted at 2021-1-6 14-51

0.1 Hexrays Decompiler View

Image Pasted at 2021-1-6 14-57

0.2 Assembly view

Image Pasted at 2021-1-6 14-51(1)

0.2 Data X-Refs

Image Pasted at 2021-1-6 14-52

0.1 Data X-Refs

Image Pasted at 2021-1-6 14-56

obfstr 0.1.x: Support raw strings

obfstr 1.x currently doesn't support raw string, e.g. the following causes a panic:

obfstr!(r"do\stuff"); // Panics
obfstr!(r#"do\stuff"#); // Panics too

To fix this, obfstr-impl's string_parse should probably be updated to take a TokenStream instead of a Literal, and check each token in the stream.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.