some mor strobf opts
This commit is contained in:
parent
f817d45c88
commit
cdc64658cd
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
namespace str_obf {
|
namespace str_obf {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
template <typename char_t, size_t size, typename key_t>
|
template <typename char_t, size_t buffer_size, size_t size, typename key_t>
|
||||||
struct message {
|
struct message {
|
||||||
/* helper to access the types */
|
/* helper to access the types */
|
||||||
static constexpr auto _size = size;
|
static constexpr auto _size = size;
|
||||||
@ -14,7 +14,7 @@ namespace str_obf {
|
|||||||
using _key_t = key_t;
|
using _key_t = key_t;
|
||||||
|
|
||||||
/* memory */
|
/* memory */
|
||||||
std::array<char_t, size> buffer{0};
|
std::array<char_t, buffer_size> buffer{0};
|
||||||
key_t key{};
|
key_t key{};
|
||||||
|
|
||||||
/* some memory access helpers */
|
/* some memory access helpers */
|
||||||
@ -48,6 +48,11 @@ namespace str_obf {
|
|||||||
std::uint32_t rot = oldstate >> 59u;
|
std::uint32_t rot = oldstate >> 59u;
|
||||||
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
|
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* we use a buffer dividable by 8 so the compiler could do crazy shit, when loading (moving) the characters */
|
||||||
|
constexpr size_t recommand_message_buffer(size_t message_size) noexcept {
|
||||||
|
return (message_size & 0xFFFFFFF8) + ((message_size & 0x7) > 0 ? 8 : 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename char_t, typename key_t>
|
template <typename char_t, typename key_t>
|
||||||
@ -60,7 +65,17 @@ namespace str_obf {
|
|||||||
if(kbegin == kend) return;
|
if(kbegin == kend) return;
|
||||||
|
|
||||||
auto it = kbegin;
|
auto it = kbegin;
|
||||||
while(length-- > 0) {
|
|
||||||
|
auto left = length;
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
/*
|
||||||
|
* Enforce clang here to not evaluate this loop at compile time as long its not called in a constexpr context!
|
||||||
|
* We lose compiler opts. here a bit, but cases where a xor was made over larger than 8 bit registers were really rare!
|
||||||
|
*/
|
||||||
|
#pragma nounroll
|
||||||
|
#endif
|
||||||
|
while(left-- > 0) {
|
||||||
if(it == kend)
|
if(it == kend)
|
||||||
it = kbegin;
|
it = kbegin;
|
||||||
|
|
||||||
@ -72,8 +87,9 @@ namespace str_obf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename char_t, size_t message_size, typename key_t>
|
template <typename char_t, size_t message_size, typename key_t>
|
||||||
constexpr inline internal::message<char_t, message_size, key_t> encode(const char_t(&message)[message_size], const key_t& key) noexcept {
|
constexpr inline auto encode(const char_t(&message)[message_size], const key_t& key) noexcept {
|
||||||
internal::message<char_t, message_size, key_t> result{};
|
constexpr auto message_buffer_size = internal::recommand_message_buffer(message_size);
|
||||||
|
internal::message<char_t, message_buffer_size, message_size, key_t> result{};
|
||||||
result.key = key;
|
result.key = key;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -83,14 +99,25 @@ namespace str_obf {
|
|||||||
size_t index = message_size;
|
size_t index = message_size;
|
||||||
while(index-- > 0)
|
while(index-- > 0)
|
||||||
*bit++ = *mit++;
|
*bit++ = *mit++;
|
||||||
|
|
||||||
|
size_t padding = message_buffer_size - message_size;
|
||||||
|
if(padding) { /* to make the string end less obvious we add some noise here (it does not harm user performance) */
|
||||||
|
std::uint64_t rng_seed = internal::time_seed() ^ internal::string_hash(message, 0);
|
||||||
|
std::uint64_t rng_base = rng_seed;
|
||||||
|
while(padding-- > 0)
|
||||||
|
*bit++ = internal::rng32_next(rng_base, rng_seed) & 0xFFUL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crypt(result.buffer.data(), message_size, key);
|
crypt<char_t, key_t>(result.buffer.data(), message_size, key);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename char_t, size_t message_size, typename key_t>
|
template <typename char_t, size_t length>
|
||||||
inline std::string decode(const internal::message<char_t, message_size, key_t>& message) {
|
constexpr inline auto str_length(const char_t(&message)[length]) noexcept { return length; }
|
||||||
|
|
||||||
|
template <typename char_t, size_t buffer_size, size_t message_size, typename key_t>
|
||||||
|
inline std::string decode(const internal::message<char_t, buffer_size, message_size, key_t>& message) {
|
||||||
std::string result{};
|
std::string result{};
|
||||||
result.resize(message_size);
|
result.resize(message_size);
|
||||||
|
|
||||||
@ -100,11 +127,27 @@ namespace str_obf {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline std::array<uint8_t, 16> generate_key(const char* _str_seed, unsigned int line) noexcept {
|
constexpr inline size_t generate_key_length(std::uint64_t seed, size_t max_size) noexcept {
|
||||||
std::uint64_t rng_seed = internal::time_seed() ^ internal::string_hash(_str_seed, 0) ^ line;
|
if(max_size <= 8) return max_size; /* We dont need a longer key then the message itself. As well compiler opt. doesn't matter here */
|
||||||
|
if(max_size > 64) max_size = 64;
|
||||||
|
|
||||||
|
std::uint64_t rng_base = seed;
|
||||||
|
size_t length = 0;
|
||||||
|
do {
|
||||||
|
length = (internal::rng32_next(rng_base, seed) >> 12UL) & 0xFFUL;
|
||||||
|
} while(length < 8 || length >= max_size);
|
||||||
|
|
||||||
|
/* it does not really matter if we have a 8 byte aligned number here, because we iterate so or so byte for byte */
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t line_number, size_t max_size>
|
||||||
|
constexpr inline auto generate_key(const char* _str_seed) noexcept {
|
||||||
|
std::uint64_t rng_seed = internal::time_seed() ^ internal::string_hash(_str_seed, 0) ^ line_number;
|
||||||
std::uint64_t rng_base = rng_seed;
|
std::uint64_t rng_base = rng_seed;
|
||||||
|
|
||||||
std::array<uint8_t, 16> result{};
|
constexpr size_t key_length = generate_key_length(internal::time_seed() ^ (line_number << 37), max_size);
|
||||||
|
std::array<uint8_t, key_length> result{};
|
||||||
for(auto& it : result)
|
for(auto& it : result)
|
||||||
it = (internal::rng32_next(rng_base, rng_seed) >> 16UL) & 0xFFUL;
|
it = (internal::rng32_next(rng_base, rng_seed) >> 16UL) & 0xFFUL;
|
||||||
return result;
|
return result;
|
||||||
@ -116,15 +159,20 @@ namespace str_obf {
|
|||||||
std::array<typename message::_char_t, message::_size + 1> buffer{0};
|
std::array<typename message::_char_t, message::_size + 1> buffer{0};
|
||||||
bool decoded = false; /* a trivial check which (if this only gets used once) the compiler could evaluate */
|
bool decoded = false; /* a trivial check which (if this only gets used once) the compiler could evaluate */
|
||||||
|
|
||||||
#ifndef WIN32 /* else if you call string_view() or string() it wound inline this method */
|
#ifndef _MSC_VER /* else if you call string_view() or string() it wound inline this method */
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline)) inline
|
||||||
|
#else
|
||||||
|
__forceinline
|
||||||
#endif
|
#endif
|
||||||
const char* c_str() noexcept {
|
const char* c_str() noexcept {
|
||||||
if(!this->decoded) {
|
if(!this->decoded) {
|
||||||
memcpy(this->buffer.data(), this->encoded.buffer.begin(), message::_size);
|
memcpy(this->buffer.data(), this->encoded.buffer.begin(), message::_size);
|
||||||
crypt((typename message::_char_t*) this->buffer.data(), message::_size, this->encoded.key);
|
crypt<
|
||||||
|
typename message::_char_t,
|
||||||
|
typename message::_key_t
|
||||||
|
>((typename message::_char_t*) &this->buffer[0], message::_size, this->encoded.key);
|
||||||
buffer[message::_size] = 0; /* append the null terminator at the end */
|
buffer[message::_size] = 0; /* append the null terminator at the end */
|
||||||
this->decoded = true; /* let the compiler combine buffer[message::_size] and this->decoded = true; */
|
this->decoded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &this->buffer[0];
|
return &this->buffer[0];
|
||||||
@ -135,10 +183,18 @@ namespace str_obf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline std::string string() { return {this->c_str(), message::_size}; }
|
inline std::string string() { return {this->c_str(), message::_size}; }
|
||||||
|
|
||||||
|
//operator const char*() noexcept { return this->c_str(); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#define strobf_define(variable_name, string) \
|
#define strobf_define(variable_name, string) \
|
||||||
constexpr const auto variable_name = ::str_obf::encode(string, str_obf::generate_key(__FILE__ __TIME__, __LINE__))
|
constexpr auto variable_name = ::str_obf::encode(string, str_obf::generate_key<__LINE__, str_obf::str_length(string)>(__FILE__ __TIME__))
|
||||||
|
|
||||||
#define strobf_val(variable_name) (::str_obf::decode_helper<decltype(variable_name)>{variable_name})
|
#define strobf_val(variable_name) (str_obf::decode_helper<decltype(variable_name)>{variable_name})
|
||||||
|
|
||||||
|
#define strobf(message) \
|
||||||
|
(([]{ \
|
||||||
|
static strobf_define(_, message); \
|
||||||
|
return strobf_val(_); \
|
||||||
|
})())
|
Loading…
x
Reference in New Issue
Block a user