├── .gitattributes ├── .gitignore ├── cryptpe.sln ├── cryptpe ├── MemoryModule.c ├── MemoryModule.h ├── cryptpe.vcxproj ├── cryptpe.vcxproj.filters ├── debfuq.asm ├── huffman_dec.c ├── huffman_dec.h ├── main.c └── rlevel.h ├── license.txt ├── mkbintable ├── huffman_enc.c ├── huffman_enc.h ├── main.c ├── mkbintable.vcxproj └── mkbintable.vcxproj.filters ├── readme.txt ├── script ├── clean.bat └── mktable.bat ├── shared ├── huffman.h ├── salsa20.c └── salsa20.h └── testbin ├── main.c ├── testbin.vcxproj └── testbin.vcxproj.filters /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | cryptpe/bintable.h 2 | 3 | ################# 4 | ## Eclipse 5 | ################# 6 | 7 | *.pydevproject 8 | .project 9 | .metadata 10 | bin/ 11 | tmp/ 12 | *.tmp 13 | *.bak 14 | *.swp 15 | *~.nib 16 | local.properties 17 | .classpath 18 | .settings/ 19 | .loadpath 20 | 21 | # External tool builders 22 | .externalToolBuilders/ 23 | 24 | # Locally stored "Eclipse launch configurations" 25 | *.launch 26 | 27 | # CDT-specific 28 | .cproject 29 | 30 | # PDT-specific 31 | .buildpath 32 | 33 | 34 | ################# 35 | ## Visual Studio 36 | ################# 37 | 38 | ## Ignore Visual Studio temporary files, build results, and 39 | ## files generated by popular Visual Studio add-ons. 40 | 41 | # User-specific files 42 | *.suo 43 | *.user 44 | *.sln.docstates 45 | 46 | # Build results 47 | [Dd]ebug/ 48 | [Rr]elease/ 49 | *_i.c 50 | *_p.c 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.vspscc 65 | .builds 66 | *.dotCover 67 | 68 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 69 | #packages/ 70 | 71 | # Visual C++ cache files 72 | ipch/ 73 | *.aps 74 | *.ncb 75 | *.opensdf 76 | *.sdf 77 | 78 | # Visual Studio profiler 79 | *.psess 80 | *.vsp 81 | 82 | # ReSharper is a .NET coding add-in 83 | _ReSharper* 84 | 85 | # Installshield output folder 86 | [Ee]xpress 87 | 88 | # DocProject is a documentation generator add-in 89 | DocProject/buildhelp/ 90 | DocProject/Help/*.HxT 91 | DocProject/Help/*.HxC 92 | DocProject/Help/*.hhc 93 | DocProject/Help/*.hhk 94 | DocProject/Help/*.hhp 95 | DocProject/Help/Html2 96 | DocProject/Help/html 97 | 98 | # Click-Once directory 99 | publish 100 | 101 | # Others 102 | [Bb]in 103 | [Oo]bj 104 | sql 105 | TestResults 106 | *.Cache 107 | ClientBin 108 | stylecop.* 109 | ~$* 110 | *.dbmdl 111 | Generated_Code #added for RIA/Silverlight projects 112 | 113 | # Backup & report files from converting an old project file to a newer 114 | # Visual Studio version. Backup files are not needed, because we have git ;-) 115 | _UpgradeReport_Files/ 116 | Backup*/ 117 | UpgradeLog*.XML 118 | 119 | 120 | 121 | ############ 122 | ## Windows 123 | ############ 124 | 125 | # Windows image file caches 126 | Thumbs.db 127 | 128 | # Folder config file 129 | Desktop.ini 130 | 131 | 132 | ############# 133 | ## Python 134 | ############# 135 | 136 | *.py[co] 137 | 138 | # Packages 139 | *.egg 140 | *.egg-info 141 | dist 142 | build 143 | eggs 144 | parts 145 | bin 146 | var 147 | sdist 148 | develop-eggs 149 | .installed.cfg 150 | 151 | # Installer logs 152 | pip-log.txt 153 | 154 | # Unit test / coverage reports 155 | .coverage 156 | .tox 157 | 158 | #Translations 159 | *.mo 160 | 161 | #Mr Developer 162 | .mr.developer.cfg 163 | 164 | # Mac crap 165 | .DS_Store 166 | -------------------------------------------------------------------------------- /cryptpe.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cryptpe", "cryptpe\cryptpe.vcxproj", "{7FF57FC9-7BE1-4730-B9DA-BEBC5156DA33}" 5 | ProjectSection(ProjectDependencies) = postProject 6 | {8EFA16CF-2CD4-4BEF-ABD4-2F7F234CD91D} = {8EFA16CF-2CD4-4BEF-ABD4-2F7F234CD91D} 7 | EndProjectSection 8 | EndProject 9 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testbin", "testbin\testbin.vcxproj", "{B4192D03-4E38-4F45-B115-EAC8C9A98620}" 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mkbintable", "mkbintable\mkbintable.vcxproj", "{8EFA16CF-2CD4-4BEF-ABD4-2F7F234CD91D}" 12 | ProjectSection(ProjectDependencies) = postProject 13 | {B4192D03-4E38-4F45-B115-EAC8C9A98620} = {B4192D03-4E38-4F45-B115-EAC8C9A98620} 14 | EndProjectSection 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Win32 = Debug|Win32 19 | Debug|x64 = Debug|x64 20 | Release|Win32 = Release|Win32 21 | Release|x64 = Release|x64 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {7FF57FC9-7BE1-4730-B9DA-BEBC5156DA33}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {7FF57FC9-7BE1-4730-B9DA-BEBC5156DA33}.Debug|Win32.Build.0 = Debug|Win32 26 | {7FF57FC9-7BE1-4730-B9DA-BEBC5156DA33}.Debug|x64.ActiveCfg = Debug|x64 27 | {7FF57FC9-7BE1-4730-B9DA-BEBC5156DA33}.Debug|x64.Build.0 = Debug|x64 28 | {7FF57FC9-7BE1-4730-B9DA-BEBC5156DA33}.Release|Win32.ActiveCfg = Release|Win32 29 | {7FF57FC9-7BE1-4730-B9DA-BEBC5156DA33}.Release|Win32.Build.0 = Release|Win32 30 | {7FF57FC9-7BE1-4730-B9DA-BEBC5156DA33}.Release|x64.ActiveCfg = Release|x64 31 | {7FF57FC9-7BE1-4730-B9DA-BEBC5156DA33}.Release|x64.Build.0 = Release|x64 32 | {B4192D03-4E38-4F45-B115-EAC8C9A98620}.Debug|Win32.ActiveCfg = Release|Win32 33 | {B4192D03-4E38-4F45-B115-EAC8C9A98620}.Debug|Win32.Build.0 = Release|Win32 34 | {B4192D03-4E38-4F45-B115-EAC8C9A98620}.Debug|x64.ActiveCfg = Release|x64 35 | {B4192D03-4E38-4F45-B115-EAC8C9A98620}.Debug|x64.Build.0 = Release|x64 36 | {B4192D03-4E38-4F45-B115-EAC8C9A98620}.Release|Win32.ActiveCfg = Release|Win32 37 | {B4192D03-4E38-4F45-B115-EAC8C9A98620}.Release|Win32.Build.0 = Release|Win32 38 | {B4192D03-4E38-4F45-B115-EAC8C9A98620}.Release|x64.ActiveCfg = Release|x64 39 | {B4192D03-4E38-4F45-B115-EAC8C9A98620}.Release|x64.Build.0 = Release|x64 40 | {8EFA16CF-2CD4-4BEF-ABD4-2F7F234CD91D}.Debug|Win32.ActiveCfg = Debug|Win32 41 | {8EFA16CF-2CD4-4BEF-ABD4-2F7F234CD91D}.Debug|Win32.Build.0 = Debug|Win32 42 | {8EFA16CF-2CD4-4BEF-ABD4-2F7F234CD91D}.Debug|x64.ActiveCfg = Debug|x64 43 | {8EFA16CF-2CD4-4BEF-ABD4-2F7F234CD91D}.Debug|x64.Build.0 = Debug|x64 44 | {8EFA16CF-2CD4-4BEF-ABD4-2F7F234CD91D}.Release|Win32.ActiveCfg = Release|Win32 45 | {8EFA16CF-2CD4-4BEF-ABD4-2F7F234CD91D}.Release|Win32.Build.0 = Release|Win32 46 | {8EFA16CF-2CD4-4BEF-ABD4-2F7F234CD91D}.Release|x64.ActiveCfg = Release|x64 47 | {8EFA16CF-2CD4-4BEF-ABD4-2F7F234CD91D}.Release|x64.Build.0 = Release|x64 48 | EndGlobalSection 49 | GlobalSection(SolutionProperties) = preSolution 50 | HideSolutionNode = FALSE 51 | EndGlobalSection 52 | EndGlobal 53 | -------------------------------------------------------------------------------- /cryptpe/MemoryModule.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Memory DLL loading code 3 | * Version 0.0.4 4 | * 5 | * Copyright (c) 2004-2015 by Joachim Bauch / mail@joachim-bauch.de 6 | * http://www.joachim-bauch.de 7 | * 8 | * The contents of this file are subject to the Mozilla Public License Version 9 | * 2.0 (the "License"); you may not use this file except in compliance with 10 | * the License. You may obtain a copy of the License at 11 | * http://www.mozilla.org/MPL/ 12 | * 13 | * Software distributed under the License is distributed on an "AS IS" basis, 14 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 15 | * for the specific language governing rights and limitations under the 16 | * License. 17 | * 18 | * The Original Code is MemoryModule.c 19 | * 20 | * The Initial Developer of the Original Code is Joachim Bauch. 21 | * 22 | * Portions created by Joachim Bauch are Copyright (C) 2004-2015 23 | * Joachim Bauch. All Rights Reserved. 24 | * 25 | * 26 | * THeller: Added binary search in MemoryGetProcAddress function 27 | * (#define USE_BINARY_SEARCH to enable it). This gives a very large 28 | * speedup for libraries that exports lots of functions. 29 | * 30 | * These portions are Copyright (C) 2013 Thomas Heller. 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #ifdef DEBUG_OUTPUT 38 | #include 39 | #endif 40 | 41 | #if _MSC_VER 42 | // Disable warning about data -> function pointer conversion 43 | #pragma warning(disable:4055) 44 | // C4244: conversion from 'uintptr_t' to 'DWORD', possible loss of data. 45 | #pragma warning(error: 4244) 46 | // C4267: conversion from 'size_t' to 'int', possible loss of data. 47 | #pragma warning(error: 4267) 48 | 49 | #define inline __inline 50 | #endif 51 | 52 | #ifndef IMAGE_SIZEOF_BASE_RELOCATION 53 | // Vista SDKs no longer define IMAGE_SIZEOF_BASE_RELOCATION!? 54 | #define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION)) 55 | #endif 56 | 57 | #ifdef _WIN64 58 | #define HOST_MACHINE IMAGE_FILE_MACHINE_AMD64 59 | #else 60 | #define HOST_MACHINE IMAGE_FILE_MACHINE_I386 61 | #endif 62 | 63 | #include "MemoryModule.h" 64 | 65 | struct ExportNameEntry { 66 | LPCSTR name; 67 | WORD idx; 68 | }; 69 | 70 | typedef BOOL(WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved); 71 | typedef int (WINAPI *ExeEntryProc)(void); 72 | 73 | #ifdef _WIN64 74 | typedef struct POINTER_LIST { 75 | struct POINTER_LIST *next; 76 | void *address; 77 | } POINTER_LIST; 78 | #endif 79 | 80 | typedef struct { 81 | PIMAGE_NT_HEADERS headers; 82 | unsigned char *codeBase; 83 | HCUSTOMMODULE *modules; 84 | int numModules; 85 | BOOL initialized; 86 | BOOL isDLL; 87 | BOOL isRelocated; 88 | CustomAllocFunc alloc; 89 | CustomFreeFunc free; 90 | CustomLoadLibraryFunc loadLibrary; 91 | CustomGetProcAddressFunc getProcAddress; 92 | CustomFreeLibraryFunc freeLibrary; 93 | struct ExportNameEntry *nameExportsTable; 94 | void *userdata; 95 | ExeEntryProc exeEntry; 96 | DWORD pageSize; 97 | #ifdef _WIN64 98 | POINTER_LIST *blockedMemory; 99 | #endif 100 | } MEMORYMODULE, *PMEMORYMODULE; 101 | 102 | typedef struct { 103 | LPVOID address; 104 | LPVOID alignedAddress; 105 | SIZE_T size; 106 | DWORD characteristics; 107 | BOOL last; 108 | } SECTIONFINALIZEDATA, *PSECTIONFINALIZEDATA; 109 | 110 | #define GET_HEADER_DICTIONARY(module, idx) &(module)->headers->OptionalHeader.DataDirectory[idx] 111 | 112 | static inline uintptr_t 113 | AlignValueDown(uintptr_t value, uintptr_t alignment) { 114 | return value & ~(alignment - 1); 115 | } 116 | 117 | static inline LPVOID 118 | AlignAddressDown(LPVOID address, uintptr_t alignment) { 119 | return (LPVOID)AlignValueDown((uintptr_t)address, alignment); 120 | } 121 | 122 | static inline size_t 123 | AlignValueUp(size_t value, size_t alignment) { 124 | return (value + alignment - 1) & ~(alignment - 1); 125 | } 126 | 127 | static inline void * 128 | OffsetPointer(void *data, ptrdiff_t offset) { 129 | return (void *)((uintptr_t)data + offset); 130 | } 131 | 132 | static inline void 133 | OutputLastError(const char *msg) { 134 | #ifndef DEBUG_OUTPUT 135 | UNREFERENCED_PARAMETER(msg); 136 | #else 137 | LPVOID tmp; 138 | char *tmpmsg; 139 | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 140 | NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&tmp, 0, NULL); 141 | tmpmsg = (char *)LocalAlloc(LPTR, strlen(msg) + strlen(tmp) + 3); 142 | sprintf(tmpmsg, "%s: %s", msg, tmp); 143 | OutputDebugString(tmpmsg); 144 | LocalFree(tmpmsg); 145 | LocalFree(tmp); 146 | #endif 147 | } 148 | 149 | #ifdef _WIN64 150 | static void 151 | FreePointerList(POINTER_LIST *head, CustomFreeFunc freeMemory, void *userdata) { 152 | POINTER_LIST *node = head; 153 | while(node) { 154 | POINTER_LIST *next; 155 | freeMemory(node->address, 0, MEM_RELEASE, userdata); 156 | next = node->next; 157 | free(node); 158 | node = next; 159 | } 160 | } 161 | #endif 162 | 163 | static BOOL 164 | CheckSize(size_t size, size_t expected) { 165 | if(size < expected) { 166 | SetLastError(ERROR_INVALID_DATA); 167 | return FALSE; 168 | } 169 | 170 | return TRUE; 171 | } 172 | 173 | static BOOL 174 | CopySections(const unsigned char *data, size_t size, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module) { 175 | int i, section_size; 176 | unsigned char *codeBase = module->codeBase; 177 | unsigned char *dest; 178 | PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers); 179 | for(i = 0; i < module->headers->FileHeader.NumberOfSections; i++, section++) { 180 | if(section->SizeOfRawData == 0) { 181 | // section doesn't contain data in the dll itself, but may define 182 | // uninitialized data 183 | section_size = old_headers->OptionalHeader.SectionAlignment; 184 | if(section_size > 0) { 185 | dest = (unsigned char *)module->alloc(codeBase + section->VirtualAddress, 186 | section_size, 187 | MEM_COMMIT, 188 | PAGE_READWRITE, 189 | module->userdata); 190 | if(dest == NULL) { 191 | return FALSE; 192 | } 193 | 194 | // Always use position from file to support alignments smaller 195 | // than page size (allocation above will align to page size). 196 | dest = codeBase + section->VirtualAddress; 197 | // NOTE: On 64bit systems we truncate to 32bit here but expand 198 | // again later when "PhysicalAddress" is used. 199 | section->Misc.PhysicalAddress = (DWORD)((uintptr_t)dest & 0xffffffff); 200 | memset(dest, 0, section_size); 201 | } 202 | 203 | // section is empty 204 | continue; 205 | } 206 | 207 | if(!CheckSize(size, section->PointerToRawData + section->SizeOfRawData)) { 208 | return FALSE; 209 | } 210 | 211 | // commit memory block and copy data from dll 212 | dest = (unsigned char *)module->alloc(codeBase + section->VirtualAddress, 213 | section->SizeOfRawData, 214 | MEM_COMMIT, 215 | PAGE_READWRITE, 216 | module->userdata); 217 | if(dest == NULL) { 218 | return FALSE; 219 | } 220 | 221 | // Always use position from file to support alignments smaller 222 | // than page size (allocation above will align to page size). 223 | dest = codeBase + section->VirtualAddress; 224 | memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData); 225 | // NOTE: On 64bit systems we truncate to 32bit here but expand 226 | // again later when "PhysicalAddress" is used. 227 | section->Misc.PhysicalAddress = (DWORD)((uintptr_t)dest & 0xffffffff); 228 | } 229 | 230 | return TRUE; 231 | } 232 | 233 | // Protection flags for memory pages (Executable, Readable, Writeable) 234 | static int ProtectionFlags[2][2][2] = { 235 | { 236 | // not executable 237 | {PAGE_NOACCESS, PAGE_WRITECOPY}, 238 | {PAGE_READONLY, PAGE_READWRITE}, 239 | }, { 240 | // executable 241 | {PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY}, 242 | {PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE}, 243 | }, 244 | }; 245 | 246 | static SIZE_T 247 | GetRealSectionSize(PMEMORYMODULE module, PIMAGE_SECTION_HEADER section) { 248 | DWORD size = section->SizeOfRawData; 249 | if(size == 0) { 250 | if(section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) { 251 | size = module->headers->OptionalHeader.SizeOfInitializedData; 252 | } else if(section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) { 253 | size = module->headers->OptionalHeader.SizeOfUninitializedData; 254 | } 255 | } 256 | return (SIZE_T)size; 257 | } 258 | 259 | static BOOL 260 | FinalizeSection(PMEMORYMODULE module, PSECTIONFINALIZEDATA sectionData) { 261 | DWORD protect, oldProtect; 262 | BOOL executable; 263 | BOOL readable; 264 | BOOL writeable; 265 | 266 | if(sectionData->size == 0) { 267 | return TRUE; 268 | } 269 | 270 | if(sectionData->characteristics & IMAGE_SCN_MEM_DISCARDABLE) { 271 | // section is not needed any more and can safely be freed 272 | if(sectionData->address == sectionData->alignedAddress && 273 | (sectionData->last || 274 | module->headers->OptionalHeader.SectionAlignment == module->pageSize || 275 | (sectionData->size % module->pageSize) == 0) 276 | ) { 277 | // Only allowed to decommit whole pages 278 | module->free(sectionData->address, sectionData->size, MEM_DECOMMIT, module->userdata); 279 | } 280 | return TRUE; 281 | } 282 | 283 | // determine protection flags based on characteristics 284 | executable = (sectionData->characteristics & IMAGE_SCN_MEM_EXECUTE) != 0; 285 | readable = (sectionData->characteristics & IMAGE_SCN_MEM_READ) != 0; 286 | writeable = (sectionData->characteristics & IMAGE_SCN_MEM_WRITE) != 0; 287 | protect = ProtectionFlags[executable][readable][writeable]; 288 | if(sectionData->characteristics & IMAGE_SCN_MEM_NOT_CACHED) { 289 | protect |= PAGE_NOCACHE; 290 | } 291 | 292 | // change memory access flags 293 | if(VirtualProtect(sectionData->address, sectionData->size, protect, &oldProtect) == 0) { 294 | OutputLastError("Error protecting memory page"); 295 | return FALSE; 296 | } 297 | 298 | return TRUE; 299 | } 300 | 301 | static BOOL 302 | FinalizeSections(PMEMORYMODULE module) { 303 | int i; 304 | PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers); 305 | #ifdef _WIN64 306 | // "PhysicalAddress" might have been truncated to 32bit above, expand to 307 | // 64bits again. 308 | uintptr_t imageOffset = ((uintptr_t)module->headers->OptionalHeader.ImageBase & 0xffffffff00000000); 309 | #else 310 | static const uintptr_t imageOffset = 0; 311 | #endif 312 | SECTIONFINALIZEDATA sectionData; 313 | sectionData.address = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset); 314 | sectionData.alignedAddress = AlignAddressDown(sectionData.address, module->pageSize); 315 | sectionData.size = GetRealSectionSize(module, section); 316 | sectionData.characteristics = section->Characteristics; 317 | sectionData.last = FALSE; 318 | section++; 319 | 320 | // loop through all sections and change access flags 321 | for(i = 1; i < module->headers->FileHeader.NumberOfSections; i++, section++) { 322 | LPVOID sectionAddress = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset); 323 | LPVOID alignedAddress = AlignAddressDown(sectionAddress, module->pageSize); 324 | SIZE_T sectionSize = GetRealSectionSize(module, section); 325 | // Combine access flags of all sections that share a page 326 | // TODO(fancycode): We currently share flags of a trailing large section 327 | // with the page of a first small section. This should be optimized. 328 | if(sectionData.alignedAddress == alignedAddress || (uintptr_t)sectionData.address + sectionData.size > (uintptr_t) alignedAddress) { 329 | // Section shares page with previous 330 | if((section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0 || (sectionData.characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0) { 331 | sectionData.characteristics = (sectionData.characteristics | section->Characteristics) & ~IMAGE_SCN_MEM_DISCARDABLE; 332 | } else { 333 | sectionData.characteristics |= section->Characteristics; 334 | } 335 | sectionData.size = (((uintptr_t)sectionAddress) + ((uintptr_t)sectionSize)) - (uintptr_t)sectionData.address; 336 | continue; 337 | } 338 | 339 | if(!FinalizeSection(module, §ionData)) { 340 | return FALSE; 341 | } 342 | sectionData.address = sectionAddress; 343 | sectionData.alignedAddress = alignedAddress; 344 | sectionData.size = sectionSize; 345 | sectionData.characteristics = section->Characteristics; 346 | } 347 | sectionData.last = TRUE; 348 | if(!FinalizeSection(module, §ionData)) { 349 | return FALSE; 350 | } 351 | return TRUE; 352 | } 353 | 354 | static BOOL 355 | ExecuteTLS(PMEMORYMODULE module) { 356 | unsigned char *codeBase = module->codeBase; 357 | PIMAGE_TLS_DIRECTORY tls; 358 | PIMAGE_TLS_CALLBACK *callback; 359 | 360 | PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_TLS); 361 | if(directory->VirtualAddress == 0) { 362 | return TRUE; 363 | } 364 | 365 | tls = (PIMAGE_TLS_DIRECTORY)(codeBase + directory->VirtualAddress); 366 | callback = (PIMAGE_TLS_CALLBACK *)tls->AddressOfCallBacks; 367 | if(callback) { 368 | while(*callback) { 369 | (*callback)((LPVOID)codeBase, DLL_PROCESS_ATTACH, NULL); 370 | callback++; 371 | } 372 | } 373 | return TRUE; 374 | } 375 | 376 | static BOOL 377 | PerformBaseRelocation(PMEMORYMODULE module, ptrdiff_t delta) { 378 | unsigned char *codeBase = module->codeBase; 379 | PIMAGE_BASE_RELOCATION relocation; 380 | 381 | PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC); 382 | if(directory->Size == 0) { 383 | return (delta == 0); 384 | } 385 | 386 | relocation = (PIMAGE_BASE_RELOCATION)(codeBase + directory->VirtualAddress); 387 | for(; relocation->VirtualAddress > 0; ) { 388 | DWORD i; 389 | unsigned char *dest = codeBase + relocation->VirtualAddress; 390 | unsigned short *relInfo = (unsigned short *)OffsetPointer(relocation, IMAGE_SIZEOF_BASE_RELOCATION); 391 | for(i = 0; i < ((relocation->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++) { 392 | // the upper 4 bits define the type of relocation 393 | int type = *relInfo >> 12; 394 | // the lower 12 bits define the offset 395 | int offset = *relInfo & 0xfff; 396 | 397 | switch(type) { 398 | case IMAGE_REL_BASED_ABSOLUTE: 399 | // skip relocation 400 | break; 401 | 402 | case IMAGE_REL_BASED_HIGHLOW: 403 | // change complete 32 bit address 404 | { 405 | DWORD *patchAddrHL = (DWORD *)(dest + offset); 406 | *patchAddrHL += (DWORD)delta; 407 | } 408 | break; 409 | 410 | #ifdef _WIN64 411 | case IMAGE_REL_BASED_DIR64: 412 | { 413 | ULONGLONG *patchAddr64 = (ULONGLONG *)(dest + offset); 414 | *patchAddr64 += (ULONGLONG)delta; 415 | } 416 | break; 417 | #endif 418 | 419 | default: 420 | //printf("Unknown relocation: %d\n", type); 421 | break; 422 | } 423 | } 424 | 425 | // advance to next relocation block 426 | relocation = (PIMAGE_BASE_RELOCATION)OffsetPointer(relocation, relocation->SizeOfBlock); 427 | } 428 | return TRUE; 429 | } 430 | 431 | static BOOL 432 | BuildImportTable(PMEMORYMODULE module) { 433 | unsigned char *codeBase = module->codeBase; 434 | PIMAGE_IMPORT_DESCRIPTOR importDesc; 435 | BOOL result = TRUE; 436 | 437 | PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT); 438 | if(directory->Size == 0) { 439 | return TRUE; 440 | } 441 | 442 | importDesc = (PIMAGE_IMPORT_DESCRIPTOR)(codeBase + directory->VirtualAddress); 443 | for(; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++) { 444 | uintptr_t *thunkRef; 445 | FARPROC *funcRef; 446 | HCUSTOMMODULE *tmp; 447 | HCUSTOMMODULE handle = module->loadLibrary((LPCSTR)(codeBase + importDesc->Name), module->userdata); 448 | if(handle == NULL) { 449 | SetLastError(ERROR_MOD_NOT_FOUND); 450 | result = FALSE; 451 | break; 452 | } 453 | 454 | tmp = (HCUSTOMMODULE *)realloc(module->modules, (module->numModules + 1) * (sizeof(HCUSTOMMODULE))); 455 | if(tmp == NULL) { 456 | module->freeLibrary(handle, module->userdata); 457 | SetLastError(ERROR_OUTOFMEMORY); 458 | result = FALSE; 459 | break; 460 | } 461 | module->modules = tmp; 462 | 463 | module->modules[module->numModules++] = handle; 464 | if(importDesc->OriginalFirstThunk) { 465 | thunkRef = (uintptr_t *)(codeBase + importDesc->OriginalFirstThunk); 466 | funcRef = (FARPROC *)(codeBase + importDesc->FirstThunk); 467 | } else { 468 | // no hint table 469 | thunkRef = (uintptr_t *)(codeBase + importDesc->FirstThunk); 470 | funcRef = (FARPROC *)(codeBase + importDesc->FirstThunk); 471 | } 472 | for(; *thunkRef; thunkRef++, funcRef++) { 473 | if(IMAGE_SNAP_BY_ORDINAL(*thunkRef)) { 474 | *funcRef = module->getProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef), module->userdata); 475 | } else { 476 | PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)(codeBase + (*thunkRef)); 477 | *funcRef = module->getProcAddress(handle, (LPCSTR)&thunkData->Name, module->userdata); 478 | } 479 | if(*funcRef == 0) { 480 | result = FALSE; 481 | break; 482 | } 483 | } 484 | 485 | if(!result) { 486 | module->freeLibrary(handle, module->userdata); 487 | SetLastError(ERROR_PROC_NOT_FOUND); 488 | break; 489 | } 490 | } 491 | 492 | return result; 493 | } 494 | 495 | LPVOID MemoryDefaultAlloc(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect, void *userdata) { 496 | UNREFERENCED_PARAMETER(userdata); 497 | return VirtualAlloc(address, size, allocationType, protect); 498 | } 499 | 500 | BOOL MemoryDefaultFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType, void *userdata) { 501 | UNREFERENCED_PARAMETER(userdata); 502 | return VirtualFree(lpAddress, dwSize, dwFreeType); 503 | } 504 | 505 | HCUSTOMMODULE MemoryDefaultLoadLibrary(LPCSTR filename, void *userdata) { 506 | HMODULE result; 507 | UNREFERENCED_PARAMETER(userdata); 508 | result = LoadLibraryA(filename); 509 | if(result == NULL) { 510 | return NULL; 511 | } 512 | 513 | return (HCUSTOMMODULE)result; 514 | } 515 | 516 | FARPROC MemoryDefaultGetProcAddress(HCUSTOMMODULE module, LPCSTR name, void *userdata) { 517 | UNREFERENCED_PARAMETER(userdata); 518 | return (FARPROC)GetProcAddress((HMODULE)module, name); 519 | } 520 | 521 | void MemoryDefaultFreeLibrary(HCUSTOMMODULE module, void *userdata) { 522 | UNREFERENCED_PARAMETER(userdata); 523 | FreeLibrary((HMODULE)module); 524 | } 525 | 526 | HMEMORYMODULE MemoryLoadLibrary(const void *data, size_t size) { 527 | return MemoryLoadLibraryEx(data, size, MemoryDefaultAlloc, MemoryDefaultFree, MemoryDefaultLoadLibrary, MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, NULL); 528 | } 529 | 530 | HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, 531 | CustomAllocFunc allocMemory, 532 | CustomFreeFunc freeMemory, 533 | CustomLoadLibraryFunc loadLibrary, 534 | CustomGetProcAddressFunc getProcAddress, 535 | CustomFreeLibraryFunc freeLibrary, 536 | void *userdata) { 537 | PMEMORYMODULE result = NULL; 538 | PIMAGE_DOS_HEADER dos_header; 539 | PIMAGE_NT_HEADERS old_header; 540 | unsigned char *code, *headers; 541 | ptrdiff_t locationDelta; 542 | SYSTEM_INFO sysInfo; 543 | PIMAGE_SECTION_HEADER section; 544 | DWORD i; 545 | size_t optionalSectionSize; 546 | size_t lastSectionEnd = 0; 547 | size_t alignedImageSize; 548 | #ifdef _WIN64 549 | POINTER_LIST *blockedMemory = NULL; 550 | #endif 551 | 552 | if(!CheckSize(size, sizeof(IMAGE_DOS_HEADER))) { 553 | return NULL; 554 | } 555 | dos_header = (PIMAGE_DOS_HEADER)data; 556 | if(dos_header->e_magic != IMAGE_DOS_SIGNATURE) { 557 | SetLastError(ERROR_BAD_EXE_FORMAT); 558 | return NULL; 559 | } 560 | 561 | if(!CheckSize(size, dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS))) { 562 | return NULL; 563 | } 564 | old_header = (PIMAGE_NT_HEADERS) & ((const unsigned char *)(data))[dos_header->e_lfanew]; 565 | if(old_header->Signature != IMAGE_NT_SIGNATURE) { 566 | SetLastError(ERROR_BAD_EXE_FORMAT); 567 | return NULL; 568 | } 569 | 570 | if(old_header->FileHeader.Machine != HOST_MACHINE) { 571 | SetLastError(ERROR_BAD_EXE_FORMAT); 572 | return NULL; 573 | } 574 | 575 | if(old_header->OptionalHeader.SectionAlignment & 1) { 576 | // Only support section alignments that are a multiple of 2 577 | SetLastError(ERROR_BAD_EXE_FORMAT); 578 | return NULL; 579 | } 580 | 581 | section = IMAGE_FIRST_SECTION(old_header); 582 | optionalSectionSize = old_header->OptionalHeader.SectionAlignment; 583 | for(i = 0; i < old_header->FileHeader.NumberOfSections; i++, section++) { 584 | size_t endOfSection; 585 | if(section->SizeOfRawData == 0) { 586 | // Section without data in the DLL 587 | endOfSection = section->VirtualAddress + optionalSectionSize; 588 | } else { 589 | endOfSection = section->VirtualAddress + section->SizeOfRawData; 590 | } 591 | 592 | if(endOfSection > lastSectionEnd) { 593 | lastSectionEnd = endOfSection; 594 | } 595 | } 596 | 597 | GetNativeSystemInfo(&sysInfo); 598 | alignedImageSize = AlignValueUp(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize); 599 | if(alignedImageSize != AlignValueUp(lastSectionEnd, sysInfo.dwPageSize)) { 600 | SetLastError(ERROR_BAD_EXE_FORMAT); 601 | return NULL; 602 | } 603 | 604 | // reserve memory for image of library 605 | // XXX: is it correct to commit the complete memory region at once? 606 | // calling DllEntry raises an exception if we don't... 607 | code = (unsigned char *)allocMemory((LPVOID)(old_header->OptionalHeader.ImageBase), 608 | alignedImageSize, 609 | MEM_RESERVE | MEM_COMMIT, 610 | PAGE_READWRITE, 611 | userdata); 612 | 613 | if(code == NULL) { 614 | // try to allocate memory at arbitrary position 615 | code = (unsigned char *)allocMemory(NULL, 616 | alignedImageSize, 617 | MEM_RESERVE | MEM_COMMIT, 618 | PAGE_READWRITE, 619 | userdata); 620 | if(code == NULL) { 621 | SetLastError(ERROR_OUTOFMEMORY); 622 | return NULL; 623 | } 624 | } 625 | 626 | #ifdef _WIN64 627 | // Memory block may not span 4 GB boundaries. 628 | while((((uintptr_t)code) >> 32) < (((uintptr_t)(code + alignedImageSize)) >> 32)) { 629 | POINTER_LIST *node = (POINTER_LIST *)malloc(sizeof(POINTER_LIST)); 630 | if(!node) { 631 | freeMemory(code, 0, MEM_RELEASE, userdata); 632 | FreePointerList(blockedMemory, freeMemory, userdata); 633 | SetLastError(ERROR_OUTOFMEMORY); 634 | return NULL; 635 | } 636 | 637 | node->next = blockedMemory; 638 | node->address = code; 639 | blockedMemory = node; 640 | 641 | code = (unsigned char *)allocMemory(NULL, 642 | alignedImageSize, 643 | MEM_RESERVE | MEM_COMMIT, 644 | PAGE_READWRITE, 645 | userdata); 646 | if(code == NULL) { 647 | FreePointerList(blockedMemory, freeMemory, userdata); 648 | SetLastError(ERROR_OUTOFMEMORY); 649 | return NULL; 650 | } 651 | } 652 | #endif 653 | 654 | result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEMORYMODULE)); 655 | if(result == NULL) { 656 | freeMemory(code, 0, MEM_RELEASE, userdata); 657 | #ifdef _WIN64 658 | FreePointerList(blockedMemory, freeMemory, userdata); 659 | #endif 660 | SetLastError(ERROR_OUTOFMEMORY); 661 | return NULL; 662 | } 663 | 664 | result->codeBase = code; 665 | result->isDLL = (old_header->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0; 666 | result->alloc = allocMemory; 667 | result->free = freeMemory; 668 | result->loadLibrary = loadLibrary; 669 | result->getProcAddress = getProcAddress; 670 | result->freeLibrary = freeLibrary; 671 | result->userdata = userdata; 672 | result->pageSize = sysInfo.dwPageSize; 673 | #ifdef _WIN64 674 | result->blockedMemory = blockedMemory; 675 | #endif 676 | 677 | if(!CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) { 678 | goto error; 679 | } 680 | 681 | // commit memory for headers 682 | headers = (unsigned char *)allocMemory(code, 683 | old_header->OptionalHeader.SizeOfHeaders, 684 | MEM_COMMIT, 685 | PAGE_READWRITE, 686 | userdata); 687 | 688 | // copy PE header to code 689 | memcpy(headers, dos_header, old_header->OptionalHeader.SizeOfHeaders); 690 | result->headers = (PIMAGE_NT_HEADERS) & ((const unsigned char *)(headers))[dos_header->e_lfanew]; 691 | 692 | // update position 693 | result->headers->OptionalHeader.ImageBase = (uintptr_t)code; 694 | 695 | // copy sections from DLL file block to new memory location 696 | if(!CopySections((const unsigned char *)data, size, old_header, result)) { 697 | goto error; 698 | } 699 | 700 | // adjust base address of imported data 701 | locationDelta = (ptrdiff_t)(result->headers->OptionalHeader.ImageBase - old_header->OptionalHeader.ImageBase); 702 | if(locationDelta != 0) { 703 | result->isRelocated = PerformBaseRelocation(result, locationDelta); 704 | } else { 705 | result->isRelocated = TRUE; 706 | } 707 | 708 | // load required dlls and adjust function table of imports 709 | if(!BuildImportTable(result)) { 710 | goto error; 711 | } 712 | 713 | // mark memory pages depending on section headers and release 714 | // sections that are marked as "discardable" 715 | if(!FinalizeSections(result)) { 716 | goto error; 717 | } 718 | 719 | // TLS callbacks are executed BEFORE the main loading 720 | if(!ExecuteTLS(result)) { 721 | goto error; 722 | } 723 | 724 | // get entry point of loaded library 725 | if(result->headers->OptionalHeader.AddressOfEntryPoint != 0) { 726 | if(result->isDLL) { 727 | DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(code + result->headers->OptionalHeader.AddressOfEntryPoint); 728 | // notify library about attaching to process 729 | BOOL successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0); 730 | if(!successfull) { 731 | SetLastError(ERROR_DLL_INIT_FAILED); 732 | goto error; 733 | } 734 | result->initialized = TRUE; 735 | } else { 736 | result->exeEntry = (ExeEntryProc)(LPVOID)(code + result->headers->OptionalHeader.AddressOfEntryPoint); 737 | } 738 | } else { 739 | result->exeEntry = NULL; 740 | } 741 | 742 | return (HMEMORYMODULE)result; 743 | 744 | error: 745 | // cleanup 746 | MemoryFreeLibrary(result); 747 | return NULL; 748 | } 749 | 750 | static int _compare(const void *a, const void *b) { 751 | const struct ExportNameEntry *p1 = (const struct ExportNameEntry *)a; 752 | const struct ExportNameEntry *p2 = (const struct ExportNameEntry *)b; 753 | return strcmp(p1->name, p2->name); 754 | } 755 | 756 | static int _find(const void *a, const void *b) { 757 | LPCSTR *name = (LPCSTR *)a; 758 | const struct ExportNameEntry *p = (const struct ExportNameEntry *)b; 759 | return strcmp(*name, p->name); 760 | } 761 | 762 | FARPROC MemoryGetProcAddress(HMEMORYMODULE mod, LPCSTR name) { 763 | PMEMORYMODULE module = (PMEMORYMODULE)mod; 764 | unsigned char *codeBase = module->codeBase; 765 | DWORD idx = 0; 766 | PIMAGE_EXPORT_DIRECTORY exports; 767 | PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_EXPORT); 768 | if(directory->Size == 0) { 769 | // no export table found 770 | SetLastError(ERROR_PROC_NOT_FOUND); 771 | return NULL; 772 | } 773 | 774 | exports = (PIMAGE_EXPORT_DIRECTORY)(codeBase + directory->VirtualAddress); 775 | if(exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) { 776 | // DLL doesn't export anything 777 | SetLastError(ERROR_PROC_NOT_FOUND); 778 | return NULL; 779 | } 780 | 781 | if(HIWORD(name) == 0) { 782 | // load function by ordinal value 783 | if(LOWORD(name) < exports->Base) { 784 | SetLastError(ERROR_PROC_NOT_FOUND); 785 | return NULL; 786 | } 787 | 788 | idx = LOWORD(name) - exports->Base; 789 | } else if(!exports->NumberOfNames) { 790 | SetLastError(ERROR_PROC_NOT_FOUND); 791 | return NULL; 792 | } else { 793 | const struct ExportNameEntry *found; 794 | 795 | // Lazily build name table and sort it by names 796 | if(!module->nameExportsTable) { 797 | DWORD i; 798 | DWORD *nameRef = (DWORD *)(codeBase + exports->AddressOfNames); 799 | WORD *ordinal = (WORD *)(codeBase + exports->AddressOfNameOrdinals); 800 | struct ExportNameEntry *entry = (struct ExportNameEntry *)malloc(exports->NumberOfNames * sizeof(struct ExportNameEntry)); 801 | module->nameExportsTable = entry; 802 | if(!entry) { 803 | SetLastError(ERROR_OUTOFMEMORY); 804 | return NULL; 805 | } 806 | for(i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++, entry++) { 807 | entry->name = (const char *)(codeBase + (*nameRef)); 808 | entry->idx = *ordinal; 809 | } 810 | qsort(module->nameExportsTable, 811 | exports->NumberOfNames, 812 | sizeof(struct ExportNameEntry), _compare); 813 | } 814 | 815 | // search function name in list of exported names with binary search 816 | found = (const struct ExportNameEntry *)bsearch(&name, 817 | module->nameExportsTable, 818 | exports->NumberOfNames, 819 | sizeof(struct ExportNameEntry), _find); 820 | if(!found) { 821 | // exported symbol not found 822 | SetLastError(ERROR_PROC_NOT_FOUND); 823 | return NULL; 824 | } 825 | 826 | idx = found->idx; 827 | } 828 | 829 | if(idx > exports->NumberOfFunctions) { 830 | // name <-> ordinal number don't match 831 | SetLastError(ERROR_PROC_NOT_FOUND); 832 | return NULL; 833 | } 834 | 835 | // AddressOfFunctions contains the RVAs to the "real" functions 836 | return (FARPROC)(LPVOID)(codeBase + (*(DWORD *)(codeBase + exports->AddressOfFunctions + (idx * 4)))); 837 | } 838 | 839 | void MemoryFreeLibrary(HMEMORYMODULE mod) { 840 | PMEMORYMODULE module = (PMEMORYMODULE)mod; 841 | 842 | if(module == NULL) { 843 | return; 844 | } 845 | if(module->initialized) { 846 | // notify library about detaching from process 847 | DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(module->codeBase + module->headers->OptionalHeader.AddressOfEntryPoint); 848 | (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0); 849 | } 850 | 851 | free(module->nameExportsTable); 852 | if(module->modules != NULL) { 853 | // free previously opened libraries 854 | int i; 855 | for(i = 0; i < module->numModules; i++) { 856 | if(module->modules[i] != NULL) { 857 | module->freeLibrary(module->modules[i], module->userdata); 858 | } 859 | } 860 | 861 | free(module->modules); 862 | } 863 | 864 | if(module->codeBase != NULL) { 865 | // release memory of library 866 | module->free(module->codeBase, 0, MEM_RELEASE, module->userdata); 867 | } 868 | 869 | #ifdef _WIN64 870 | FreePointerList(module->blockedMemory, module->free, module->userdata); 871 | #endif 872 | HeapFree(GetProcessHeap(), 0, module); 873 | } 874 | 875 | int MemoryCallEntryPoint(HMEMORYMODULE mod) { 876 | PMEMORYMODULE module = (PMEMORYMODULE)mod; 877 | 878 | if(module == NULL || module->isDLL || module->exeEntry == NULL || !module->isRelocated) { 879 | return -1; 880 | } 881 | 882 | return module->exeEntry(); 883 | } 884 | 885 | #define DEFAULT_LANGUAGE MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) 886 | 887 | HMEMORYRSRC MemoryFindResource(HMEMORYMODULE module, LPCTSTR name, LPCTSTR type) { 888 | return MemoryFindResourceEx(module, name, type, DEFAULT_LANGUAGE); 889 | } 890 | 891 | static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry( 892 | void *root, 893 | PIMAGE_RESOURCE_DIRECTORY resources, 894 | LPCTSTR key) { 895 | PIMAGE_RESOURCE_DIRECTORY_ENTRY entries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resources + 1); 896 | PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL; 897 | DWORD start; 898 | DWORD end; 899 | DWORD middle; 900 | 901 | if(!IS_INTRESOURCE(key) && key[0] == TEXT('#')) { 902 | // special case: resource id given as string 903 | TCHAR *endpos = NULL; 904 | long int tmpkey = (WORD)_tcstol((TCHAR *)&key[1], &endpos, 10); 905 | if(tmpkey <= 0xffff && lstrlen(endpos) == 0) { 906 | key = MAKEINTRESOURCE(tmpkey); 907 | } 908 | } 909 | 910 | // entries are stored as ordered list of named entries, 911 | // followed by an ordered list of id entries - we can do 912 | // a binary search to find faster... 913 | if(IS_INTRESOURCE(key)) { 914 | WORD check = (WORD)(uintptr_t)key; 915 | start = resources->NumberOfNamedEntries; 916 | end = start + resources->NumberOfIdEntries; 917 | 918 | while(end > start) { 919 | WORD entryName; 920 | middle = (start + end) >> 1; 921 | entryName = (WORD)entries[middle].Name; 922 | if(check < entryName) { 923 | end = (end != middle ? middle : middle - 1); 924 | } else if(check > entryName) { 925 | start = (start != middle ? middle : middle + 1); 926 | } else { 927 | result = &entries[middle]; 928 | break; 929 | } 930 | } 931 | } else { 932 | LPCWSTR searchKey; 933 | size_t searchKeyLen = _tcslen(key); 934 | #if defined(UNICODE) 935 | searchKey = key; 936 | #else 937 | // Resource names are always stored using 16bit characters, need to 938 | // convert string we search for. 939 | #define MAX_LOCAL_KEY_LENGTH 2048 940 | // In most cases resource names are short, so optimize for that by 941 | // using a pre-allocated array. 942 | wchar_t _searchKeySpace[MAX_LOCAL_KEY_LENGTH + 1]; 943 | LPWSTR _searchKey; 944 | if(searchKeyLen > MAX_LOCAL_KEY_LENGTH) { 945 | size_t _searchKeySize = (searchKeyLen + 1) * sizeof(wchar_t); 946 | _searchKey = (LPWSTR)malloc(_searchKeySize); 947 | if(_searchKey == NULL) { 948 | SetLastError(ERROR_OUTOFMEMORY); 949 | return NULL; 950 | } 951 | } else { 952 | _searchKey = &_searchKeySpace[0]; 953 | } 954 | 955 | mbstowcs(_searchKey, key, searchKeyLen); 956 | _searchKey[searchKeyLen] = 0; 957 | searchKey = _searchKey; 958 | #endif 959 | start = 0; 960 | end = resources->NumberOfNamedEntries; 961 | while(end > start) { 962 | int cmp; 963 | PIMAGE_RESOURCE_DIR_STRING_U resourceString; 964 | middle = (start + end) >> 1; 965 | resourceString = (PIMAGE_RESOURCE_DIR_STRING_U)OffsetPointer(root, entries[middle].Name & 0x7FFFFFFF); 966 | cmp = _wcsnicmp(searchKey, resourceString->NameString, resourceString->Length); 967 | if(cmp == 0) { 968 | // Handle partial match 969 | if(searchKeyLen > resourceString->Length) { 970 | cmp = 1; 971 | } else if(searchKeyLen < resourceString->Length) { 972 | cmp = -1; 973 | } 974 | } 975 | if(cmp < 0) { 976 | end = (middle != end ? middle : middle - 1); 977 | } else if(cmp > 0) { 978 | start = (middle != start ? middle : middle + 1); 979 | } else { 980 | result = &entries[middle]; 981 | break; 982 | } 983 | } 984 | #if !defined(UNICODE) 985 | if(searchKeyLen > MAX_LOCAL_KEY_LENGTH) { 986 | free(_searchKey); 987 | } 988 | #undef MAX_LOCAL_KEY_LENGTH 989 | #endif 990 | } 991 | 992 | return result; 993 | } 994 | 995 | HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE module, LPCTSTR name, LPCTSTR type, WORD language) { 996 | unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase; 997 | PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_RESOURCE); 998 | PIMAGE_RESOURCE_DIRECTORY rootResources; 999 | PIMAGE_RESOURCE_DIRECTORY nameResources; 1000 | PIMAGE_RESOURCE_DIRECTORY typeResources; 1001 | PIMAGE_RESOURCE_DIRECTORY_ENTRY foundType; 1002 | PIMAGE_RESOURCE_DIRECTORY_ENTRY foundName; 1003 | PIMAGE_RESOURCE_DIRECTORY_ENTRY foundLanguage; 1004 | if(directory->Size == 0) { 1005 | // no resource table found 1006 | SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); 1007 | return NULL; 1008 | } 1009 | 1010 | if(language == DEFAULT_LANGUAGE) { 1011 | // use language from current thread 1012 | language = LANGIDFROMLCID(GetThreadLocale()); 1013 | } 1014 | 1015 | // resources are stored as three-level tree 1016 | // - first node is the type 1017 | // - second node is the name 1018 | // - third node is the language 1019 | rootResources = (PIMAGE_RESOURCE_DIRECTORY)(codeBase + directory->VirtualAddress); 1020 | foundType = _MemorySearchResourceEntry(rootResources, rootResources, type); 1021 | if(foundType == NULL) { 1022 | SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND); 1023 | return NULL; 1024 | } 1025 | 1026 | typeResources = (PIMAGE_RESOURCE_DIRECTORY)(codeBase + directory->VirtualAddress + (foundType->OffsetToData & 0x7fffffff)); 1027 | foundName = _MemorySearchResourceEntry(rootResources, typeResources, name); 1028 | if(foundName == NULL) { 1029 | SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); 1030 | return NULL; 1031 | } 1032 | 1033 | nameResources = (PIMAGE_RESOURCE_DIRECTORY)(codeBase + directory->VirtualAddress + (foundName->OffsetToData & 0x7fffffff)); 1034 | foundLanguage = _MemorySearchResourceEntry(rootResources, nameResources, (LPCTSTR)(uintptr_t)language); 1035 | if(foundLanguage == NULL) { 1036 | // requested language not found, use first available 1037 | if(nameResources->NumberOfIdEntries == 0) { 1038 | SetLastError(ERROR_RESOURCE_LANG_NOT_FOUND); 1039 | return NULL; 1040 | } 1041 | 1042 | foundLanguage = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(nameResources + 1); 1043 | } 1044 | 1045 | return (codeBase + directory->VirtualAddress + (foundLanguage->OffsetToData & 0x7fffffff)); 1046 | } 1047 | 1048 | DWORD MemorySizeofResource(HMEMORYMODULE module, HMEMORYRSRC resource) { 1049 | PIMAGE_RESOURCE_DATA_ENTRY entry; 1050 | UNREFERENCED_PARAMETER(module); 1051 | entry = (PIMAGE_RESOURCE_DATA_ENTRY)resource; 1052 | if(entry == NULL) { 1053 | return 0; 1054 | } 1055 | 1056 | return entry->Size; 1057 | } 1058 | 1059 | LPVOID MemoryLoadResource(HMEMORYMODULE module, HMEMORYRSRC resource) { 1060 | unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase; 1061 | PIMAGE_RESOURCE_DATA_ENTRY entry = (PIMAGE_RESOURCE_DATA_ENTRY)resource; 1062 | if(entry == NULL) { 1063 | return NULL; 1064 | } 1065 | 1066 | return codeBase + entry->OffsetToData; 1067 | } 1068 | 1069 | int 1070 | MemoryLoadString(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize) { 1071 | return MemoryLoadStringEx(module, id, buffer, maxsize, DEFAULT_LANGUAGE); 1072 | } 1073 | 1074 | int 1075 | MemoryLoadStringEx(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize, WORD language) { 1076 | HMEMORYRSRC resource; 1077 | PIMAGE_RESOURCE_DIR_STRING_U data; 1078 | DWORD size; 1079 | if(maxsize == 0) { 1080 | return 0; 1081 | } 1082 | 1083 | resource = MemoryFindResourceEx(module, MAKEINTRESOURCE((id >> 4) + 1), RT_STRING, language); 1084 | if(resource == NULL) { 1085 | buffer[0] = 0; 1086 | return 0; 1087 | } 1088 | 1089 | data = (PIMAGE_RESOURCE_DIR_STRING_U)MemoryLoadResource(module, resource); 1090 | id = id & 0x0f; 1091 | while(id--) { 1092 | data = (PIMAGE_RESOURCE_DIR_STRING_U)OffsetPointer(data, (data->Length + 1) * sizeof(WCHAR)); 1093 | } 1094 | if(data->Length == 0) { 1095 | SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); 1096 | buffer[0] = 0; 1097 | return 0; 1098 | } 1099 | 1100 | size = data->Length; 1101 | if(size >= (DWORD)maxsize) { 1102 | size = maxsize; 1103 | } else { 1104 | buffer[size] = 0; 1105 | } 1106 | #if defined(UNICODE) 1107 | wcsncpy(buffer, data->NameString, size); 1108 | #else 1109 | wcstombs(buffer, data->NameString, size); 1110 | #endif 1111 | return size; 1112 | } 1113 | 1114 | #ifdef TESTSUITE 1115 | #include 1116 | 1117 | #ifndef PRIxPTR 1118 | #ifdef _WIN64 1119 | #define PRIxPTR "I64x" 1120 | #else 1121 | #define PRIxPTR "x" 1122 | #endif 1123 | #endif 1124 | 1125 | static const uintptr_t AlignValueDownTests[][3] = { 1126 | {16, 16, 16}, 1127 | {17, 16, 16}, 1128 | {32, 16, 32}, 1129 | {33, 16, 32}, 1130 | #ifdef _WIN64 1131 | {0x12345678abcd1000, 0x1000, 0x12345678abcd1000}, 1132 | {0x12345678abcd101f, 0x1000, 0x12345678abcd1000}, 1133 | #endif 1134 | {0, 0, 0}, 1135 | }; 1136 | 1137 | static const uintptr_t AlignValueUpTests[][3] = { 1138 | {16, 16, 16}, 1139 | {17, 16, 32}, 1140 | {32, 16, 32}, 1141 | {33, 16, 48}, 1142 | #ifdef _WIN64 1143 | {0x12345678abcd1000, 0x1000, 0x12345678abcd1000}, 1144 | {0x12345678abcd101f, 0x1000, 0x12345678abcd2000}, 1145 | #endif 1146 | {0, 0, 0}, 1147 | }; 1148 | 1149 | BOOL MemoryModuleTestsuite() { 1150 | BOOL success = TRUE; 1151 | size_t idx; 1152 | for(idx = 0; AlignValueDownTests[idx][0]; ++idx) { 1153 | const uintptr_t *tests = AlignValueDownTests[idx]; 1154 | uintptr_t value = AlignValueDown(tests[0], tests[1]); 1155 | if(value != tests[2]) { 1156 | printf("AlignValueDown failed for 0x%" PRIxPTR "/0x%" PRIxPTR ": expected 0x%" PRIxPTR ", got 0x%" PRIxPTR "\n", 1157 | tests[0], tests[1], tests[2], value); 1158 | success = FALSE; 1159 | } 1160 | } 1161 | for(idx = 0; AlignValueDownTests[idx][0]; ++idx) { 1162 | const uintptr_t *tests = AlignValueUpTests[idx]; 1163 | uintptr_t value = AlignValueUp(tests[0], tests[1]); 1164 | if(value != tests[2]) { 1165 | printf("AlignValueUp failed for 0x%" PRIxPTR "/0x%" PRIxPTR ": expected 0x%" PRIxPTR ", got 0x%" PRIxPTR "\n", 1166 | tests[0], tests[1], tests[2], value); 1167 | success = FALSE; 1168 | } 1169 | } 1170 | if(success) { 1171 | printf("OK\n"); 1172 | } 1173 | return success; 1174 | } 1175 | #endif -------------------------------------------------------------------------------- /cryptpe/MemoryModule.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Memory DLL loading code 3 | * Version 0.0.4 4 | * 5 | * Copyright (c) 2004-2015 by Joachim Bauch / mail@joachim-bauch.de 6 | * http://www.joachim-bauch.de 7 | * 8 | * The contents of this file are subject to the Mozilla Public License Version 9 | * 2.0 (the "License"); you may not use this file except in compliance with 10 | * the License. You may obtain a copy of the License at 11 | * http://www.mozilla.org/MPL/ 12 | * 13 | * Software distributed under the License is distributed on an "AS IS" basis, 14 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 15 | * for the specific language governing rights and limitations under the 16 | * License. 17 | * 18 | * The Original Code is MemoryModule.h 19 | * 20 | * The Initial Developer of the Original Code is Joachim Bauch. 21 | * 22 | * Portions created by Joachim Bauch are Copyright (C) 2004-2015 23 | * Joachim Bauch. All Rights Reserved. 24 | * 25 | */ 26 | 27 | #ifndef __MEMORY_MODULE_HEADER 28 | #define __MEMORY_MODULE_HEADER 29 | 30 | #include 31 | 32 | typedef void *HMEMORYMODULE; 33 | 34 | typedef void *HMEMORYRSRC; 35 | 36 | typedef void *HCUSTOMMODULE; 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | typedef LPVOID(*CustomAllocFunc)(LPVOID, SIZE_T, DWORD, DWORD, void *); 43 | typedef BOOL(*CustomFreeFunc)(LPVOID, SIZE_T, DWORD, void *); 44 | typedef HCUSTOMMODULE(*CustomLoadLibraryFunc)(LPCSTR, void *); 45 | typedef FARPROC(*CustomGetProcAddressFunc)(HCUSTOMMODULE, LPCSTR, void *); 46 | typedef void (*CustomFreeLibraryFunc)(HCUSTOMMODULE, void *); 47 | 48 | /** 49 | * Load EXE/DLL from memory location with the given size. 50 | * 51 | * All dependencies are resolved using default LoadLibrary/GetProcAddress 52 | * calls through the Windows API. 53 | */ 54 | HMEMORYMODULE MemoryLoadLibrary(const void *, size_t); 55 | 56 | /** 57 | * Load EXE/DLL from memory location with the given size using custom dependency 58 | * resolvers. 59 | * 60 | * Dependencies will be resolved using passed callback methods. 61 | */ 62 | HMEMORYMODULE MemoryLoadLibraryEx(const void *, size_t, 63 | CustomAllocFunc, 64 | CustomFreeFunc, 65 | CustomLoadLibraryFunc, 66 | CustomGetProcAddressFunc, 67 | CustomFreeLibraryFunc, 68 | void *); 69 | 70 | /** 71 | * Get address of exported method. Supports loading both by name and by 72 | * ordinal value. 73 | */ 74 | FARPROC MemoryGetProcAddress(HMEMORYMODULE, LPCSTR); 75 | 76 | /** 77 | * Free previously loaded EXE/DLL. 78 | */ 79 | void MemoryFreeLibrary(HMEMORYMODULE); 80 | 81 | /** 82 | * Execute entry point (EXE only). The entry point can only be executed 83 | * if the EXE has been loaded to the correct base address or it could 84 | * be relocated (i.e. relocation information have not been stripped by 85 | * the linker). 86 | * 87 | * Important: calling this function will not return, i.e. once the loaded 88 | * EXE finished running, the process will terminate. 89 | * 90 | * Returns a negative value if the entry point could not be executed. 91 | */ 92 | int MemoryCallEntryPoint(HMEMORYMODULE); 93 | 94 | /** 95 | * Find the location of a resource with the specified type and name. 96 | */ 97 | HMEMORYRSRC MemoryFindResource(HMEMORYMODULE, LPCTSTR, LPCTSTR); 98 | 99 | /** 100 | * Find the location of a resource with the specified type, name and language. 101 | */ 102 | HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE, LPCTSTR, LPCTSTR, WORD); 103 | 104 | /** 105 | * Get the size of the resource in bytes. 106 | */ 107 | DWORD MemorySizeofResource(HMEMORYMODULE, HMEMORYRSRC); 108 | 109 | /** 110 | * Get a pointer to the contents of the resource. 111 | */ 112 | LPVOID MemoryLoadResource(HMEMORYMODULE, HMEMORYRSRC); 113 | 114 | /** 115 | * Load a string resource. 116 | */ 117 | int MemoryLoadString(HMEMORYMODULE, UINT, LPTSTR, int); 118 | 119 | /** 120 | * Load a string resource with a given language. 121 | */ 122 | int MemoryLoadStringEx(HMEMORYMODULE, UINT, LPTSTR, int, WORD); 123 | 124 | /** 125 | * Default implementation of CustomAllocFunc that calls VirtualAlloc 126 | * internally to allocate memory for a library 127 | * 128 | * This is the default as used by MemoryLoadLibrary. 129 | */ 130 | LPVOID MemoryDefaultAlloc(LPVOID, SIZE_T, DWORD, DWORD, void *); 131 | 132 | /** 133 | * Default implementation of CustomFreeFunc that calls VirtualFree 134 | * internally to free the memory used by a library 135 | * 136 | * This is the default as used by MemoryLoadLibrary. 137 | */ 138 | BOOL MemoryDefaultFree(LPVOID, SIZE_T, DWORD, void *); 139 | 140 | /** 141 | * Default implementation of CustomLoadLibraryFunc that calls LoadLibraryA 142 | * internally to load an additional libary. 143 | * 144 | * This is the default as used by MemoryLoadLibrary. 145 | */ 146 | HCUSTOMMODULE MemoryDefaultLoadLibrary(LPCSTR, void *); 147 | 148 | /** 149 | * Default implementation of CustomGetProcAddressFunc that calls GetProcAddress 150 | * internally to get the address of an exported function. 151 | * 152 | * This is the default as used by MemoryLoadLibrary. 153 | */ 154 | FARPROC MemoryDefaultGetProcAddress(HCUSTOMMODULE, LPCSTR, void *); 155 | 156 | /** 157 | * Default implementation of CustomFreeLibraryFunc that calls FreeLibrary 158 | * internally to release an additional libary. 159 | * 160 | * This is the default as used by MemoryLoadLibrary. 161 | */ 162 | void MemoryDefaultFreeLibrary(HCUSTOMMODULE, void *); 163 | 164 | #ifdef __cplusplus 165 | } 166 | #endif 167 | 168 | #endif // __MEMORY_MODULE_HEADER -------------------------------------------------------------------------------- /cryptpe/cryptpe.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | Document 37 | 38 | 39 | 40 | {7FF57FC9-7BE1-4730-B9DA-BEBC5156DA33} 41 | Win32Proj 42 | cryptpe 43 | 44 | 45 | 46 | Application 47 | true 48 | Unicode 49 | 50 | 51 | Application 52 | true 53 | Unicode 54 | 55 | 56 | Application 57 | false 58 | true 59 | Unicode 60 | 61 | 62 | Application 63 | false 64 | true 65 | Unicode 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | true 86 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 87 | $(Platform)\$(Configuration)\ 88 | 89 | 90 | true 91 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 92 | $(Platform)\$(Configuration)\ 93 | 94 | 95 | false 96 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 97 | $(Platform)\$(Configuration)\ 98 | 99 | 100 | false 101 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 102 | $(Platform)\$(Configuration)\ 103 | 104 | 105 | 106 | 107 | 108 | Level3 109 | Disabled 110 | WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 111 | MultiThreadedDebug 112 | 113 | 114 | Console 115 | true 116 | 117 | 118 | 119 | 120 | 121 | 122 | Level3 123 | Disabled 124 | WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 125 | MultiThreadedDebug 126 | 127 | 128 | Console 129 | true 130 | 131 | 132 | 133 | 134 | Level3 135 | 136 | 137 | MaxSpeed 138 | true 139 | true 140 | WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 141 | 142 | 143 | Console 144 | false 145 | true 146 | true 147 | false 148 | 149 | 150 | 151 | 152 | Level3 153 | 154 | 155 | MaxSpeed 156 | true 157 | true 158 | WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 159 | 160 | 161 | Console 162 | false 163 | true 164 | true 165 | false 166 | 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /cryptpe/cryptpe.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {6b4e50b1-4296-42a3-9dbf-8777698226ca} 18 | 19 | 20 | {678a3b0f-488e-4b52-9ef9-6050da89a8ee} 21 | 22 | 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files\shared 32 | 33 | 34 | Source Files 35 | 36 | 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files\shared 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | 55 | 56 | Source Files 57 | 58 | 59 | -------------------------------------------------------------------------------- /cryptpe/debfuq.asm: -------------------------------------------------------------------------------- 1 | ; cryptpe -- Encryption tool for PE binaries 2 | ; (C) 2012-2016 Martin Wolters 3 | ; 4 | ; This program is free software. It comes without any warranty, to 5 | ; the extent permitted by applicable law. You can redistribute it 6 | ; and/or modify it under the terms of the Do What The Fuck You Want 7 | ; To Public License, Version 2, as published by Sam Hocevar. See 8 | ; http://sam.zoy.org/wtfpl/COPYING for more details. 9 | ; 10 | 11 | IFDEF RAX ; Nicer check for x64? 12 | 13 | .code 14 | detrlvl PROC ; Code to hide the debugger detector 15 | mov rax, _label 16 | db 0ebh ; EB FF JMP -1 The Disassembler should lose sync here. 17 | jmp rax ; FF E0 Note the FF coming from the previous instruction. 18 | db 8dh, 0ffh 19 | 20 | _label: ; Debugger detector proper, part I 21 | mov rax, gs:[60h] 22 | mov rax, [rax + 0bch] ; PEB, offset 0xbc 23 | 24 | ; FLG_HEAP_ENABLE_TAIL_CHECK (0x10) 25 | ; FLG_HEAP_ENABLE_FREE_CHECK (0x20) 26 | ; FLG_HEAP_VALIDATE_PARAMETERS (0x40) 27 | ; ------ 28 | and rax, 70h 29 | 30 | mov rbx, _label2 ; Same as above, rbx this time, because 31 | db 0ebh ; we use eax to test for the debugger. 32 | jmp rbx 33 | db 8dh, 0ffh 34 | 35 | _label2: ; Debugger detector, part II 36 | cmp rax, 70h ; Actual check. 37 | 38 | je _xor ; If there is a debugger present, skip 39 | mov rbx, 42h ; Set return value to known state 40 | 41 | _xor: 42 | xor rbx, 42h ; Manipulate the return value, so that a 43 | ; random initial state gives a bad result. 44 | mov rax, rbx 45 | ret 46 | detrlvl ENDP 47 | 48 | ELSE 49 | 50 | .386 ; Win32 variant. Pretty much the same as above. 51 | .model flat, c 52 | .code 53 | assume fs:nothing 54 | 55 | detrlvl PROC 56 | mov eax, _label 57 | db 0ebh 58 | jmp eax 59 | db 8dh, 0ffh 60 | 61 | _label: 62 | mov eax, fs:[30h] 63 | mov eax, [eax+68h] 64 | 65 | mov ebx, _label2 66 | db 0ebh 67 | jmp ebx 68 | db 8dh, 0ffh 69 | 70 | _label2: 71 | and eax, 70h 72 | cmp eax, 70h 73 | je _xor 74 | mov ebx, 42h 75 | 76 | _xor: 77 | xor ebx, 42h 78 | mov eax, ebx 79 | retn 80 | detrlvl ENDP 81 | 82 | ENDIF 83 | 84 | end -------------------------------------------------------------------------------- /cryptpe/huffman_dec.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cryptpe -- Encryption tool for PE binaries 3 | * (C) 2012-2016 Martin Wolters 4 | * 5 | * This program is free software. It comes without any warranty, to 6 | * the extent permitted by applicable law. You can redistribute it 7 | * and/or modify it under the terms of the Do What The Fuck You Want 8 | * To Public License, Version 2, as published by Sam Hocevar. See 9 | * http://sam.zoy.org/wtfpl/COPYING for more details. 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | #include "..\shared\huffman.h" 16 | 17 | static uint8_t get_bits(uint8_t *in, size_t *offs, size_t n) { 18 | size_t byteoffs = (*offs) / 8; 19 | size_t bitoffs = (*offs) & 7; 20 | 21 | *offs += n; 22 | if(n == 1) 23 | return (in[byteoffs] >> (7 - bitoffs)) & 1; 24 | else 25 | return (in[byteoffs] << bitoffs) ^ (in[byteoffs + 1] >> (8 - bitoffs)); 26 | } 27 | 28 | static hfm_node_t *reconstruct_node(uint8_t *in, size_t *offs) { 29 | hfm_node_t *out; 30 | uint8_t bit = get_bits(in, offs, 1); 31 | 32 | if((out = malloc(sizeof(hfm_node_t))) == NULL) 33 | return NULL; 34 | 35 | if(bit == 0) { 36 | out->left = out->right = NULL; 37 | out->c = get_bits(in, offs, 8); 38 | return out; 39 | } else { 40 | out->left = reconstruct_node(in, offs); 41 | out->right = reconstruct_node(in, offs); 42 | return out; 43 | } 44 | return out; 45 | } 46 | 47 | hfm_node_t *reconstruct_tree(uint8_t *in) { 48 | size_t start = 0; 49 | return reconstruct_node(in, &start); 50 | } 51 | 52 | uint8_t *decode(uint8_t *in, hfm_node_t *root, size_t len) { 53 | size_t nchar, pos; 54 | hfm_node_t *node; 55 | uint8_t *out; 56 | 57 | if((out = malloc(len)) == NULL) 58 | return NULL; 59 | 60 | nchar = pos = 0; 61 | node = root; 62 | do { 63 | if(!(node->left)) { 64 | out[nchar++] = node->c; 65 | node = root; 66 | } else { 67 | if((in[pos / 8] >> (7 - (pos & 7))) & 1) { 68 | node = node->right; 69 | } else { 70 | node = node->left; 71 | } 72 | pos++; 73 | } 74 | } while(nchar < len); 75 | 76 | return out; 77 | } 78 | 79 | void free_tree(hfm_node_t *node) { 80 | if(node->left) 81 | free_tree(node->left); 82 | if(node->right) 83 | free_tree(node->right); 84 | free(node); 85 | } -------------------------------------------------------------------------------- /cryptpe/huffman_dec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cryptpe -- Encryption tool for PE binaries 3 | * (C) 2012-2016 Martin Wolters 4 | * 5 | * This program is free software. It comes without any warranty, to 6 | * the extent permitted by applicable law. You can redistribute it 7 | * and/or modify it under the terms of the Do What The Fuck You Want 8 | * To Public License, Version 2, as published by Sam Hocevar. See 9 | * http://sam.zoy.org/wtfpl/COPYING for more details. 10 | */ 11 | 12 | #include "..\shared\huffman.h" 13 | 14 | #ifndef HUFFMAN_DEC_H_ 15 | #define HUFFMAN_DEC_H_ 16 | 17 | hfm_node_t *reconstruct_tree(uint8_t *in); 18 | uint8_t *decode(uint8_t *in, hfm_node_t *root, size_t len); 19 | void free_tree(hfm_node_t *node); 20 | 21 | #endif -------------------------------------------------------------------------------- /cryptpe/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cryptpe -- Encryption tool for PE binaries 3 | * (C) 2012-2016 Martin Wolters 4 | * 5 | * This program is free software. It comes without any warranty, to 6 | * the extent permitted by applicable law. You can redistribute it 7 | * and/or modify it under the terms of the Do What The Fuck You Want 8 | * To Public License, Version 2, as published by Sam Hocevar. See 9 | * http://sam.zoy.org/wtfpl/COPYING for more details. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "bintable.h" 17 | #include "rlevel.h" 18 | #include "huffman_dec.h" 19 | 20 | #include "MemoryModule.h" 21 | 22 | #include "..\shared\salsa20.h" 23 | 24 | typedef int (*MainProc_t)(int, char**); 25 | 26 | int callmain(const uint8_t *binary, const size_t bin_size, int argc, char **argv) { 27 | HMEMORYMODULE Module; 28 | MainProc_t MainProc; 29 | int MainRet = EXIT_FAILURE; 30 | 31 | if((Module = MemoryLoadLibrary(binary, bin_size)) == NULL) { 32 | fprintf(stderr, "MemoryLoadLibrary() failed.\n"); 33 | return EXIT_FAILURE; 34 | } 35 | 36 | if((MainProc = (MainProc_t)MemoryGetProcAddress(Module, "main")) == NULL) { 37 | fprintf(stderr, "MemoryGetProcAddress() couldn't fine main().\n"); 38 | goto fail; 39 | } 40 | 41 | MainRet = MainProc(argc, argv); 42 | 43 | fail: 44 | MemoryFreeLibrary(Module); 45 | return MainRet; 46 | } 47 | 48 | int main(int argc, char **argv) { 49 | salsa20_ctx_t salsa20_ctx; 50 | uint8_t *salsa20_buf, *decoded, rlevel = detrlvl(); 51 | int i; 52 | hfm_node_t *root; 53 | int retval; 54 | 55 | salsa20_ctx = salsa20_init(key, nonce, SALSA20_KEY_SIZE); 56 | 57 | for(i = 0; i < sizeof(tree); i++) { 58 | if(!(i % SALSA20_BLOCK_SIZE)) 59 | salsa20_buf = salsa20_gen_block(&salsa20_ctx); 60 | tree[i] ^= salsa20_buf[i % SALSA20_BLOCK_SIZE] ^ rlevel; 61 | } 62 | root = reconstruct_tree(tree); 63 | 64 | for(i = 0; i < sizeof(binary); i++) { 65 | if(!(i % SALSA20_BLOCK_SIZE)) 66 | salsa20_buf = salsa20_gen_block(&salsa20_ctx); 67 | binary[i] ^= salsa20_buf[i % SALSA20_BLOCK_SIZE]; 68 | } 69 | 70 | decoded = decode(binary, root, file_size); 71 | free_tree(root); 72 | 73 | for(i = 0; i < sizeof(binary); i++) 74 | if(2 * i + rlevel) decoded[1] ^= rlevel; 75 | 76 | retval = callmain(decoded, file_size, argc, argv); 77 | 78 | free(decoded); 79 | return retval; 80 | } -------------------------------------------------------------------------------- /cryptpe/rlevel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cryptpe -- Encryption tool for PE binaries 3 | * (C) 2012-2016 Martin Wolters 4 | * 5 | * This program is free software. It comes without any warranty, to 6 | * the extent permitted by applicable law. You can redistribute it 7 | * and/or modify it under the terms of the Do What The Fuck You Want 8 | * To Public License, Version 2, as published by Sam Hocevar. See 9 | * http://sam.zoy.org/wtfpl/COPYING for more details. 10 | */ 11 | 12 | #ifndef RLEVEL_H_ 13 | #define RLEVEL_H_ 14 | 15 | int detrlvl(void); 16 | 17 | #endif -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. -------------------------------------------------------------------------------- /mkbintable/huffman_enc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cryptpe -- Encryption tool for PE binaries 3 | * (C) 2012-2016 Martin Wolters 4 | * 5 | * This program is free software. It comes without any warranty, to 6 | * the extent permitted by applicable law. You can redistribute it 7 | * and/or modify it under the terms of the Do What The Fuck You Want 8 | * To Public License, Version 2, as published by Sam Hocevar. See 9 | * http://sam.zoy.org/wtfpl/COPYING for more details. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "huffman_enc.h" 17 | 18 | static hfm_node_t *makenode(int weight, uint8_t c, hfm_node_t *left, hfm_node_t *right, hfm_node_t *parent) { 19 | hfm_node_t *out = malloc(sizeof(hfm_node_t)); 20 | if(!out) 21 | return NULL; 22 | 23 | out->weight = weight; 24 | out->c = c; 25 | out->left = left; 26 | out->right = right; 27 | out->parent = parent; 28 | 29 | return out; 30 | } 31 | 32 | static void findlowest(hfm_node_t **tree, size_t size, int *node1, int *node2) { 33 | uint32_t idx1, idx2, i, buf; 34 | 35 | *node1 = *node2 = INT_MAX; 36 | 37 | for(i = 0; (i < size) && (tree[i]->parent != NULL); i++); idx1 = i; 38 | if(i >= size) 39 | return; 40 | 41 | for(++i; (i < size) && (tree[i]->parent != NULL); i++); idx2 = i; 42 | if(i >= size) 43 | return; 44 | 45 | if(tree[idx1]->weight > tree[idx2]->weight) { 46 | buf = idx1; 47 | idx1 = idx2; 48 | idx2 = buf; 49 | } 50 | 51 | for(i++; i < size; i++) { 52 | if(!tree[i]->parent) { 53 | if(tree[i]->weight <= tree[idx1]->weight) { 54 | idx2 = idx1; 55 | idx1 = i; 56 | } else if(tree[i]->weight <= tree[idx2]->weight) 57 | idx2 = i; 58 | } 59 | } 60 | 61 | *node1 = idx1; 62 | *node2 = idx2; 63 | } 64 | 65 | hfm_node_t *maketree(uint8_t *in, size_t len) { 66 | uint32_t freq[256], i, j = 0; 67 | int low1, low2; 68 | hfm_node_t *tree[511]; 69 | 70 | memset(freq, 0, 256 * sizeof(uint32_t)); 71 | 72 | for(i = 0; i < len; i++) 73 | freq[in[i]]++; 74 | 75 | for(i = 0; i < 256; i++) 76 | if(freq[i]) 77 | tree[j++] = makenode(freq[i], i, NULL, NULL, NULL); 78 | 79 | findlowest(tree, j, &low1, &low2); 80 | do { 81 | tree[j] = makenode(tree[low1]->weight + tree[low2]->weight, '\0', tree[low1], tree[low2], NULL); 82 | tree[low1]->parent = tree[j]; 83 | tree[low2]->parent = tree[j]; 84 | 85 | findlowest(tree, ++j, &low1, &low2); 86 | } while(low1 != low2); 87 | 88 | return tree[j - 1]; 89 | } 90 | 91 | static void add_bits(uint8_t *c, size_t nbits, uint8_t *str, size_t *size) { 92 | int outpos, outoffs, bit; 93 | int inpos, inoffs = 0; 94 | 95 | do { 96 | outpos = (*size) / 8; 97 | outoffs = (*size) % 8; 98 | inpos = inoffs / 8; 99 | 100 | bit = (c[inpos] >> (7 - (inoffs % 8))) & 1; 101 | str[outpos] |= (bit << (7 - outoffs)); 102 | (*size)++; 103 | inoffs++; 104 | } while(--nbits); 105 | } 106 | 107 | static void encode_node(hfm_node_t *node, uint8_t *tree, size_t *size) { 108 | uint8_t NIL = 0, ONE = 0x80; 109 | if(node->left == NULL) { 110 | add_bits(&NIL, 1, tree, size); 111 | add_bits(&(node->c), 8, tree, size); 112 | } else { 113 | add_bits(&ONE, 1, tree, size); 114 | encode_node(node->left, tree, size); 115 | encode_node(node->right, tree, size); 116 | } 117 | } 118 | 119 | uint8_t *encode_tree(hfm_node_t *root, size_t *charsize) { 120 | uint8_t *tree = malloc(320); 121 | size_t bitsize; 122 | 123 | bitsize = (*charsize) = 0; 124 | if(tree == NULL) 125 | return NULL; 126 | 127 | memset(tree, 0, 320); 128 | encode_node(root, tree, &bitsize); 129 | 130 | *charsize = bitsize / 8; 131 | *charsize += (bitsize % 8)?1:0; 132 | 133 | return tree; 134 | } 135 | 136 | static void walk_tree(hfm_node_t *node, hfm_cdb_t in, hfm_cdb_t *codebook) { 137 | hfm_cdb_t left = in, right = in; 138 | uint8_t NIL = 0, ONE = 0x80; 139 | 140 | if(node->left == NULL) { 141 | codebook[node->c] = in; 142 | } else { 143 | add_bits(&NIL, 1, left.val, &left.len); 144 | add_bits(&ONE, 1, right.val, &right.len); 145 | walk_tree(node->left, left, codebook); 146 | walk_tree(node->right, right, codebook); 147 | } 148 | } 149 | 150 | hfm_cdb_t *make_codebook(hfm_node_t *root) { 151 | hfm_cdb_t *out, zero; 152 | 153 | if((out = malloc(256 * sizeof(hfm_cdb_t))) == NULL) 154 | return NULL; 155 | 156 | zero.len = 0; 157 | memset(zero.val, 0, 32); 158 | 159 | walk_tree(root, zero, out); 160 | 161 | return out; 162 | } 163 | 164 | uint8_t *encode(uint8_t *in, size_t insize, hfm_cdb_t *codebook, size_t *charsize) { 165 | size_t i, bitsize = 0; 166 | uint8_t *out; 167 | *charsize = 0; 168 | 169 | for(i = 0; i < insize; i++) 170 | bitsize += codebook[in[i]].len; 171 | 172 | *charsize = (bitsize / 8) + ((bitsize % 8) ? 1 : 0); 173 | 174 | if((out = malloc(*charsize)) == NULL) 175 | return NULL; 176 | 177 | memset(out, 0, *charsize); 178 | bitsize = 0; 179 | 180 | for(i = 0; i < insize; i++) 181 | add_bits(codebook[in[i]].val, codebook[in[i]].len, out, &bitsize); 182 | 183 | return out; 184 | } 185 | 186 | void free_tree(hfm_node_t *node) { 187 | if(node->left) 188 | free_tree(node->left); 189 | if(node->right) 190 | free_tree(node->right); 191 | free(node); 192 | } -------------------------------------------------------------------------------- /mkbintable/huffman_enc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cryptpe -- Encryption tool for PE binaries 3 | * (C) 2012-2016 Martin Wolters 4 | * 5 | * This program is free software. It comes without any warranty, to 6 | * the extent permitted by applicable law. You can redistribute it 7 | * and/or modify it under the terms of the Do What The Fuck You Want 8 | * To Public License, Version 2, as published by Sam Hocevar. See 9 | * http://sam.zoy.org/wtfpl/COPYING for more details. 10 | */ 11 | 12 | #ifndef HUFFMAN_ENC_H_ 13 | #define HUFFMAN_ENC_H_ 14 | 15 | #include "..\shared\huffman.h" 16 | 17 | hfm_node_t *maketree(uint8_t *in, size_t len); 18 | uint8_t *encode_tree(hfm_node_t *root, size_t *size); 19 | hfm_cdb_t *make_codebook(hfm_node_t *root); 20 | uint8_t *encode(uint8_t *in, size_t insize, hfm_cdb_t *codebook, size_t *charsize); 21 | void free_tree(hfm_node_t *node); 22 | 23 | #endif -------------------------------------------------------------------------------- /mkbintable/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cryptpe -- Encryption tool for PE binaries 3 | * (C) 2012-2016 Martin Wolters 4 | * 5 | * This program is free software. It comes without any warranty, to 6 | * the extent permitted by applicable law. You can redistribute it 7 | * and/or modify it under the terms of the Do What The Fuck You Want 8 | * To Public License, Version 2, as published by Sam Hocevar. See 9 | * http://sam.zoy.org/wtfpl/COPYING for more details. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "huffman_enc.h" 17 | 18 | #include "..\shared\salsa20.h" 19 | 20 | static void getrandom(uint8_t *dst, const int len) { 21 | HCRYPTPROV provider; 22 | 23 | CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); 24 | CryptGenRandom(provider, len, dst); 25 | CryptReleaseContext(provider, 0); 26 | } 27 | 28 | static void printtable(char *name, const uint8_t *bin, const size_t len, salsa20_ctx_t *ctx) { 29 | size_t i; 30 | uint8_t *salsa_buf; 31 | 32 | printf("static uint8_t %s[] = {", name); 33 | for(i = 0; i < len; i++) { 34 | if(!(i % 32)) 35 | printf("\n\t"); 36 | if(ctx && !(i % SALSA20_BLOCK_SIZE)) 37 | salsa_buf = salsa20_gen_block(ctx); 38 | 39 | printf("0x%02x", bin[i] ^ (ctx ? salsa_buf[i % SALSA20_BLOCK_SIZE] : 0)); 40 | if(i < (len - 1)) 41 | printf(", "); 42 | } 43 | printf("\n};\n\n"); 44 | } 45 | 46 | int main(int argc, char **argv) { 47 | salsa20_ctx_t salsa20_ctx; 48 | uint8_t salsa20_key[SALSA20_KEY_SIZE]; 49 | uint8_t salsa20_nonce[SALSA20_NONCE_SIZE]; 50 | 51 | uint8_t *file_buf, *enc_tree, *encoded; 52 | size_t pos = 0, file_size, comp_size, tree_size; 53 | hfm_node_t *root; 54 | hfm_cdb_t *codebook; 55 | FILE *fp; 56 | 57 | if(argc == 1) { 58 | fprintf(stderr, "USAGE: %s \n", argv[0]); 59 | return EXIT_FAILURE; 60 | } 61 | 62 | if((fp = fopen(argv[1], "rb")) == NULL) { 63 | fprintf(stderr, "ERROR: Could not open '%s'.\n", argv[1]); 64 | return EXIT_FAILURE; 65 | } 66 | 67 | printf("/* THIS FILE HAS BEEN AUTOMATICALLY GENERATED BY MKBINTABLE */\n\n"); 68 | printf("#include \n\n#ifndef BINTABLE_H_\n#define BINTABLE_H_\n\n"); 69 | 70 | fseek(fp, 0, SEEK_END); 71 | file_size = ftell(fp); 72 | file_buf = malloc(file_size); 73 | fseek(fp, 0, SEEK_SET); 74 | fread(file_buf, file_size, 1, fp); 75 | printf("static size_t file_size = %d;\n\n", file_size); 76 | 77 | getrandom(salsa20_key, SALSA20_KEY_SIZE); 78 | getrandom(salsa20_nonce, SALSA20_NONCE_SIZE); 79 | salsa20_ctx = salsa20_init(salsa20_key, salsa20_nonce, SALSA20_KEY_SIZE); 80 | 81 | printtable("key", salsa20_key, SALSA20_KEY_SIZE, NULL); 82 | printtable("nonce", salsa20_nonce, SALSA20_NONCE_SIZE, NULL); 83 | 84 | root = maketree(file_buf, file_size); 85 | enc_tree = encode_tree(root, &tree_size); 86 | printtable("tree", enc_tree, tree_size, &salsa20_ctx); 87 | 88 | codebook = make_codebook(root); 89 | encoded = encode(file_buf, file_size, codebook, &comp_size); 90 | printtable("binary", encoded, comp_size, &salsa20_ctx); 91 | printf("#endif\n"); 92 | 93 | free(codebook); 94 | free(enc_tree); 95 | free(file_buf); 96 | free_tree(root); 97 | fclose(fp); 98 | 99 | return EXIT_SUCCESS; 100 | } 101 | -------------------------------------------------------------------------------- /mkbintable/mkbintable.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {8EFA16CF-2CD4-4BEF-ABD4-2F7F234CD91D} 23 | Win32Proj 24 | mkbintable 25 | 26 | 27 | 28 | Application 29 | true 30 | Unicode 31 | 32 | 33 | Application 34 | true 35 | Unicode 36 | 37 | 38 | Application 39 | false 40 | true 41 | Unicode 42 | 43 | 44 | Application 45 | false 46 | true 47 | Unicode 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | true 67 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 68 | $(Platform)\$(Configuration)\ 69 | 70 | 71 | true 72 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 73 | $(Platform)\$(Configuration)\ 74 | 75 | 76 | false 77 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 78 | $(Platform)\$(Configuration)\ 79 | 80 | 81 | false 82 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 83 | $(Platform)\$(Configuration)\ 84 | 85 | 86 | 87 | 88 | 89 | Level3 90 | Disabled 91 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | MultiThreadedDebug 93 | 94 | 95 | Console 96 | true 97 | 98 | 99 | call ..\script\mktable.bat win32 100 | 101 | 102 | 103 | 104 | 105 | 106 | Level3 107 | Disabled 108 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 109 | MultiThreadedDebug 110 | 111 | 112 | Console 113 | true 114 | 115 | 116 | call ..\script\mktable.bat x64 117 | 118 | 119 | 120 | 121 | Level3 122 | 123 | 124 | MaxSpeed 125 | true 126 | true 127 | _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 128 | 129 | 130 | Console 131 | true 132 | true 133 | true 134 | 135 | 136 | call ..\script\mktable.bat win32 137 | 138 | 139 | 140 | 141 | Level3 142 | 143 | 144 | MaxSpeed 145 | true 146 | true 147 | _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 148 | 149 | 150 | Console 151 | true 152 | true 153 | true 154 | 155 | 156 | call ..\script\mktable.bat x64 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /mkbintable/mkbintable.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {a6edf264-c6b8-46e7-83f4-6bb3fae05eca} 18 | 19 | 20 | {39f2fbce-49e8-460c-bc98-a4b63e9a94b7} 21 | 22 | 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files\shared 32 | 33 | 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files\shared 40 | 41 | 42 | Header Files\shared 43 | 44 | 45 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | CryptPE -- An encryption tool for PE binaries 2 | 3 | How to use 4 | ---------- 5 | 6 | Just running "Build solution" will first create an example executable 7 | (testbin.exe) and encrypt it. This is probably not what you want. 8 | 9 | To encrypt a binary of your choice: 10 | - Build mkbintable.exe 11 | - Run mkbintable on the desired binary to compress and encrypt it 12 | - Store the output in cryptpe\bintable.h 13 | - Build cryptpe.exe - This is the final encrypted executable 14 | 15 | License 16 | ------- 17 | 18 | The majority of CryptPE is licensed unter the WTFPL (see license.txt). 19 | Loader.c is a modified version of MemoryModule.c, part of MemoryModule, 20 | written by Joachim Bauch. It is licensed unter the MPL. -------------------------------------------------------------------------------- /script/clean.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd .. 4 | 5 | attrib -h -s log.txt 6 | attrib -h cryptpe.suo 7 | del /q log.txt 8 | del /q remotelog.txt 9 | del /q memlog.txt 10 | del /q cryptpe.suo 11 | del /q cryptpe.sdf 12 | del /q cryptpe.opensdf 13 | rd /q /s debug 14 | rd /q /s release 15 | rd /q /s ipch 16 | 17 | rd /q /s testbin\debug 18 | rd /q /s testbin\release 19 | del /q testbin\testbin.vcxproj.user 20 | del /q testbin\testbin.sdf 21 | 22 | rd /q /s mkbintable\debug 23 | rd /q /s mkbintable\release 24 | del /q mkbintable\mkbintable.vcxproj.user 25 | del /q mkbintable\mkbintable.sdf 26 | 27 | rd /q /s cryptpe\debug 28 | rd /q /s cryptpe\release 29 | del /q cryptpe\bintable.h 30 | del /q cryptpe\cryptpe.aps 31 | del /q cryptpe\cryptpe.vcxproj.user 32 | del /q cryptpe\cryptpe.sdf 33 | 34 | cd script -------------------------------------------------------------------------------- /script/mktable.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | pushd .. 4 | echo Looking for mkbintable.exe... 5 | 6 | FOR %%a IN (Win32 x64) DO ( 7 | FOR %%b IN (debug release) DO ( 8 | CALL :FINDBIN %%a %%b 9 | ) 10 | ) 11 | 12 | echo %BINARY% 13 | 14 | echo Creating table... 15 | 16 | %BINARY% bin\%1\Release\testbin.exe > cryptpe\bintable.h 17 | popd 18 | echo done. 19 | 20 | :FINDBIN 21 | IF EXIST bin\%1\%2\mkbintable.exe SET BINARY="bin\%1\%2\mkbintable.exe" 22 | EXIT /B -------------------------------------------------------------------------------- /shared/huffman.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cryptpe -- Encryption tool for PE binaries 3 | * (C) 2012-2016 Martin Wolters 4 | * 5 | * This program is free software. It comes without any warranty, to 6 | * the extent permitted by applicable law. You can redistribute it 7 | * and/or modify it under the terms of the Do What The Fuck You Want 8 | * To Public License, Version 2, as published by Sam Hocevar. See 9 | * http://sam.zoy.org/wtfpl/COPYING for more details. 10 | */ 11 | 12 | #include 13 | 14 | #ifndef HUFFMAN_H_ 15 | #define HUFFMAN_H_ 16 | 17 | typedef struct hfm_node_t { 18 | int weight; 19 | uint8_t c; 20 | struct hfm_node_t *left, *right, *parent; 21 | } hfm_node_t; 22 | 23 | typedef struct { 24 | uint8_t val[32]; 25 | size_t len; 26 | } hfm_cdb_t; 27 | 28 | #endif -------------------------------------------------------------------------------- /shared/salsa20.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cryptpe -- Encryption tool for PE binaries 3 | * (C) 2012-2016 Martin Wolters 4 | * 5 | * This program is free software. It comes without any warranty, to 6 | * the extent permitted by applicable law. You can redistribute it 7 | * and/or modify it under the terms of the Do What The Fuck You Want 8 | * To Public License, Version 2, as published by Sam Hocevar. See 9 | * http://sam.zoy.org/wtfpl/COPYING for more details. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "salsa20.h" 18 | 19 | #define rotl(x, n) (((x) << n) | ((x) >> (32 - n))) 20 | #define lend(a, b, c, d) ((a) | ((b) << 8) | ((c) << 16) | (d << 24)) 21 | 22 | static const uint8_t sigma[16] = { 23 | 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x20, 0x33, 24 | 0x32, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b 25 | }; 26 | 27 | static const uint8_t tau[16] = { 28 | 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x20, 0x31, 29 | 0x36, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b 30 | }; 31 | 32 | /* double round */ 33 | static void dround(uint32_t *y) { 34 | y[ 4] = y[ 4] ^ rotl((y[ 0] + y[12]), 7); 35 | y[ 8] = y[ 8] ^ rotl((y[ 4] + y[ 0]), 9); 36 | y[12] = y[12] ^ rotl((y[ 8] + y[ 4]), 13); 37 | y[ 0] = y[ 0] ^ rotl((y[12] + y[ 8]), 18); 38 | y[ 9] = y[ 9] ^ rotl((y[ 5] + y[ 1]), 7); 39 | y[13] = y[13] ^ rotl((y[ 9] + y[ 5]), 9); 40 | y[ 1] = y[ 1] ^ rotl((y[13] + y[ 9]), 13); 41 | y[ 5] = y[ 5] ^ rotl((y[ 1] + y[13]), 18); 42 | y[14] = y[14] ^ rotl((y[10] + y[ 6]), 7); 43 | y[ 2] = y[ 2] ^ rotl((y[14] + y[10]), 9); 44 | y[ 6] = y[ 6] ^ rotl((y[ 2] + y[14]), 13); 45 | y[10] = y[10] ^ rotl((y[ 6] + y[ 2]), 18); 46 | y[ 3] = y[ 3] ^ rotl((y[15] + y[11]), 7); 47 | y[ 7] = y[ 7] ^ rotl((y[ 3] + y[15]), 9); 48 | y[11] = y[11] ^ rotl((y[ 7] + y[ 3]), 13); 49 | y[15] = y[15] ^ rotl((y[11] + y[ 7]), 18); 50 | y[ 1] = y[ 1] ^ rotl((y[ 0] + y[ 3]), 7); 51 | y[ 2] = y[ 2] ^ rotl((y[ 1] + y[ 0]), 9); 52 | y[ 3] = y[ 3] ^ rotl((y[ 2] + y[ 1]), 13); 53 | y[ 0] = y[ 0] ^ rotl((y[ 3] + y[ 2]), 18); 54 | y[ 6] = y[ 6] ^ rotl((y[ 5] + y[ 4]), 7); 55 | y[ 7] = y[ 7] ^ rotl((y[ 6] + y[ 5]), 9); 56 | y[ 4] = y[ 4] ^ rotl((y[ 7] + y[ 6]), 13); 57 | y[ 5] = y[ 5] ^ rotl((y[ 4] + y[ 7]), 18); 58 | y[11] = y[11] ^ rotl((y[10] + y[ 9]), 7); 59 | y[ 8] = y[ 8] ^ rotl((y[11] + y[10]), 9); 60 | y[ 9] = y[ 9] ^ rotl((y[ 8] + y[11]), 13); 61 | y[10] = y[10] ^ rotl((y[ 9] + y[ 8]), 18); 62 | y[12] = y[12] ^ rotl((y[15] + y[14]), 7); 63 | y[13] = y[13] ^ rotl((y[12] + y[15]), 9); 64 | y[14] = y[14] ^ rotl((y[13] + y[12]), 13); 65 | y[15] = y[15] ^ rotl((y[14] + y[13]), 18); 66 | } 67 | 68 | static void salsa20(uint8_t *in) { 69 | size_t i; 70 | uint32_t x[16]; 71 | uint32_t o[16]; 72 | 73 | for(i = 0; i < 16; i++) { 74 | o[i] = x[i] = lend(in[i * 4], in[i * 4 + 1], in[i * 4 + 2], in[i * 4 + 3]); 75 | } 76 | 77 | for(i = 0; i < 10; i++) 78 | dround(x); 79 | 80 | for(i = 0; i < 16; i++) { 81 | o[i] += x[i]; 82 | in[i * 4] = o[i]; 83 | in[i * 4 + 1] = (o[i] >> 8); 84 | in[i * 4 + 2] = (o[i] >> 16); 85 | in[i * 4 + 3] = (o[i] >> 24); 86 | } 87 | } 88 | 89 | static void expand(uint8_t *x, const uint8_t *k, const uint8_t *n, const size_t n_bytes) { 90 | size_t i; 91 | const uint8_t *c, *l; 92 | 93 | if(n_bytes == 32) { 94 | c = sigma; 95 | l = k + 16; 96 | } else { 97 | c = tau; 98 | l = k; 99 | } 100 | 101 | for(i = 0; i < 4; i++) { 102 | x[i] = c[i]; 103 | x[i + 20] = c[i + 4]; 104 | x[i + 40] = c[i + 8]; 105 | x[i + 60] = c[i + 12]; 106 | } 107 | 108 | memcpy(x + 4, k, 16); 109 | memcpy(x + 24, n, 16); 110 | memcpy(x + 44, l, 16); 111 | } 112 | 113 | static void increment(uint8_t *n) { 114 | int carry = 0; 115 | size_t offs = 8; 116 | 117 | do { 118 | if(n[offs] == 0xff) 119 | carry = 1; 120 | else 121 | carry = 0; 122 | 123 | n[offs]++; 124 | offs++; 125 | } while((offs < 16) && carry); 126 | } 127 | 128 | salsa20_ctx_t salsa20_init(const uint8_t *key, const uint8_t *nonce, const size_t ksize) { 129 | salsa20_ctx_t out; 130 | 131 | memset(out.state, 0, 64); 132 | memcpy(out.key, key, 32); 133 | memcpy(out.nonce, nonce, 16); 134 | out.ksize = ksize; 135 | 136 | return out; 137 | } 138 | 139 | uint8_t *salsa20_gen_block(salsa20_ctx_t *ctx) { 140 | expand(ctx->state, ctx->key, ctx->nonce, ctx->ksize); 141 | salsa20(ctx->state); 142 | increment(ctx->nonce); 143 | 144 | return ctx->state; 145 | } -------------------------------------------------------------------------------- /shared/salsa20.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cryptpe -- Encryption tool for PE binaries 3 | * (C) 2012-2016 Martin Wolters 4 | * 5 | * This program is free software. It comes without any warranty, to 6 | * the extent permitted by applicable law. You can redistribute it 7 | * and/or modify it under the terms of the Do What The Fuck You Want 8 | * To Public License, Version 2, as published by Sam Hocevar. See 9 | * http://sam.zoy.org/wtfpl/COPYING for more details. 10 | */ 11 | 12 | #ifndef SALSA20_H_ 13 | #define SALSA20_H_ 14 | 15 | #define SALSA20_KEY_SIZE 32 16 | #define SALSA20_BLOCK_SIZE 64 17 | #define SALSA20_NONCE_SIZE 16 18 | 19 | typedef struct salsa20_ctx_t { 20 | uint8_t state[64]; 21 | uint8_t key[32]; 22 | uint8_t nonce[16]; 23 | size_t ksize; 24 | } salsa20_ctx_t; 25 | 26 | salsa20_ctx_t salsa20_init(const uint8_t *key, const uint8_t *nonce, const size_t ksize); 27 | uint8_t *salsa20_gen_block(salsa20_ctx_t *ctx); 28 | 29 | #endif -------------------------------------------------------------------------------- /testbin/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * testbin -- Example program for cryptpe 3 | * (C) 2012-2016 Martin Wolters 4 | * 5 | * This program is free software. It comes without any warranty, to 6 | * the extent permitted by applicable law. You can redistribute it 7 | * and/or modify it under the terms of the Do What The Fuck You Want 8 | * To Public License, Version 2, as published by Sam Hocevar. See 9 | * http://sam.zoy.org/wtfpl/COPYING for more details. 10 | */ 11 | 12 | #include 13 | 14 | /* We need to explicitly export main(), or MemoryModule won't find it. */ 15 | __declspec(dllexport) 16 | int main(int argc, char **argv) { 17 | int i; 18 | 19 | printf("argc = %d\n", argc); 20 | for(i = 0; i < argc; i++) 21 | printf("argv[%d] = '%s'\n", i, argv[i]); 22 | 23 | return 0; 24 | } -------------------------------------------------------------------------------- /testbin/testbin.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Release 6 | Win32 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {B4192D03-4E38-4F45-B115-EAC8C9A98620} 15 | Win32Proj 16 | testbin 17 | 18 | 19 | 20 | Application 21 | false 22 | true 23 | NotSet 24 | 25 | 26 | Application 27 | false 28 | true 29 | NotSet 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | false 43 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 44 | $(Platform)\$(Configuration)\ 45 | 46 | 47 | false 48 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 49 | $(Platform)\$(Configuration)\ 50 | 51 | 52 | 53 | Level3 54 | 55 | 56 | MaxSpeed 57 | true 58 | true 59 | WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 60 | 61 | 62 | Console 63 | true 64 | true 65 | true 66 | 67 | 68 | 69 | 70 | Level3 71 | 72 | 73 | MaxSpeed 74 | true 75 | true 76 | WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 77 | 78 | 79 | Console 80 | true 81 | true 82 | true 83 | 84 | 85 | 86 | 87 | CompileAsC 88 | CompileAsC 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /testbin/testbin.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | --------------------------------------------------------------------------------