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
-![Alt text](Screenshots/Server.PNG "Screenshot du server") \ No newline at end of file +![Alt text](Screenshots/Server.PNG "Screenshot du server") + +# Crypter + +En WIP. + +
+TODO + +* Ajouter du code mutation +* Control flow flattening +* Anti-disassembly +