Browse Source

started work on 3.0, a recode with xed and cmake... also cross

platform...
3.0
_xeroxz 3 months ago
parent
commit
56ca6b3d07
  1. 5
      .clang-format
  2. 2
      .gitignore
  3. 12
      .gitmodules
  4. 31
      CMakeLists.txt
  5. 29
      LICENSE
  6. 776
      README.md
  7. 5
      cmake.toml
  8. 236
      cmkr.cmake
  9. 13
      demos/DemoDll/AnotherObj.cpp
  10. 46
      demos/DemoDll/ClassDemo.cpp
  11. 31
      demos/DemoDll/ClassDemo.hpp
  12. 122
      demos/DemoDll/DemoDll.vcxproj
  13. 31
      demos/DemoDll/DemoDll.vcxproj.filters
  14. 4
      demos/DemoDll/DemoDll.vcxproj.user
  15. 19
      demos/DemoDll/Theodosius.h
  16. 22
      demos/DemoDll/main.cpp
  17. 116
      demos/DemoDrv/DemoDrv.vcxproj
  18. 22
      demos/DemoDrv/DemoDrv.vcxproj.filters
  19. 4
      demos/DemoDrv/DemoDrv.vcxproj.user
  20. 36
      demos/DemoDrv/DriverEntry.cpp
  21. 43
      demos/DemoDrv/Theodosius.h
  22. 560
      demos/DemoImGui/backends/imgui_impl_dx11.cpp
  23. 31
      demos/DemoImGui/backends/imgui_impl_dx11.h
  24. 504
      demos/DemoImGui/backends/imgui_impl_win32.cpp
  25. 42
      demos/DemoImGui/backends/imgui_impl_win32.h
  26. 19
      demos/DemoImGui/examples/example_win32_directx11/Theodosius.h
  27. 92
      demos/DemoImGui/examples/example_win32_directx11/example_win32_directx11.vcxproj
  28. 62
      demos/DemoImGui/examples/example_win32_directx11/example_win32_directx11.vcxproj.filters
  29. 4
      demos/DemoImGui/examples/example_win32_directx11/example_win32_directx11.vcxproj.user
  30. 249
      demos/DemoImGui/examples/example_win32_directx11/main.cpp
  31. 125
      demos/DemoImGui/imconfig.h
  32. 11452
      demos/DemoImGui/imgui.cpp
  33. 2832
      demos/DemoImGui/imgui.h
  34. 7665
      demos/DemoImGui/imgui_demo.cpp
  35. 3971
      demos/DemoImGui/imgui_draw.cpp
  36. 2597
      demos/DemoImGui/imgui_internal.h
  37. 3953
      demos/DemoImGui/imgui_tables.cpp
  38. 7980
      demos/DemoImGui/imgui_widgets.cpp
  39. 639
      demos/DemoImGui/imstb_rectpack.h
  40. 1447
      demos/DemoImGui/imstb_textedit.h
  41. 4903
      demos/DemoImGui/imstb_truetype.h
  42. 24
      demos/DemoImGui/misc/README.txt
  43. 10
      demos/DemoImGui/misc/cpp/README.txt
  44. 76
      demos/DemoImGui/misc/cpp/imgui_stdlib.cpp
  45. 22
      demos/DemoImGui/misc/cpp/imgui_stdlib.h
  46. BIN
      demos/DemoImGui/misc/fonts/Cousine-Regular.ttf
  47. BIN
      demos/DemoImGui/misc/fonts/DroidSans.ttf
  48. BIN
      demos/DemoImGui/misc/fonts/Karla-Regular.ttf
  49. BIN
      demos/DemoImGui/misc/fonts/ProggyClean.ttf
  50. BIN
      demos/DemoImGui/misc/fonts/ProggyTiny.ttf
  51. BIN
      demos/DemoImGui/misc/fonts/Roboto-Medium.ttf
  52. 385
      demos/DemoImGui/misc/fonts/binary_to_compressed_c.cpp
  53. 30
      demos/DemoImGui/misc/freetype/README.md
  54. 769
      demos/DemoImGui/misc/freetype/imgui_freetype.cpp
  55. 50
      demos/DemoImGui/misc/freetype/imgui_freetype.h
  56. 4
      demos/DemoImGui/misc/natvis/README.txt
  57. 49
      demos/DemoImGui/misc/natvis/imgui.natvis
  58. 18
      demos/DemoImGui/misc/single_file/imgui_single_file.h
  59. 175
      demos/Theodosius-Client/Theodosius-Client.vcxproj
  60. 79
      demos/Theodosius-Client/Theodosius-Client.vcxproj.filters
  61. 4
      demos/Theodosius-Client/Theodosius-Client.vcxproj.user
  62. 70
      demos/Theodosius-Client/client.cpp
  63. 92
      demos/Theodosius-Client/client.hpp
  64. 263
      demos/Theodosius-Client/loadup.hpp
  65. 525
      demos/Theodosius-Client/main.cpp
  66. 21527
      demos/Theodosius-Client/msrexec/ia32.hpp
  67. 194
      demos/Theodosius-Client/msrexec/msrexec.cpp
  68. 43
      demos/Theodosius-Client/msrexec/msrexec.hpp
  69. 1733
      demos/Theodosius-Client/msrexec/raw_driver.hpp
  70. 90
      demos/Theodosius-Client/msrexec/syscall_handler.asm
  71. 14
      demos/Theodosius-Client/msrexec/syscall_handler.h
  72. 66
      demos/Theodosius-Client/msrexec/vdm.hpp
  73. 494
      demos/Theodosius-Client/utils.hpp
  74. 2242
      demos/Theodosius-Client/vdm/raw_driver.hpp
  75. 139
      demos/Theodosius-Client/vdm/vdm.hpp
  76. 103
      demos/Theodosius-Client/vdm/vdm_ctx.cpp
  77. 71
      demos/Theodosius-Client/vdm/vdm_ctx.hpp
  78. 90
      demos/Theodosius-Examples.sln
  79. 111
      demos/Theodosius-Kernel/Theodosius-MSREXEC/Theodosius-MSREXEC.vcxproj
  80. 55
      demos/Theodosius-Kernel/Theodosius-MSREXEC/Theodosius-MSREXEC.vcxproj.filters
  81. 13
      demos/Theodosius-Kernel/Theodosius-MSREXEC/Theodosius-MSREXEC.vcxproj.user
  82. 21527
      demos/Theodosius-Kernel/Theodosius-MSREXEC/ia32.hpp
  83. 76
      demos/Theodosius-Kernel/Theodosius-MSREXEC/linker.hpp
  84. 263
      demos/Theodosius-Kernel/Theodosius-MSREXEC/loadup.hpp
  85. 236
      demos/Theodosius-Kernel/Theodosius-MSREXEC/main.cpp
  86. 205
      demos/Theodosius-Kernel/Theodosius-MSREXEC/msrexec.cpp
  87. 43
      demos/Theodosius-Kernel/Theodosius-MSREXEC/msrexec.hpp
  88. 1730
      demos/Theodosius-Kernel/Theodosius-MSREXEC/raw_driver.hpp
  89. 90
      demos/Theodosius-Kernel/Theodosius-MSREXEC/syscall_handler.asm
  90. 14
      demos/Theodosius-Kernel/Theodosius-MSREXEC/syscall_handler.h
  91. 40
      demos/Theodosius-Kernel/Theodosius-MSREXEC/theo.h
  92. 423
      demos/Theodosius-Kernel/Theodosius-MSREXEC/utils.hpp
  93. 66
      demos/Theodosius-Kernel/Theodosius-MSREXEC/vdm.hpp
  94. 105
      demos/Theodosius-Kernel/Theodosius-VDM/Theodosius-VDM.vcxproj
  95. 47
      demos/Theodosius-Kernel/Theodosius-VDM/Theodosius-VDM.vcxproj.filters
  96. 13
      demos/Theodosius-Kernel/Theodosius-VDM/Theodosius-VDM.vcxproj.user
  97. 76
      demos/Theodosius-Kernel/Theodosius-VDM/linker.hpp
  98. 262
      demos/Theodosius-Kernel/Theodosius-VDM/loadup.hpp
  99. 229
      demos/Theodosius-Kernel/Theodosius-VDM/main.cpp
  100. 40
      demos/Theodosius-Kernel/Theodosius-VDM/theo.h
  101. Some files were not shown because too many files have changed in this diff Show More

