Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve “str” to any constant #45

Open
llxiaoyuan opened this issue Sep 11, 2021 · 8 comments
Open

improve “str” to any constant #45

llxiaoyuan opened this issue Sep 11, 2021 · 8 comments
Labels
enhancement New feature or request

Comments

@llxiaoyuan
Copy link
Contributor

Can we improve str to any constant ? like enumintfloatdouble ...

My project link below,but it can't make data embedded directly into code like xorstr

oxorany

@JustasMasiulis
Copy link
Owner

JustasMasiulis commented Sep 11, 2021

Hey,

It would certainly be possible, but I think this doesn't fit into the idea / implementation of my library.

The main part that is responsible for stuffing everything into the code is load_from_reg function and packing all data into 64 bit integers at compile time. I think it would be possible to achieve the same in your library as well. If you're having trouble implementing that, feel free to reach out.

@llxiaoyuan
Copy link
Contributor Author

I'm try to port xorstr to C++14

FL18WTA U0J$0IMM1P@K{Y7

C++17 build pass

C++14 get error C2975

8MY{_7K Y`5GN9~{PUHWD75


Is it possible to port to C++14 ?

@JustasMasiulis
Copy link
Owner

Is it possible to port to C++14 ?

I think you will have a lot of problems. Easier to rewrite from 0 I think. I optimized and rewrote code for it to compile as fast as feasible with a maximum of 2 functions ending up even in debug builds from each xorstr.

@llxiaoyuan
Copy link
Contributor Author

The simplest xorint here, doesn't seem to need too many templates, would you mind merging something like this into your repository in the future ?

#include <iostream>
#include <immintrin.h>
#include <cstdint>
#include <cstddef>
#include <utility>
#include <type_traits>
#include <iostream>
#define xorint(data) ::jm::xor_int([]() { return data; }).crypt_get()
namespace jm {
    __forceinline constexpr uint64_t load_int(const int value) {
        uint64_t key = 0x1234567812345678;
        return (uint64_t)value ^ key;
    }
    class xor_int {
        alignas(16) uint64_t storage[1];
    public:
        template<class Lambda>
        __forceinline xor_int(Lambda lambda)
            : storage{ std::integral_constant<uint64_t, load_int(lambda())>::value } {
        }
        __forceinline int crypt_get() {
            alignas(16) uint64_t key[1] = { 0x1234567812345678 };
            _mm_store_si128(reinterpret_cast<__m128i*>(storage),
                            _mm_xor_si128(
                                _mm_load_si128(reinterpret_cast<const __m128i*>(storage)),
                                _mm_load_si128(reinterpret_cast<const __m128i*>(key))
                            )
            );
            return *(int*)(storage);
        }
    };
}
int main()
{
    //output: 2208630
    printf("%x\n", xorint(0x2208630));
    return 0;
}

Copy form IDA

sub     rsp, 48h
mov     rax, 123456781014D048h
lea     rcx, _Format    ; "%x\n"
mov     qword ptr [rsp+48h+var_28], rax
mov     rax, 1234567812345678h
movdqa  xmm0, [rsp+48h+var_28]
mov     qword ptr [rsp+48h+var_18], rax
pxor    xmm0, [rsp+48h+var_18]
movq    rdx, xmm0
call    printf
xor     eax, eax
add     rsp, 48h
retn

@JustasMasiulis
Copy link
Owner

The simplest xorint here, doesn't seem to need too many templates, would you mind merging something like this into your repository in the future ?

Maybe. I would need to do some extra work, testing and optimization.

@llxiaoyuan
Copy link
Contributor Author

By minimally modifying your code, xorstr for integer is implemented

But I don’t know how to modify the following function to support enum or floating point types

// loads up to 8 characters of string into uint64 and xors it with the key
template<std::size_t N, class CharT>
XORSTR_FORCEINLINE constexpr std::uint64_t
load_xored_str8(std::uint64_t key, std::size_t idx, const CharT str) noexcept
{
    return key ^ str;
}

Tested

#include <stdio.h>
#include "xorstr.hpp"
int main() {
    //12 1234 12345678 1234567887654321
    //12 1234 12345678 1234567887654321
    printf("%hhx %hx %x %llx\n%hhx %hx %x %llx\n"
           , *xorstr_((int8_t)0x12)                                       //uint8_t
           , *xorstr_((int16_t)0x1234)                                    //uint16_t
           , *xorstr_((int32_t)0x12345678)                                //uint32_t
           , *xorstr_((int64_t)0x1234567887654321)                        //uint64_t
           , *xorstr_((uint8_t)0x12)                                       //uint8_t
           , *xorstr_((uint16_t)0x1234)                                    //uint16_t
           , *xorstr_((uint32_t)0x12345678)                                //uint32_t
           , *xorstr_((uint64_t)0x1234567887654321)                        //uint64_t
    );
    return *xorstr_(0);
}
  • msvc (x86 x64)
  • clang (x86 x64)
  • gcc (x86 x64)

@gurachan
Copy link

gurachan commented Nov 20, 2021

By minimally modifying your code, xorstr for integer is implemented

But I don’t know how to modify the following function to support enum or floating point types

// loads up to 8 characters of string into uint64 and xors it with the key
template<std::size_t N, class CharT>
XORSTR_FORCEINLINE constexpr std::uint64_t
load_xored_str8(std::uint64_t key, std::size_t idx, const CharT str) noexcept
{
    return key ^ str;
}

Tested

#include <stdio.h>
#include "xorstr.hpp"
int main() {
    //12 1234 12345678 1234567887654321
    //12 1234 12345678 1234567887654321
    printf("%hhx %hx %x %llx\n%hhx %hx %x %llx\n"
           , *xorstr_((int8_t)0x12)                                       //uint8_t
           , *xorstr_((int16_t)0x1234)                                    //uint16_t
           , *xorstr_((int32_t)0x12345678)                                //uint32_t
           , *xorstr_((int64_t)0x1234567887654321)                        //uint64_t
           , *xorstr_((uint8_t)0x12)                                       //uint8_t
           , *xorstr_((uint16_t)0x1234)                                    //uint16_t
           , *xorstr_((uint32_t)0x12345678)                                //uint32_t
           , *xorstr_((uint64_t)0x1234567887654321)                        //uint64_t
    );
    return *xorstr_(0);
}
  • msvc (x86 x64)
  • clang (x86 x64)
  • gcc (x86 x64)

I tried this .. this is very nice but you broke the string.
image

I guess this demo only accept ints

IDA PRO is showing this .. its kinda too much xD or overpowering but it does work.

SSE2

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __m128i v3; // xmm7
  __m128i v4; // xmm6
  __m128i v5; // xmm5
  __m128i v6; // xmm4
  __m128i v7; // xmm3
  __m128i v8; // xmm2
  __m128i v9; // xmm1
  __m128i v10; // xmm0
  __m128i v11; // xmm0
  int v13; // [rsp+28h] [rbp-170h]
  int v14; // [rsp+30h] [rbp-168h]
  int v15; // [rsp+38h] [rbp-160h]
  __m128i v16; // [rsp+50h] [rbp-148h] BYREF
  __m128i v17; // [rsp+60h] [rbp-138h] BYREF
  __m128i v18; // [rsp+70h] [rbp-128h] BYREF
  __m128i v19; // [rsp+80h] [rbp-118h] BYREF
  __m128i v20; // [rsp+90h] [rbp-108h] BYREF
  __m128i v21; // [rsp+A0h] [rbp-F8h] BYREF
  __m128i v22; // [rsp+B0h] [rbp-E8h] BYREF
  __m128i v23; // [rsp+C0h] [rbp-D8h] BYREF
  __m128i v24; // [rsp+D0h] [rbp-C8h]
  __m128i v25; // [rsp+E0h] [rbp-B8h]
  __m128i v26; // [rsp+F0h] [rbp-A8h]
  __m128i v27; // [rsp+100h] [rbp-98h]
  __m128i v28; // [rsp+110h] [rbp-88h]
  __m128i v29; // [rsp+120h] [rbp-78h]
  __m128i v30; // [rsp+130h] [rbp-68h]
  __m128i v31; // [rsp+140h] [rbp-58h]
  __m128i v32; // [rsp+150h] [rbp-48h] BYREF
  __m128i v33; // [rsp+160h] [rbp-38h]

  v16.m128i_i64[0] = 0x5429C9595A85AFC4i64;
  v16.m128i_i64[1] = 0xFD26A19CE07E88CBui64;
  v3 = _mm_load_si128(&v16);
  v24.m128i_i64[0] = 0x461D9F21DDE0ECE5i64;
  v24.m128i_i64[1] = 0xEF12F7E4671BCBEAui64;
  v17.m128i_i64[0] = 0x461D9F21CFD4BA9Di64;
  v17.m128i_i64[1] = 0xEF12F7E4752F9D92ui64;
  v4 = _mm_load_si128(&v17);
  v25.m128i_i64[0] = 0x461D9F21DDE0ECE5i64;
  v25.m128i_i64[1] = 0xEF12F7E4671BCBEAui64;
  v18.m128i_i64[0] = 0x461D9F21DDE0FED1i64;
  v18.m128i_i64[1] = 0xEF12F7E4671BD9DEui64;
  v5 = _mm_load_si128(&v18);
  v26.m128i_i64[0] = 0x461D9F21DDE0ECE5i64;
  v26.m128i_i64[1] = 0xEF12F7E4671BCBEAui64;
  v19.m128i_i64[0] = 0x461D9F21DDE0ECF7i64;
  v19.m128i_i64[1] = 0xEF12F7E4671BCBF8ui64;
  v6 = _mm_load_si128(&v19);
  v27.m128i_i64[0] = 0x461D9F21DDE0ECE5i64;
  v27.m128i_i64[1] = 0xEF12F7E4671BCBEAui64;
  v20.m128i_i64[0] = 0x5429C9595A85AFC4i64;
  v20.m128i_i64[1] = 0xFD26A19CE07E88CBui64;
  v7 = _mm_load_si128(&v20);
  v28.m128i_i64[0] = 0x461D9F21DDE0ECE5i64;
  v28.m128i_i64[1] = 0xEF12F7E4671BCBEAui64;
  v21.m128i_i64[0] = 0x461D9F21CFD4BA9Di64;
  v21.m128i_i64[1] = 0xEF12F7E4752F9D92ui64;
  v8 = _mm_load_si128(&v21);
  v29.m128i_i64[0] = 0x461D9F21DDE0ECE5i64;
  v29.m128i_i64[1] = 0xEF12F7E4671BCBEAui64;
  v22.m128i_i64[0] = 0x461D9F21DDE0FED1i64;
  v22.m128i_i64[1] = 0xEF12F7E4671BD9DEui64;
  v9 = _mm_load_si128(&v22);
  v30.m128i_i64[0] = 0x461D9F21DDE0ECE5i64;
  v30.m128i_i64[1] = 0xEF12F7E4671BCBEAui64;
  v23.m128i_i64[0] = 0x461D9F21DDE0ECF7i64;
  v23.m128i_i64[1] = 0xEF12F7E4671BCBF8ui64;
  v10 = _mm_load_si128(&v23);
  v31.m128i_i64[0] = 0x461D9F21DDE0ECE5i64;
  v15 = _mm_cvtsi128_si32(_mm_xor_si128(v4, v25));
  v31.m128i_i64[1] = 0xEF12F7E4671BCBEAui64;
  v14 = _mm_xor_si128(v5, v26).m128i_u16[0];
  v13 = _mm_xor_si128(v6, v27).m128i_u8[0];
  sub_140001030(
    "%hhx %hx %x %llx\n%hhx %hx %x %llx\n",
    (unsigned int)_mm_xor_si128(v10, v31).m128i_i8[0],
    (unsigned int)_mm_xor_si128(v9, v30).m128i_i16[0],
    _mm_xor_si128(v8, v29).m128i_u64[0],
    _mm_xor_si128(v7, v28).m128i_u64[0],
    v13,
    v14,
    v15,
    _mm_xor_si128(v3, v24).m128i_u64[0]);
  v32.m128i_i64[0] = 0x461D9F21DDE0ECE5i64;
  v32.m128i_i64[1] = 0xEF12F7E4671BCBEAui64;
  v11 = _mm_load_si128(&v32);
  v33.m128i_i64[0] = 0x461D9F21DDE0ECE5i64;
  v33.m128i_i64[1] = 0xEF12F7E4671BCBEAui64;
  return _mm_xor_si128(v11, v33).m128i_u32[0];
}

AVX 2

int __cdecl main(int argc, const char** argv, const char** envp)
{
    int v10; // er9
    int v14; // ecx
    __int64 v22; // r8
    __int64 v31; // [rsp+20h] [rbp-288h]
    int v32; // [rsp+28h] [rbp-280h]
    int v33; // [rsp+30h] [rbp-278h]
    int v34; // [rsp+38h] [rbp-270h]
    __int64 v35; // [rsp+40h] [rbp-268h]
    __int128 v36; // [rsp+50h] [rbp-258h]
    __int128 v37; // [rsp+70h] [rbp-238h]
    __int128 v38; // [rsp+90h] [rbp-218h]
    __int128 v39; // [rsp+B0h] [rbp-1F8h]
    __int128 v40; // [rsp+D0h] [rbp-1D8h]
    __int128 v41; // [rsp+F0h] [rbp-1B8h]
    __int128 v42; // [rsp+110h] [rbp-198h]
    __int128 v43; // [rsp+130h] [rbp-178h]
    __int128 v44; // [rsp+250h] [rbp-58h]

    *(_QWORD*)&v36 = 0xAD6F96434E1A20E8ui64;
    *((_QWORD*)&v36 + 1) = 0x8C26338203B39BE7ui64;
    __asm
    {
        vmovdqu xmm0, [rsp + 2A8h + var_258]
        vpxor   xmm5, xmm0, [rsp + 2A8h + var_158]
    }
    *(_QWORD*)&v37 = 0xBF5BC03BDB4B35B1ui64;
    *((_QWORD*)&v37 + 1) = 0x9E1265FA96E28EBEui64;
    __asm
    {
        vmovdqu xmm0, [rsp + 2A8h + var_238]
        vpxor   xmm4, xmm0, [rsp + 2A8h + var_138]
    }
    *(_QWORD*)&v38 = 0xBF5BC03BC97F70FEui64;
    *((_QWORD*)&v38 + 1) = 0x9E1265FA84D6CBF1ui64;
    __asm
    {
        vmovdqu xmm0, [rsp + 2A8h + var_218]
        vpxor   xmm1, xmm0, [rsp + 2A8h + var_118]
        vmovq   rax, xmm1
    }
    v10 = (unsigned __int16)_RAX;
    *(_QWORD*)&v39 = 0xBF5BC03BC97F63DBui64;
    *((_QWORD*)&v39 + 1) = 0x9E1265FA84D6D8D4ui64;
    __asm
    {
        vmovdqu xmm0, [rsp + 2A8h + var_1F8]
        vpxor   xmm1, xmm0, [rsp + 2A8h + var_F8]
        vmovq   rax, xmm1
    }
    v14 = (unsigned __int8)_RAX;
    *(_QWORD*)&v40 = 0xAD6F96434E1A20E8ui64;
    *((_QWORD*)&v40 + 1) = 0x8C26338203B39BE7ui64;
    __asm
    {
        vmovdqu xmm0, [rsp + 2A8h + var_1D8]
        vpxor   xmm3, xmm0, [rsp + 2A8h + var_D8]
    }
    *(_QWORD*)&v41 = 0xBF5BC03BDB4B35B1ui64;
    *((_QWORD*)&v41 + 1) = 0x9E1265FA96E28EBEui64;
    __asm
    {
        vmovdqu xmm0, [rsp + 2A8h + var_1B8]
        vpxor   xmm2, xmm0, [rsp + 2A8h + var_B8]
    }
    *(_QWORD*)&v42 = 0xBF5BC03BC97F70FEui64;
    *((_QWORD*)&v42 + 1) = 0x9E1265FA84D6CBF1ui64;
    __asm
    {
        vmovdqu xmm0, [rsp + 2A8h + var_198]
        vpxor   xmm1, xmm0, [rsp + 2A8h + var_98]
        vmovq[rsp + 2A8h + var_268], xmm5
        vmovq   rax, xmm1
    }
    v22 = (unsigned int)(__int16)_RAX;
    *(_QWORD*)&v43 = 0xBF5BC03BC97F63DBui64;
    *((_QWORD*)&v43 + 1) = 0x9E1265FA84D6D8D4ui64;
    __asm
    {
        vmovdqu xmm0, [rsp + 2A8h + var_178]
        vmovd[rsp + 2A8h + var_270], xmm4
    }
    v33 = v10;
    v32 = v14;
    __asm
    {
        vpxor   xmm1, xmm0, [rsp + 2A8h + var_78]
        vmovq   rax, xmm1
        vmovq   r9, xmm2
        vmovq[rsp + 2A8h + var_288], xmm3
    }
    printf("%hhx %hx %x %llx\n%hhx %hx %x %llx\n", (unsigned int)(char)_RAX, v22, _R9, v31, v32, v33, v34, v35);
    *(_QWORD*)&v44 = 0xBF5BC03BC97F63C9ui64;
    *((_QWORD*)&v44 + 1) = 0x9E1265FA84D6D8C6ui64;
    __asm
    {
        vmovdqu xmm0, [rsp + 2A8h + var_58]
        vpxor   xmm1, xmm0, [rsp + 2A8h + var_38]
        vmovq   rax, xmm1
    }
    return _RAX;
}

XD I tried to copy the IDA PRO result into my program.. and it works fine.. quite amazing. if people wanted to manually decode what's on this function.. but only the sse2 IDA PRO decompilation works.

image

but again I know the purpose of this project is just to hide the value. :) and you guys did it. <3

@llxiaoyuan
Copy link
Contributor Author

I guess this demo only accept ints

yeah, demo only, if we add ints to xorstr, the repo may be need rename

@JustasMasiulis JustasMasiulis added the enhancement New feature or request label Apr 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants