#include #include #include #include #ifdef _WIN32 #include #else #include #endif #include "shcutils.h" #ifdef _MSC_VER #pragma warning(disable:4996) #pragma section("shcode", execute) #endif // This method should be fully inline. No use of static fields & external methods is allowed since the shellcode // Is supposed to be fully inline & offset independent (use PEB for windows & syscalls for linux) SECTION_CODE("shcode") NOINLINE int /*_fastcall*/ shellcode() { #ifdef _WINDOWS // Typedefs for all the required methods typedef void* (*LoadLibraryA_t)(char*); typedef void* (*MessageBoxA_t)(int, char*, char*, int); // Some compilers insert the strings into the .data no matter what you do. So we need to trick em volatile char u32[30]; volatile int i = 0; u32[i++] = 'u'; u32[i++] = 's'; u32[i++] = 'e'; u32[i++] = 'r'; u32[i++] = '3'; u32[i++] = '2'; u32[i++] = '.'; u32[i++] = 'd'; u32[i++] = 'l'; u32[i++] = 'l', u32[i++] = '\0'; volatile char msg[30]; i = 0; msg[i++] = 't'; msg[i++] = 'e'; msg[i++] = 's'; msg[i++] = 't', msg[i++] = '\0'; /* Note that any definitions should remain stack only. Otherwise the shellcode will be invalid // This gets stored to .data section 100% char s1[] = "test"; // This gets stored to .data section 50/50 on different compilers char s2[] = {'t', 'e', 's', 't', 0}; // This is stored to stack in 100% cases. Allows to trick the compiler char s3[32]; int i = 0; s3[i++] = 't', s3[i++] = 'e', s3[i++] = 's', s3[i++] = 't',s3[i++] = '\0'; */ void* base = get_module_handle(HASH("kernel32.dll")); if (base) { LoadLibraryA_t LoadLibA = (LoadLibraryA_t) get_proc_address(base, HASH("LoadLibraryA")); if (LoadLibA) { void* handle = LoadLibA((char*)u32); if (handle) { MessageBoxA_t MsgBoxA = (MessageBoxA_t) get_proc_address(handle, HASH("MessageBoxA")); MsgBoxA(0, (char*)msg, (char*)msg, MB_OK); return 0; } } } #elif defined(_LINUX) volatile char msg[30]; volatile int i = 0; msg[i++] = 'H'; msg[i++] = 'e'; msg[i++] = 'l'; msg[i++] = 'l' , msg[i++] = 'o', msg[i++] = ' ', msg[i++] = 'f', msg[i++] = 'r', msg[i++] = 'o', msg[i++] = 'm', msg[i++] = ' ', msg[i++] = 's', msg[i++] = 'h', msg[i++] = 'e', msg[i++] = 'l', msg[i++] = 'l', msg[i++] = '!', msg[i++] = '\n' , msg[i++] = '\0'; inline_syscall(SYS_write, STDOUT_FILENO, (long)msg, i, 0, 0); return 0; #endif return 1; } // Next function goes directly after the shellcode, this allows to figure out shellcode size & dump it SECTION_CODE("shcode") NAKED void shellcode_end(void) {} typedef int (*shellcode_t)(); int main() { FILE* output_file = fopen("shellcode.bin", "wb"); if (!output_file) { fprintf(stderr, "[e] Failed to open shellcode.bin\n"); return 1; } size_t shellcode_size = (uintptr_t)shellcode_end - (uintptr_t)shellcode; printf("[i] Shellcode size: %lu, located at 0x%p\n", shellcode_size, shellcode); fwrite((char*)&shellcode, shellcode_size, 1, output_file); if (!fwrite((char*)&shellcode, shellcode_size, 1, output_file)) { fprintf(stderr, "[e] Failed to dump shellcode to disk. Check your compiler settings.\n"); fclose(output_file); return 1; } fclose(output_file); printf("[i] Shellcode saved to file shellcode.bin.\n"); FILE* file = fopen("shellcode.bin", "rb"); if (!file) { fprintf(stderr, "[e] Failed to open shellcode.bin\n"); return 1; } fseek(file, 0, SEEK_END); long fileSize = ftell(file); fseek(file, 0, SEEK_SET); char* shellcode_buff = (char*)malloc(fileSize); if (!shellcode_buff) { fprintf(stderr, "[e] Failed to allocate memory for shellcode\n"); fclose(file); return 1; } if (fread(shellcode_buff, 1, fileSize, file) != fileSize) { fprintf(stderr, "[e] Failed to read shellcode\n"); #ifdef _WIN32 VirtualFree(shellcode_buff, 0, MEM_RELEASE); #else free(shellcode_buff); #endif fclose(file); return 1; } fclose(file); printf("[i] Loaded shellcode size: %ld\n", fileSize); #ifdef _WIN32 DWORD flOldProtect; if (!VirtualProtect(shellcode_buff, fileSize, PAGE_EXECUTE_READWRITE, &flOldProtect)) { fprintf(stderr, "[e] Failed to change memory protection\n"); VirtualFree(shellcode_buff, 0, MEM_RELEASE); return 1; } #else if (mprotect(shellcode_buff, fileSize, PROT_EXEC | PROT_READ | PROT_WRITE) == -1) { fprintf(stderr, "[e] Failed to change memory protection\n"); free(shellcode_buff); return 1; } #endif shellcode_t code = (shellcode_t)shellcode_buff; printf("Result: %d\n", code()); printf("Shellcode execution completed successfully.\n"); return 0; }