5
.clang-format

@ -0,0 +1,5 @@
---
BasedOnStyle: Chromium
...

2
.gitignore vendored

@ -0,0 +1,2 @@
*.exe
build/

12
.gitmodules vendored

@ -0,0 +1,12 @@
[submodule "dependencies/linux-pe"]
path = dependencies/linux-pe
url = https://github.com/can1357/linux-pe.git
[submodule "dependencies/googletest"]
path = dependencies/googletest
url = https://github.com/google/googletest.git
[submodule "dependencies/xed"]
path = dependencies/xed
url = https://github.com/intelxed/xed.git
[submodule "dependencies/mbuild"]
path = dependencies/mbuild
url = https://github.com/intelxed/mbuild.git

31
CMakeLists.txt

@ -0,0 +1,31 @@
# This file is automatically generated from cmake.toml - DO NOT EDIT
# See https://github.com/build-cpp/cmkr for more information
cmake_minimum_required(VERSION 3.15)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build")
endif()
# Regenerate CMakeLists.txt automatically in the root project
set(CMKR_ROOT_PROJECT OFF)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(CMKR_ROOT_PROJECT ON)
# Bootstrap cmkr
include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
if(CMKR_INCLUDE_RESULT)
cmkr()
endif()
# Enable folder support
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
endif()
# Create a configure-time dependency on cmake.toml to improve IDE support
if(CMKR_ROOT_PROJECT)
configure_file(cmake.toml cmake.toml COPYONLY)
endif()
project(Theodosius)

29
LICENSE

@ -1,29 +0,0 @@
BSD 3-Clause License
Copyright (c) 2021, _xeroxz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

776
README.md

