├── .gitattributes
├── .gitignore
├── BDASM.sln
├── BDASM
├── BDASM.vcxproj
├── BDASM.vcxproj.filters
├── BDASM.vcxproj.user
├── addr_width.h
├── align.h
├── backtrace.h
├── common_code.h
├── condition_code.h
├── constant_encryption.h
├── dasm.h
├── dasm2.h
├── dpattern.h
├── emu.h
├── encoder.h
├── encrypted_blocks.h
├── encrypted_routines.h
├── flags.h
├── flat_control.h
├── inst.h
├── ir.h
├── linker.h
├── main.cpp
├── mba.h
├── obf.h
├── opaques.h
├── original.h
├── other_vm.h
├── pex.h
├── pi_blocks.h
├── rvas.txt
├── sff.h
├── size_casting.h
├── stack_allocation.h
├── substitution.h
├── symbol.h
├── traits.h
├── virtual_operands.h
└── x64
│ ├── Debug
│ ├── BDASM.ilk
│ └── vc143.idb
│ └── Release
│ └── BDASM.vcxproj.FileListAbsolute.txt
├── README.md
├── TestExe
├── TestExe.vcxproj
├── TestExe.vcxproj.filters
├── TestExe.vcxproj.user
├── main.cpp
└── x64
│ └── Release
│ └── TestExe.vcxproj.FileListAbsolute.txt
└── sdk.h
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 |
10 | # Precompiled Headers
11 | *.gch
12 | *.pch
13 |
14 | # Compiled Dynamic libraries
15 | *.so
16 | *.dylib
17 | *.dll
18 |
19 | # Fortran module files
20 | *.mod
21 | *.smod
22 |
23 | # Compiled Static libraries
24 | *.lai
25 | *.la
26 | *.a
27 |
28 | # Executables
29 | *.exe
30 | *.out
31 | *.app
32 | *.ipch
33 | *.tlog
34 | *.ipdb
35 | *.db
36 | *.db-shm
37 | *.db-wal
38 | *.opendb
39 | *.log
40 | *.recipe
41 | *.iobj
42 | *.pdb
43 | *.vsidx
44 | *.id0
45 | *.id1
46 | *.id2
47 | x64/Release/TestExe.exe.nam
48 | x64/Release/TestExe.exe.til
49 | *.idb
50 | *.ilk
51 | *.nam
52 |
53 | .vs/
54 | x64/
55 | build/
56 |
--------------------------------------------------------------------------------
/BDASM.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.32210.238
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BDASM", "BDASM\BDASM.vcxproj", "{69339CAA-45EE-4CA5-A688-B37653825BE8}"
7 | ProjectSection(ProjectDependencies) = postProject
8 | {4006C556-E4CF-4562-8D04-1F3ABB594571} = {4006C556-E4CF-4562-8D04-1F3ABB594571}
9 | EndProjectSection
10 | EndProject
11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestExe", "TestExe\TestExe.vcxproj", "{4006C556-E4CF-4562-8D04-1F3ABB594571}"
12 | EndProject
13 | Global
14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
15 | Debug|x64 = Debug|x64
16 | Debug|x86 = Debug|x86
17 | Release|x64 = Release|x64
18 | Release|x86 = Release|x86
19 | EndGlobalSection
20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
21 | {69339CAA-45EE-4CA5-A688-B37653825BE8}.Debug|x64.ActiveCfg = Debug|x64
22 | {69339CAA-45EE-4CA5-A688-B37653825BE8}.Debug|x64.Build.0 = Debug|x64
23 | {69339CAA-45EE-4CA5-A688-B37653825BE8}.Debug|x86.ActiveCfg = Debug|Win32
24 | {69339CAA-45EE-4CA5-A688-B37653825BE8}.Debug|x86.Build.0 = Debug|Win32
25 | {69339CAA-45EE-4CA5-A688-B37653825BE8}.Release|x64.ActiveCfg = Release|x64
26 | {69339CAA-45EE-4CA5-A688-B37653825BE8}.Release|x64.Build.0 = Release|x64
27 | {69339CAA-45EE-4CA5-A688-B37653825BE8}.Release|x86.ActiveCfg = Release|Win32
28 | {69339CAA-45EE-4CA5-A688-B37653825BE8}.Release|x86.Build.0 = Release|Win32
29 | {4006C556-E4CF-4562-8D04-1F3ABB594571}.Debug|x64.ActiveCfg = Debug|x64
30 | {4006C556-E4CF-4562-8D04-1F3ABB594571}.Debug|x64.Build.0 = Debug|x64
31 | {4006C556-E4CF-4562-8D04-1F3ABB594571}.Debug|x86.ActiveCfg = Debug|Win32
32 | {4006C556-E4CF-4562-8D04-1F3ABB594571}.Debug|x86.Build.0 = Debug|Win32
33 | {4006C556-E4CF-4562-8D04-1F3ABB594571}.Release|x64.ActiveCfg = Release|x64
34 | {4006C556-E4CF-4562-8D04-1F3ABB594571}.Release|x64.Build.0 = Release|x64
35 | {4006C556-E4CF-4562-8D04-1F3ABB594571}.Release|x86.ActiveCfg = Release|Win32
36 | {4006C556-E4CF-4562-8D04-1F3ABB594571}.Release|x86.Build.0 = Release|Win32
37 | EndGlobalSection
38 | GlobalSection(SolutionProperties) = preSolution
39 | HideSolutionNode = FALSE
40 | EndGlobalSection
41 | GlobalSection(ExtensibilityGlobals) = postSolution
42 | SolutionGuid = {9BE56D46-FA20-4666-A005-A27213D17D26}
43 | EndGlobalSection
44 | EndGlobal
45 |
--------------------------------------------------------------------------------
/BDASM/BDASM.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {69339caa-45ee-4ca5-a688-b37653825be8}
25 | BDASM
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v143
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v143
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v143
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v143
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 |
76 |
77 | false
78 |
79 |
80 | true
81 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)build\obj\wkit\include
82 |
83 |
84 | false
85 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)build\obj\wkit\include
86 |
87 |
88 |
89 | Level3
90 | true
91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
92 | true
93 |
94 |
95 | Console
96 | true
97 |
98 |
99 |
100 |
101 | Level3
102 | true
103 | true
104 | true
105 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 |
108 |
109 | Console
110 | true
111 | true
112 | true
113 |
114 |
115 |
116 |
117 | Level3
118 | true
119 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
120 | true
121 | $(SolutionDir);%(AdditionalIncludeDirectories)
122 | stdcpp20
123 |
124 |
125 | Console
126 | true
127 | xed.lib;%(AdditionalDependencies)
128 | $(SolutionDir)build\obj\wkit\lib
129 |
130 |
131 |
132 |
133 | Level3
134 | true
135 | true
136 | true
137 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
138 | true
139 | $(SolutionDir);%(AdditionalIncludeDirectories)
140 | stdcpp20
141 |
142 |
143 | Console
144 | true
145 | true
146 | true
147 | xed.lib;%(AdditionalDependencies)
148 | $(SolutionDir)build\obj\wkit\lib
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
195 |
196 |
197 |
--------------------------------------------------------------------------------
/BDASM/BDASM.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Testing
6 |
7 |
8 | headers\dasm
9 |
10 |
11 | headers\dasm
12 |
13 |
14 | headers\dasm
15 |
16 |
17 | headers\xed
18 |
19 |
20 | headers
21 |
22 |
23 | headers\utils
24 |
25 |
26 | headers
27 |
28 |
29 | headers\dasm
30 |
31 |
32 | headers\dasm
33 |
34 |
35 | headers\utils
36 |
37 |
38 | headers\utils
39 |
40 |
41 | headers\utils
42 |
43 |
44 | headers\dasm
45 |
46 |
47 | headers\obfuscator
48 |
49 |
50 | headers\obfuscator
51 |
52 |
53 | headers\obfuscator\passes\mutation
54 |
55 |
56 | headers\obfuscator\passes\mutation
57 |
58 |
59 | headers\obfuscator\passes\mutation
60 |
61 |
62 | headers\obfuscator\passes\mutation
63 |
64 |
65 | headers\obfuscator\passes\mutation
66 |
67 |
68 | headers\obfuscator\passes\mutation
69 |
70 |
71 | headers\obfuscator\passes\mutation
72 |
73 |
74 | headers\dasm
75 |
76 |
77 | headers\obfuscator\virtualizer\ir
78 |
79 |
80 | headers\obfuscator\passes\mutation
81 |
82 |
83 | headers\xed
84 |
85 |
86 | headers\obfuscator\passes\utility
87 |
88 |
89 | headers\utils
90 |
91 |
92 | headers\obfuscator\passes\mutation
93 |
94 |
95 | headers\obfuscator\passes\mutation
96 |
97 |
98 | headers\obfuscator\passes\mutation
99 |
100 |
101 |
102 |
103 | {210126f2-8894-4b8d-b89c-13ad10de0906}
104 |
105 |
106 | {2022b579-6edd-4d14-817d-d13fda4315b0}
107 |
108 |
109 | {e838d32b-d295-409f-ada1-ff952beed48a}
110 |
111 |
112 | {f08220bb-65a3-4763-82ea-b6ab6662ed8f}
113 |
114 |
115 | {0136dbc2-1a9e-4fed-b3eb-8333ba453967}
116 |
117 |
118 | {7bff6ba0-bb46-4961-81b0-3fc14ffc27cf}
119 |
120 |
121 | {16f57466-8880-4c24-918d-0ea63aa306b9}
122 |
123 |
124 | {98d91127-8483-46b5-beca-2eb974560df8}
125 |
126 |
127 | {8b341389-a348-4f53-a425-4812e390a8b8}
128 |
129 |
130 | {c1e8db83-bfed-4591-8c7e-cba64dbe7148}
131 |
132 |
133 | {9e4fd3df-da25-41a0-81cd-560754733ebf}
134 |
135 |
136 | {e616c714-937e-4ff4-8164-b1cb15628f08}
137 |
138 |
139 |
140 |
141 | Testing
142 |
143 |
144 |
145 |
146 | headers\obfuscator\passes\utility
147 |
148 |
149 |
--------------------------------------------------------------------------------
/BDASM/BDASM.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WindowsLocalDebugger
5 |
6 |
--------------------------------------------------------------------------------
/BDASM/addr_width.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | extern "C"
6 | {
7 | #include
8 | }
9 |
10 | namespace addr_width
11 | {
12 | enum class type : uint32_t
13 | {
14 | __x86 = 0,
15 | __x64 = 1,
16 | __invalid,
17 | };
18 |
19 | constexpr type x86 = type::__x86;
20 | constexpr type x64 = type::__x64;
21 | constexpr type invalid = type::__invalid;
22 |
23 | template struct bits;
24 | template<> struct bits { constexpr static uint32_t value = 32; };
25 | template<> struct bits { constexpr static uint32_t value = 64; };
26 |
27 | template struct bytes;
28 | template<> struct bytes { constexpr static uint32_t value = 4; };
29 | template<> struct bytes { constexpr static uint32_t value = 8; };
30 |
31 | template struct storage;
32 | template<> struct storage { using type = uint32_t; };
33 | template<> struct storage { using type = uint64_t; };
34 |
35 | template struct register_count;
36 | template<> struct register_count { constexpr static uint32_t value = 8; };
37 | template<> struct register_count { constexpr static uint32_t value = 16; };
38 |
39 | template struct machine_state;
40 | template<> struct machine_state
41 | {
42 | constexpr static xed_state_t value = { XED_MACHINE_MODE_LONG_COMPAT_32, XED_ADDRESS_WIDTH_32b };
43 | };
44 | template<> struct machine_state
45 | {
46 | constexpr static xed_state_t value = { XED_MACHINE_MODE_LONG_64, XED_ADDRESS_WIDTH_64b };
47 | };
48 |
49 | template struct fastcall_regs;
50 | template<> struct fastcall_regs
51 | {
52 | constexpr static xed_reg_enum_t regs[] = { XED_REG_EDX, XED_REG_ECX };
53 | };
54 | template<> struct fastcall_regs
55 | {
56 | constexpr static xed_reg_enum_t regs[] = { XED_REG_R9, XED_REG_R8, XED_REG_RDX, XED_REG_RCX };
57 | };
58 |
59 | //template struct gprs;
60 | //template<> struct gprs
61 | //{
62 | // constexpr static xed_reg_enum_t regs[] = { XED_REG_EAX, XED_REG_RBX };
63 | //};
64 | //template<> struct gprs
65 | //{
66 | // constexpr static xed_reg_enum_t regs[] = { XED_REG_RAX, XED_REG_RBX };
67 | //};
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/BDASM/align.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 |
4 | #include
5 | #include
6 |
7 |
8 | template
9 | inline Align_type align_up(Align_type val, uint32_t alignment)
10 | {
11 | static_assert(std::is_integral::value, "Invalid parameter passed to align_up.");
12 | const Align_type ralign = alignment - 1;
13 | return static_cast((val + ralign) & (~ralign));
14 | }
15 |
16 | template
17 | inline Align_type align_up_ptr(Align_type val, uint32_t alignment)
18 | {
19 | static_assert(std::is_pointer::value, "Invalid parameter passed to align_up_ptr.");
20 | const uint64_t ralign = alignment - 1;
21 | return reinterpret_cast((reinterpret_cast(val) + ralign) & (~ralign));
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/BDASM/backtrace.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "dasm.h"
4 |
5 |
6 |
7 | // Trace backwards in the current block to see if a register equals another
8 | // This is useful when the compiler decodes to randomly do something like:
9 | //
10 | // mov rax,rsp
11 | // mov [rax+offset],val
12 | //
13 | // Or some other annoyingly weird thing. this can follow something like this:
14 | // mov rcx,rsp
15 | // mov rax,rcx
16 | // mov [rax+10h],rbx
17 | //
18 | template
19 | bool trace_for_reg_alias(dasm::block_t& block, dasm::inst_it_t start, xed_reg_enum_t reg1, xed_reg_enum_t reg2)
20 | {
21 | for (auto rev = std::make_reverse_iterator(start); rev != block.instructions.rend(); ++rev)
22 | {
23 | if (auto iform = rev->iform();
24 | (iform == XED_IFORM_MOV_GPRv_GPRv_89 || iform == XED_IFORM_MOV_GPRv_GPRv_8B) &&
25 | reg1 == xed_decoded_inst_get_reg(&rev->decoded_inst, XED_OPERAND_REG0))
26 | {
27 | auto right_reg = xed_decoded_inst_get_reg(&rev->decoded_inst, XED_OPERAND_REG0);
28 | if (reg2 == right_reg)
29 | return true;
30 | else
31 | reg1 = right_reg;
32 | }
33 | else
34 | {
35 | auto inst = rev->inst();
36 | auto num_operands = rev->noperands();
37 |
38 | for (uint32_t i = 0; i < num_operands; ++i)
39 | {
40 | auto operand = xed_inst_operand(inst, i);
41 | if (xed_operand_written(operand))
42 | {
43 | auto operand_name = xed_operand_name(operand);
44 | if (xed_operand_is_register(operand_name))
45 | {
46 | if (reg1 == xed_decoded_inst_get_reg(&rev->decoded_inst, operand_name))
47 | return false;
48 | }
49 | }
50 | }
51 | }
52 | }
53 |
54 | system("pause");
55 | return false;
56 | }
57 |
--------------------------------------------------------------------------------
/BDASM/common_code.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "obf.h"
4 |
5 | #include "dpattern.h"
6 | // So, a lot of code is repeated in binaries. So the idea is ill put these common blocks of code that
7 | // all routines can jump to. Like vm handlers :)
8 | //
9 | // [IMPORTANT] You access these blocks by transfering control flow with a call, then its returned to you
10 | // with a ret. this however moves the stack by 8(or 4) bytes so this must be accounted for. All [rsp]
11 | // displacements must be adjusted, [rbp] does not need this however.
12 | //
13 | // The most obvious example of this can be applied in function prologues. Specifically around stack
14 | // allocations and home space storage.
15 | //
16 |
17 | struct common_stack_manip_t
18 | {
19 | // Inserts a function that does this
20 | // Assumes rax is caller saved
21 | // Ex:
22 | // push stack_adjustment ; +8
23 | // call stack_manipulator ; +8-8
24 | //
25 | //
26 | // stack_manipulator proc
27 | // xchg rax,[rsp+8h] ; swap rax and stack adjustment
28 | // xchg rbx,[rsp]
29 | // sub rsp,rax ; +stack_adjustment
30 | // mov [rsp+8h],rbx ; [rsp+8] is return address
31 | // mov rbx,[rsp+rax] ; restore the original rbx value
32 | // mov rax,[rsp+rax+8h]
33 | // add rsp,8h ; take care of the 8 bytes from pushed stack_adjustment value
34 | // ret ; pops [rsp]
35 | // stack_manipulator endp
36 | //
37 | // //xchg rbx,[rsp+rax+8]
38 | // add rsp,8h
39 | // mov [rsp],rax
40 | //
41 | template
42 | static uint32_t insert_stack_manipulator(obf::obf_t& ctx)
43 | {
44 | auto link = ctx.linker->allocate_link();
45 |
46 | dasm::routine_t& routine = ctx.additional_routines.emplace_back();
47 | routine.entry_link = link;
48 |
49 | auto& block = routine.blocks.emplace_back(routine.blocks.end());
50 | block.termination_type = dasm::termination_type_t::returns;
51 | block.link = link;
52 |
53 | routine.entry_block = routine.blocks.begin();
54 |
55 | auto& insts = block.instructions;
56 |
57 |
58 |
59 | }
60 |
61 | template
62 | static obf::pass_status_t pass(obf::obf_t& ctx)
63 | {
64 |
65 | }
66 | };
67 |
68 | struct common_prologue_t
69 | {
70 |
71 | template
72 | static obf::pass_status_t pass(obf::obf_t& ctx)
73 | {
74 |
75 | }
76 | };
77 |
78 | struct common_epilogue_t
79 | {
80 | template
81 | static obf::pass_status_t pass(obf::obf_t& ctx)
82 | {
83 |
84 | }
85 | };
86 |
87 | struct common_code_t
88 | {
89 | template
90 | static obf::pass_status_t pass(obf::obf_t& ctx)
91 | {
92 |
93 | }
94 | };
95 |
96 |
--------------------------------------------------------------------------------
/BDASM/condition_code.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 |
4 | extern "C"
5 | {
6 | #include
7 | }
8 |
9 | #include
10 |
11 | enum xed_condition_code_t : uint8_t
12 | {
13 | XED_CC_B,
14 | XED_CC_BE,
15 | XED_CC_L,
16 | XED_CC_LE,
17 | XED_CC_NB,
18 | XED_CC_NBE,
19 | XED_CC_NL,
20 | XED_CC_NLE,
21 | XED_CC_NO,
22 | XED_CC_NP,
23 | XED_CC_NS,
24 | XED_CC_NZ,
25 | XED_CC_O,
26 | XED_CC_P,
27 | XED_CC_S,
28 | XED_CC_Z,
29 | XED_CC_COMPAT_END, //Everything before this has jcc and cmovcc versions
30 | XED_CC_CXZ,
31 | XED_CC_ECXZ,
32 | XED_CC_RCXZ,
33 | XED_CC_INVALID,
34 | };
35 |
36 | xed_condition_code_t __cc_inversion_map[] = {
37 | XED_CC_NB,
38 | XED_CC_NBE,
39 | XED_CC_NL,
40 | XED_CC_NLE,
41 | XED_CC_B,
42 | XED_CC_BE,
43 | XED_CC_L,
44 | XED_CC_LE,
45 | XED_CC_O,
46 | XED_CC_P,
47 | XED_CC_S,
48 | XED_CC_Z,
49 | XED_CC_NO,
50 | XED_CC_NP,
51 | XED_CC_NS,
52 | XED_CC_NZ,
53 | XED_CC_INVALID,
54 | XED_CC_INVALID,
55 | XED_CC_INVALID,
56 | XED_CC_INVALID,
57 | XED_CC_INVALID,
58 | };
59 |
60 | xed_iclass_enum_t __cc_cmovcc_map[] = {
61 | XED_ICLASS_CMOVB,
62 | XED_ICLASS_CMOVBE,
63 | XED_ICLASS_CMOVL,
64 | XED_ICLASS_CMOVLE,
65 | XED_ICLASS_CMOVNB,
66 | XED_ICLASS_CMOVNBE,
67 | XED_ICLASS_CMOVNL,
68 | XED_ICLASS_CMOVNLE,
69 | XED_ICLASS_CMOVNO,
70 | XED_ICLASS_CMOVNP,
71 | XED_ICLASS_CMOVNS,
72 | XED_ICLASS_CMOVNZ,
73 | XED_ICLASS_CMOVO,
74 | XED_ICLASS_CMOVP,
75 | XED_ICLASS_CMOVS,
76 | XED_ICLASS_CMOVZ,
77 | XED_ICLASS_INVALID,
78 | XED_ICLASS_INVALID,
79 | XED_ICLASS_INVALID,
80 | XED_ICLASS_INVALID,
81 | XED_ICLASS_INVALID,
82 | };
83 |
84 | xed_iclass_enum_t __cc_jcc_map[] = {
85 | XED_ICLASS_JB,
86 | XED_ICLASS_JBE,
87 | XED_ICLASS_JL,
88 | XED_ICLASS_JLE,
89 | XED_ICLASS_JNB,
90 | XED_ICLASS_JNBE,
91 | XED_ICLASS_JNL,
92 | XED_ICLASS_JNLE,
93 | XED_ICLASS_JNO,
94 | XED_ICLASS_JNP,
95 | XED_ICLASS_JNS,
96 | XED_ICLASS_JNZ,
97 | XED_ICLASS_JO,
98 | XED_ICLASS_JP,
99 | XED_ICLASS_JS,
100 | XED_ICLASS_JZ,
101 | XED_ICLASS_INVALID,
102 | XED_ICLASS_JCXZ,
103 | XED_ICLASS_JECXZ,
104 | XED_ICLASS_JRCXZ,
105 | XED_ICLASS_INVALID,
106 | };
107 |
108 | bool __cc_supports_cmovcc[] = {
109 | true,
110 | true,
111 | true,
112 | true,
113 | true,
114 | true,
115 | true,
116 | true,
117 | true,
118 | true,
119 | true,
120 | true,
121 | true,
122 | true,
123 | true,
124 | true,
125 | false,
126 | false,
127 | false,
128 | false,
129 | false,
130 | };
131 |
132 | bool __cc_supports_jcc[] = {
133 | true,
134 | true,
135 | true,
136 | true,
137 | true,
138 | true,
139 | true,
140 | true,
141 | true,
142 | true,
143 | true,
144 | true,
145 | true,
146 | true,
147 | true,
148 | true,
149 | false,
150 | true,
151 | true,
152 | true,
153 | false,
154 | };
155 |
156 | constexpr bool xed_condition_code_supports_cmovcc(xed_condition_code_t cc)
157 | {
158 | return __cc_supports_cmovcc[cc];
159 | }
160 |
161 | constexpr bool xed_condition_code_supports_jcc(xed_condition_code_t cc)
162 | {
163 | return __cc_supports_jcc[cc];
164 | }
165 |
166 | constexpr xed_condition_code_t xed_invert_condition_code(xed_condition_code_t cc)
167 | {
168 | return __cc_inversion_map[cc];
169 | }
170 |
171 | constexpr bool xed_condition_code_is_convertible(xed_condition_code_t cc)
172 | {
173 | return (xed_condition_code_supports_cmovcc(cc) && xed_condition_code_supports_jcc(cc));
174 | }
175 |
176 | constexpr xed_iclass_enum_t xed_condition_code_to_cmovcc(xed_condition_code_t cc)
177 | {
178 | return __cc_cmovcc_map[cc];
179 | }
180 |
181 | constexpr xed_iclass_enum_t xed_condition_code_to_jcc(xed_condition_code_t cc)
182 | {
183 | return __cc_jcc_map[cc];
184 | }
185 |
186 | constexpr xed_condition_code_t xed_iclass_to_condition_code(xed_iclass_enum_t iclass)
187 | {
188 | switch (iclass)
189 | {
190 | case XED_ICLASS_JB: [[fallthrough]]; case XED_ICLASS_CMOVB: return XED_CC_B;
191 | case XED_ICLASS_JBE: [[fallthrough]]; case XED_ICLASS_CMOVBE: return XED_CC_BE;
192 | case XED_ICLASS_JL: [[fallthrough]]; case XED_ICLASS_CMOVL: return XED_CC_L;
193 | case XED_ICLASS_JLE: [[fallthrough]]; case XED_ICLASS_CMOVLE: return XED_CC_LE;
194 | case XED_ICLASS_JNB: [[fallthrough]]; case XED_ICLASS_CMOVNB: return XED_CC_NB;
195 | case XED_ICLASS_JNBE: [[fallthrough]]; case XED_ICLASS_CMOVNBE: return XED_CC_NBE;
196 | case XED_ICLASS_JNL: [[fallthrough]]; case XED_ICLASS_CMOVNL: return XED_CC_NL;
197 | case XED_ICLASS_JNLE: [[fallthrough]]; case XED_ICLASS_CMOVNLE: return XED_CC_NLE;
198 | case XED_ICLASS_JNO: [[fallthrough]]; case XED_ICLASS_CMOVNO: return XED_CC_NO;
199 | case XED_ICLASS_JNP: [[fallthrough]]; case XED_ICLASS_CMOVNP: return XED_CC_NP;
200 | case XED_ICLASS_JNS: [[fallthrough]]; case XED_ICLASS_CMOVNS: return XED_CC_NS;
201 | case XED_ICLASS_JNZ: [[fallthrough]]; case XED_ICLASS_CMOVNZ: return XED_CC_NZ;
202 | case XED_ICLASS_JO: [[fallthrough]]; case XED_ICLASS_CMOVO: return XED_CC_O;
203 | case XED_ICLASS_JP: [[fallthrough]]; case XED_ICLASS_CMOVP: return XED_CC_P;
204 | case XED_ICLASS_JS: [[fallthrough]]; case XED_ICLASS_CMOVS: return XED_CC_S;
205 | case XED_ICLASS_JZ: [[fallthrough]]; case XED_ICLASS_CMOVZ: return XED_CC_Z;
206 | case XED_ICLASS_JCXZ: return XED_CC_CXZ;
207 | case XED_ICLASS_JECXZ: return XED_CC_ECXZ;
208 | case XED_ICLASS_JRCXZ: return XED_CC_RCXZ;
209 | default: return XED_CC_INVALID;
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/BDASM/constant_encryption.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "obf.h"
4 | #include "flags.h"
5 | #include "size_casting.h"
6 |
7 | struct constant_encryption_t
8 | {
9 | template
10 | static uint32_t encrypted_const_custom_encoder(dasm::inst_t* inst, pex::binary_t* bin, dasm::linker_t* linker, uint8_t* dest, uint32_t xor_key)
11 | {
12 | uint32_t expected_length = inst->length();
13 |
14 | inst->resolve_deltas(bin, linker, dest, expected_length);
15 |
16 | auto imm = xed_decoded_inst_get_unsigned_immediate(&inst->decoded_inst);
17 | //printf("Custom encoder called %X %X %X\n", imm, inst->used_link, inst->flags);
18 | imm ^= xor_key;
19 | xed_decoded_inst_set_immediate_unsigned_bits(&inst->decoded_inst, imm, xed_decoded_inst_get_immediate_width_bits(&inst->decoded_inst));
20 |
21 | uint32_t ilen = 0;
22 | xed_error_enum_t err = xed_encode(&inst->decoded_inst, dest, XED_MAX_INSTRUCTION_BYTES, &ilen);
23 | if (XED_ERROR_NONE != err)
24 | return 0;
25 |
26 | if (ilen != expected_length)
27 | {
28 | printf("Encoded inst length did not match what was expected.\n");
29 | return 0;
30 | }
31 |
32 | return ilen;
33 | }
34 |
35 | template
36 | static obf::pass_status_t pass(dasm::routine_t& routine, obf::obf_t& ctx)
37 | {
38 | for (auto block_it = routine.blocks.begin(); block_it != routine.blocks.end(); ++block_it)
39 | {
40 | for (auto inst_it = block_it->instructions.begin(); inst_it != block_it->instructions.end();)
41 | {
42 | auto next = std::next(inst_it);
43 |
44 | switch (inst_it->iform())
45 | {
46 | case XED_IFORM_MOV_GPRv_IMMv:
47 | case XED_IFORM_MOV_GPRv_IMMz:
48 | case XED_IFORM_MOV_GPR8_IMMb_B0:
49 | {
50 | auto imm_width = xed_decoded_inst_get_immediate_width_bits(&inst_it->decoded_inst);
51 | if (imm_width > 32 || xed_decoded_inst_get_immediate_is_signed(&inst_it->decoded_inst) || inst_it->custom_encoder)
52 | break;
53 |
54 | xed_flag_set_t ledger;
55 | ledger.s.of = 1;
56 | ledger.s.cf = 1;
57 | ledger.s.sf = 1;
58 | ledger.s.zf = 1;
59 | ledger.s.pf = 1;
60 | ledger.s.af = 1;
61 | bool need_to_save = dasm::flags_clobbered_before_use(routine, block_it, next, ledger);
62 |
63 |
64 | //printf("Found mov gpr,imm to obfuscate.\n");
65 | auto reg = xed_decoded_inst_get_reg(&inst_it->decoded_inst, XED_OPERAND_REG0);
66 | auto max_reg = change_reg_width(reg, addr_width::reg_width::value);
67 | uint64_t imm_value = xed_decoded_inst_get_unsigned_immediate(&inst_it->decoded_inst);
68 | //printf("Imm value %llu %X\n", imm_value, inst_it->original_rva);
69 | uint32_t xor_key = (((static_cast(rand()) << 16) |
70 | (static_cast(rand()) << 0)) & 0xFFFFFFFF);
71 |
72 | switch (imm_width)
73 | {
74 | case 8: xor_key &= 0xFF; break;
75 | case 16: xor_key &= 0xFFFF; break;
76 | }
77 |
78 | dasm::inst_list_t enc;
79 | enc.emplace_back(
80 | XED_ICLASS_PUSH,
81 | addr_width::bits::value,
82 | xed_imm0(imm_value, imm_width)
83 | ).common_edit(ctx.linker->allocate_link(), inst_it->used_link, inst_it->flags);
84 | enc.back().custom_encoder = std::bind(encrypted_const_custom_encoder,
85 | std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, xor_key);
86 |
87 | if (!need_to_save)
88 | enc.emplace_back(
89 | XED_ICLASS_PUSHF,
90 | addr_width::bits::value
91 | ).common_edit(ctx.linker->allocate_link(), 0, 0);
92 |
93 | enc.emplace_back(
94 | XED_ICLASS_MOV,
95 | addr_width::bits::value,
96 | xed_reg(max_reg),
97 | xed_imm0(xor_key, addr_width::bits::value)
98 | ).common_edit(ctx.linker->allocate_link(), 0, 0);
99 |
100 | if (!need_to_save)
101 | {
102 | enc.emplace_back(
103 | XED_ICLASS_XOR,
104 | addr_width::bits::value,
105 | xed_mem_bd(
106 | max_reg_width::value,
107 | xed_disp(8, 8),
108 | addr_width::bits::value
109 | ),
110 | xed_reg(max_reg)
111 | ).common_edit(ctx.linker->allocate_link(), 0, 0);
112 |
113 | enc.emplace_back(
114 | XED_ICLASS_POPF,
115 | addr_width::bits::value
116 | ).common_edit(ctx.linker->allocate_link(), 0, 0);
117 | }
118 | else
119 | {
120 | enc.emplace_back(
121 | XED_ICLASS_XOR,
122 | addr_width::bits::value,
123 | xed_mem_b(
124 | max_reg_width::value,
125 | addr_width::bits::value
126 | ),
127 | xed_reg(max_reg)
128 | ).common_edit(ctx.linker->allocate_link(), 0, 0);
129 | }
130 |
131 | enc.emplace_back(
132 | XED_ICLASS_POP,
133 | addr_width::bits::value,
134 | xed_reg(max_reg)
135 | ).common_edit(ctx.linker->allocate_link(), 0, 0);
136 |
137 | block_it->instructions.splice(inst_it, enc);
138 | block_it->instructions.erase(inst_it);
139 | break;
140 | }
141 | case XED_IFORM_PUSH_IMMb:
142 | case XED_IFORM_PUSH_IMMz:
143 | {
144 | printf("Found a push imm to obfuscate.\n");
145 | break;
146 | }
147 |
148 | }
149 |
150 | //auto inst = inst_it->inst();
151 | //auto num_operands = isnt->noperands();
152 | //for (uint32_t i = 0; i < num_operands; ++i)
153 | //{
154 | // auto operand_name = xed_operand_name(xed_inst_operand(inst, i));
155 | // if (operand_name == XED_OPERAND_IMM0/* || operand_name == XED_OPERAND_IMM0SIGNED*/)
156 | // {
157 | //
158 | // }
159 | //}
160 |
161 | inst_it = next;
162 | }
163 | }
164 | return obf::pass_status_t::success;
165 | }
166 | };
--------------------------------------------------------------------------------
/BDASM/dasm2.h:
--------------------------------------------------------------------------------
1 | //#pragma once
2 | //
3 | //#include "addr_width.h"
4 | //#include "inst.h"
5 | //#include "pex.h"
6 | //#include "size_casting.h"
7 | //
8 | //namespace dasm
9 | //{
10 | // template
11 | // struct rva_descriptor_t
12 | // {
13 | // std::list>::iterator block;
14 | //
15 | // std::atomic_bool decoded;
16 | // };
17 | //
18 | // template
19 | // struct thread_context_t
20 | // {
21 | // pex::binary_t* bin;
22 | //
23 | // const uint8_t* rva_base;
24 | // const uint64_t rva_max;
25 | //
26 | // rva_descriptor_t* lookup_table;
27 | //
28 | // std::function report_func_rva;
29 | //
30 | // thread_context_t(pex::binary_t* binary)
31 | // : rva_base(binary->mapped_image)
32 | // , rva_max(static_cast(binary->optional_header.get_size_of_image()))
33 | // , bin(binary)
34 | // { }
35 | //
36 | // bool validate_rva(uint64_t rva)
37 | // {
38 | // return rva < rva_max;
39 | // }
40 | // };
41 | //
42 | // template
43 | // struct block_discovery_thread_t
44 | // {
45 | // thread_context_t* m_context;
46 | //
47 | // std::thread* m_thread;
48 | //
49 | // std::atomic_bool m_signal_start;
50 | // std::atomic_bool m_signal_shutdown;
51 | //
52 | // std::mutex m_queued_routines_lock;
53 | // std::vector m_queued_routines;
54 | // public:
55 | // inline static std::atomic_uint32_t queued_routine_count;
56 | //
57 | // std::vector routine_starts;
58 | //
59 | // std::list> blocks;
60 | //
61 | // explicit block_discovery_thread_t(thread_context_t* context)
62 | // : m_context(context)
63 | // , m_signal_start(false)
64 | // , m_signal_shutdown(false)
65 | // {
66 | // m_thread = new std::thread(&block_discovery_thread_t::run, this);
67 | // }
68 | // explicit block_discovery_thread_t(block_discovery_thread_t const& to_copy) = delete;
69 | // ~block_discovery_thread_t()
70 | // {
71 | // if (m_thread->joinable())
72 | // m_thread->join();
73 | // delete m_thread;
74 | // }
75 | // bool pop_queued_routine(uint64_t& routine_rva)
76 | // {
77 | // if (!m_signal_start)
78 | // return false;
79 | //
80 | // std::lock_guard g(m_queued_routines_lock);
81 | // if (m_queued_routines.size())
82 | // {
83 | // routine_rva = m_queued_routines.back();
84 | // m_queued_routines.pop_back();
85 | // return true;
86 | // }
87 | // return false;
88 | // }
89 | //
90 | // void queue_routine(uint64_t routine_rva)
91 | // {
92 | // ++queued_routine_count;
93 | // std::lock_guard g(m_queued_routines_lock);
94 | // m_queued_routines.emplace_back(routine_rva);
95 | // }
96 | //
97 | // void start()
98 | // {
99 | // m_signal_start = true;
100 | // }
101 | // void stop()
102 | // {
103 | // m_signal_shutdown = true;
104 | // }
105 | //
106 | // void run()
107 | // {
108 | // while (!m_signal_shutdown)
109 | // {
110 | // uint64_t routine_rva = 0;
111 | // if (pop_queued_routine(routine_rva))
112 | // {
113 | // decode(routine_rva);
114 | // --queued_routine_count;
115 | // continue; //Skip the sleep.
116 | // }
117 | //
118 | // std::this_thread::sleep_for(std::chrono::milliseconds(1));
119 | // }
120 | // }
121 | //
122 | // void decode_block(uint64_t rva)
123 | // {
124 | // uint64_t rva_start = rva;
125 | // blocks.emplace_front();
126 | // auto cur_block_it = blocks.begin();
127 | // while (!m_context->lookup_table->decoded.exchange(true))
128 | // {
129 | //
130 | // auto& inst = cur_block_it->emplace_back();
131 | //
132 | // int32_t ilen = inst.decode(const_cast(m_context->rva_base + rva), m_context->rva_max - rva);
133 | // if (ilen == 0)
134 | // {
135 | // std::printf("Failed to decode, 0 inst length. RVA: 0x%p\n", rva);
136 | // return;
137 | // }
138 | //
139 | // if (auto iform = xed_decoded_inst_get_iform_enum(&inst.decoded_inst);
140 | // (iform == XED_IFORM_SUB_GPRv_IMMb ||
141 | // iform == XED_IFORM_SUB_GPRv_IMMz) &&
142 | // xed_decoded_inst_get_reg(&inst.decoded_inst, XED_OPERAND_REG0))
143 | // m_context->report_func_rva(rva_start);
144 | //
145 | //
146 | // //std::printf("IClass: %s\n", xed_iclass_enum_t2str(xed_decoded_inst_get_iclass(&inst.decoded_inst)));
147 | //
148 | // inst.original_rva = rva; // m_decoder_context->binary_interface->data_table->unsafe_get_symbol_index_for_rva(rva);
149 | //
150 | // bool has_reloc = m_context->bin->data_table->inst_uses_reloc(rva, ilen, inst.additional_data.reloc.offset_in_inst, inst.additional_data.reloc.type);
151 | //
152 | // // Parse operands for rip relative addressing and relocs
153 | // //
154 | // uint32_t num_operands = xed_decoded_inst_noperands(&inst.decoded_inst);
155 | // auto decoded_inst_inst = xed_decoded_inst_inst(&inst.decoded_inst);
156 | // for (uint32_t i = 0; i < num_operands; ++i)
157 | // {
158 | // auto operand_name = xed_operand_name(xed_inst_operand(decoded_inst_inst, i));
159 | // if (XED_OPERAND_MEM0 == operand_name || XED_OPERAND_AGEN == operand_name)
160 | // {
161 | // auto base_reg = xed_decoded_inst_get_base_reg(&inst.decoded_inst, 0);
162 | // if (max_reg_width::value == base_reg)
163 | // {
164 | // inst.used_link = rva + ilen + xed_decoded_inst_get_memory_displacement(&inst.decoded_inst, 0);/* m_decoder_context->binary_interface->data_table->unsafe_get_symbol_index_for_rva(
165 | // rva + ilen + xed_decoded_inst_get_memory_displacement(&inst.decoded_inst, 0)
166 | // );*/
167 | // inst.flags |= inst_flag::disp;
168 | // }
169 | // else if (XED_REG_INVALID == base_reg &&
170 | // xed_decoded_inst_get_memory_displacement_width_bits(&inst.decoded_inst, 0) == addr_width::bits::value)
171 | // {
172 | // if (has_reloc)
173 | // {
174 | // inst.used_link = static_cast(xed_decoded_inst_get_memory_displacement(&inst.decoded_inst, 0)) -
175 | // m_decoder_context->binary_interface->optional_header.get_image_base();
176 | // /*m_decoder_context->binary_interface->data_table->unsafe_get_symbol_index_for_rva(
177 | // static_cast(xed_decoded_inst_get_memory_displacement(&inst.decoded_inst, 0)) -
178 | // m_decoder_context->binary_interface->optional_header.get_image_base()
179 | // );*/
180 | // inst.additional_data.reloc.original_rva = rva + inst.additional_data.reloc.offset_in_inst;
181 | // inst.flags |= inst_flag::reloc_disp;
182 | // }
183 | // }
184 | // }
185 | // else if (has_reloc && XED_OPERAND_IMM0 == operand_name &&
186 | // xed_decoded_inst_get_immediate_width_bits(&inst.decoded_inst) == addr_width::bits::value)
187 | // {
188 | // inst.used_link = xed_decoded_inst_get_unsigned_immediate(&inst.decoded_inst) -
189 | // m_decoder_context->binary_interface->optional_header.get_image_base();
190 | // /*m_decoder_context->binary_interface->data_table->unsafe_get_symbol_index_for_rva(
191 | // xed_decoded_inst_get_unsigned_immediate(&inst.decoded_inst) -
192 | // m_decoder_context->binary_interface->optional_header.get_image_base()
193 | // );*/
194 | // inst.additional_data.reloc.original_rva = rva + inst.additional_data.reloc.offset_in_inst;
195 | // inst.flags |= inst_flag::reloc_imm;
196 | // }
197 | // }
198 | //
199 | // rva += ilen;
200 | //
201 | // // Update the end of the current block so its correct if we need to call split_block
202 | // cur_block_it->rva_end = rva;
203 | //
204 | // // Follow control flow
205 | // //
206 | // auto cat = xed_decoded_inst_get_category(&inst.decoded_inst);
207 | // if (cat == XED_CATEGORY_COND_BR)
208 | // {
209 | // int32_t br_disp = xed_decoded_inst_get_branch_displacement(&inst.decoded_inst);
210 | // uint64_t taken_rva = rva + br_disp;
211 | //
212 | // if (!m_decoder_context->validate_rva(taken_rva))
213 | // {
214 | // std::printf("Conditional branch to invalid rva.\n");
215 | // return current_routine->blocks.end();
216 | // }
217 | //
218 | // inst.used_link = taken_rva; // m_decoder_context->binary_interface->data_table->unsafe_get_symbol_index_for_rva(taken_rva);
219 | // inst.flags |= inst_flag::rel_br;
220 | //
221 | // if (!m_lookup_table.is_inst_start(taken_rva))
222 | // {
223 | // if (decode_block(taken_rva) == current_routine->blocks.end())
224 | // return current_routine->blocks.end();
225 | //
226 | // //if (m_decoder_context->routine_table[taken_rva] == true)
227 | // //{
228 | // //if (found_prologue)
229 | // m_decoder_context->relbr_table[taken_rva] = true;
230 | // //}
231 | // }
232 | // else
233 | // {
234 | // if (!split_block(taken_rva))
235 | // return current_routine->blocks.end();
236 | // }
237 | //
238 | // auto fallthrough = decode_block(rva);
239 | // if (fallthrough == current_routine->blocks.end())
240 | // return current_routine->blocks.end();
241 | //
242 | // cur_block_it->fallthrough_block = fallthrough;
243 | //
244 | // goto ExitInstDecodeLoop;
245 | // }
246 | // else if (cat == XED_CATEGORY_UNCOND_BR)
247 | // {
248 | // switch (xed_decoded_inst_get_iform_enum(&inst.decoded_inst))
249 | // {
250 | // case XED_IFORM_JMP_GPRv:
251 | // // Jump table.
252 | // //
253 | // std::printf("Unhandled inst[%08X]: XED_IFORM_JMP_GPRv.\n", rva - ilen);
254 | // return current_routine->blocks.end();
255 | // case XED_IFORM_JMP_MEMv:
256 | // if (!inst.used_link)
257 | // {
258 | // std::printf("Unhandled inst[%08X]: XED_IFORM_JMP_MEMv.\n", rva - ilen);
259 | // return current_routine->blocks.end();
260 | // }
261 | // goto ExitInstDecodeLoop;
262 | // case XED_IFORM_JMP_RELBRb:
263 | // case XED_IFORM_JMP_RELBRd:
264 | // case XED_IFORM_JMP_RELBRz:
265 | // {
266 | // int32_t jmp_disp = xed_decoded_inst_get_branch_displacement(&inst.decoded_inst);
267 | // uint64_t dest_rva = rva + jmp_disp;
268 | //
269 | // if (!m_decoder_context->validate_rva(dest_rva))
270 | // {
271 | // std::printf("Unconditional branch to invalid rva.\n");
272 | // goto ExitInstDecodeLoop;
273 | // }
274 | // inst.used_link = dest_rva; // m_decoder_context->binary_interface->data_table->unsafe_get_symbol_index_for_rva(dest_rva);
275 | // inst.flags |= inst_flag::rel_br;
276 | //
277 | //
278 | // // REWRITE ME
279 | // if (!m_lookup_table.is_inst_start(dest_rva))
280 | // {
281 | // // Here i will try to detect odd function calls that use a jump instead.
282 | // //
283 | // if constexpr (aw == addr_width::x64)
284 | // {
285 | // if (dest_rva < e_range_start || dest_rva >= e_range_end)
286 | // {
287 | // // No func data, this is a tail call to a leaf.
288 | // //
289 | // if (!m_decoder_context->binary_interface->data_table->has_func_data(dest_rva))
290 | // {
291 | // m_decoder_context->report_routine_rva(dest_rva);
292 | // goto ExitInstDecodeLoop;
293 | // }
294 | // else
295 | // {
296 | // // Not a leaf? lets see if the unwind info is the same
297 | // // If it is, this is just an oddly formed function
298 | // //
299 | // auto runtime_func = m_decoder_context->binary_interface->get_it(
300 | // m_decoder_context->binary_interface->data_table->get_func_data(rva).runtime_function_rva
301 | // );
302 | //
303 | // // This relies on the fact that multiple runtime function structures for a single func will
304 | // // use the same unwind info structure, and the rvas will be the same
305 | // //
306 | // if (runtime_func.get_unwindw_info_address() != e_unwind_info)
307 | // {
308 | // m_decoder_context->report_routine_rva(dest_rva);
309 | // goto ExitInstDecodeLoop;
310 | // }
311 | // }
312 | // }
313 | // }
314 | //
315 | // if (decode_block(dest_rva) == current_routine->blocks.end())
316 | // return current_routine->blocks.end();
317 | //
318 | // //if (m_decoder_context->routine_table[dest_rva].load() == true)
319 | // //{
320 | // //if (found_prologue)
321 | // m_decoder_context->relbr_table[dest_rva] = true;
322 | // //}
323 | // }
324 | // else
325 | // {
326 | // if (!split_block(dest_rva))
327 | // return current_routine->blocks.end();
328 | // }
329 | //
330 | // goto ExitInstDecodeLoop;
331 | // }
332 | // case XED_IFORM_JMP_FAR_MEMp2:
333 | // case XED_IFORM_JMP_FAR_PTRp_IMMw:
334 | // std::printf("Unhandled inst[%08X]: JMP_FAR_MEM/PTR.\n", rva - ilen);
335 | // return current_routine->blocks.end();
336 | // }
337 | // }
338 | // else if (cat == XED_CATEGORY_CALL && m_decoder_context->settings.recurse_calls)
339 | // {
340 | // switch (xed_decoded_inst_get_iform_enum(&inst.decoded_inst))
341 | // {
342 | // case XED_IFORM_CALL_NEAR_GPRv:
343 | // // Call table?!
344 | // //
345 | // std::printf("Unhandled inst[%08X]: XED_IFORM_CALL_NEAR_GPRv.\n", rva - ilen);
346 | // return current_routine->blocks.end();
347 | // case XED_IFORM_CALL_NEAR_MEMv:
348 | // // Import or call to absolute address...
349 | // //
350 | // if (!inst.used_link)
351 | // {
352 | // std::printf("Unhandled inst[%08X]: XED_IFORM_CALL_NEAR_MEMv.\n", rva - ilen);
353 | // return current_routine->blocks.end();
354 | // }
355 | // break;
356 | //
357 | // case XED_IFORM_CALL_NEAR_RELBRd:
358 | // case XED_IFORM_CALL_NEAR_RELBRz:
359 | // {
360 | // int32_t call_disp = xed_decoded_inst_get_branch_displacement(&inst.decoded_inst);
361 | // uint64_t dest_rva = rva + call_disp;
362 | // if (!m_decoder_context->validate_rva(dest_rva))
363 | // {
364 | // std::printf("Call to invalid rva.\n");
365 | // return current_routine->blocks.end();
366 | // }
367 | //
368 | // //std::printf("Found call at 0x%X, 0x%X\n", rva - ilen, dest_rva);
369 | //
370 | // inst.used_link = dest_rva; // m_decoder_context->binary_interface->data_table->unsafe_get_symbol_index_for_rva(dest_rva);
371 | // inst.flags |= inst_flag::rel_br;
372 | //
373 | // if (!m_lookup_table.is_self(dest_rva))
374 | // {
375 | // m_decoder_context->report_routine_rva(dest_rva);
376 | // }
377 | // break;
378 | // }
379 | // case XED_IFORM_CALL_FAR_MEMp2:
380 | // case XED_IFORM_CALL_FAR_PTRp_IMMw:
381 | // std::printf("Unhandled inst[%08X]: XED_IFORM_CALL_FAR_MEM/PTR.\n", rva - ilen);
382 | // return current_routine->blocks.end();
383 | // }
384 | // }
385 | // else if (cat == XED_CATEGORY_RET)
386 | // {
387 | // break;
388 | // }
389 | // else if (XED_ICLASS_INT3 == xed_decoded_inst_get_iclass(&inst.decoded_inst)/* && current_block.instructions.size() > 1*/)
390 | // {
391 | // break;
392 | // }
393 | // }
394 | //
395 | // // If we make it here, we found an already decoded instruction and need to set the fallthrough
396 | // //
397 | // for (auto block_it_t = current_routine->blocks.begin(); block_it_t != current_routine->blocks.end(); ++block_it_t)
398 | // {
399 | // if (rva >= block_it_t->rva_start && rva < block_it_t->rva_end)
400 | // {
401 | // for (auto inst_it = block_it_t->instructions.begin(); inst_it != block_it_t->instructions.end(); ++inst_it)
402 | // {
403 | // if (inst_it->original_rva == rva)
404 | // {
405 | // cur_block_it->fallthrough_block = block_it_t;
406 | // }
407 | // }
408 | // }
409 | // }
410 | //
411 | // ExitInstDecodeLoop:
412 | // cur_block_it->rva_end = rva;
413 | //
414 | // return cur_block_it;
415 | // }
416 | // void decode(uint64_t rva)
417 | // {
418 | // if (!m_decoder_context->validate_rva(rva))
419 | // {
420 | // std::printf("Attempting to decode routine at invalid rva.\n");
421 | // return;
422 | // }
423 | // /*if (m_decoder_context->relbr_table[rva])
424 | // {
425 | // std::printf("Skipping decode on a proposed routine start that is actually just a function chunk. %X\n", rva);
426 | // return;
427 | // }*/
428 | //
429 | // // Since this is only available for x64...
430 | // //
431 | // if constexpr (aw == addr_width::x64)
432 | // {
433 | // if (m_decoder_context->binary_interface->data_table->unsafe_get_symbol_for_rva(rva).has_func_data())
434 | // {
435 | // e_runtime_func.set(m_decoder_context->binary_interface->mapped_image +
436 | // m_decoder_context->binary_interface->data_table->get_func_data(rva).runtime_function_rva);
437 | //
438 | // e_range_start = e_runtime_func.get_begin_address();
439 | // e_range_end = e_runtime_func.get_end_address();
440 | // e_unwind_info = e_runtime_func.get_unwindw_info_address();
441 | // }
442 | // }
443 | //
444 | // completed_routines.emplace_back();
445 | // current_routine = &completed_routines.back();
446 | //
447 | // if (decode_block(rva) == current_routine->blocks.end())
448 | // {
449 | // ++invalid_routine_count;
450 | // return;
451 | // }
452 | //
453 | // current_routine->original_entry_rva = rva;
454 | // current_routine->entry_link = rva; // m_decoder_context->binary_interface->data_table->unsafe_get_symbol_index_for_rva(rva);
455 | // }
456 | // };
457 | //
458 | //
459 | // // Step1: FIND all code and put them into dasm_blocks which are just lists of consecutively executed
460 | // // instructions. these are not basic blocks because they only end at ABSOLUTE jumps or ret.
461 | // //
462 | // // Step2: Use a list of determined function entry points to use up blocks and create functions.
463 | // //
464 | // template
465 | // class dasm2_t
466 | // {
467 | // pex::binary_t m_binary;
468 | // };
469 | //
470 | //
471 | //
472 | //}
--------------------------------------------------------------------------------
/BDASM/dpattern.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include "inst.h"
7 | #include "traits.h"
8 |
9 |
10 | namespace dasm
11 | {
12 | template... Compare_list>
13 | struct static_pattern_t
14 | {
15 | // Searches a list for a pattern.
16 | //
17 | inline static const bool match(inst_list_t& list, inst_it_t start)
18 | {
19 | return (
20 | (
21 | (Compare_list == Accessor(&start->decoded_inst)) &&
22 | (++start != list.end())
23 | ) &&
24 | ...
25 | );
26 | }
27 |
28 | // Does not check to make sure we dont iterate past the end of the list
29 | //
30 | inline static const bool unsafe_match(inst_it_t start)
31 | {
32 | return ((Compare_list == Accessor(&(start++)->decoded_inst)) && ...);
33 | }
34 | };
35 |
36 | template>
37 | class multi_pattern
38 | {
39 | std::vector> patterns;
40 | std::vector valid_mask;
41 | };
42 |
43 | //template
44 | //class ipattern_t
45 | //{
46 | //public:
47 | // std::vector pattern;
48 | //
49 | // constexpr ipattern_t(std::initializer_list pat)
50 | // {
51 | // pattern.insert(pattern.end(), pat.end(), pat.begin());
52 | // }
53 | // constexpr ipattern_t(ipattern_t const& to_copy)
54 | // {
55 | // pattern.insert(pattern.end(), to_copy.pattern.end(), to_copy.pattern.begin());
56 | // }
57 |
58 | // void set_to(std::initializer_list pat)
59 | // {
60 | // pattern.clear();
61 | // pattern.insert(pattern.end(), pat.end(), pat.begin());
62 | // }
63 | // bool match(inst_list_t& list, inst_it_t start)
64 | // {
65 | // for (uint32_t i = 0; i < pattern.size() && start != list.end(); ++i, ++start)
66 | // {
67 | // if (pattern[i] != xed_decoded_inst_get_iclass(&start->decoded_inst))
68 | // return false;
69 | // }
70 | // return true;
71 | // }
72 | // const bool unsafe_match(inst_it_t start)
73 | // {
74 | // for (uint32_t i = 0; i < pattern.size(); ++i, ++start)
75 | // {
76 | // if (pattern[i] != xed_decoded_inst_get_iclass(&start->decoded_inst))
77 | // return false;
78 | // }
79 | // return true;
80 | // }
81 | // bool check(inst_it_t it, uint32_t pat_idx)
82 | // {
83 | // if (pat_idx < pattern.size())
84 | // return (pattern[pat_idx] == xed_decoded_inst_get_iclass(&it->decoded_inst));
85 | // return false;
86 | // }
87 | //};
88 |
89 |
90 | //// The idea will be to use this to detect prologues so I can weed out exports that
91 | //// are data vs exports that are functions
92 | ////
93 | //template
94 | //class pattern_tracker_t
95 | //{
96 | // std::vector> m_pattern_list;
97 | // uint32_t m_index;
98 | //public:
99 | // std::vector valid_mask;
100 |
101 | // constexpr pattern_tracker_t(std::initializer_list> pattern_list)
102 | // {
103 | // m_pattern_list.insert(m_pattern_list.end(), pattern_list.begin(), pattern_list.end());
104 | // for (uint32_t i = 0; i < m_pattern_list.size(); ++i)
105 | // valid_mask.push_back(true);
106 | // m_index = 0;
107 | // }
108 | // void reset()
109 | // {
110 | // for (uint32_t i = 0; i < m_pattern_list.size(); ++i)
111 | // valid_mask[i] = true;
112 | // m_index = 0;
113 | // }
114 | // void advance(inst_it_t it)
115 | // {
116 | // for (uint32_t i = 0; i < m_pattern_list.size(); ++i)
117 | // {
118 | // if (!m_pattern_list[i].check(it, m_index))
119 | // valid_mask[i] = false;
120 | // }
121 | // ++m_index;
122 | // }
123 | //};
124 | }
125 |
126 |
--------------------------------------------------------------------------------
/BDASM/emu.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 |
4 | namespace obf
5 | {
6 | namespace emu
7 | {
8 |
9 | }
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/BDASM/encoder.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Damn I do be pretty smart.
4 | //
5 |
6 | extern "C"
7 | {
8 | #include
9 | }
10 |
11 | #include
12 | #include
13 | //
14 | //
15 | //uint8_t* __encode_encoder_inst(xed_encoder_instruction_t* enc_inst, xed_state_t machine_state)
16 | //{
17 | // xed_encoder_request_t encoder_request;
18 | // xed_encoder_request_zero_set_mode(&encoder_request, &machine_state);
19 | //
20 | // if (!xed_convert_to_encoder_request(&encoder_request, enc_inst))
21 | // {
22 | // std::printf("Failed to convert encoder inst to encoder request.\n");
23 | // return nullptr;
24 | // }
25 | // uint8_t* encode_buffer = new uint8_t[XED_MAX_INSTRUCTION_BYTES];
26 | // uint32_t out_length = 0;
27 | // if (auto err = xed_encode(&encoder_request, encode_buffer, XED_MAX_INSTRUCTION_BYTES, &out_length); XED_ERROR_NONE != err)
28 | // {
29 | // std::printf("Failed to dumb_encode instruction with error: %s\n", xed_error_enum_t2str(err));
30 | // delete[] encode_buffer;
31 | // return nullptr;
32 | // }
33 | // return encode_buffer;
34 | //}
35 | //
36 | //template
37 | //uint32_t encode_inst(xed_state_t machine_state, xed_iclass_enum_t iclass, xed_uint_t effective_operand_width, Operands... operands)
38 | //{
39 | // xed_encoder_instruction_t inst;
40 | //
41 | //#define ENCODE_IF(N) \
42 | // if constexpr (Operand_count == N) \
43 | // xed_inst##N(&inst, machine_state, iclass, effective_operand_width, operands...)
44 | //
45 | // ENCODE_IF(0);
46 | // ENCODE_IF(1);
47 | // ENCODE_IF(2);
48 | // ENCODE_IF(3);
49 | // ENCODE_IF(4);
50 | // ENCODE_IF(5);
51 | // ENCODE_IF(6);
52 | // ENCODE_IF(7);
53 | //
54 | //#undef ENCODE_IF
55 | //
56 | // static_assert(Operant_count <= 7, "Invalid number of operands passed to encode_instruction_in_place");
57 | //
58 | // return __encode_encoder_inst(&inst, machine_state);
59 | //}
60 |
61 |
62 | uint32_t __encode_encoder_inst_in_place(uint8_t* place, xed_encoder_instruction_t* enc_inst, xed_state_t machine_state)
63 | {
64 | xed_encoder_request_t encoder_request;
65 | xed_encoder_request_zero_set_mode(&encoder_request, &machine_state);
66 |
67 | if (!xed_convert_to_encoder_request(&encoder_request, enc_inst))
68 | {
69 | std::printf("Failed to convert encoder inst to encoder request.\n");
70 | return 0;
71 | }
72 | uint32_t out_length = 0;
73 | if (auto err = xed_encode(&encoder_request, place, XED_MAX_INSTRUCTION_BYTES, &out_length); XED_ERROR_NONE != err)
74 | {
75 | std::printf("Failed to encode instruction with error: %s\n", xed_error_enum_t2str(err));
76 | return 0;
77 | }
78 | return out_length;
79 | }
80 |
81 | template
82 | uint32_t encode_inst_in_place(uint8_t* place, xed_state_t machine_state, xed_iclass_enum_t iclass, xed_uint_t effective_operand_width, Operands... operands)
83 | {
84 | xed_encoder_instruction_t inst;
85 |
86 | #define ENCODE_IF(N) \
87 | if constexpr (Operand_count == N) \
88 | xed_inst##N(&inst, machine_state, iclass, effective_operand_width, operands...)
89 |
90 | ENCODE_IF(0);
91 | ENCODE_IF(1);
92 | ENCODE_IF(2);
93 | ENCODE_IF(3);
94 | ENCODE_IF(4);
95 | ENCODE_IF(5);
96 | ENCODE_IF(6);
97 | ENCODE_IF(7);
98 |
99 | #undef ENCODE_IF
100 |
101 | static_assert(Operand_count <= 7, "Invalid number of operands passed to encode_instruction_in_place");
102 |
103 | return __encode_encoder_inst_in_place(place, &inst, machine_state);
104 | }
105 |
106 |
107 |
--------------------------------------------------------------------------------
/BDASM/encrypted_blocks.h:
--------------------------------------------------------------------------------
1 | //#pragma once
2 | //
3 | //#include
4 | //
5 | //#include "obf.h"
6 | //
7 | //// These are all the passes that play around with the original memory of the function
8 | ////
9 | //
10 | //
11 | // // So this is an interesting one, it should be done LAST if you want all instructions to be encrypted
12 | // // The way it works and maintains its thread saftey is by acquiring a spinlock before entering the function
13 | // // then releasing it on exit. The order is as follows
14 | // //
15 | // // - Wait to acquire spinlock
16 | // // - Decrypt block
17 | // // - Execute block
18 | // // - Encrypt block
19 | // // - Release spinlock
20 | // //
21 | // //
22 | //
23 | //struct encrypted_blocks_t
24 | //{
25 | // template
26 | // static bool post_encode_xor_callback(dasm::inst_t* inst, uint8_t* target, dasm::linker_t* linker, pex::binary_t* bin, Xor_val_type xor_val)
27 | // {
28 | // *reinterpret_cast(target) ^= xor_val;
29 | // return true;
30 | // }
31 | //
32 | // template
33 | // static bool post_encode_xor_loop_callback(dasm::inst_t* inst, uint8_t* target, dasm::linker_t* linker, pex::binary_t* bin, uint8_t xor_val)
34 | // {
35 | // auto len = inst->length();
36 | // for (uint32_t i = 0; i < len; ++i)
37 | // target[i] ^= xor_val;
38 | // return true;
39 | // }
40 | //
41 | // // Takes a link that represents a byte in memory to use as the spinlock
42 | // //
43 | // template
44 | // static dasm::inst_list_t acquire_spinlock(obf::obf_t& ctx, uint32_t spinlock_link)
45 | // {
46 | // // pushfq
47 | // // push rax
48 | // // continue_wait:
49 | // // mov al,0
50 | // // lock xchg [rip+spinlock_offset],al
51 | // // test al,al
52 | // // jz continue_wait
53 | // //
54 | //
55 | // uint32_t continue_wait = ctx.linker->allocate_link();
56 | //
57 | // dasm::inst_list_t result;
58 | //
59 | //
60 | // result.emplace_back(
61 | // XED_ICLASS_PUSHF,
62 | // addr_width::bits::value
63 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
64 | //
65 | // result.emplace_back(
66 | // XED_ICLASS_PUSH,
67 | // addr_width::bits::value,
68 | // xed_reg(max_reg_width::value)
69 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
70 | //
71 | // result.emplace_back(
72 | // XED_ICLASS_MOV,
73 | // 8,
74 | // xed_reg(XED_REG_AL),
75 | // xed_imm0(0, 8)
76 | // ).common_edit(continue_wait, 0, 0);
77 | //
78 | // result.emplace_back(
79 | // XED_ICLASS_XCHG,
80 | // 8,
81 | // xed_mem_bd(
82 | // max_reg_width::value,
83 | // xed_disp(0, 32),
84 | // 8
85 | // ),
86 | // xed_reg(XED_REG_AL)
87 | // ).common_edit(ctx.linker->allocate_link(), spinlock_link, dasm::inst_flag::disp);
88 | //
89 | // result.emplace_back(
90 | // XED_ICLASS_TEST,
91 | // 8,
92 | // xed_reg(XED_REG_AL),
93 | // xed_reg(XED_REG_AL)
94 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
95 | //
96 | // result.emplace_back(
97 | // XED_ICLASS_JZ,
98 | // 8,
99 | // xed_relbr(0, 32)
100 | // ).common_edit(ctx.linker->allocate_link(), continue_wait, dasm::inst_flag::rel_br);
101 | //
102 | //
103 | // return result;
104 | // }
105 | //
106 | // template
107 | // static dasm::inst_list_t release_spinlock(obf::obf_t& ctx, uint32_t spinlock_link)
108 | // {
109 | // // mov al,0x90
110 | // // lock xchg [rip+spinlock_offset],al
111 | // // pop rax
112 | // // popfq
113 | // //
114 | //
115 | // dasm::inst_list_t result;
116 | //
117 | // result.emplace_back(
118 | // XED_ICLASS_MOV,
119 | // 8,
120 | // xed_reg(XED_REG_AL),
121 | // xed_imm0(0x90, 8)
122 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
123 | //
124 | // result.emplace_back(
125 | // XED_ICLASS_XCHG,
126 | // 8,
127 | // xed_mem_bd(
128 | // max_reg_width::value,
129 | // xed_disp(0, 32),
130 | // 8
131 | // ),
132 | // xed_reg(XED_REG_AL)
133 | // ).common_edit(ctx.linker->allocate_link(), spinlock_link, dasm::inst_flag::disp);
134 | //
135 | // result.emplace_back(
136 | // XED_ICLASS_POP,
137 | // addr_width::bits::value,
138 | // xed_reg(max_reg_width::value)
139 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
140 | //
141 | // result.emplace_back(
142 | // XED_ICLASS_POPF,
143 | // addr_width::bits::value
144 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
145 | //
146 | // return result;
147 | // }
148 | //
149 | // template
150 | // static void shuffle_list(dasm::inst_list_t& list)
151 | // {
152 | // for (uint32_t i = 0; i < 8; ++i)
153 | // {
154 | // for (auto inst_it = list.begin(); inst_it != list.end();)
155 | // {
156 | // auto next = std::next(inst_it);
157 | // if (rand() % 100 < 50)
158 | // list.splice(list.begin(), list, inst_it);
159 | // inst_it = next;
160 | // }
161 | // }
162 | // }
163 | //
164 | // static uint8_t encr_width(uint32_t inst_width)
165 | // {
166 | // constexpr static uint8_t table[3] = { 1,2,4 };
167 | //
168 | // if (inst_width > 3)
169 | // return table[rand() % 3];
170 | // else if (inst_width > 1)
171 | // return table[rand() % 2];
172 | // else
173 | // return 1;
174 | // }
175 | //
176 | // template
177 | // static void gen_encryption_pair(obf::obf_t& ctx, dasm::inst_t& inst, dasm::inst_list_t& prologue, dasm::inst_list_t& epilogue, bool post_encode)
178 | // {
179 | // // For xoring, prologue and epilogue are the same
180 | // //
181 | //
182 | // auto len = inst.length();
183 | // auto width = encr_width(len);
184 | // auto width_bits = width * 8;
185 | //
186 | // uint32_t val = rand();
187 | //
188 | // prologue.emplace_back(
189 | // XED_ICLASS_XOR,
190 | // width_bits,
191 | // xed_mem_bd(
192 | // max_reg_width::value,
193 | // xed_disp(0, 32),
194 | // width_bits
195 | // ),
196 | // xed_imm0(val, width_bits)
197 | // ).common_edit(ctx.linker->allocate_link(), inst.my_link, dasm::inst_flag::disp);
198 | //
199 | // epilogue.emplace_back(
200 | // XED_ICLASS_XOR,
201 | // width_bits,
202 | // xed_mem_bd(
203 | // max_reg_width::value,
204 | // xed_disp(0, 32),
205 | // width_bits
206 | // ),
207 | // xed_imm0(val, width_bits)
208 | // ).common_edit(ctx.linker->allocate_link(), inst.my_link, dasm::inst_flag::disp);
209 | //
210 | // if (post_encode)
211 | // {
212 | // switch (width)
213 | // {
214 | // case 1:
215 | // inst.encode_callback = std::bind(post_encode_xor_callback,
216 | // std::placeholders::_1,
217 | // std::placeholders::_2,
218 | // std::placeholders::_3,
219 | // std::placeholders::_4,
220 | // val
221 | // );
222 | // break;
223 | // case 2:
224 | // inst.encode_callback = std::bind(post_encode_xor_callback,
225 | // std::placeholders::_1,
226 | // std::placeholders::_2,
227 | // std::placeholders::_3,
228 | // std::placeholders::_4,
229 | // val
230 | // );
231 | // break;
232 | // case 4:
233 | // inst.encode_callback = std::bind(post_encode_xor_callback,
234 | // std::placeholders::_1,
235 | // std::placeholders::_2,
236 | // std::placeholders::_3,
237 | // std::placeholders::_4,
238 | // val
239 | // );
240 | // break;
241 | // default:
242 | // std::printf("Invalid width for encryption.\n");
243 | // }
244 | // }
245 | // }
246 | //
247 | // template
248 | // static dasm::inst_list_t gen_encryption_loop(obf::obf_t& ctx, dasm::block_t& block, uint8_t xor_key, bool pre)
249 | // {
250 | // // pushfq
251 | // // push rax
252 | // // push rbx
253 | // // lea rax,[rip+start_link]
254 | // // lea rbx,[rip+end_link]
255 | // // continue_loop:
256 | // // xor byte ptr[rax],xor_key
257 | // // add rax,1
258 | // // cmp rax,rbx
259 | // // jnz continue_loop
260 | // // pop rbx
261 | // // pop rax
262 | // //
263 | // // no popfq because its handled by the spinlock or appended after
264 | // //
265 | //
266 | // dasm::inst_list_t result;
267 | //
268 | // uint32_t start_link = block.instructions.front().my_link;
269 | // uint32_t end_link = start_link;
270 | //
271 | // // This is the additional disp added on to the end
272 | // int32_t end_add = block.instructions.front().length();
273 | //
274 | // for (auto& inst : block.instructions)
275 | // {
276 | // inst.redecode();
277 | //
278 | // if (inst.flags & dasm::inst_flag::block_terminator)
279 | // break;
280 | //
281 | // end_link = inst.my_link;
282 | // end_add = inst.length();
283 | //
284 | // inst.encode_callback = std::bind(post_encode_xor_loop_callback,
285 | // std::placeholders::_1,
286 | // std::placeholders::_2,
287 | // std::placeholders::_3,
288 | // std::placeholders::_4,
289 | // xor_key
290 | // );
291 | // }
292 | //
293 | //
294 | // auto continue_loop = ctx.linker->allocate_link();
295 | //
296 | // if (!pre)
297 | // {
298 | // result.emplace_back(
299 | // XED_ICLASS_PUSHF,
300 | // addr_width::bits::value
301 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
302 | //
303 | // result.emplace_back(
304 | // XED_ICLASS_PUSH,
305 | // addr_width::bits::value,
306 | // xed_reg(max_reg_width::value)
307 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
308 | // }
309 | //
310 | // result.emplace_back(
311 | // XED_ICLASS_PUSH,
312 | // addr_width::bits::value,
313 | // xed_reg(max_reg_width::value)
314 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
315 | //
316 | // result.emplace_back(
317 | // XED_ICLASS_LEA,
318 | // addr_width::bits::value,
319 | // xed_reg(max_reg_width::value),
320 | // xed_mem_bd(
321 | // max_reg_width::value,
322 | // xed_disp(0, 32),
323 | // addr_width::bits::value
324 | // )
325 | // ).common_edit(ctx.linker->allocate_link(), start_link, dasm::inst_flag::disp);
326 | //
327 | // result.emplace_back(
328 | // XED_ICLASS_LEA,
329 | // addr_width::bits::value,
330 | // xed_reg(max_reg_width::value),
331 | // xed_mem_bd(
332 | // max_reg_width::value,
333 | // xed_disp(0, 32),
334 | // addr_width::bits::value
335 | // )
336 | // ).common_edit(ctx.linker->allocate_link(), end_link, dasm::inst_flag::disp);
337 | // result.back().encode_data.additional_disp = end_add;
338 | //
339 | // result.emplace_back(
340 | // XED_ICLASS_XOR,
341 | // addr_width::bits::value,
342 | // xed_mem_b(max_reg_width::value, 8),
343 | // xed_imm0(xor_key, 8)
344 | // ).common_edit(continue_loop, 0, 0);
345 | //
346 | // result.emplace_back(
347 | // XED_ICLASS_ADD,
348 | // addr_width::bits::value,
349 | // xed_reg(max_reg_width::value),
350 | // xed_imm0(1, 8)
351 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
352 | //
353 | // result.emplace_back(
354 | // XED_ICLASS_CMP,
355 | // addr_width::bits::value,
356 | // xed_reg(max_reg_width::value),
357 | // xed_reg(max_reg_width::value)
358 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
359 | //
360 | // result.emplace_back(
361 | // XED_ICLASS_JNZ,
362 | // addr_width::bits::value,
363 | // xed_relbr(0, 8)
364 | // ).common_edit(ctx.linker->allocate_link(), continue_loop, dasm::inst_flag::rel_br);
365 | //
366 | // result.emplace_back(
367 | // XED_ICLASS_POP,
368 | // addr_width::bits::value,
369 | // xed_reg(max_reg_width::value)
370 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
371 | //
372 | // if (pre)
373 | // {
374 | // result.emplace_back(
375 | // XED_ICLASS_POP,
376 | // addr_width::bits::value,
377 | // xed_reg(max_reg_width::value)
378 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
379 | // }
380 | //
381 | // return result;
382 | // }
383 | //
384 | // template
385 | // static std::pair, dasm::inst_list_t> encryption(obf::obf_t& ctx, dasm::block_t& block)
386 | // {
387 | // dasm::inst_list_t prologue, epilogue;
388 | //
389 | // if (block.instructions.size() < 10)
390 | // {
391 | // for (auto& inst : block.instructions)
392 | // {
393 | // if (!inst.encode_callback)
394 | // {
395 | // inst.redecode();
396 | // gen_encryption_pair(ctx, inst, prologue, epilogue, !(inst.flags & dasm::inst_flag::block_terminator));
397 | // }
398 | // }
399 | //
400 | // shuffle_list(prologue);
401 | // shuffle_list(epilogue);
402 | //
403 | // epilogue.emplace_front(
404 | // XED_ICLASS_PUSH,
405 | // addr_width::bits::value,
406 | // xed_reg(max_reg_width::value)
407 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
408 | //
409 | // epilogue.emplace_front(
410 | // XED_ICLASS_PUSHF,
411 | // addr_width::bits::value
412 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
413 | //
414 | //
415 | // prologue.emplace_back(
416 | // XED_ICLASS_POP,
417 | // addr_width::bits::value,
418 | // xed_reg(max_reg_width::value)
419 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
420 | //
421 | // }
422 | // else
423 | // {
424 | // uint8_t xor_key = rand();
425 | // prologue = gen_encryption_loop(ctx, block, xor_key, true);
426 | // epilogue = gen_encryption_loop(ctx, block, xor_key, false);
427 | // }
428 | //
429 | // prologue.emplace_back(
430 | // XED_ICLASS_POPF,
431 | // addr_width::bits::value
432 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
433 | //
434 | // return { prologue, epilogue };
435 | // }
436 | //
437 | // // TODO:
438 | // // - Make large blocks over a certain threshold use a loop and simple xor encrypting
439 | // // - Add different types of crypting
440 | // //
441 | //
442 | // template
443 | // static obf::pass_status_t pass(dasm::routine_t& routine, obf::obf_t& ctx, bool spinlock = true)
444 | // {
445 | // /*auto [prologue, epilogue] = encryption();*/
446 | //
447 | // for (auto& block : routine.blocks)
448 | // {
449 | // // Now we need to find where to insert the epilogue and spinlock release
450 | // //
451 | // auto inst_it = std::prev(block.instructions.end());
452 | // uint32_t terminator_size = 0;
453 | //
454 | // while (true)
455 | // {
456 | // if (!(inst_it->flags & dasm::inst_flag::block_terminator))
457 | // {
458 | // ++inst_it;
459 | // break;
460 | // }
461 | //
462 | // ++terminator_size;
463 | //
464 | // if (inst_it == block.instructions.begin())
465 | // break;
466 | //
467 | // --inst_it;
468 | // }
469 | //
470 | //
471 | // // Make sure there are actually some instructions we can encrypt
472 | // //
473 | // if (block.instructions.size() <= terminator_size)
474 | // continue;
475 | //
476 | //
477 | // uint32_t spinlock_link = ctx.linker->allocate_link();
478 | //
479 | // // Gen the prologue and epilogues here, prepend and append them
480 | // //
481 | // auto [prologue, epilogue] = encryption(ctx, block);
482 | //
483 | // block.instructions.splice(block.instructions.begin(), prologue);
484 | // block.instructions.splice(inst_it, epilogue);
485 | //
486 | // // Now add the spinlock acquire and release
487 | // //
488 | // auto acquire = acquire_spinlock(ctx, spinlock_link);
489 | // auto release = release_spinlock(ctx, spinlock_link);
490 | //
491 | // block.instructions.splice(block.instructions.begin(), acquire);
492 | // block.instructions.splice(inst_it, release);
493 | //
494 | // block.instructions.emplace_back(
495 | // XED_ICLASS_NOP,
496 | // 32
497 | // ).common_edit(spinlock_link, 0, dasm::inst_flag::block_terminator);
498 | // }
499 | //
500 | // return obf::pass_status_t::success;
501 | // }
502 | //};
503 |
--------------------------------------------------------------------------------
/BDASM/encrypted_routines.h:
--------------------------------------------------------------------------------
1 | //#pragma once
2 | //
3 | //#include
4 | //
5 | //#include "obf.h"
6 | //
7 | //// Very similar to encrypted_blocks_t but this encrypts/decrypts the entire routine at one time
8 | //// This is going to be MUCH(thousands of times) faster for routines that contain loops.
9 | ////
10 | //
11 | //// Basic function entry logic:
12 | ////
13 | //// Save registers and flags
14 | //// Acquire logic spinlock
15 | //// mov rax,[rip+counter_offset]
16 | //// test rax,rax
17 | //// jnz no_decrypt
18 | ////
19 | //// Decrypt function here
20 | ////
21 | //// no_decrypt:
22 | //// add [rip+counter_offset],1
23 | //// Release logic spinlock
24 | //// Restore registers and flags
25 | ////
26 | ////
27 | ////
28 | //// Basic function exit logic:
29 | ////
30 | //// Save registers and flags
31 | //// Acquire logic spinlock
32 | //// sub [rip+counter_offset],1
33 | //// jnz no_encrypt
34 | ////
35 | //// Encrypt the function here
36 | ////
37 | //// no_encrypt:
38 | //// Release logic spinlock
39 | //// Restore registers and flags
40 | //// Function exit terminator(ret or undetermined unconditional jmp)
41 | ////
42 | ////
43 | //// I think i dont actually need to save the flags? Since this only happens on entry and exit
44 | //// to a function. I also dont need to save rax on entry.
45 | ////
46 | //
47 | //struct encrypted_routine_t
48 | //{
49 | // template
50 | // static bool xor_encode_callback(dasm::inst_t* inst, uint8_t* target, dasm::linker_t* linker, pex::binary_t* bin, Xor_val_type xor_val)
51 | // {
52 | // *reinterpret_cast(target) ^= xor_val;
53 | // return true;
54 | // }
55 | //
56 | // template
57 | // static bool xor_loop_encode_callback(dasm::inst_t* inst, uint8_t* target, dasm::linker_t* linker, pex::binary_t* bin, uint8_t xor_val)
58 | // {
59 | // auto len = inst->length();
60 | // for (uint32_t i = 0; i < len; ++i)
61 | // target[i] ^= xor_val;
62 | // return true;
63 | // }
64 | //
65 | // template
66 | // static bool spinlock_encode_callback(dasm::inst_t* inst, uint8_t* target, dasm::linker_t* linker, pex::binary_t* bin)
67 | // {
68 | // *target = 0;
69 | // return true;
70 | // }
71 | //
72 | // template
73 | // static bool counter_encode_callback(dasm::inst_t* inst, uint8_t* target, dasm::linker_t* linker, pex::binary_t* bin)
74 | // {
75 | // *reinterpret_cast(target) = 0;
76 | // return true;
77 | // }
78 | //
79 | // template
80 | // static void shuffle_list(dasm::inst_list_t& list)
81 | // {
82 | // for (uint32_t i = 0; i < 8; ++i)
83 | // {
84 | // for (auto inst_it = list.begin(); inst_it != list.end();)
85 | // {
86 | // auto next = std::next(inst_it);
87 | // if (rand() % 100 < 50)
88 | // list.splice(list.begin(), list, inst_it);
89 | // inst_it = next;
90 | // }
91 | // }
92 | // }
93 | //
94 | // template
95 | // static dasm::inst_list_t acquire_spinlock(obf::obf_t& ctx, uint32_t spinlock_link)
96 | // {
97 | // // continue_wait:
98 | // // mov al,0
99 | // // lock xchg [rip+spinlock_offset],al
100 | // // test al,al
101 | // // jz continue_wait
102 | // //
103 | //
104 | // uint32_t continue_wait = ctx.linker->allocate_link();
105 | //
106 | // dasm::inst_list_t result;
107 | //
108 | // result.emplace_back(
109 | // XED_ICLASS_MOV,
110 | // 8,
111 | // xed_reg(XED_REG_AL),
112 | // xed_imm0(1, 8)
113 | // ).common_edit(continue_wait, 0, 0);
114 | //
115 | // result.emplace_back(
116 | // XED_ICLASS_XCHG,
117 | // 8,
118 | // xed_mem_bd(
119 | // max_reg_width::value,
120 | // xed_disp(0, 32),
121 | // 8
122 | // ),
123 | // xed_reg(XED_REG_AL)
124 | // ).common_edit(ctx.linker->allocate_link(), spinlock_link, dasm::inst_flag::disp);
125 | //
126 | // result.emplace_back(
127 | // XED_ICLASS_TEST,
128 | // 8,
129 | // xed_reg(XED_REG_AL),
130 | // xed_reg(XED_REG_AL)
131 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
132 | //
133 | // result.emplace_back(
134 | // XED_ICLASS_JNZ,
135 | // 8,
136 | // xed_relbr(0, 32)
137 | // ).common_edit(ctx.linker->allocate_link(), continue_wait, dasm::inst_flag::rel_br);
138 | //
139 | // return result;
140 | // }
141 | //
142 | // template
143 | // static dasm::inst_list_t release_spinlock(obf::obf_t& ctx, uint32_t spinlock_link)
144 | // {
145 | // // mov al,0
146 | // // lock xchg [rip+spinlock_offset],al
147 | // //
148 | //
149 | // dasm::inst_list_t result;
150 | //
151 | // result.emplace_back(
152 | // XED_ICLASS_MOV,
153 | // 8,
154 | // xed_reg(XED_REG_AL),
155 | // xed_imm0(0, 8)
156 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
157 | //
158 | // result.emplace_back(
159 | // XED_ICLASS_XCHG,
160 | // 8,
161 | // xed_mem_bd(
162 | // max_reg_width::value,
163 | // xed_disp(0, 32),
164 | // 8
165 | // ),
166 | // xed_reg(XED_REG_AL)
167 | // ).common_edit(ctx.linker->allocate_link(), spinlock_link, dasm::inst_flag::disp);
168 | //
169 | // return result;
170 | // }
171 | //
172 | // template
173 | // static dasm::inst_list_t save_values(obf::obf_t& ctx)
174 | // {
175 | // dasm::inst_list_t result;
176 | //
177 | // result.emplace_front(
178 | // XED_ICLASS_PUSHF,
179 | // addr_width::bits::value
180 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
181 | //
182 | // result.emplace_front(
183 | // XED_ICLASS_PUSH,
184 | // addr_width::bits::value,
185 | // xed_reg(max_reg_width::value)
186 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
187 | //
188 | // result.emplace_front(
189 | // XED_ICLASS_PUSH,
190 | // addr_width::bits::value,
191 | // xed_reg(max_reg_width::value)
192 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
193 | //
194 | // return result;
195 | // }
196 | //
197 | // template
198 | // static dasm::inst_list_t restore_values(obf::obf_t& ctx)
199 | // {
200 | // dasm::inst_list_t result;
201 | //
202 | // result.emplace_front(
203 | // XED_ICLASS_POP,
204 | // addr_width::bits::value,
205 | // xed_reg(max_reg_width::value)
206 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
207 | //
208 | // result.emplace_front(
209 | // XED_ICLASS_POP,
210 | // addr_width::bits::value,
211 | // xed_reg(max_reg_width::value)
212 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
213 | //
214 | // result.emplace_front(
215 | // XED_ICLASS_POPF,
216 | // addr_width::bits::value
217 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
218 | //
219 | // return result;
220 | // }
221 | //
222 | // template
223 | // static void build_prologue_logic(obf::obf_t& ctx, dasm::inst_list_t& prologue, uint32_t spinlock_link, uint32_t counter_link)
224 | // {
225 | // auto no_decrypt = ctx.linker->allocate_link();
226 | //
227 | // // Setup the beginning
228 | // //
229 | // prologue.emplace_front(
230 | // XED_ICLASS_JNZ,
231 | // 32,
232 | // xed_relbr(0, 32)
233 | // ).common_edit(ctx.linker->allocate_link(), no_decrypt, dasm::inst_flag::rel_br);
234 | //
235 | // prologue.emplace_front(
236 | // XED_ICLASS_TEST,
237 | // 32,
238 | // xed_reg(XED_REG_EAX),
239 | // xed_reg(XED_REG_EAX)
240 | // ).common_edit(ctx.linker->allocate_link(), 0, 0);
241 | //
242 | // prologue.emplace_front(
243 | // XED_ICLASS_MOV,
244 | // 32,
245 | // xed_reg(XED_REG_EAX),
246 | // xed_mem_bd(
247 | // max_reg_width::value,
248 | // xed_disp(0, 32),
249 | // 32
250 | // )
251 | // ).common_edit(ctx.linker->allocate_link(), counter_link, dasm::inst_flag::disp);
252 | //
253 | // prologue.splice(prologue.begin(), acquire_spinlock(ctx, spinlock_link));
254 | // prologue.splice(prologue.begin(), save_values(ctx));
255 | //
256 | // // Setup the end.
257 | // //
258 | // prologue.emplace_back(
259 | // XED_ICLASS_ADD,
260 | // 32,
261 | // xed_mem_bd(
262 | // max_reg_width::value,
263 | // xed_disp(0, 32),
264 | // 32
265 | // ),
266 | // xed_imm0(1, 8)
267 | // ).common_edit(no_decrypt, counter_link, dasm::inst_flag::disp);
268 | //
269 | // prologue.splice(prologue.end(), release_spinlock(ctx, spinlock_link));
270 | // prologue.splice(prologue.end(), restore_values(ctx));
271 | // }
272 | //
273 | // template
274 | // static void build_epilogue_logic(obf::obf_t