@ -1,776 +0,0 @@
<div align="center">
<div>
<img width="27%" src="https://githacks.org/_xeroxz/theodosius/-/raw/07b58a233c0fbd289856c90158fe342fc4be4deb/imgs/theo.jpg"/>
</div>
<img src="https://githacks.org/_xeroxz/theodosius/-/raw/b9ac84ec1458469c707f89f89da8f3815a54fb9d/imgs/MSREXEC-Inherited-green.svg"/>
<img src="https://githacks.org/_xeroxz/theodosius/-/raw/b9ac84ec1458469c707f89f89da8f3815a54fb9d/imgs/VDM-Inherited-green.svg"/>
</div>
# Theodosius - Jit linker, Mapper, Mutator, and Obfuscator
Theodosius (Theo for short) is a jit linker created entirely for obfuscation and mutation of both code, and code flow. The project is extremely modular in design and supports
both kernel and usermode projects. Since Theo inherits HMDM (highly modular driver mapper), any vulnerable driver that exposes arbitrary MSR writes, or physical memory read/write can be used with this framework to map unsigned code into the kernel. This is possible since HMDM inherits VDM (vulnerable driver manipulation), and MSREXEC (elevation of arbitrary MSR writes to kernel execution).
Theo can be used for many projects. The modularity of the code allows for a programmer to use this framework however they please. A few example usages of Theo would be, streaming code and data from a .lib over a network directly into memory, resolving unexported symbols via PDB, allocating each instruction of a function inside of code caves, and much more.
### Table Of Contents
* [Theodosius - Jit linker, Mapper, Mutator, and Obfuscator](https://githacks.org/_xeroxz/theodosius#theodosius-jit-linker-mapper-mutator-and-obfuscator)
* [Credit And Dependencies](https://githacks.org/_xeroxz/theodosius#credit-and-dependencies)
* [Linking - Dynamic And Static](https://githacks.org/_xeroxz/theodosius#linking-dynamic-and-static)
* [What Is A Linker](https://githacks.org/_xeroxz/theodosius#what-is-a-linker)
* [Object Files](https://githacks.org/_xeroxz/theodosius#object-files)
* [Static Linking](https://githacks.org/_xeroxz/theodosius#static-linking)
* [Dynamic Linking](https://githacks.org/_xeroxz/theodosius#dynamic-linking)
* [Usage - Using Theodosius](https://githacks.org/_xeroxz/theodosius#usage-using-theodosius)
* [Integrating Clang](https://githacks.org/_xeroxz/theodosius#integrating-clang)
* [Requirements](https://githacks.org/_xeroxz/theodosius#requirements)
* [Lambdas For Explicit Constructor](https://githacks.org/_xeroxz/theodosius#lambdas-for-explicit-constructor)
* [`theo::memcpy_t` - copy memory lambda](https://githacks.org/_xeroxz/theodosius#theomemcpy_t-copy-memory-lambda)
* [`theo::malloc_t` - allocate executable memory](https://githacks.org/_xeroxz/theodosius#theomalloc_t-allocate-executable-memory)
* [`theo::resolve_symbol_t` - resolve external symbol](https://githacks.org/_xeroxz/theodosius#theoresolve_symbol_t-resolve-external-symbol)
* [Creating Instance](https://githacks.org/_xeroxz/theodosius#creating-instance)
* [Calling Entry](https://githacks.org/_xeroxz/theodosius#calling-entry)
* [MSREXEC - Call Entry Example](https://githacks.org/_xeroxz/theodosius#msrexec-call-entry-example)
* [VDM - Call Entry Example](https://githacks.org/_xeroxz/theodosius#vdm-call-entry-example)
* [WinAPI - Call Entry Example](https://githacks.org/_xeroxz/theodosius#winapi-call-entry-example)
* [RIP Relative Addressing](https://githacks.org/_xeroxz/theodosius#rip-relative-addressing)
* [JCC - RIP Relative](https://githacks.org/_xeroxz/theodosius#jcc-rip-relative)
* [Obfuscation](https://githacks.org/_xeroxz/theodosius#obfuscation)
* [Obfuscate - Base Class](https://githacks.org/_xeroxz/theodosius#obfuscate-base-class)
* [Mutation - Inherts Obfuscation](https://githacks.org/_xeroxz/theodosius#mutation-inherts-obfuscation)
* [Examples](https://githacks.org/_xeroxz/theodosius#examples)
* [Kernel Example](https://githacks.org/_xeroxz/theodosius#kernel-example)
* [Usermode Example](https://githacks.org/_xeroxz/theodosius#usermode-example)
* [License - BSD 3-Clause](https://githacks.org/_xeroxz/theodosius#license-bsd-3-clause)
### Credit And Dependencies
* [BTBD](https://github.com/btbd) - Huge thanks for providing suggestions and bouncing ideas back and forth.
* [SMAP](https://github.com/btbd/smap) - scatter mapper, this project is heavily influenced by SMAP.
* [Zydis](https://github.com/zyantific/zydis) - used to decompile obfuscated routines and find JCC's.
* [asmjit](https://github.com/asmjit/asmjit) - used to generate link-time code (mutated routines).
* [LLVM-Obfuscator](https://github.com/obfuscator-llvm/obfuscator/wiki) - Here are the following devs:
* [Pascal Junod](https://crypto.junod.info/)
* Julien Rinaldini
* [Johan Wehrli](https://twitter.com/jowehrli)
* Julie Michielin
* Stéphane Ongagna
* Grégory Ruch
* Sébastien Bischof
## Linking - Dynamic And Static
#### What Is A Linker
A linker is a program which takes object files produces by a compiler and generates a final executable native to the operating system. A linker interfaces with not only object files but also static libraries, "lib" files. What is a "lib" file? Well a lib file is just an archive of obj's. You can invision it as a zip/rar without any compression, just concatination of said object files.
Theo is a jit linker, which means it will link objs together and map them into memory all at once. For usability however, instead of handling object files, Theo can parse entire lib files and extract the objects out of the lib.
#### Object Files
If you define a c++ file called "main.cpp" the compiler will generate an object file by the name of "main.obj". When you refer to data or code defined in another c/c++ file, the linker uses a symbol table to resolve the address of said code/data. In this situation I am the linker and I resolve all of your symbols :).
#### Static Linking
Static linking is when the linker links entire routines not created by you, into your code. Say `memcpy` (if its not inlined), will be staticlly linked with the CRT. Static linking also allows for your code to be more independant as all the code you need you bring with you. However, with Theo, you cannot link static libraries which are not compiled with `mcmodel=large`. Theo supports actual static linking, in other words, using multiple static libraries at the same time.
#### Dynamic Linking
Dynamic linking is when external symbols are resolved at runtime. This is done by imports and exports in DLL's (dynamiclly linked libraries). Theo supports "dynamic linking", or in better terms, linking against exported routines. You can see examples of this inside of both usermode and kernelmode examples.
# Usage - Using Theodosius
## Integrating Clang
For integration with visual studios please open install [llvm2019](https://marketplace.visualstudio.com/items?itemName=MarekAniola.mangh-llvm2019) extension, or [llvm2017](https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.llvm-toolchain) extension. Once installed, create or open a visual studio project which you want to use with LLVM-Obfuscator and Theo. Open ***Properties*** --> ***Configuration Properties*** ---> ***General***, then set ***Platform Toolset*** to ***LLVM***.
Once LLVM is selected, under the ***LLVM*** tab change the clang-cl location to the place where you extracted [clang-cl.rar](https://githacks.org/_xeroxz/theodosius/-/blob/cc9496ccceba3d1f0916859ddb2583be9362c908/resources/clang-cl.rar). Finally under ***Additional Compiler Options*** (same LLVM tab), set the following: `-Xclang -std=c++1z -Xclang -mcode-model -Xclang large -Xclang -fno-jump-tables -mllvm -split -mllvm -split_num=4 -mllvm -sub_loop=4`.
Please refer to the [LLVM-Obfuscator Wiki](https://github.com/obfuscator-llvm/obfuscator/wiki) for more information on commandline arguments.
#### Requirements
* No SEH support, do not add `__try/__except` in your code.
* No CFG (control flow guard) support. Please disable this in C/C++ ---> Code Generation ---> Control Flow Guard
* No Stack Security Check Support. Please disablel this in C/C++ ---> Code Generation ---> Security Check (/GS-)
* Your project must be set to produce a .lib file.
* Your project must not link with other static libraries which are not compiled with `-Xclang -mcmodel-large`.
* Project must be compiled with the following flags
* `-Xclang -mcmodel=large`, removes RIP relative addressing besides JCC's.
* `-Xclang -fno-jump-tables`, removes jump tables created by switch cases.
* `/Zc:threadSafeInit-`, static will not use TLS (thread local storage).
## Lambdas For Explicit Constructor
Theodosius uses the same class structure as HMDM does. Its a highly modular format which allows for extreme usage, supporting almost every idea one might have. In order to use Theo, you must first define three lambdas, `theo::memcpy_t` a method of copying memory, `theo::malloc_t` a method to allocate executable memory, and lastely `theo::resolve_symbol_t` a lamdba to resolve external symbols.
### `theo::memcpy_t` - copy memory lambda
This is used to write memory, it is never used to read memory. An example of this lambda using VDM could be:
```cpp
theo::memcpy_t _kmemcpy =
[&](void* dest, const void* src, std::size_t size) -> void*
{
static const auto kmemcpy =
reinterpret_cast<void*>(
utils::kmodule::get_export(
"ntoskrnl.exe", "memcpy"));
return vdm.syscall<decltype(&memcpy)>(kmemcpy, dest, src, size);
};
```
This uses VDM to syscall into memcpy exported by ntoskrnl... If you want to do something in usermode you can proxy memcpy to `WriteProcessMemory` or any other method of writing memory.
```cpp
theo::memcpy_t _memcpy =
[&](void* dest, const void* src, std::size_t size) -> void*
{
SIZE_T bytes_handled;
if (!WriteProcessMemory(phandle, dest, src, size, &bytes_handled))
{
std::printf("[!] failed to write process memory...\n");
exit(-1);
}
return dest;
};
```
### `theo::malloc_t` - allocate executable memory
This lambda is used to allocate executable memory. Any method will do as long as the memcpy lambda can write to the allocated memory. An MSREXEC example for this lambda is defined below.
```cpp
theo::malloc_t _kalloc = [&](std::size_t size) -> void*
{
void* alloc_base;
msrexec.exec
(
[&](void* krnl_base, get_system_routine_t get_kroutine) -> void
{
using ex_alloc_pool_t =
void* (*)(std::uint32_t, std::size_t);
const auto ex_alloc_pool =
reinterpret_cast<ex_alloc_pool_t>(
get_kroutine(krnl_base, "ExAllocatePool"));
alloc_base = ex_alloc_pool(NULL, size);
}
);
return alloc_base;
};
```
This lambda uses MSREXEC to allocate kernel memory via ExAllocatePool. However this is completely open ended on how you want to do it, you can allocate your memory into discarded
sections, you can allocate your memory in another address space, etc... Its extremely modular.
Another, yet simple, usermode example for this lambda is defined below.
```cpp
theo::malloc_t _alloc = [&](std::size_t size) -> void*
{
return VirtualAllocEx
(
phandle,
nullptr,
size,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
};
```
### `theo::resolve_symbol_t` - resolve external symbol
This lambda will try and resolve external symbols. Symbols which are not defined inside of any object files. For example `PiddbCacheTable`, an unexported ntoskrnl symbol, which normally people sig scan for, can now be jit linked. This is possible by parsing a MAP file, however you can recode this to support PDB's, etc. Again its completely opened ended on how you want to resolve symbols.
```cpp
theo::resolve_symbol_t resolve_symbol =
[&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t
{
std::uintptr_t result = 0u;
for (auto& [drv_name, drv_symbols] : extern_symbols)
{
// each kernel module... find a driver with a matching map file name...
// I.E ntoskrnl.exe.map == ntoskrnl.exe...
utils::kmodule::each_module
(
[&, &drv_name = drv_name, &drv_symbols = drv_symbols]
(PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto _drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
// if this is the driver, load it, loop over its sections
// calc the absolute virtual address of the symbol...
if (!strcmp(_drv_name, drv_name.c_str()))
{
const auto drv_load_addr =
reinterpret_cast<std::uintptr_t>(
LoadLibraryExA(drv_path, NULL, DONT_RESOLVE_DLL_REFERENCES));
std::uint32_t section_count = 1u;
utils::pe::each_section
(
[&, &drv_symbols = drv_symbols]
(PIMAGE_SECTION_HEADER section_header, std::uintptr_t img_base) -> bool
{
if (section_count == drv_symbols[symbol_name].first)
{
result = reinterpret_cast<std::uintptr_t>(drv_info->ImageBase) +
section_header->VirtualAddress + drv_symbols[symbol_name].second;
// we found the symbol...
return false;
}
++section_count;
// keep going over sections...
return true;
}, drv_load_addr
);
}
// keep looping over modules until we resolve the symbol...
return !result;
}
);
}
// if the symbol was not resolved in any of the map files then try
// to see if its an export from any other drivers...
if (!result)
{
utils::kmodule::each_module
(
[&](PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool
{
const auto drv_name =
reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName);
// false if we found the symbol...
return (!(result = utils::kmodule::get_export(drv_name, symbol_name)));
}
);
}
return result;
};
```
Another example of this lambda can be viewed in the usermode examples. This routine simply loops over every single module mapped into the specific process you want to map/link with.
```cpp
theo::resolve_symbol_t _resolver =
[&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t
{
auto loaded_modules = std::make_unique<HMODULE[]>(64);
std::uintptr_t result = 0u, loaded_module_sz = 0u;
if (!EnumProcessModules(phandle,
loaded_modules.get(), 512, (PDWORD)&loaded_module_sz))
return {};
for (auto i = 0u; i < loaded_module_sz / 8u; i++)
{
wchar_t file_name[MAX_PATH] = L"";
if (!GetModuleFileNameExW(phandle,
loaded_modules.get()[i], file_name, _countof(file_name)))
continue;
if ((result = reinterpret_cast<std::uintptr_t>(
GetProcAddress(LoadLibrary(file_name), symbol_name))))
break;
}
return result;
};
```
### Creating Instance
Once all three lambdas are defined, you can then create a `theo::hmm_ctx` (highly modular mapper context). This class is like the one from HMDM however it requires an extra lambda to resolve external symbols.
```cpp
theo::hmm_ctx drv_mapper({ _alloc, _memcpy, _resolver });
const auto drv_entry =
reinterpret_cast<LPTHREAD_START_ROUTINE>(
drv_mapper.map_objs(image_objs));
```
### Calling Entry
#### MSREXEC - Call Entry Example
The entry point of the mapped code is not invoked by `hmm_ctx`, but rather its left up to you to call. An example of calling the entry point can be seen below.
```cpp
int result;
msrexec.exec([&result, drv_entry = drv_entry]
(void* krnl_base, get_system_routine_t get_kroutine) -> void
{
using drv_entry_t = int(*)();
result = reinterpret_cast<drv_entry_t>(drv_entry)();
});
```
#### VDM - Call Entry Example
Another example, this one using VDM, can be seen below.
```cpp
const auto entry_result =
vdm.syscall<NTSTATUS(*)()>(
reinterpret_cast<void*>(drv_entry));
```
#### WinAPI - Call Entry Example
Another example, this one using WinAPI's, can be seen below.
```cpp
std::uint32_t tid = 0u;
CreateRemoteThread
(
phandle, NULL,
NULL, drv_entry,
NULL, NULL,
(LPDWORD)&tid
);
```
## RIP Relative Addressing
In order to allow for a routine to be scattered throughout a 64bit address space, RIP relative addressing must not be used. In order to facilitate this, a very special version
of clang-cl is used which can use `mcmodel=large`. This will generate instructions which do not use RIP relative addressing when referencing symbols outside of the routine in which the
instruction itself resides. The only exception to this is JCC instructions, (besides call) also known as branching instructions. Take this c++ code for an example:
```cpp
ObfuscateRoutine
extern "C" int ModuleEntry()
{
MessageBoxA(0, "Demo", "Hello From Obfuscated Routine!", 0);
UsermodeMutateDemo();
UsermodeNoObfuscation();
}
```
This c++ function, compiled by clang-cl with `mcmodel=large`, will generate a routine with the following instructions:
```
0x00: ; void UsermodeNoObfuscation(void)
0x00: public [email protected]@YAXXZ
0x00: [email protected]@YAXXZ proc near ; CODE XREF: ModuleEntry+42↓p
0x00: var_4 = dword ptr -4
0x00: 48 83 EC 28 sub rsp, 28h
0x04: C7 44 24 24 00 00 00 00 mov [rsp+28h+var_4], 0
0x0C: loc_C:
0x0C: 83 7C 24 24 05 cmp [rsp+28h+var_4], 5
0x11: 0F 83 38 00 00 00 jnb loc_4F
0x17: 31 C0 xor eax, eax
0x19: 48 BA 28 01 00 00 00 00 00 00 mov rdx, offset [email protected][email protected][email protected] ; "Demo"
0x23: 49 B8 00 01 00 00 00 00 00 00 mov r8, offset [email protected][email protected]@Hello?5... ; "Hello From Non-Obfuscated Routine!"
0x2D: 48 B8 A0 01 00 00 00 00 00 00 mov rax, offset MessageBoxA
0x37: 45 31 C9 xor r9d, r9d ; uType
0x3A: 44 89 C9 mov ecx, r9d ; hWnd
0x3D: FF D0 call rax ; MessageBoxA
0x3F: 8B 44 24 24 mov eax, [rsp+28h+var_4]
0x43: 83 C0 01 add eax, 1
0x46: 89 44 24 24 mov [rsp+28h+var_4], eax
0x4A: E9 BD FF FF FF jmp loc_C
0x4F: loc_4F:
0x4F: 48 83 C4 28 add rsp, 28h
0x53: C3 retn
0x53: [email protected]@YAXXZ endp
```
As you can see from the code above, (sorry for the terrible syntax highlighting), references to strings and calls to functions are done by first loading the address of the symbol into a register and then interfacing with the symbol.
```
0x2D: 48 B8 A0 01 00 00 00 00 00 00 mov rax, offset MessageBoxA
; ...
0x3D: FF D0 call rax ; MessageBoxA
```
Each of these instructions can be anywhere in virtual memory and it would not effect code execution one bit. However this is not the case with routines which have conditional branches. Take the following c++ code for example.
## JCC - RIP Relative
```cpp
ObfuscateRoutine
void LoopDemo()
{
for (auto idx = 0u; idx < 10; ++idx)
DbgPrint("> Loop Demo: %d\n", idx);
}
```
This c++ function, compiled by clang-cl with `mcmodel=large`, will generate a routine with the following instructions:
```
0x58 ; void LoopDemo(void)
0x58 public [email protected]@YAXXZ
0x58 [email protected]@YAXXZ proc near
0x58 var_4 = dword ptr -4
0x58
0x58 48 83 EC 28 sub rsp, 28h
0x5C C7 44 24 24 00 00 00 00 mov [rsp+28h+var_4], 0
0x64 loc_64:
0x64 83 7C 24 24 0A cmp [rsp+28h+var_4], 0Ah
0x69 0F 83 2A 00 00 00 jnb loc_99
0x6F 8B 54 24 24 mov edx, [rsp+28h+var_4]
0x73 48 B9 60 01 00 00 00 00 00 00 mov rcx, offset [email protected][email protected]@?$.... ; "> Loop Demo: %d\n"
0x7D 48 B8 38 02 00 00 00 00 00 00 mov rax, offset DbgPrint
0x87 FF D0 call rax ; DbgPrint
0x89 8B 44 24 24 mov eax, [rsp+28h+var_4]
0x8D 83 C0 01 add eax, 1
0x90 89 44 24 24 mov [rsp+28h+var_4], eax
0x94 E9 CB FF FF FF jmp loc_64
0x99 loc_99:
0x99 48 83 C4 28 add rsp, 28h
0x9D C3 retn
0x9D [email protected]@YAXXZ endp
```
Uh oh, `jnb loc_99`?, thats RIP relative! In order to handle branching operations, a "jump table" is generated by `obfuscation::obfuscate` explicit default constructor. Instead of branching to the RIP relative code, it will instead branch to an inline jump (`JMP [RIP+0x0]`). As demonstrated below, the branching operation is altered to branch to an asbolute jump.
```
ffff998b`c5369e60 0f830e000000 jnb ffff998b`c5369e74
ffff998b`c5369e66 ff2500000000 jmp qword ptr [ffff998b`c5369e6c]
...
ffff998b`c5369e74 ff2500000000 jmp qword ptr [ffff998b`c5369e7a]
```
The linker is able to get the address of the branching code by taking the rip relative virtual address of the branching operation, which is a signed number, and adding it to the current byte offset into the current routine, plus the size of the branching instruction. For example `[email protected]` + size of the branching instruction, which is six bytes, then adding the signed relative virtual address (0x2A). The result of this simple calculation gives us `[email protected]`, which is correct, the branch goes to `add rsp, 28h` in the above example.
## Obfuscation
The usage of the word obfuscation in this project is use to define any changes made to code, this includes code flow. `obfuscation::obfuscate`, a base class, which is inherited and expanded upon by `obfuscation::mutation`, obfuscates code flow by inserting `JMP [RIP+0x0]` instructions after every single instruction. This allows for a routine to be broken up into unique allocations of memory and thus provides more canvas room for creative ideas.
### Obfuscate - Base Class
The base class, as described in the above section, contains a handful of util routines and a single explicit constructor which is the corner stone of the class. The constructor fixes JCC relative virtual addresses so that if the condition is met, instead of jumping instruction pointer relativitly, it will jump to an addition jmp (`JMP [RIP+0x0]`).
LEA's, nor CALL's are rip relative, even for symbols defined inside of the routine in which the instruction is compiled into. In other words JCC instructions are the only instruction pointer relative instructions that are generated.
```
instruction
jmp next instruction
instruction
jmp next instruction
instruction
jmp next instruction
```
### Mutation - Inherts Obfuscation
This class inherits from `obfuscate` and adds additional code, or "mutation". This class is a small example of how to use inheritance with `obfuscate` base class. It generates a stack push/pop palindrome. The state of the stack is restored before the routines actual instruction is executed. The assembly will now look like this in memory:
```
push gp
push gp
push gp
...
pop gp
pop gp
pop gp
exec routine instruction
jmp next instruction
push gp
push gp
push gp
push gp
push gp
...
pop gp
pop gp
pop gp
pop gp
pop gp
exec routine instruction
jmp next instruction
push gp
push gp
push gp
...
pop gp
pop gp
pop gp
exec routine instruction
jmp next instruction
```
Again this is just a demo/POC on how you can inherit `obfuscate`. This also shows an example of how to use `asmjit`.
# Examples
### Kernel Example
<img src="https://githacks.org/_xeroxz/theodosius/-/raw/d286946c4727c91e0ca8d6059335382f00db4b91/imgs/kernel-example-2.png"/>
This example uses MSREXEC and Theodosius to map unsigned code into the kernel. This example is inside of the "Examples" folder. I would also like to note that in this demo external unexported ntoskrnl symbols are resolved by using a MAP file. This map file looks like this:
```
00000001:0000000000000F10 KiOpTwoByteTable
00000001:0000000000001168 SeSubsystemName
00000001:0000000000001180 PlugPlayHandlerTable
00000001:00000000000013E0 PiDmAggregatedBooleanDefs
00000001:0000000000001490 PiDmCachedDeviceKeys
00000001:0000000000001580 PiDmCachedDeviceInterfaceKeys
00000001:00000000000015F0 AllowedCachedObjectNames
00000001:0000000000001640 EmptyUnicodeString
```
Mind the space at the beginning of each line. If you want to generate a file like this, put ntoskrnl.exe into IDA Pro and then click File ---> Produce File ---> Create MAP File, dont select "Segment Information", but do select "Demangled Names". After the MAP file is generate, please delete all of the garbage at the beginning of the file. I.E delete all spaces and "Address, Public By Value" stuff.
```
Address Publics by Value
00000001:0000000000000000 VrpRegistryString
....
```
Once you have generated a map file for ntoskrnl.exe, or any other binary you want to link with, you can then use it to resolve external symbols. In the `DemoDrv` project, I reference two external symbols. One being `PiddbCacheTable`, and the other being a win32kfull.sys export.
```cpp
// this is a demo of resolving non-exported symbols...
// win32kfull.sys export example...
extern "C" void NtUserRegisterShellPTPListener();
extern "C" void* PiDDBCacheTable;
```
These two symbols are simply printed out via DbgPrint.
```cpp
MutateRoutine extern "C" void DrvEntry()
{
DbgPrint("> Hello World!\n");
// non-exported symbols being resolved by jit linker...
DbgPrint("> PiDDBCacheTable = 0x%p\n", &PiDDBCacheTable);
DbgPrint("> win32kfull!NtUserRegisterShellPTPListener = 0x%p\n", &NtUserRegisterShellPTPListener);
// example of referencing itself...
DbgPrint("> DrvEntry = 0x%p\n", &DrvEntry);
// example of calling other obfuscated/non obfuscated routines...
PrintCR3();
LoopDemo();
}
```
Once compiled the assembly will look like this. Note that each reference to symbols is done via a relocation to an absolute address. This means strings can (and will) be mapped into their own allocation of memory.
```
0X0A8: public DrvEntry
0X0A8: DrvEntry proc near
0X0A8: 48 83 EC 28 sub rsp, 28h
0X0AC: 48 B9 78 01 00 00 00 00 00 00 mov rcx, offset [email protected][email protected]@?$D...; "> Hello World!\n"
0X0B6: 48 B8 38 02 00 00 00 00 00 00 mov rax, offset DbgPrint
0X0C0: FF D0 call rax ; DbgPrint
0X0C2: 48 B9 88 01 00 00 00 00 00 00 mov rcx, offset [email protected][email protected]; "> PiDDBCacheTable = 0x%p\n"
0X0CC: 48 BA 40 02 00 00 00 00 00 00 mov rdx, offset PiDDBCacheTable
0X0D6: 48 B8 38 02 00 00 00 00 00 00 mov rax, offset DbgPrint
0X0E0: FF D0 call rax ; DbgPrint
0X0E2: 48 B9 A8 01 00 00 00 00 00 00 mov rcx, offset [email protected][email protected]; "> win32kfull!NtUserRegisterShellPTPList"...
0X0EC: 48 BA 48 02 00 00 00 00 00 00 mov rdx, offset NtUserRegisterShellPTPListener
0X0F6: 48 B8 38 02 00 00 00 00 00 00 mov rax, offset DbgPrint
0X100: FF D0 call rax ; DbgPrint
0X102: 48 B9 E0 01 00 00 00 00 00 00 mov rcx, offset [email protected][email protected] ; "> DrvEntry = 0x%p\n"
0X10C: 48 BA A8 00 00 00 00 00 00 00 mov rdx, offset DrvEntry
0X116: 48 B8 38 02 00 00 00 00 00 00 mov rax, offset DbgPrint
0X120: FF D0 call rax ; DbgPrint
0X122: 48 B8 00 00 00 00 00 00 00 00 mov rax, offset [email protected]@YAXXZ ; PrintCR3(void)
0X12C: FF D0 call rax ; PrintCR3(void) ; PrintCR3(void)
0X12E: 48 B8 58 00 00 00 00 00 00 00 mov rax, offset [email protected]@YAXXZ ; LoopDemo(void)
0X138: FF D0 call rax ; LoopDemo(void) ; LoopDemo(void)
0X13A: 90 nop
0X13B: 48 83 C4 28 add rsp, 28h
0X13F: C3 retn
0X13F: DrvEntry endp
```
Theo calculates the size of each symbol by subtracting the address of the next symbol (in the same section), from the address of the symbol itself. If the symbol is the last one in a section, the distance between the start of the symbol and the end of the section is used. Now lets take a look at what happens when we link/map this routine. Theo starts by allocating space for all non-obfuscated symbols.
```
[+] allocating space for symbols...
> [email protected][email protected]@[email protected] allocated at = 0xFFFF998BC5361FB0, size = 22
> [email protected][email protected]@[email protected] allocated at = 0xFFFF998BC5364FA0, size = 17
> [email protected][email protected]@[email protected] allocated at = 0xFFFF998BC5365FA0, size = 16
> [email protected][email protected]@[email protected] allocated at = 0xFFFF998BC5366EA0, size = 26
> [email protected][email protected]@[email protected] allocated at = 0xFFFF998BC5366EE0, size = 52
> [email protected][email protected]@[email protected] allocated at = 0xFFFF998BC5366F40, size = 19
> [email protected]@YAXXZ allocated at = 0xFFFF998BC5366F80, size = 58
```
As you can see, each string gets its own pool, each global variable does too, and every non-obfuscated routine is mapped into its own pool. The memory however, has not been copied yet since there are relocations that need to happen before they are copied into memory (in PrintCr3).
The next thing Theo does is allocate space for obfuscated routines. In the `DemoDrv`, there is a demo for each type of obfuscation (just mutation and control flow obfuscation for now).
```
[+] allocating space for obfuscated symbols...
> [email protected]@YAXXZ allocated = 0xFFFF998BC5369DA0, size = 18
> [email protected]@[email protected] allocated = 0xFFFF998BC5369DE0, size = 22
> [email protected]@[email protected] allocated = 0xFFFF998BC5369E20, size = 19
> fixing JCC rva...
> new rva = 0xe
> old rva = 0x2a
> [email protected]@[email protected] allocated = 0xFFFF998BC5369E60, size = 34
> [email protected]@[email protected] allocated = 0xFFFF998BC5369EB0, size = 18
> [email protected]@[email protected] allocated = 0xFFFF998BC5369EF0, size = 24
> [email protected]@[email protected] allocated = 0xFFFF998BC5369F30, size = 24
> [email protected]@[email protected] allocated = 0xFFFF998BC5369F70, size = 16
> [email protected]@[email protected] allocated = 0xFFFF998BC5369FA0, size = 18
> [email protected]@[email protected] allocated = 0xFFFF998BC5368BA0, size = 17
> [email protected]@[email protected] allocated = 0xFFFF998BC5368BE0, size = 18
> [email protected]@[email protected] allocated = 0xFFFF998BC5368C20, size = 14
> [email protected]@[email protected] allocated = 0xFFFF998BC5368C50, size = 18
> [email protected]@[email protected] allocated = 0xFFFF998BC5368C90, size = 15
```
As you can see, Theo uses Zydis to go over all routines marked for obfuscation and generates new symbols for each instruction inside of the routine. The symbol goes by `[RoutineName]@[Instruction Offset]`. Note that JCC's are indeed rip relative, these need to be fixed.
```
> fixing JCC rva...
> new rva = 0xe
> old rva = 0x2a
> [email protected]@[email protected] allocated = 0xFFFF998BC5369E60, size = 34
```
Note that in DemoDrv there is a function called "LoopDemo" which is obfuscated. Instead of the JCC instruction branching to the conditional code, it instead branches to an inline jmp. If it doesnt branch, then it simply jumps to the next instruction like normal.
```
ffff998b`c5369e60 0f830e000000 jae ffff998b`c5369e74
ffff998b`c5369e66 ff2500000000 jmp qword ptr [ffff998b`c5369e6c]
ffff998b`c5369e74 ff2500000000 jmp qword ptr [ffff998b`c5369e7a]
```
As you can see above, this is what Theo generates for JCC's. Also note that this clang compiler does not generate RIP relative LEA's or CALL's. The only RIP relative stuff Theo deals with are JCC's.
#### Memory View Of Obfuscation
The instructions for `LoopDemo` now look like this in memory:
```
ffff998b`c5369da0 4883ec28 sub rsp,28h
ffff998b`c5369da4 ff2500000000 jmp qword ptr [ffff998b`c5369daa]
...
ffff998b`c5369de0 c74424...... mov dword ptr [rsp+24h],0
ffff998b`c5369de8 ff2500000000 jmp qword ptr [ffff998b`c5369dee]
...
ffff998b`c5369e20 837c24240a cmp dword ptr [rsp+24h],0Ah
ffff998b`c5369e25 ff2500000000 jmp qword ptr [ffff998b`c5369e2b]
...
ffff998b`c5369e60 0f830e000000 jae ffff998b`c5369e74
ffff998b`c5369e66 ff2500000000 jmp qword ptr [ffff998b`c5369e6c]
ffff998b`c5369e74 ff2500000000 jmp qword ptr [ffff998b`c5369e7a]
...
ffff998b`c5369eb0 8b542424 mov edx,dword ptr [rsp+24h]
ffff998b`c5369eb4 ff2500000000 jmp qword ptr [ffff998b`c5369eba]
...
ffff998b`c5369ef0 48b9........ mov rcx,0FFFF998BC5364FA0h ; "> Loop Demo: %d\n"
ffff998b`c5369efa ff2500000000 jmp qword ptr [ffff998b`c5369f00]
...
ffff998b`c5369f30 48b8........ mov rax,offset nt!DbgPrint (fffff803`6a750f60)
ffff998b`c5369f3a ff2500000000 jmp qword ptr [ffff998b`c5369f40]
...
ffff998b`c5369f70 ffd0 call rax
ffff998b`c5369f72 ff2500000000 jmp qword ptr [ffff998b`c5369f78]
...
ffff998b`c5369fa0 8b442424 mov eax,dword ptr [rsp+24h]
ffff998b`c5369fa4 ff2500000000 jmp qword ptr [ffff998b`c5369faa]
...
ffff998b`c5368ba0 83c001 add eax,1
ffff998b`c5368ba3 ff2500000000 jmp qword ptr [ffff998b`c5368ba9]
...
ffff998b`c5368be0 89442424 mov dword ptr [rsp+24h],eax
ffff998b`c5368be4 ff2500000000 jmp qword ptr [ffff998b`c5368bea]
...
ffff998b`c5368c20 ff2500000000 jmp qword ptr [ffff998b`c5368c26]
...
ffff998b`c5368c50 4883c428 add rsp,28h
ffff998b`c5368c54 ff2500000000 jmp qword ptr [ffff998b`c5368c5a]
...
ffff998b`c5368c90 c3 ret
```
### Usermode Example
<img src="https://githacks.org/_xeroxz/theodosius/-/raw/a5de4b8a1a6cf32bb0213d8d9602f5dc955275b1/imgs/um-example-2.png"/>
This example uses WinAPI's to allocate virtual memory in another process and also to copy virtual memory. Only exported routines from loaded DLL's in the target process can be resolved.
# License - BSD 3-Clause
Copyright (c) 2021, _xeroxz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

5
cmake.toml

@ -0,0 +1,5 @@
[project]
name = "Theodosius"
[target.Theodosius]
type = "static"

236
cmkr.cmake

@ -0,0 +1,236 @@
include_guard()
# Change these defaults to point to your infrastructure if desired
set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE)
set(CMKR_TAG "v0.2.12" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE)
# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake
if(CMAKE_SCRIPT_MODE_FILE)
set(CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}/build")
set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_BINARY_DIR}")
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}")
endif()
# Set these from the command line to customize for development/debugging purposes
set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable")
set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation")
set(CMKR_BUILD_TYPE "Debug" CACHE STRING "cmkr build configuration")
mark_as_advanced(CMKR_REPO CMKR_TAG CMKR_COMMIT_HASH CMKR_EXECUTABLE CMKR_SKIP_GENERATION CMKR_BUILD_TYPE)
# Disable cmkr if generation is disabled
if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION)
message(STATUS "[cmkr] Skipping automatic cmkr generation")
unset(CMKR_BUILD_SKIP_GENERATION CACHE)
macro(cmkr)
endmacro()
return()
endif()
# Disable cmkr if no cmake.toml file is found
if(NOT CMAKE_SCRIPT_MODE_FILE AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml")
message(AUTHOR_WARNING "[cmkr] Not found: ${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml")
macro(cmkr)
endmacro()
return()
endif()
# Convert a Windows native path to CMake path
if(CMKR_EXECUTABLE MATCHES "\\\\")
string(REPLACE "\\" "/" CMKR_EXECUTABLE_CMAKE "${CMKR_EXECUTABLE}")
set(CMKR_EXECUTABLE "${CMKR_EXECUTABLE_CMAKE}" CACHE FILEPATH "" FORCE)
unset(CMKR_EXECUTABLE_CMAKE)
endif()
# Helper macro to execute a process (COMMAND_ERROR_IS_FATAL ANY is 3.19 and higher)
function(cmkr_exec)
execute_process(COMMAND ${ARGV} RESULT_VARIABLE CMKR_EXEC_RESULT)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "cmkr_exec(${ARGV}) failed (exit code ${CMKR_EXEC_RESULT})")
endif()
endfunction()
# Windows-specific hack (CMAKE_EXECUTABLE_PREFIX is not set at the moment)
if(WIN32)
set(CMKR_EXECUTABLE_NAME "cmkr.exe")
else()
set(CMKR_EXECUTABLE_NAME "cmkr")
endif()
# Use cached cmkr if found
if(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}")
set(CMKR_DIRECTORY_PREFIX "$ENV{CMKR_CACHE}")
string(REPLACE "\\" "/" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}")
if(NOT CMKR_DIRECTORY_PREFIX MATCHES "\\/$")
set(CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}/")
endif()
# Build in release mode for the cache
set(CMKR_BUILD_TYPE "Release")
else()
set(CMKR_DIRECTORY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_")
endif()
set(CMKR_DIRECTORY "${CMKR_DIRECTORY_PREFIX}${CMKR_TAG}")
set(CMKR_CACHED_EXECUTABLE "${CMKR_DIRECTORY}/bin/${CMKR_EXECUTABLE_NAME}")
# Handle upgrading logic
if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE)
if(CMKR_EXECUTABLE MATCHES "^${CMAKE_CURRENT_BINARY_DIR}/_cmkr")
if(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}")
message(AUTHOR_WARNING "[cmkr] Switching to cached cmkr: '${CMKR_CACHED_EXECUTABLE}'")
if(EXISTS "${CMKR_CACHED_EXECUTABLE}")
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
else()
unset(CMKR_EXECUTABLE CACHE)
endif()
else()
message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'")
unset(CMKR_EXECUTABLE CACHE)
endif()
elseif(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}" AND CMKR_EXECUTABLE MATCHES "^${CMKR_DIRECTORY_PREFIX}")
message(AUTHOR_WARNING "[cmkr] Upgrading cached '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'")
unset(CMKR_EXECUTABLE CACHE)
endif()
endif()
if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}")
message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'")
elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE)
message(FATAL_ERROR "[cmkr] '${CMKR_EXECUTABLE}' not found")
elseif(NOT CMKR_EXECUTABLE AND EXISTS "${CMKR_CACHED_EXECUTABLE}")
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
message(STATUS "[cmkr] Found cached cmkr: '${CMKR_EXECUTABLE}'")
else()
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'")
message(STATUS "[cmkr] Fetching cmkr...")
if(EXISTS "${CMKR_DIRECTORY}")
cmkr_exec("${CMAKE_COMMAND}" -E rm -rf "${CMKR_DIRECTORY}")
endif()
find_package(Git QUIET REQUIRED)
cmkr_exec("${GIT_EXECUTABLE}"
clone
--config advice.detachedHead=false
--branch ${CMKR_TAG}
--depth 1
${CMKR_REPO}
"${CMKR_DIRECTORY}"
)
if(CMKR_COMMIT_HASH)
execute_process(
COMMAND "${GIT_EXECUTABLE}" checkout -q "${CMKR_COMMIT_HASH}"
RESULT_VARIABLE CMKR_EXEC_RESULT
WORKING_DIRECTORY "${CMKR_DIRECTORY}"
)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "Tag '${CMKR_TAG}' hash is not '${CMKR_COMMIT_HASH}'")
endif()
endif()
message(STATUS "[cmkr] Building cmkr (using system compiler)...")
cmkr_exec("${CMAKE_COMMAND}"
--no-warn-unused-cli
"${CMKR_DIRECTORY}"
"-B${CMKR_DIRECTORY}/build"
"-DCMAKE_BUILD_TYPE=${CMKR_BUILD_TYPE}"
"-DCMAKE_UNITY_BUILD=ON"
"-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}"
"-DCMKR_GENERATE_DOCUMENTATION=OFF"
)
cmkr_exec("${CMAKE_COMMAND}"
--build "${CMKR_DIRECTORY}/build"
--config "${CMKR_BUILD_TYPE}"
--parallel
)
cmkr_exec("${CMAKE_COMMAND}"
--install "${CMKR_DIRECTORY}/build"
--config "${CMKR_BUILD_TYPE}"
--prefix "${CMKR_DIRECTORY}"
--component cmkr
)
if(NOT EXISTS ${CMKR_EXECUTABLE})
message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'")
endif()
cmkr_exec("${CMKR_EXECUTABLE}" version)
message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}")
endif()
execute_process(COMMAND "${CMKR_EXECUTABLE}" version
RESULT_VARIABLE CMKR_EXEC_RESULT
)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding")
endif()
# Use cmkr.cmake as a script
if(CMAKE_SCRIPT_MODE_FILE)
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml")
execute_process(COMMAND "${CMKR_EXECUTABLE}" init
RESULT_VARIABLE CMKR_EXEC_RESULT
)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "[cmkr] Failed to bootstrap cmkr project. Please report an issue: https://github.com/build-cpp/cmkr/issues/new")
else()
message(STATUS "[cmkr] Modify cmake.toml and then configure using: cmake -B build")
endif()
else()
execute_process(COMMAND "${CMKR_EXECUTABLE}" gen
RESULT_VARIABLE CMKR_EXEC_RESULT
)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "[cmkr] Failed to generate project.")
else()
message(STATUS "[cmkr] Configure using: cmake -B build")
endif()
endif()
endif()
# This is the macro that contains black magic
macro(cmkr)
# When this macro is called from the generated file, fake some internal CMake variables
get_source_file_property(CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" CMKR_CURRENT_LIST_FILE)
if(CMKR_CURRENT_LIST_FILE)
set(CMAKE_CURRENT_LIST_FILE "${CMKR_CURRENT_LIST_FILE}")
get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
endif()
# File-based include guard (include_guard is not documented to work)
get_source_file_property(CMKR_INCLUDE_GUARD "${CMAKE_CURRENT_LIST_FILE}" CMKR_INCLUDE_GUARD)
if(NOT CMKR_INCLUDE_GUARD)
set_source_files_properties("${CMAKE_CURRENT_LIST_FILE}" PROPERTIES CMKR_INCLUDE_GUARD TRUE)
file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_PRE)
# Generate CMakeLists.txt
cmkr_exec("${CMKR_EXECUTABLE}" gen
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_POST)
# Delete the temporary file if it was left for some reason
set(CMKR_TEMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CMakerLists.txt")
if(EXISTS "${CMKR_TEMP_FILE}")
file(REMOVE "${CMKR_TEMP_FILE}")
endif()
if(NOT CMKR_LIST_FILE_SHA256_PRE STREQUAL CMKR_LIST_FILE_SHA256_POST)
# Copy the now-generated CMakeLists.txt to CMakerLists.txt
# This is done because you cannot include() a file you are currently in
configure_file(CMakeLists.txt "${CMKR_TEMP_FILE}" COPYONLY)
# Add the macro required for the hack at the start of the cmkr macro
set_source_files_properties("${CMKR_TEMP_FILE}" PROPERTIES
CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}"
)
# 'Execute' the newly-generated CMakeLists.txt
include("${CMKR_TEMP_FILE}")
# Delete the generated file
file(REMOVE "${CMKR_TEMP_FILE}")
# Do not execute the rest of the original CMakeLists.txt
return()
endif()
# Resume executing the unmodified CMakeLists.txt
endif()
endmacro()

13
demos/DemoDll/AnotherObj.cpp

@ -1,13 +0,0 @@
#include "Theodosius.h"
#include <Windows.h>
void UsermodeNoObfuscation()
{
MessageBoxA(0, "Demo", "Hello From Non-Obfuscated Routine!", 0);
}
THEO_MUTATE(LLVM_BCF LLVM_SUB void UsermodeMutateDemo()
{
for (auto idx = 0u; idx < 5; ++idx)
MessageBoxA(0, "Demo", "Hello From Mutated Routine!", 0);
})

46
demos/DemoDll/ClassDemo.cpp

@ -1,46 +0,0 @@
#include "ClassDemo.hpp"
VirtualFuncDemo::VirtualFuncDemo()
{
MessageBoxA(0, "VirtualFuncDemo (Base Class)", "Virtual Func Demo!", 0);
}
VirtualFuncDemo::~VirtualFuncDemo()
{
MessageBoxA(0, "VirtualFuncDemo (Base Class)", "Virtual Destructor Demo!", 0);
}
void VirtualFuncDemo::PrintTest()
{
MessageBoxA(0, "VirtualFuncDemo (Base Class)", "Virtual Func Demo!", 0);
}
Demo::Demo()
{
MessageBoxA(0, "Demo", "Virtual Func Demo!", 0);
}
Demo::~Demo()
{
MessageBoxA(0, "Demo", "Virtual Destructor Demo!", 0);
}
void Demo::PrintTest()
{
MessageBoxA(0, "PrintTest", "Hello World!", 0);
}
Demo2::Demo2()
{
MessageBoxA(0, "Demo2", "Virtual Func Demo!", 0);
}
Demo2::~Demo2()
{
MessageBoxA(0, "Demo2", "Virtual Destructor Demo!", 0);
}
void Demo2::PrintTest()
{
MessageBoxA(0, "PrintTest2", "Hello World!", 0);
}

31
demos/DemoDll/ClassDemo.hpp

@ -1,31 +0,0 @@
#pragma once
#include "Theodosius.h"
#include <Windows.h>
#include <stdio.h>
void UsermodeMutateDemo();
void UsermodeNoObfuscation();
class VirtualFuncDemo
{
public:
explicit VirtualFuncDemo();
virtual ~VirtualFuncDemo();
virtual void PrintTest();
};
class Demo : public VirtualFuncDemo
{
public:
explicit Demo();
~Demo() override;
void PrintTest() override;
};
class Demo2 : public VirtualFuncDemo
{
public:
explicit Demo2();
~Demo2() override;
void PrintTest() override;
};

122
demos/DemoDll/DemoDll.vcxproj

@ -1,122 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{19B2E75C-385A-40BF-8FAE-2F5E1E24E2EC}</ProjectGuid>
<TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<RootNamespace>DemoDrv</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>ClangCL</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Driver_SpectreMitigation>false</Driver_SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>llvm</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Driver_SpectreMitigation>false</Driver_SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<EnableInf2cat>false</EnableInf2cat>
<IncludePath>$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
<ExecutablePath>$(LLVMInstallDir)\bin;$(ExecutablePath);</ExecutablePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<EnableInf2cat>false</EnableInf2cat>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
<ExecutablePath>$(LLVMInstallDir)\bin;$(ExecutablePath);</ExecutablePath>
</PropertyGroup>
<PropertyGroup Label="LLVM" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClangClExecutable>$(ProjectDir)..\..\clang-cl.exe</ClangClExecutable>
<UseClangCl>true</UseClangCl>
<ClangClAdditionalOptions>-Xclang -std=c++1z -Xclang -mcode-model -Xclang large -Xclang -fno-jump-tables -mllvm -split -mllvm -split_num=4 -mllvm -sub_loop=4 </ClangClAdditionalOptions>
<LldLinkExecutable>
</LldLinkExecutable>
<UseLldLink>false</UseLldLink>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<TreatWarningAsError>false</TreatWarningAsError>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ControlFlowGuard>false</ControlFlowGuard>
<AdditionalOptions>-Xclang -mcmodel=large -Xclang -fno-jump-tables /Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile>
<Link>
<EntryPointSymbol>DriverEntry</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<TreatWarningAsError>false</TreatWarningAsError>
<Optimization>Disabled</Optimization>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ControlFlowGuard>false</ControlFlowGuard>
<ExceptionHandling>false</ExceptionHandling>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<FunctionLevelLinking>false</FunctionLevelLinking>
<LanguageStandard_C>Default</LanguageStandard_C>
<CompileAs>Default</CompileAs>
<DiagnosticsFormat />
<AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<EntryPointSymbol>main</EntryPointSymbol>
</Link>
<BuildLog>
<Path>$(IntDir)ignore\$(MSBuildProjectName).log</Path>
</BuildLog>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ClassDemo.hpp" />
<ClInclude Include="Theodosius.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AnotherObj.cpp" />
<ClCompile Include="ClassDemo.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

31
demos/DemoDll/DemoDll.vcxproj.filters

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{92e25b44-aaeb-40a2-b8c9-7eab6c210e8d}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Theodosius.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ClassDemo.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AnotherObj.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ClassDemo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

4
demos/DemoDll/DemoDll.vcxproj.user

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

19
demos/DemoDll/Theodosius.h

@ -1,19 +0,0 @@
#pragma once
#define WINUSERAPI
#define _KERNEL32_
#define _ACRTIMP
#define NTKERNELAPI
#define THEO_OBFUSCATE(...) \
_Pragma("code_seg(\".theo\")") \
__VA_ARGS__ \
_Pragma("code_seg()")
#define THEO_MUTATE(...) \
_Pragma("code_seg(\".theo1\")") \
__VA_ARGS__ \
_Pragma("code_seg()")
#define LLVM_BCF __attribute((__annotate__(("bcf"))))
#define LLVM_SUB __attribute((__annotate__(("sub"))))
#define LLVM_FLA __attribute((__annotate__(("fla"))))

22
demos/DemoDll/main.cpp

@ -1,22 +0,0 @@
#include "ClassDemo.hpp"
// ignore this warning... its VS...
THEO_OBFUSCATE(extern "C" int main()
{
AllocConsole();